/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/Android.mk |
---|
0,0 → 1,76 |
# |
# Copyright (C) 2011 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 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) |
# Import mesa_dri_common_INCLUDES. |
include $(LOCAL_PATH)/common/Makefile.sources |
#----------------------------------------------- |
# Variables common to all DRI drivers |
MESA_DRI_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/dri |
MESA_DRI_MODULE_UNSTRIPPED_PATH := $(TARGET_OUT_SHARED_LIBRARIES_UNSTRIPPED)/dri |
MESA_DRI_CFLAGS := \ |
-DFEATURE_GL=1 \ |
-DFEATURE_ES1=1 \ |
-DFEATURE_ES2=1 \ |
-DHAVE_ANDROID_PLATFORM |
MESA_DRI_C_INCLUDES := \ |
$(call intermediates-dir-for,STATIC_LIBRARIES,libmesa_dri_common) \ |
$(addprefix $(MESA_TOP)/, $(mesa_dri_common_INCLUDES)) \ |
$(DRM_TOP) \ |
$(DRM_TOP)/include/drm \ |
external/expat/lib |
MESA_DRI_WHOLE_STATIC_LIBRARIES := \ |
libmesa_glsl \ |
libmesa_dri_common \ |
libmesa_dricore |
MESA_DRI_SHARED_LIBRARIES := \ |
libcutils \ |
libdl \ |
libdrm \ |
libexpat \ |
libglapi \ |
liblog |
# All DRI modules must add this to LOCAL_GENERATED_SOURCES. |
MESA_DRI_OPTIONS_H := $(call intermediates-dir-for,STATIC_LIBRARIES,libmesa_dri_common)/xmlpool/options.h |
#----------------------------------------------- |
# Build drivers and libmesa_dri_common |
SUBDIRS := common |
ifneq ($(filter i915, $(MESA_GPU_DRIVERS)),) |
SUBDIRS += i915 |
endif |
ifneq ($(filter i965, $(MESA_GPU_DRIVERS)),) |
SUBDIRS += i965 |
endif |
include $(foreach d, $(SUBDIRS), $(LOCAL_PATH)/$(d)/Android.mk) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/Makefile.am |
---|
0,0 → 1,35 |
SUBDIRS = |
if HAVE_COMMON_DRI |
SUBDIRS+=common |
endif |
if HAVE_I915_DRI |
SUBDIRS+=i915 |
endif |
if HAVE_I965_DRI |
SUBDIRS+=i965 |
endif |
if HAVE_NOUVEAU_DRI |
SUBDIRS+=nouveau |
endif |
if HAVE_R200_DRI |
SUBDIRS+=r200 |
endif |
if HAVE_RADEON_DRI |
SUBDIRS+=radeon |
endif |
if HAVE_SWRAST_DRI |
SUBDIRS+=swrast |
endif |
pkgconfigdir = $(libdir)/pkgconfig |
pkgconfig_DATA = dri.pc |
driincludedir = $(includedir)/GL/internal |
driinclude_HEADERS = $(top_srcdir)/include/GL/internal/dri_interface.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/Makefile.in |
---|
0,0 → 1,871 |
# 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@ |
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@ |
@HAVE_COMMON_DRI_TRUE@am__append_1 = common |
@HAVE_I915_DRI_TRUE@am__append_2 = i915 |
@HAVE_I965_DRI_TRUE@am__append_3 = i965 |
@HAVE_NOUVEAU_DRI_TRUE@am__append_4 = nouveau |
@HAVE_R200_DRI_TRUE@am__append_5 = r200 |
@HAVE_RADEON_DRI_TRUE@am__append_6 = radeon |
@HAVE_SWRAST_DRI_TRUE@am__append_7 = swrast |
subdir = src/mesa/drivers/dri |
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ |
$(srcdir)/dri.pc.in $(driinclude_HEADERS) |
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 = dri.pc |
CONFIG_CLEAN_VPATH_FILES = |
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 = |
SOURCES = |
DIST_SOURCES = |
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ |
ctags-recursive dvi-recursive html-recursive info-recursive \ |
install-data-recursive install-dvi-recursive \ |
install-exec-recursive install-html-recursive \ |
install-info-recursive install-pdf-recursive \ |
install-ps-recursive install-recursive installcheck-recursive \ |
installdirs-recursive pdf-recursive ps-recursive \ |
tags-recursive uninstall-recursive |
am__can_run_installinfo = \ |
case $$AM_UPDATE_INFO_DIR in \ |
n|no|NO) false;; \ |
*) (install-info --version) >/dev/null 2>&1;; \ |
esac |
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; |
am__vpath_adj = case $$p in \ |
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |
*) f=$$p;; \ |
esac; |
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; |
am__install_max = 40 |
am__nobase_strip_setup = \ |
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` |
am__nobase_strip = \ |
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" |
am__nobase_list = $(am__nobase_strip_setup); \ |
for p in $$list; do echo "$$p $$p"; done | \ |
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ |
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ |
if (++n[$$2] == $(am__install_max)) \ |
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ |
END { for (dir in files) print dir, files[dir] }' |
am__base_list = \ |
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ |
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' |
am__uninstall_files_from_dir = { \ |
test -z "$$files" \ |
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ |
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \ |
$(am__cd) "$$dir" && rm -f $$files; }; \ |
} |
am__installdirs = "$(DESTDIR)$(pkgconfigdir)" \ |
"$(DESTDIR)$(driincludedir)" |
DATA = $(pkgconfig_DATA) |
HEADERS = $(driinclude_HEADERS) |
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ |
distclean-recursive maintainer-clean-recursive |
am__recursive_targets = \ |
$(RECURSIVE_TARGETS) \ |
$(RECURSIVE_CLEAN_TARGETS) \ |
$(am__extra_recursive_targets) |
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ |
distdir |
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 |
DIST_SUBDIRS = common i915 i965 nouveau r200 radeon swrast |
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
am__relativize = \ |
dir0=`pwd`; \ |
sed_first='s,^\([^/]*\)/.*$$,\1,'; \ |
sed_rest='s,^[^/]*/*,,'; \ |
sed_last='s,^.*/\([^/]*\)$$,\1,'; \ |
sed_butlast='s,/*[^/]*$$,,'; \ |
while test -n "$$dir1"; do \ |
first=`echo "$$dir1" | sed -e "$$sed_first"`; \ |
if test "$$first" != "."; then \ |
if test "$$first" = ".."; then \ |
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ |
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ |
else \ |
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ |
if test "$$first2" = "$$first"; then \ |
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ |
else \ |
dir2="../$$dir2"; \ |
fi; \ |
dir0="$$dir0"/"$$first"; \ |
fi; \ |
fi; \ |
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ |
done; \ |
reldir="$$dir2" |
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@ |
SUBDIRS = $(am__append_1) $(am__append_2) $(am__append_3) \ |
$(am__append_4) $(am__append_5) $(am__append_6) \ |
$(am__append_7) |
pkgconfigdir = $(libdir)/pkgconfig |
pkgconfig_DATA = dri.pc |
driincludedir = $(includedir)/GL/internal |
driinclude_HEADERS = $(top_srcdir)/include/GL/internal/dri_interface.h |
all: all-recursive |
.SUFFIXES: |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(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/mesa/drivers/dri/Makefile'; \ |
$(am__cd) $(top_srcdir) && \ |
$(AUTOMAKE) --foreign src/mesa/drivers/dri/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_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): |
dri.pc: $(top_builddir)/config.status $(srcdir)/dri.pc.in |
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ |
mostlyclean-libtool: |
-rm -f *.lo |
clean-libtool: |
-rm -rf .libs _libs |
install-pkgconfigDATA: $(pkgconfig_DATA) |
@$(NORMAL_INSTALL) |
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ |
if test -n "$$list"; then \ |
echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ |
$(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ |
fi; \ |
for p in $$list; do \ |
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ |
echo "$$d$$p"; \ |
done | $(am__base_list) | \ |
while read files; do \ |
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ |
$(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ |
done |
uninstall-pkgconfigDATA: |
@$(NORMAL_UNINSTALL) |
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ |
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ |
dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) |
install-driincludeHEADERS: $(driinclude_HEADERS) |
@$(NORMAL_INSTALL) |
@list='$(driinclude_HEADERS)'; test -n "$(driincludedir)" || list=; \ |
if test -n "$$list"; then \ |
echo " $(MKDIR_P) '$(DESTDIR)$(driincludedir)'"; \ |
$(MKDIR_P) "$(DESTDIR)$(driincludedir)" || exit 1; \ |
fi; \ |
for p in $$list; do \ |
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ |
echo "$$d$$p"; \ |
done | $(am__base_list) | \ |
while read files; do \ |
echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(driincludedir)'"; \ |
$(INSTALL_HEADER) $$files "$(DESTDIR)$(driincludedir)" || exit $$?; \ |
done |
uninstall-driincludeHEADERS: |
@$(NORMAL_UNINSTALL) |
@list='$(driinclude_HEADERS)'; test -n "$(driincludedir)" || list=; \ |
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ |
dir='$(DESTDIR)$(driincludedir)'; $(am__uninstall_files_from_dir) |
# This directory's subdirectories are mostly independent; you can cd |
# into them and run 'make' without going through this Makefile. |
# To change the values of 'make' variables: instead of editing Makefiles, |
# (1) if the variable is set in 'config.status', edit 'config.status' |
# (which will cause the Makefiles to be regenerated when you run 'make'); |
# (2) otherwise, pass the desired values on the 'make' command line. |
$(am__recursive_targets): |
@fail=; \ |
if $(am__make_keepgoing); then \ |
failcom='fail=yes'; \ |
else \ |
failcom='exit 1'; \ |
fi; \ |
dot_seen=no; \ |
target=`echo $@ | sed s/-recursive//`; \ |
case "$@" in \ |
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ |
*) list='$(SUBDIRS)' ;; \ |
esac; \ |
for subdir in $$list; do \ |
echo "Making $$target in $$subdir"; \ |
if test "$$subdir" = "."; then \ |
dot_seen=yes; \ |
local_target="$$target-am"; \ |
else \ |
local_target="$$target"; \ |
fi; \ |
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ |
|| eval $$failcom; \ |
done; \ |
if test "$$dot_seen" = "no"; then \ |
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ |
fi; test -z "$$fail" |
ID: $(am__tagged_files) |
$(am__define_uniq_tagged_files); mkid -fID $$unique |
tags: tags-recursive |
TAGS: tags |
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) |
set x; \ |
here=`pwd`; \ |
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ |
include_option=--etags-include; \ |
empty_fix=.; \ |
else \ |
include_option=--include; \ |
empty_fix=; \ |
fi; \ |
list='$(SUBDIRS)'; for subdir in $$list; do \ |
if test "$$subdir" = .; then :; else \ |
test ! -f $$subdir/TAGS || \ |
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ |
fi; \ |
done; \ |
$(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-recursive |
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-recursive |
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 |
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ |
if test "$$subdir" = .; then :; else \ |
$(am__make_dryrun) \ |
|| test -d "$(distdir)/$$subdir" \ |
|| $(MKDIR_P) "$(distdir)/$$subdir" \ |
|| exit 1; \ |
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ |
$(am__relativize); \ |
new_distdir=$$reldir; \ |
dir1=$$subdir; dir2="$(top_distdir)"; \ |
$(am__relativize); \ |
new_top_distdir=$$reldir; \ |
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ |
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ |
($(am__cd) $$subdir && \ |
$(MAKE) $(AM_MAKEFLAGS) \ |
top_distdir="$$new_top_distdir" \ |
distdir="$$new_distdir" \ |
am__remove_distdir=: \ |
am__skip_length_check=: \ |
am__skip_mode_fix=: \ |
distdir) \ |
|| exit 1; \ |
fi; \ |
done |
check-am: all-am |
check: check-recursive |
all-am: Makefile $(DATA) $(HEADERS) |
installdirs: installdirs-recursive |
installdirs-am: |
for dir in "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(driincludedir)"; do \ |
test -z "$$dir" || $(MKDIR_P) "$$dir"; \ |
done |
install: install-recursive |
install-exec: install-exec-recursive |
install-data: install-data-recursive |
uninstall: uninstall-recursive |
install-am: all-am |
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am |
installcheck: installcheck-recursive |
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-recursive |
clean-am: clean-generic clean-libtool mostlyclean-am |
distclean: distclean-recursive |
-rm -f Makefile |
distclean-am: clean-am distclean-generic distclean-tags |
dvi: dvi-recursive |
dvi-am: |
html: html-recursive |
html-am: |
info: info-recursive |
info-am: |
install-data-am: install-driincludeHEADERS install-pkgconfigDATA |
install-dvi: install-dvi-recursive |
install-dvi-am: |
install-exec-am: |
install-html: install-html-recursive |
install-html-am: |
install-info: install-info-recursive |
install-info-am: |
install-man: |
install-pdf: install-pdf-recursive |
install-pdf-am: |
install-ps: install-ps-recursive |
install-ps-am: |
installcheck-am: |
maintainer-clean: maintainer-clean-recursive |
-rm -f Makefile |
maintainer-clean-am: distclean-am maintainer-clean-generic |
mostlyclean: mostlyclean-recursive |
mostlyclean-am: mostlyclean-generic mostlyclean-libtool |
pdf: pdf-recursive |
pdf-am: |
ps: ps-recursive |
ps-am: |
uninstall-am: uninstall-driincludeHEADERS uninstall-pkgconfigDATA |
.MAKE: $(am__recursive_targets) install-am install-strip |
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ |
check-am clean clean-generic clean-libtool cscopelist-am ctags \ |
ctags-am distclean 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-driincludeHEADERS 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-pkgconfigDATA install-ps install-ps-am \ |
install-strip installcheck installcheck-am installdirs \ |
installdirs-am maintainer-clean maintainer-clean-generic \ |
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ |
ps ps-am tags tags-am uninstall uninstall-am \ |
uninstall-driincludeHEADERS uninstall-pkgconfigDATA |
# 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/src/mesa/drivers/dri/common/Android.mk |
---|
0,0 → 1,88 |
# |
# Mesa 3-D graphics library |
# |
# Copyright (C) 2011 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 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. |
# |
# |
# Build libmesa_dri_common |
# |
LOCAL_PATH := $(call my-dir) |
include $(CLEAR_VARS) |
include $(LOCAL_PATH)/Makefile.sources |
LOCAL_MODULE := libmesa_dri_common |
LOCAL_MODULE_CLASS := STATIC_LIBRARIES |
intermediates := $(call local-intermediates-dir) |
LOCAL_C_INCLUDES := \ |
$(intermediates) \ |
$(MESA_DRI_C_INCLUDES) |
LOCAL_SRC_FILES := $(mesa_dri_common_SOURCES) |
LOCAL_GENERATED_SOURCES := \ |
$(intermediates)/xmlpool/options.h |
# |
# Generate options.h from gettext translations. |
# |
MESA_DRI_OPTIONS_LANGS := de es nl fr sv |
POT := $(intermediates)/xmlpool.pot |
$(POT): $(LOCAL_PATH)/xmlpool/t_options.h |
@mkdir -p $(dir $@) |
xgettext -L C --from-code utf-8 -o $@ $< |
$(intermediates)/xmlpool/%.po: $(LOCAL_PATH)/xmlpool/%.po $(POT) |
lang=$(basename $(notdir $@)); \ |
mkdir -p $(dir $@); \ |
if [ -f $< ]; then \ |
msgmerge -o $@ $^; \ |
else \ |
msginit -i $(POT) \ |
-o $@ \ |
--locale=$$lang \ |
--no-translator; \ |
sed -i -e 's/charset=.*\\n/charset=UTF-8\\n/' $@; \ |
fi |
$(intermediates)/xmlpool/%/LC_MESSAGES/options.mo: $(intermediates)/xmlpool/%.po |
mkdir -p $(dir $@) |
msgfmt -o $@ $< |
$(intermediates)/xmlpool/options.h: PRIVATE_SCRIPT := $(LOCAL_PATH)/xmlpool/gen_xmlpool.py |
$(intermediates)/xmlpool/options.h: PRIVATE_LOCALEDIR := $(intermediates)/xmlpool |
$(intermediates)/xmlpool/options.h: PRIVATE_TEMPLATE_HEADER := $(LOCAL_PATH)/xmlpool/t_options.h |
$(intermediates)/xmlpool/options.h: PRIVATE_MO_FILES := $(MESA_DRI_OPTIONS_LANGS:%=$(intermediates)/xmlpool/%/LC_MESSAGES/options.mo) |
.SECONDEXPANSION: |
$(intermediates)/xmlpool/options.h: $$(PRIVATE_SCRIPT) $$(PRIVATE_TEMPLATE_HEADER) $$(PRIVATE_MO_FILES) |
mkdir -p $(dir $@) |
mkdir -p $(PRIVATE_LOCALEDIR) |
$(MESA_PYTHON2) $(PRIVATE_SCRIPT) $(PRIVATE_TEMPLATE_HEADER) \ |
$(PRIVATE_LOCALEDIR) $(MESA_DRI_OPTIONS_LANGS) > $@ |
include $(MESA_COMMON_MK) |
include $(BUILD_STATIC_LIBRARY) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/Makefile.am |
---|
0,0 → 1,46 |
# 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. |
SUBDIRS = xmlpool |
AM_CFLAGS = \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
$(DEFINES) \ |
$(LIBDRM_CFLAGS) \ |
$(VISIBILITY_CFLAGS) |
noinst_LTLIBRARIES = \ |
libdricommon.la \ |
libdri_test_stubs.la |
libdricommon_la_SOURCES = \ |
utils.c \ |
dri_util.c \ |
xmlconfig.c |
libdri_test_stubs_la_SOURCES = \ |
dri_test.c |
libdri_test_stubs_la_CFLAGS = $(AM_CFLAGS) -DNO_MAIN |
sysconf_DATA = drirc |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/Makefile.in |
---|
0,0 → 1,977 |
# 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@ |
subdir = src/mesa/drivers/dri/common |
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ |
$(top_srcdir)/bin/depcomp |
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) |
libdri_test_stubs_la_LIBADD = |
am_libdri_test_stubs_la_OBJECTS = libdri_test_stubs_la-dri_test.lo |
libdri_test_stubs_la_OBJECTS = $(am_libdri_test_stubs_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 = |
libdri_test_stubs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ |
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ |
$(libdri_test_stubs_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ |
$(LDFLAGS) -o $@ |
libdricommon_la_LIBADD = |
am_libdricommon_la_OBJECTS = utils.lo dri_util.lo xmlconfig.lo |
libdricommon_la_OBJECTS = $(am_libdricommon_la_OBJECTS) |
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 = $(libdri_test_stubs_la_SOURCES) $(libdricommon_la_SOURCES) |
DIST_SOURCES = $(libdri_test_stubs_la_SOURCES) \ |
$(libdricommon_la_SOURCES) |
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ |
ctags-recursive dvi-recursive html-recursive info-recursive \ |
install-data-recursive install-dvi-recursive \ |
install-exec-recursive install-html-recursive \ |
install-info-recursive install-pdf-recursive \ |
install-ps-recursive install-recursive installcheck-recursive \ |
installdirs-recursive pdf-recursive ps-recursive \ |
tags-recursive uninstall-recursive |
am__can_run_installinfo = \ |
case $$AM_UPDATE_INFO_DIR in \ |
n|no|NO) false;; \ |
*) (install-info --version) >/dev/null 2>&1;; \ |
esac |
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; |
am__vpath_adj = case $$p in \ |
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |
*) f=$$p;; \ |
esac; |
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; |
am__install_max = 40 |
am__nobase_strip_setup = \ |
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` |
am__nobase_strip = \ |
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" |
am__nobase_list = $(am__nobase_strip_setup); \ |
for p in $$list; do echo "$$p $$p"; done | \ |
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ |
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ |
if (++n[$$2] == $(am__install_max)) \ |
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ |
END { for (dir in files) print dir, files[dir] }' |
am__base_list = \ |
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ |
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' |
am__uninstall_files_from_dir = { \ |
test -z "$$files" \ |
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ |
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \ |
$(am__cd) "$$dir" && rm -f $$files; }; \ |
} |
am__installdirs = "$(DESTDIR)$(sysconfdir)" |
DATA = $(sysconf_DATA) |
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ |
distclean-recursive maintainer-clean-recursive |
am__recursive_targets = \ |
$(RECURSIVE_TARGETS) \ |
$(RECURSIVE_CLEAN_TARGETS) \ |
$(am__extra_recursive_targets) |
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ |
distdir |
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 |
DIST_SUBDIRS = $(SUBDIRS) |
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
am__relativize = \ |
dir0=`pwd`; \ |
sed_first='s,^\([^/]*\)/.*$$,\1,'; \ |
sed_rest='s,^[^/]*/*,,'; \ |
sed_last='s,^.*/\([^/]*\)$$,\1,'; \ |
sed_butlast='s,/*[^/]*$$,,'; \ |
while test -n "$$dir1"; do \ |
first=`echo "$$dir1" | sed -e "$$sed_first"`; \ |
if test "$$first" != "."; then \ |
if test "$$first" = ".."; then \ |
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ |
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ |
else \ |
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ |
if test "$$first2" = "$$first"; then \ |
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ |
else \ |
dir2="../$$dir2"; \ |
fi; \ |
dir0="$$dir0"/"$$first"; \ |
fi; \ |
fi; \ |
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ |
done; \ |
reldir="$$dir2" |
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@ |
SUBDIRS = xmlpool |
AM_CFLAGS = \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
$(DEFINES) \ |
$(LIBDRM_CFLAGS) \ |
$(VISIBILITY_CFLAGS) |
noinst_LTLIBRARIES = \ |
libdricommon.la \ |
libdri_test_stubs.la |
libdricommon_la_SOURCES = \ |
utils.c \ |
dri_util.c \ |
xmlconfig.c |
libdri_test_stubs_la_SOURCES = \ |
dri_test.c |
libdri_test_stubs_la_CFLAGS = $(AM_CFLAGS) -DNO_MAIN |
sysconf_DATA = drirc |
all: all-recursive |
.SUFFIXES: |
.SUFFIXES: .c .lo .o .obj |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(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/mesa/drivers/dri/common/Makefile'; \ |
$(am__cd) $(top_srcdir) && \ |
$(AUTOMAKE) --foreign src/mesa/drivers/dri/common/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_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}; \ |
} |
libdri_test_stubs.la: $(libdri_test_stubs_la_OBJECTS) $(libdri_test_stubs_la_DEPENDENCIES) $(EXTRA_libdri_test_stubs_la_DEPENDENCIES) |
$(AM_V_CCLD)$(libdri_test_stubs_la_LINK) $(libdri_test_stubs_la_OBJECTS) $(libdri_test_stubs_la_LIBADD) $(LIBS) |
libdricommon.la: $(libdricommon_la_OBJECTS) $(libdricommon_la_DEPENDENCIES) $(EXTRA_libdricommon_la_DEPENDENCIES) |
$(AM_V_CCLD)$(LINK) $(libdricommon_la_OBJECTS) $(libdricommon_la_LIBADD) $(LIBS) |
mostlyclean-compile: |
-rm -f *.$(OBJEXT) |
distclean-compile: |
-rm -f *.tab.c |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dri_util.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdri_test_stubs_la-dri_test.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlconfig.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 $@ $< |
libdri_test_stubs_la-dri_test.lo: dri_test.c |
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdri_test_stubs_la_CFLAGS) $(CFLAGS) -MT libdri_test_stubs_la-dri_test.lo -MD -MP -MF $(DEPDIR)/libdri_test_stubs_la-dri_test.Tpo -c -o libdri_test_stubs_la-dri_test.lo `test -f 'dri_test.c' || echo '$(srcdir)/'`dri_test.c |
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdri_test_stubs_la-dri_test.Tpo $(DEPDIR)/libdri_test_stubs_la-dri_test.Plo |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dri_test.c' object='libdri_test_stubs_la-dri_test.lo' libtool=yes @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdri_test_stubs_la_CFLAGS) $(CFLAGS) -c -o libdri_test_stubs_la-dri_test.lo `test -f 'dri_test.c' || echo '$(srcdir)/'`dri_test.c |
mostlyclean-libtool: |
-rm -f *.lo |
clean-libtool: |
-rm -rf .libs _libs |
install-sysconfDATA: $(sysconf_DATA) |
@$(NORMAL_INSTALL) |
@list='$(sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \ |
if test -n "$$list"; then \ |
echo " $(MKDIR_P) '$(DESTDIR)$(sysconfdir)'"; \ |
$(MKDIR_P) "$(DESTDIR)$(sysconfdir)" || exit 1; \ |
fi; \ |
for p in $$list; do \ |
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ |
echo "$$d$$p"; \ |
done | $(am__base_list) | \ |
while read files; do \ |
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(sysconfdir)'"; \ |
$(INSTALL_DATA) $$files "$(DESTDIR)$(sysconfdir)" || exit $$?; \ |
done |
uninstall-sysconfDATA: |
@$(NORMAL_UNINSTALL) |
@list='$(sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \ |
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ |
dir='$(DESTDIR)$(sysconfdir)'; $(am__uninstall_files_from_dir) |
# This directory's subdirectories are mostly independent; you can cd |
# into them and run 'make' without going through this Makefile. |
# To change the values of 'make' variables: instead of editing Makefiles, |
# (1) if the variable is set in 'config.status', edit 'config.status' |
# (which will cause the Makefiles to be regenerated when you run 'make'); |
# (2) otherwise, pass the desired values on the 'make' command line. |
$(am__recursive_targets): |
@fail=; \ |
if $(am__make_keepgoing); then \ |
failcom='fail=yes'; \ |
else \ |
failcom='exit 1'; \ |
fi; \ |
dot_seen=no; \ |
target=`echo $@ | sed s/-recursive//`; \ |
case "$@" in \ |
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ |
*) list='$(SUBDIRS)' ;; \ |
esac; \ |
for subdir in $$list; do \ |
echo "Making $$target in $$subdir"; \ |
if test "$$subdir" = "."; then \ |
dot_seen=yes; \ |
local_target="$$target-am"; \ |
else \ |
local_target="$$target"; \ |
fi; \ |
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ |
|| eval $$failcom; \ |
done; \ |
if test "$$dot_seen" = "no"; then \ |
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ |
fi; test -z "$$fail" |
ID: $(am__tagged_files) |
$(am__define_uniq_tagged_files); mkid -fID $$unique |
tags: tags-recursive |
TAGS: tags |
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) |
set x; \ |
here=`pwd`; \ |
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ |
include_option=--etags-include; \ |
empty_fix=.; \ |
else \ |
include_option=--include; \ |
empty_fix=; \ |
fi; \ |
list='$(SUBDIRS)'; for subdir in $$list; do \ |
if test "$$subdir" = .; then :; else \ |
test ! -f $$subdir/TAGS || \ |
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ |
fi; \ |
done; \ |
$(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-recursive |
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-recursive |
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 |
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ |
if test "$$subdir" = .; then :; else \ |
$(am__make_dryrun) \ |
|| test -d "$(distdir)/$$subdir" \ |
|| $(MKDIR_P) "$(distdir)/$$subdir" \ |
|| exit 1; \ |
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ |
$(am__relativize); \ |
new_distdir=$$reldir; \ |
dir1=$$subdir; dir2="$(top_distdir)"; \ |
$(am__relativize); \ |
new_top_distdir=$$reldir; \ |
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ |
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ |
($(am__cd) $$subdir && \ |
$(MAKE) $(AM_MAKEFLAGS) \ |
top_distdir="$$new_top_distdir" \ |
distdir="$$new_distdir" \ |
am__remove_distdir=: \ |
am__skip_length_check=: \ |
am__skip_mode_fix=: \ |
distdir) \ |
|| exit 1; \ |
fi; \ |
done |
check-am: all-am |
check: check-recursive |
all-am: Makefile $(LTLIBRARIES) $(DATA) |
installdirs: installdirs-recursive |
installdirs-am: |
for dir in "$(DESTDIR)$(sysconfdir)"; do \ |
test -z "$$dir" || $(MKDIR_P) "$$dir"; \ |
done |
install: install-recursive |
install-exec: install-exec-recursive |
install-data: install-data-recursive |
uninstall: uninstall-recursive |
install-am: all-am |
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am |
installcheck: installcheck-recursive |
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-recursive |
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ |
mostlyclean-am |
distclean: distclean-recursive |
-rm -rf ./$(DEPDIR) |
-rm -f Makefile |
distclean-am: clean-am distclean-compile distclean-generic \ |
distclean-tags |
dvi: dvi-recursive |
dvi-am: |
html: html-recursive |
html-am: |
info: info-recursive |
info-am: |
install-data-am: |
install-dvi: install-dvi-recursive |
install-dvi-am: |
install-exec-am: install-sysconfDATA |
install-html: install-html-recursive |
install-html-am: |
install-info: install-info-recursive |
install-info-am: |
install-man: |
install-pdf: install-pdf-recursive |
install-pdf-am: |
install-ps: install-ps-recursive |
install-ps-am: |
installcheck-am: |
maintainer-clean: maintainer-clean-recursive |
-rm -rf ./$(DEPDIR) |
-rm -f Makefile |
maintainer-clean-am: distclean-am maintainer-clean-generic |
mostlyclean: mostlyclean-recursive |
mostlyclean-am: mostlyclean-compile mostlyclean-generic \ |
mostlyclean-libtool |
pdf: pdf-recursive |
pdf-am: |
ps: ps-recursive |
ps-am: |
uninstall-am: uninstall-sysconfDATA |
.MAKE: $(am__recursive_targets) install-am install-strip |
.PHONY: $(am__recursive_targets) 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 install-sysconfDATA installcheck installcheck-am \ |
installdirs installdirs-am maintainer-clean \ |
maintainer-clean-generic mostlyclean mostlyclean-compile \ |
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ |
tags tags-am uninstall uninstall-am uninstall-sysconfDATA |
# 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/src/mesa/drivers/dri/common/Makefile.sources |
---|
0,0 → 1,16 |
mesa_dri_common_gallium_SOURCES := \ |
utils.c \ |
dri_util.c \ |
xmlconfig.c |
mesa_dri_common_SOURCES := \ |
$(mesa_dri_common_gallium_SOURCES) |
# Paths are relative to MESA_TOP. |
mesa_dri_common_INCLUDES := \ |
include \ |
src/egl/drivers/dri \ |
src/egl/main \ |
src/mapi \ |
src/mesa \ |
src/mesa/drivers/dri/common |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/dri_test.c |
---|
0,0 → 1,91 |
#include "main/glheader.h" |
#include "main/compiler.h" |
#include "glapi/glapi.h" |
/* This is just supposed to make sure we get a reference to |
the driver entry symbol that the compiler doesn't optimize away */ |
extern char __driDriverExtensions[]; |
/* provide glapi symbols */ |
#if defined(GLX_USE_TLS) |
PUBLIC __thread struct _glapi_table * _glapi_tls_Dispatch |
__attribute__((tls_model("initial-exec"))); |
PUBLIC __thread void * _glapi_tls_Context |
__attribute__((tls_model("initial-exec"))); |
PUBLIC const struct _glapi_table *_glapi_Dispatch; |
PUBLIC const void *_glapi_Context; |
#else |
PUBLIC struct _glapi_table *_glapi_Dispatch; |
PUBLIC void *_glapi_Context; |
#endif |
PUBLIC void |
_glapi_check_multithread(void) |
{} |
PUBLIC void |
_glapi_set_context(void *context) |
{} |
PUBLIC void * |
_glapi_get_context(void) |
{ |
return 0; |
} |
PUBLIC void |
_glapi_set_dispatch(struct _glapi_table *dispatch) |
{} |
PUBLIC struct _glapi_table * |
_glapi_get_dispatch(void) |
{ |
return 0; |
} |
PUBLIC int |
_glapi_add_dispatch( const char * const * function_names, |
const char * parameter_signature ) |
{ |
return 0; |
} |
PUBLIC GLint |
_glapi_get_proc_offset(const char *funcName) |
{ |
return 0; |
} |
PUBLIC _glapi_proc |
_glapi_get_proc_address(const char *funcName) |
{ |
return 0; |
} |
PUBLIC GLuint |
_glapi_get_dispatch_table_size(void) |
{ |
return 0; |
} |
PUBLIC unsigned long |
_glthread_GetID(void) |
{ |
return 0; |
} |
#ifndef NO_MAIN |
int main(int argc, char** argv) |
{ |
void* p = __driDriverExtensions; |
return (int)(unsigned long)p; |
} |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/dri_util.c |
---|
0,0 → 1,629 |
/* |
* (C) Copyright IBM Corporation 2002, 2004 |
* 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 |
* on 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 THEIR 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. |
*/ |
/** |
* \file dri_util.c |
* DRI utility functions. |
* |
* This module acts as glue between GLX and the actual hardware driver. A DRI |
* driver doesn't really \e have to use any of this - it's optional. But, some |
* useful stuff is done here that otherwise would have to be duplicated in most |
* drivers. |
* |
* Basically, these utility functions take care of some of the dirty details of |
* screen initialization, context creation, context binding, DRM setup, etc. |
* |
* These functions are compiled into each DRI driver so libGL.so knows nothing |
* about them. |
*/ |
#include <xf86drm.h> |
#include "dri_util.h" |
#include "utils.h" |
#include "xmlpool.h" |
#include "../glsl/glsl_parser_extras.h" |
PUBLIC const char __dri2ConfigOptions[] = |
DRI_CONF_BEGIN |
DRI_CONF_SECTION_PERFORMANCE |
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1) |
DRI_CONF_SECTION_END |
DRI_CONF_END; |
static const uint __dri2NConfigOptions = 1; |
/*****************************************************************/ |
/** \name Screen handling functions */ |
/*****************************************************************/ |
/*@{*/ |
static void |
setupLoaderExtensions(__DRIscreen *psp, |
const __DRIextension **extensions) |
{ |
int i; |
for (i = 0; extensions[i]; i++) { |
if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0) |
psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i]; |
if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0) |
psp->dri2.image = (__DRIimageLookupExtension *) extensions[i]; |
if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0) |
psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i]; |
} |
} |
static __DRIscreen * |
dri2CreateNewScreen(int scrn, int fd, |
const __DRIextension **extensions, |
const __DRIconfig ***driver_configs, void *data) |
{ |
static const __DRIextension *emptyExtensionList[] = { NULL }; |
__DRIscreen *psp; |
drmVersionPtr version; |
psp = calloc(1, sizeof(*psp)); |
if (!psp) |
return NULL; |
setupLoaderExtensions(psp, extensions); |
version = drmGetVersion(fd); |
if (version) { |
psp->drm_version.major = version->version_major; |
psp->drm_version.minor = version->version_minor; |
psp->drm_version.patch = version->version_patchlevel; |
drmFreeVersion(version); |
} |
psp->loaderPrivate = data; |
psp->extensions = emptyExtensionList; |
psp->fd = fd; |
psp->myNum = scrn; |
psp->api_mask = (1 << __DRI_API_OPENGL); |
*driver_configs = driDriverAPI.InitScreen(psp); |
if (*driver_configs == NULL) { |
free(psp); |
return NULL; |
} |
driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions, __dri2NConfigOptions); |
driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "dri2"); |
return psp; |
} |
/** |
* Destroy the per-screen private information. |
* |
* \internal |
* This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls |
* drmClose(), and finally frees \p screenPrivate. |
*/ |
static void driDestroyScreen(__DRIscreen *psp) |
{ |
if (psp) { |
/* No interaction with the X-server is possible at this point. This |
* routine is called after XCloseDisplay, so there is no protocol |
* stream open to the X-server anymore. |
*/ |
_mesa_destroy_shader_compiler(); |
driDriverAPI.DestroyScreen(psp); |
driDestroyOptionCache(&psp->optionCache); |
driDestroyOptionInfo(&psp->optionInfo); |
free(psp); |
} |
} |
static const __DRIextension **driGetExtensions(__DRIscreen *psp) |
{ |
return psp->extensions; |
} |
/*@}*/ |
/*****************************************************************/ |
/** \name Context handling functions */ |
/*****************************************************************/ |
/*@{*/ |
static __DRIcontext * |
dri2CreateContextAttribs(__DRIscreen *screen, int api, |
const __DRIconfig *config, |
__DRIcontext *shared, |
unsigned num_attribs, |
const uint32_t *attribs, |
unsigned *error, |
void *data) |
{ |
__DRIcontext *context; |
const struct gl_config *modes = (config != NULL) ? &config->modes : NULL; |
void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; |
gl_api mesa_api; |
unsigned major_version = 1; |
unsigned minor_version = 0; |
uint32_t flags = 0; |
assert((num_attribs == 0) || (attribs != NULL)); |
if (!(screen->api_mask & (1 << api))) { |
*error = __DRI_CTX_ERROR_BAD_API; |
return NULL; |
} |
switch (api) { |
case __DRI_API_OPENGL: |
mesa_api = API_OPENGL_COMPAT; |
break; |
case __DRI_API_GLES: |
mesa_api = API_OPENGLES; |
break; |
case __DRI_API_GLES2: |
case __DRI_API_GLES3: |
mesa_api = API_OPENGLES2; |
break; |
case __DRI_API_OPENGL_CORE: |
mesa_api = API_OPENGL_CORE; |
break; |
default: |
*error = __DRI_CTX_ERROR_BAD_API; |
return NULL; |
} |
for (unsigned i = 0; i < num_attribs; i++) { |
switch (attribs[i * 2]) { |
case __DRI_CTX_ATTRIB_MAJOR_VERSION: |
major_version = attribs[i * 2 + 1]; |
break; |
case __DRI_CTX_ATTRIB_MINOR_VERSION: |
minor_version = attribs[i * 2 + 1]; |
break; |
case __DRI_CTX_ATTRIB_FLAGS: |
flags = attribs[i * 2 + 1]; |
break; |
default: |
/* We can't create a context that satisfies the requirements of an |
* attribute that we don't understand. Return failure. |
*/ |
assert(!"Should not get here."); |
*error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; |
return NULL; |
} |
} |
/* Mesa does not support the GL_ARB_compatibilty extension or the |
* compatibility profile. This means that we treat a API_OPENGL_COMPAT 3.1 as |
* API_OPENGL_CORE and reject API_OPENGL_COMPAT 3.2+. |
*/ |
if (mesa_api == API_OPENGL_COMPAT && major_version == 3 && minor_version == 1) |
mesa_api = API_OPENGL_CORE; |
if (mesa_api == API_OPENGL_COMPAT |
&& ((major_version > 3) |
|| (major_version == 3 && minor_version >= 2))) { |
*error = __DRI_CTX_ERROR_BAD_API; |
return NULL; |
} |
/* The EGL_KHR_create_context spec says: |
* |
* "Flags are only defined for OpenGL context creation, and specifying |
* a flags value other than zero for other types of contexts, |
* including OpenGL ES contexts, will generate an error." |
* |
* The GLX_EXT_create_context_es2_profile specification doesn't say |
* anything specific about this case. However, none of the known flags |
* have any meaning in an ES context, so this seems safe. |
*/ |
if (mesa_api != API_OPENGL_COMPAT |
&& mesa_api != API_OPENGL_CORE |
&& flags != 0) { |
*error = __DRI_CTX_ERROR_BAD_FLAG; |
return NULL; |
} |
/* There are no forward-compatible contexts before OpenGL 3.0. The |
* GLX_ARB_create_context spec says: |
* |
* "Forward-compatible contexts are defined only for OpenGL versions |
* 3.0 and later." |
* |
* Forward-looking contexts are supported by silently converting the |
* requested API to API_OPENGL_CORE. |
* |
* In Mesa, a debug context is the same as a regular context. |
*/ |
if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) { |
mesa_api = API_OPENGL_CORE; |
} |
if ((flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE)) |
!= 0) { |
*error = __DRI_CTX_ERROR_UNKNOWN_FLAG; |
return NULL; |
} |
context = calloc(1, sizeof *context); |
if (!context) { |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
return NULL; |
} |
context->loaderPrivate = data; |
context->driScreenPriv = screen; |
context->driDrawablePriv = NULL; |
context->driReadablePriv = NULL; |
if (!driDriverAPI.CreateContext(mesa_api, modes, context, |
major_version, minor_version, |
flags, error, shareCtx) ) { |
free(context); |
return NULL; |
} |
*error = __DRI_CTX_ERROR_SUCCESS; |
return context; |
} |
static __DRIcontext * |
dri2CreateNewContextForAPI(__DRIscreen *screen, int api, |
const __DRIconfig *config, |
__DRIcontext *shared, void *data) |
{ |
unsigned error; |
return dri2CreateContextAttribs(screen, api, config, shared, 0, NULL, |
&error, data); |
} |
static __DRIcontext * |
dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config, |
__DRIcontext *shared, void *data) |
{ |
return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL, |
config, shared, data); |
} |
/** |
* Destroy the per-context private information. |
* |
* \internal |
* This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls |
* drmDestroyContext(), and finally frees \p contextPrivate. |
*/ |
static void |
driDestroyContext(__DRIcontext *pcp) |
{ |
if (pcp) { |
driDriverAPI.DestroyContext(pcp); |
free(pcp); |
} |
} |
static int |
driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask) |
{ |
(void) dest; |
(void) src; |
(void) mask; |
return GL_FALSE; |
} |
/*@}*/ |
/*****************************************************************/ |
/** \name Context (un)binding functions */ |
/*****************************************************************/ |
/*@{*/ |
static void dri_get_drawable(__DRIdrawable *pdp); |
static void dri_put_drawable(__DRIdrawable *pdp); |
/** |
* This function takes both a read buffer and a draw buffer. This is needed |
* for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent |
* function. |
*/ |
static int driBindContext(__DRIcontext *pcp, |
__DRIdrawable *pdp, |
__DRIdrawable *prp) |
{ |
/* |
** Assume error checking is done properly in glXMakeCurrent before |
** calling driUnbindContext. |
*/ |
if (!pcp) |
return GL_FALSE; |
/* Bind the drawable to the context */ |
pcp->driDrawablePriv = pdp; |
pcp->driReadablePriv = prp; |
if (pdp) { |
pdp->driContextPriv = pcp; |
dri_get_drawable(pdp); |
} |
if (prp && pdp != prp) { |
dri_get_drawable(prp); |
} |
return driDriverAPI.MakeCurrent(pcp, pdp, prp); |
} |
/** |
* Unbind context. |
* |
* \param scrn the screen. |
* \param gc context. |
* |
* \return \c GL_TRUE on success, or \c GL_FALSE on failure. |
* |
* \internal |
* This function calls __DriverAPIRec::UnbindContext, and then decrements |
* __DRIdrawableRec::refcount which must be non-zero for a successful |
* return. |
* |
* While casting the opaque private pointers associated with the parameters |
* into their respective real types it also assures they are not \c NULL. |
*/ |
static int driUnbindContext(__DRIcontext *pcp) |
{ |
__DRIdrawable *pdp; |
__DRIdrawable *prp; |
/* |
** Assume error checking is done properly in glXMakeCurrent before |
** calling driUnbindContext. |
*/ |
if (pcp == NULL) |
return GL_FALSE; |
pdp = pcp->driDrawablePriv; |
prp = pcp->driReadablePriv; |
/* already unbound */ |
if (!pdp && !prp) |
return GL_TRUE; |
driDriverAPI.UnbindContext(pcp); |
assert(pdp); |
if (pdp->refcount == 0) { |
/* ERROR!!! */ |
return GL_FALSE; |
} |
dri_put_drawable(pdp); |
if (prp != pdp) { |
if (prp->refcount == 0) { |
/* ERROR!!! */ |
return GL_FALSE; |
} |
dri_put_drawable(prp); |
} |
/* XXX this is disabled so that if we call SwapBuffers on an unbound |
* window we can determine the last context bound to the window and |
* use that context's lock. (BrianP, 2-Dec-2000) |
*/ |
pcp->driDrawablePriv = NULL; |
pcp->driReadablePriv = NULL; |
return GL_TRUE; |
} |
/*@}*/ |
static void dri_get_drawable(__DRIdrawable *pdp) |
{ |
pdp->refcount++; |
} |
static void dri_put_drawable(__DRIdrawable *pdp) |
{ |
if (pdp) { |
pdp->refcount--; |
if (pdp->refcount) |
return; |
driDriverAPI.DestroyBuffer(pdp); |
free(pdp); |
} |
} |
static __DRIdrawable * |
dri2CreateNewDrawable(__DRIscreen *screen, |
const __DRIconfig *config, |
void *data) |
{ |
__DRIdrawable *pdraw; |
pdraw = malloc(sizeof *pdraw); |
if (!pdraw) |
return NULL; |
pdraw->loaderPrivate = data; |
pdraw->driScreenPriv = screen; |
pdraw->driContextPriv = NULL; |
pdraw->refcount = 0; |
pdraw->lastStamp = 0; |
pdraw->w = 0; |
pdraw->h = 0; |
dri_get_drawable(pdraw); |
if (!driDriverAPI.CreateBuffer(screen, pdraw, &config->modes, GL_FALSE)) { |
free(pdraw); |
return NULL; |
} |
pdraw->dri2.stamp = pdraw->lastStamp + 1; |
return pdraw; |
} |
static void |
driDestroyDrawable(__DRIdrawable *pdp) |
{ |
dri_put_drawable(pdp); |
} |
static __DRIbuffer * |
dri2AllocateBuffer(__DRIscreen *screen, |
unsigned int attachment, unsigned int format, |
int width, int height) |
{ |
return driDriverAPI.AllocateBuffer(screen, attachment, format, |
width, height); |
} |
static void |
dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) |
{ |
driDriverAPI.ReleaseBuffer(screen, buffer); |
} |
static int |
dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val) |
{ |
if (!driCheckOption(&screen->optionCache, var, DRI_BOOL)) |
return -1; |
*val = driQueryOptionb(&screen->optionCache, var); |
return 0; |
} |
static int |
dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val) |
{ |
if (!driCheckOption(&screen->optionCache, var, DRI_INT) && |
!driCheckOption(&screen->optionCache, var, DRI_ENUM)) |
return -1; |
*val = driQueryOptioni(&screen->optionCache, var); |
return 0; |
} |
static int |
dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val) |
{ |
if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT)) |
return -1; |
*val = driQueryOptionf(&screen->optionCache, var); |
return 0; |
} |
static unsigned int |
dri2GetAPIMask(__DRIscreen *screen) |
{ |
return screen->api_mask; |
} |
/** Core interface */ |
const __DRIcoreExtension driCoreExtension = { |
.base = { __DRI_CORE, __DRI_CORE_VERSION }, |
.createNewScreen = NULL, |
.destroyScreen = driDestroyScreen, |
.getExtensions = driGetExtensions, |
.getConfigAttrib = driGetConfigAttrib, |
.indexConfigAttrib = driIndexConfigAttrib, |
.createNewDrawable = NULL, |
.destroyDrawable = driDestroyDrawable, |
.swapBuffers = NULL, |
.createNewContext = NULL, |
.copyContext = driCopyContext, |
.destroyContext = driDestroyContext, |
.bindContext = driBindContext, |
.unbindContext = driUnbindContext |
}; |
/** DRI2 interface */ |
const __DRIdri2Extension driDRI2Extension = { |
.base = { __DRI_DRI2, 3 }, |
.createNewScreen = dri2CreateNewScreen, |
.createNewDrawable = dri2CreateNewDrawable, |
.createNewContext = dri2CreateNewContext, |
.getAPIMask = dri2GetAPIMask, |
.createNewContextForAPI = dri2CreateNewContextForAPI, |
.allocateBuffer = dri2AllocateBuffer, |
.releaseBuffer = dri2ReleaseBuffer, |
.createContextAttribs = dri2CreateContextAttribs |
}; |
const __DRI2configQueryExtension dri2ConfigQueryExtension = { |
.base = { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION }, |
.configQueryb = dri2ConfigQueryb, |
.configQueryi = dri2ConfigQueryi, |
.configQueryf = dri2ConfigQueryf, |
}; |
void |
dri2InvalidateDrawable(__DRIdrawable *drawable) |
{ |
drawable->dri2.stamp++; |
} |
/** |
* Check that the gl_framebuffer associated with dPriv is the right size. |
* Resize the gl_framebuffer if needed. |
* It's expected that the dPriv->driverPrivate member points to a |
* gl_framebuffer object. |
*/ |
void |
driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv) |
{ |
struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate; |
if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) { |
ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h); |
/* if the driver needs the hw lock for ResizeBuffers, the drawable |
might have changed again by now */ |
assert(fb->Width == dPriv->w); |
assert(fb->Height == dPriv->h); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/dri_util.c.bak |
---|
0,0 → 1,632 |
/* |
* (C) Copyright IBM Corporation 2002, 2004 |
* 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 |
* on 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 THEIR 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. |
*/ |
/** |
* \file dri_util.c |
* DRI utility functions. |
* |
* This module acts as glue between GLX and the actual hardware driver. A DRI |
* driver doesn't really \e have to use any of this - it's optional. But, some |
* useful stuff is done here that otherwise would have to be duplicated in most |
* drivers. |
* |
* Basically, these utility functions take care of some of the dirty details of |
* screen initialization, context creation, context binding, DRM setup, etc. |
* |
* These functions are compiled into each DRI driver so libGL.so knows nothing |
* about them. |
*/ |
#include <xf86drm.h> |
#include "dri_util.h" |
#include "utils.h" |
#include "xmlpool.h" |
#include "../glsl/glsl_parser_extras.h" |
PUBLIC const char __dri2ConfigOptions[] = |
DRI_CONF_BEGIN |
DRI_CONF_SECTION_PERFORMANCE |
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1) |
DRI_CONF_SECTION_END |
DRI_CONF_END; |
static const uint __dri2NConfigOptions = 1; |
/*****************************************************************/ |
/** \name Screen handling functions */ |
/*****************************************************************/ |
/*@{*/ |
static void |
setupLoaderExtensions(__DRIscreen *psp, |
const __DRIextension **extensions) |
{ |
int i; |
for (i = 0; extensions[i]; i++) { |
if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0) |
psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i]; |
if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0) |
psp->dri2.image = (__DRIimageLookupExtension *) extensions[i]; |
if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0) |
psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i]; |
} |
} |
static __DRIscreen * |
dri2CreateNewScreen(int scrn, int fd, |
const __DRIextension **extensions, |
const __DRIconfig ***driver_configs, void *data) |
{ |
static const __DRIextension *emptyExtensionList[] = { NULL }; |
__DRIscreen *psp; |
drmVersionPtr version; |
psp = calloc(1, sizeof(*psp)); |
if (!psp) |
return NULL; |
setupLoaderExtensions(psp, extensions); |
version = drmGetVersion(fd); |
if (version) { |
psp->drm_version.major = version->version_major; |
psp->drm_version.minor = version->version_minor; |
psp->drm_version.patch = version->version_patchlevel; |
drmFreeVersion(version); |
} |
psp->loaderPrivate = data; |
psp->extensions = emptyExtensionList; |
psp->fd = fd; |
psp->myNum = scrn; |
psp->api_mask = (1 << __DRI_API_OPENGL); |
*driver_configs = driDriverAPI.InitScreen(psp); |
if (*driver_configs == NULL) { |
free(psp); |
return NULL; |
} |
driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions, __dri2NConfigOptions); |
driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "dri2"); |
return psp; |
} |
/** |
* Destroy the per-screen private information. |
* |
* \internal |
* This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls |
* drmClose(), and finally frees \p screenPrivate. |
*/ |
static void driDestroyScreen(__DRIscreen *psp) |
{ |
if (psp) { |
/* No interaction with the X-server is possible at this point. This |
* routine is called after XCloseDisplay, so there is no protocol |
* stream open to the X-server anymore. |
*/ |
_mesa_destroy_shader_compiler(); |
driDriverAPI.DestroyScreen(psp); |
driDestroyOptionCache(&psp->optionCache); |
driDestroyOptionInfo(&psp->optionInfo); |
free(psp); |
} |
} |
static const __DRIextension **driGetExtensions(__DRIscreen *psp) |
{ |
return psp->extensions; |
} |
/*@}*/ |
/*****************************************************************/ |
/** \name Context handling functions */ |
/*****************************************************************/ |
/*@{*/ |
static __DRIcontext * |
dri2CreateContextAttribs(__DRIscreen *screen, int api, |
const __DRIconfig *config, |
__DRIcontext *shared, |
unsigned num_attribs, |
const uint32_t *attribs, |
unsigned *error, |
void *data) |
{ |
__DRIcontext *context; |
const struct gl_config *modes = (config != NULL) ? &config->modes : NULL; |
void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; |
gl_api mesa_api; |
unsigned major_version = 1; |
unsigned minor_version = 0; |
uint32_t flags = 0; |
assert((num_attribs == 0) || (attribs != NULL)); |
if (!(screen->api_mask & (1 << api))) { |
*error = __DRI_CTX_ERROR_BAD_API; |
return NULL; |
} |
switch (api) { |
case __DRI_API_OPENGL: |
mesa_api = API_OPENGL_COMPAT; |
break; |
case __DRI_API_GLES: |
mesa_api = API_OPENGLES; |
break; |
case __DRI_API_GLES2: |
case __DRI_API_GLES3: |
mesa_api = API_OPENGLES2; |
break; |
case __DRI_API_OPENGL_CORE: |
mesa_api = API_OPENGL_CORE; |
break; |
default: |
*error = __DRI_CTX_ERROR_BAD_API; |
return NULL; |
} |
for (unsigned i = 0; i < num_attribs; i++) { |
switch (attribs[i * 2]) { |
case __DRI_CTX_ATTRIB_MAJOR_VERSION: |
major_version = attribs[i * 2 + 1]; |
break; |
case __DRI_CTX_ATTRIB_MINOR_VERSION: |
minor_version = attribs[i * 2 + 1]; |
break; |
case __DRI_CTX_ATTRIB_FLAGS: |
flags = attribs[i * 2 + 1]; |
break; |
default: |
/* We can't create a context that satisfies the requirements of an |
* attribute that we don't understand. Return failure. |
*/ |
assert(!"Should not get here."); |
*error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; |
return NULL; |
} |
} |
/* Mesa does not support the GL_ARB_compatibilty extension or the |
* compatibility profile. This means that we treat a API_OPENGL_COMPAT 3.1 as |
* API_OPENGL_CORE and reject API_OPENGL_COMPAT 3.2+. |
*/ |
if (mesa_api == API_OPENGL_COMPAT && major_version == 3 && minor_version == 1) |
mesa_api = API_OPENGL_CORE; |
if (mesa_api == API_OPENGL_COMPAT |
&& ((major_version > 3) |
|| (major_version == 3 && minor_version >= 2))) { |
*error = __DRI_CTX_ERROR_BAD_API; |
return NULL; |
} |
/* The EGL_KHR_create_context spec says: |
* |
* "Flags are only defined for OpenGL context creation, and specifying |
* a flags value other than zero for other types of contexts, |
* including OpenGL ES contexts, will generate an error." |
* |
* The GLX_EXT_create_context_es2_profile specification doesn't say |
* anything specific about this case. However, none of the known flags |
* have any meaning in an ES context, so this seems safe. |
*/ |
if (mesa_api != API_OPENGL_COMPAT |
&& mesa_api != API_OPENGL_CORE |
&& flags != 0) { |
*error = __DRI_CTX_ERROR_BAD_FLAG; |
return NULL; |
} |
/* There are no forward-compatible contexts before OpenGL 3.0. The |
* GLX_ARB_create_context spec says: |
* |
* "Forward-compatible contexts are defined only for OpenGL versions |
* 3.0 and later." |
* |
* Forward-looking contexts are supported by silently converting the |
* requested API to API_OPENGL_CORE. |
* |
* In Mesa, a debug context is the same as a regular context. |
*/ |
if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) { |
mesa_api = API_OPENGL_CORE; |
} |
if ((flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE)) |
!= 0) { |
*error = __DRI_CTX_ERROR_UNKNOWN_FLAG; |
return NULL; |
} |
context = calloc(1, sizeof *context); |
if (!context) { |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
return NULL; |
} |
context->loaderPrivate = data; |
context->driScreenPriv = screen; |
context->driDrawablePriv = NULL; |
context->driReadablePriv = NULL; |
if (!driDriverAPI.CreateContext(mesa_api, modes, context, |
major_version, minor_version, |
flags, error, shareCtx) ) { |
free(context); |
return NULL; |
} |
*error = __DRI_CTX_ERROR_SUCCESS; |
return context; |
} |
static __DRIcontext * |
dri2CreateNewContextForAPI(__DRIscreen *screen, int api, |
const __DRIconfig *config, |
__DRIcontext *shared, void *data) |
{ |
unsigned error; |
return dri2CreateContextAttribs(screen, api, config, shared, 0, NULL, |
&error, data); |
} |
static __DRIcontext * |
dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config, |
__DRIcontext *shared, void *data) |
{ |
return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL, |
config, shared, data); |
} |
/** |
* Destroy the per-context private information. |
* |
* \internal |
* This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls |
* drmDestroyContext(), and finally frees \p contextPrivate. |
*/ |
static void |
driDestroyContext(__DRIcontext *pcp) |
{ |
if (pcp) { |
driDriverAPI.DestroyContext(pcp); |
free(pcp); |
} |
} |
static int |
driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask) |
{ |
(void) dest; |
(void) src; |
(void) mask; |
return GL_FALSE; |
} |
/*@}*/ |
/*****************************************************************/ |
/** \name Context (un)binding functions */ |
/*****************************************************************/ |
/*@{*/ |
static void dri_get_drawable(__DRIdrawable *pdp); |
static void dri_put_drawable(__DRIdrawable *pdp); |
/** |
* This function takes both a read buffer and a draw buffer. This is needed |
* for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent |
* function. |
*/ |
static int driBindContext(__DRIcontext *pcp, |
__DRIdrawable *pdp, |
__DRIdrawable *prp) |
{ |
/* |
** Assume error checking is done properly in glXMakeCurrent before |
** calling driUnbindContext. |
*/ |
if (!pcp) |
return GL_FALSE; |
/* Bind the drawable to the context */ |
pcp->driDrawablePriv = pdp; |
pcp->driReadablePriv = prp; |
if (pdp) { |
pdp->driContextPriv = pcp; |
dri_get_drawable(pdp); |
} |
if (prp && pdp != prp) { |
dri_get_drawable(prp); |
} |
return driDriverAPI.MakeCurrent(pcp, pdp, prp); |
} |
/** |
* Unbind context. |
* |
* \param scrn the screen. |
* \param gc context. |
* |
* \return \c GL_TRUE on success, or \c GL_FALSE on failure. |
* |
* \internal |
* This function calls __DriverAPIRec::UnbindContext, and then decrements |
* __DRIdrawableRec::refcount which must be non-zero for a successful |
* return. |
* |
* While casting the opaque private pointers associated with the parameters |
* into their respective real types it also assures they are not \c NULL. |
*/ |
static int driUnbindContext(__DRIcontext *pcp) |
{ |
__DRIdrawable *pdp; |
__DRIdrawable *prp; |
/* |
** Assume error checking is done properly in glXMakeCurrent before |
** calling driUnbindContext. |
*/ |
if (pcp == NULL) |
return GL_FALSE; |
pdp = pcp->driDrawablePriv; |
prp = pcp->driReadablePriv; |
/* already unbound */ |
if (!pdp && !prp) |
return GL_TRUE; |
driDriverAPI.UnbindContext(pcp); |
assert(pdp); |
if (pdp->refcount == 0) { |
/* ERROR!!! */ |
return GL_FALSE; |
} |
dri_put_drawable(pdp); |
if (prp != pdp) { |
if (prp->refcount == 0) { |
/* ERROR!!! */ |
return GL_FALSE; |
} |
dri_put_drawable(prp); |
} |
/* XXX this is disabled so that if we call SwapBuffers on an unbound |
* window we can determine the last context bound to the window and |
* use that context's lock. (BrianP, 2-Dec-2000) |
*/ |
pcp->driDrawablePriv = NULL; |
pcp->driReadablePriv = NULL; |
return GL_TRUE; |
} |
/*@}*/ |
static void dri_get_drawable(__DRIdrawable *pdp) |
{ |
pdp->refcount++; |
} |
static void dri_put_drawable(__DRIdrawable *pdp) |
{ |
if (pdp) { |
pdp->refcount--; |
if (pdp->refcount) |
return; |
driDriverAPI.DestroyBuffer(pdp); |
free(pdp); |
} |
} |
static __DRIdrawable * |
dri2CreateNewDrawable(__DRIscreen *screen, |
const __DRIconfig *config, |
void *data) |
{ |
__DRIdrawable *pdraw; |
printf("%s: screen %p config %p, data %p\n", |
__FUNCTION__, screen, config, data); |
pdraw = malloc(sizeof *pdraw); |
if (!pdraw) |
return NULL; |
pdraw->loaderPrivate = data; |
pdraw->driScreenPriv = screen; |
pdraw->driContextPriv = NULL; |
pdraw->refcount = 0; |
pdraw->lastStamp = 0; |
pdraw->w = 0; |
pdraw->h = 0; |
dri_get_drawable(pdraw); |
if (!driDriverAPI.CreateBuffer(screen, pdraw, &config->modes, GL_FALSE)) { |
free(pdraw); |
return NULL; |
} |
pdraw->dri2.stamp = pdraw->lastStamp + 1; |
return pdraw; |
} |
static void |
driDestroyDrawable(__DRIdrawable *pdp) |
{ |
dri_put_drawable(pdp); |
} |
static __DRIbuffer * |
dri2AllocateBuffer(__DRIscreen *screen, |
unsigned int attachment, unsigned int format, |
int width, int height) |
{ |
return driDriverAPI.AllocateBuffer(screen, attachment, format, |
width, height); |
} |
static void |
dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) |
{ |
driDriverAPI.ReleaseBuffer(screen, buffer); |
} |
static int |
dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val) |
{ |
if (!driCheckOption(&screen->optionCache, var, DRI_BOOL)) |
return -1; |
*val = driQueryOptionb(&screen->optionCache, var); |
return 0; |
} |
static int |
dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val) |
{ |
if (!driCheckOption(&screen->optionCache, var, DRI_INT) && |
!driCheckOption(&screen->optionCache, var, DRI_ENUM)) |
return -1; |
*val = driQueryOptioni(&screen->optionCache, var); |
return 0; |
} |
static int |
dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val) |
{ |
if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT)) |
return -1; |
*val = driQueryOptionf(&screen->optionCache, var); |
return 0; |
} |
static unsigned int |
dri2GetAPIMask(__DRIscreen *screen) |
{ |
return screen->api_mask; |
} |
/** Core interface */ |
const __DRIcoreExtension driCoreExtension = { |
.base = { __DRI_CORE, __DRI_CORE_VERSION }, |
.createNewScreen = NULL, |
.destroyScreen = driDestroyScreen, |
.getExtensions = driGetExtensions, |
.getConfigAttrib = driGetConfigAttrib, |
.indexConfigAttrib = driIndexConfigAttrib, |
.createNewDrawable = NULL, |
.destroyDrawable = driDestroyDrawable, |
.swapBuffers = NULL, |
.createNewContext = NULL, |
.copyContext = driCopyContext, |
.destroyContext = driDestroyContext, |
.bindContext = driBindContext, |
.unbindContext = driUnbindContext |
}; |
/** DRI2 interface */ |
const __DRIdri2Extension driDRI2Extension = { |
.base = { __DRI_DRI2, 3 }, |
.createNewScreen = dri2CreateNewScreen, |
.createNewDrawable = dri2CreateNewDrawable, |
.createNewContext = dri2CreateNewContext, |
.getAPIMask = dri2GetAPIMask, |
.createNewContextForAPI = dri2CreateNewContextForAPI, |
.allocateBuffer = dri2AllocateBuffer, |
.releaseBuffer = dri2ReleaseBuffer, |
.createContextAttribs = dri2CreateContextAttribs |
}; |
const __DRI2configQueryExtension dri2ConfigQueryExtension = { |
.base = { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION }, |
.configQueryb = dri2ConfigQueryb, |
.configQueryi = dri2ConfigQueryi, |
.configQueryf = dri2ConfigQueryf, |
}; |
void |
dri2InvalidateDrawable(__DRIdrawable *drawable) |
{ |
drawable->dri2.stamp++; |
} |
/** |
* Check that the gl_framebuffer associated with dPriv is the right size. |
* Resize the gl_framebuffer if needed. |
* It's expected that the dPriv->driverPrivate member points to a |
* gl_framebuffer object. |
*/ |
void |
driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv) |
{ |
struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate; |
if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) { |
ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h); |
/* if the driver needs the hw lock for ResizeBuffers, the drawable |
might have changed again by now */ |
assert(fb->Width == dPriv->w); |
assert(fb->Height == dPriv->h); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/dri_util.h |
---|
0,0 → 1,269 |
/* |
* Copyright 1998-1999 Precision Insight, 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 PRECISION INSIGHT 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. |
*/ |
/** |
* \file dri_util.h |
* DRI utility functions definitions. |
* |
* This module acts as glue between GLX and the actual hardware driver. A DRI |
* driver doesn't really \e have to use any of this - it's optional. But, some |
* useful stuff is done here that otherwise would have to be duplicated in most |
* drivers. |
* |
* Basically, these utility functions take care of some of the dirty details of |
* screen initialization, context creation, context binding, DRM setup, etc. |
* |
* These functions are compiled into each DRI driver so libGL.so knows nothing |
* about them. |
* |
* \sa dri_util.c. |
* |
* \author Kevin E. Martin <kevin@precisioninsight.com> |
* \author Brian Paul <brian@precisioninsight.com> |
*/ |
/** |
* The following structs are shared between DRISW and DRI2, the DRISW structs |
* are essentially base classes of the DRI2 structs. DRISW needs to compile on |
* platforms without DRM, so keep the structs opaque to DRM. |
*/ |
#ifndef _DRI_UTIL_H_ |
#define _DRI_UTIL_H_ |
#include <GL/gl.h> |
#include <GL/internal/dri_interface.h> |
#include "main/mtypes.h" |
#include "xmlconfig.h" |
/** |
* Extensions. |
*/ |
extern const __DRIcoreExtension driCoreExtension; |
extern const __DRIswrastExtension driSWRastExtension; |
extern const __DRIdri2Extension driDRI2Extension; |
extern const __DRI2configQueryExtension dri2ConfigQueryExtension; |
/** |
* Driver callback functions. |
* |
* Each DRI driver must have one of these structures with all the pointers set |
* to appropriate functions within the driver. |
* |
* When glXCreateContext() is called, for example, it'll call a helper function |
* dri_util.c which in turn will jump through the \a CreateContext pointer in |
* this structure. |
*/ |
struct __DriverAPIRec { |
const __DRIconfig **(*InitScreen) (__DRIscreen * priv); |
void (*DestroyScreen)(__DRIscreen *driScrnPriv); |
GLboolean (*CreateContext)(gl_api api, |
const struct gl_config *glVis, |
__DRIcontext *driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
uint32_t flags, |
unsigned *error, |
void *sharedContextPrivate); |
void (*DestroyContext)(__DRIcontext *driContextPriv); |
GLboolean (*CreateBuffer)(__DRIscreen *driScrnPriv, |
__DRIdrawable *driDrawPriv, |
const struct gl_config *glVis, |
GLboolean pixmapBuffer); |
void (*DestroyBuffer)(__DRIdrawable *driDrawPriv); |
void (*SwapBuffers)(__DRIdrawable *driDrawPriv); |
GLboolean (*MakeCurrent)(__DRIcontext *driContextPriv, |
__DRIdrawable *driDrawPriv, |
__DRIdrawable *driReadPriv); |
GLboolean (*UnbindContext)(__DRIcontext *driContextPriv); |
__DRIbuffer *(*AllocateBuffer) (__DRIscreen *screenPrivate, |
unsigned int attachment, |
unsigned int format, |
int width, int height); |
void (*ReleaseBuffer) (__DRIscreen *screenPrivate, __DRIbuffer *buffer); |
}; |
extern const struct __DriverAPIRec driDriverAPI; |
/** |
* Per-screen private driver information. |
*/ |
struct __DRIscreenRec { |
/** |
* Current screen's number |
*/ |
int myNum; |
/** |
* File descriptor returned when the kernel device driver is opened. |
* |
* Used to: |
* - authenticate client to kernel |
* - map the frame buffer, SAREA, etc. |
* - close the kernel device driver |
*/ |
int fd; |
/** |
* DRM (kernel module) version information. |
*/ |
__DRIversion drm_version; |
/** |
* Device-dependent private information (not stored in the SAREA). |
* |
* This pointer is never touched by the DRI layer. |
*/ |
void *driverPrivate; |
void *loaderPrivate; |
const __DRIextension **extensions; |
const __DRIswrastLoaderExtension *swrast_loader; |
struct { |
/* Flag to indicate that this is a DRI2 screen. Many of the above |
* fields will not be valid or initializaed in that case. */ |
__DRIdri2LoaderExtension *loader; |
__DRIimageLookupExtension *image; |
__DRIuseInvalidateExtension *useInvalidate; |
} dri2; |
driOptionCache optionInfo; |
driOptionCache optionCache; |
unsigned int api_mask; |
}; |
/** |
* Per-context private driver information. |
*/ |
struct __DRIcontextRec { |
/** |
* Device driver's private context data. This structure is opaque. |
*/ |
void *driverPrivate; |
/** |
* The loaders's private context data. This structure is opaque. |
*/ |
void *loaderPrivate; |
/** |
* Pointer to drawable currently bound to this context for drawing. |
*/ |
__DRIdrawable *driDrawablePriv; |
/** |
* Pointer to drawable currently bound to this context for reading. |
*/ |
__DRIdrawable *driReadablePriv; |
/** |
* Pointer to screen on which this context was created. |
*/ |
__DRIscreen *driScreenPriv; |
struct { |
int draw_stamp; |
int read_stamp; |
} dri2; |
}; |
/** |
* Per-drawable private DRI driver information. |
*/ |
struct __DRIdrawableRec { |
/** |
* Driver's private drawable information. |
* |
* This structure is opaque. |
*/ |
void *driverPrivate; |
/** |
* Private data from the loader. We just hold on to it and pass |
* it back when calling into loader provided functions. |
*/ |
void *loaderPrivate; |
/** |
* Pointer to context to which this drawable is currently bound. |
*/ |
__DRIcontext *driContextPriv; |
/** |
* Pointer to screen on which this drawable was created. |
*/ |
__DRIscreen *driScreenPriv; |
/** |
* Reference count for number of context's currently bound to this |
* drawable. |
* |
* Once it reaches zero, the drawable can be destroyed. |
* |
* \note This behavior will change with GLX 1.3. |
*/ |
int refcount; |
/** |
* Last value of the stamp. |
* |
* If this differs from the value stored at __DRIdrawable::dri2.stamp, |
* then the drawable information has been modified by the X server, and the |
* drawable information (below) should be retrieved from the X server. |
*/ |
unsigned int lastStamp; |
int w, h; |
/** |
* Drawable timestamp. Increased when the loader calls invalidate. |
*/ |
struct { |
unsigned int stamp; |
} dri2; |
}; |
extern void |
dri2InvalidateDrawable(__DRIdrawable *drawable); |
extern void |
driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv); |
#endif /* _DRI_UTIL_H_ */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/drirc |
---|
0,0 → 1,77 |
<!-- |
============================================ |
Application bugs worked around in this file: |
============================================ |
* Various Unigine products don't use the #version and #extension GLSL |
directives, meaning they only get GLSL 1.10 and no extensions for their |
shaders. |
Enabling all extensions for Unigine fixes most issues, but the GLSL version |
is still 1.10. |
* Unigine Heaven 3.0 with ARB_texture_multisample uses a "ivec4 * vec4" |
expression, which fails to compile with GLSL 1.10. |
Adding "#version 130" fixes this. |
* Unigine Heaven 3.0 with ARB_shader_bit_encoding uses the uint keyword, which |
fails to compile with GLSL 1.10. |
Adding "#version 130" fixes this. |
* Unigine Heaven 3.0 with ARB_shader_bit_encoding uses a "uint & int" |
expression, which fails (and should fail) to compile with any GLSL version. |
Disabling ARB_shader_bit_encoding fixes this. |
TODO: document the other workarounds. |
--> |
<driconf> |
<!-- Please always enable app-specific workarounds for all drivers and |
screens. --> |
<device> |
<application name="Unigine Sanctuary" executable="Sanctuary"> |
<option name="force_glsl_extensions_warn" value="true" /> |
<option name="disable_blend_func_extended" value="true" /> |
</application> |
<application name="Unigine Tropics" executable="Tropics"> |
<option name="force_glsl_extensions_warn" value="true" /> |
<option name="disable_blend_func_extended" value="true" /> |
</application> |
<application name="Unigine Heaven (32-bit)" executable="heaven_x86"> |
<option name="force_glsl_extensions_warn" value="true" /> |
<option name="disable_blend_func_extended" value="true" /> |
<option name="force_glsl_version" value="130" /> |
<option name="disable_shader_bit_encoding" value="true" /> |
</application> |
<application name="Unigine Heaven (64-bit)" executable="heaven_x64"> |
<option name="force_glsl_extensions_warn" value="true" /> |
<option name="disable_blend_func_extended" value="true" /> |
<option name="force_glsl_version" value="130" /> |
<option name="disable_shader_bit_encoding" value="true" /> |
</application> |
<application name="Unigine OilRush (32-bit)" executable="OilRush_x86"> |
<option name="disable_blend_func_extended" value="true" /> |
</application> |
<application name="Unigine OilRush (64-bit)" executable="OilRush_x64"> |
<option name="disable_blend_func_extended" value="true" /> |
</application> |
<application name="Savage 2" executable="savage2.bin"> |
<option name="disable_glsl_line_continuations" value="true" /> |
</application> |
<application name="Topogun (32-bit)" executable="topogun32"> |
<option name="always_have_depth_buffer" value="true" /> |
</application> |
<application name="Topogun (64-bit)" executable="topogun64"> |
<option name="always_have_depth_buffer" value="true" /> |
</application> |
</device> |
</driconf> |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/drisw_util.c |
---|
0,0 → 1,375 |
/* |
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. |
* All Rights Reserved. |
* Copyright 2010 George Sapountzis <gsapountzis@gmail.com> |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, 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. |
*/ |
/** |
* \file drisw_util.c |
* |
* DRISW utility functions, i.e. dri_util.c stripped from drm-specific bits. |
*/ |
#include "dri_util.h" |
#include "utils.h" |
/** |
* Screen functions |
*/ |
static void |
setupLoaderExtensions(__DRIscreen *psp, |
const __DRIextension **extensions) |
{ |
int i; |
for (i = 0; extensions[i]; i++) { |
if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0) |
psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i]; |
} |
} |
static __DRIscreen * |
driCreateNewScreen(int scrn, const __DRIextension **extensions, |
const __DRIconfig ***driver_configs, void *data) |
{ |
static const __DRIextension *emptyExtensionList[] = { NULL }; |
__DRIscreen *psp; |
psp = CALLOC_STRUCT(__DRIscreenRec); |
if (!psp) |
return NULL; |
setupLoaderExtensions(psp, extensions); |
psp->loaderPrivate = data; |
psp->extensions = emptyExtensionList; |
psp->fd = -1; |
psp->myNum = scrn; |
*driver_configs = driDriverAPI.InitScreen(psp); |
if (*driver_configs == NULL) { |
free(psp); |
return NULL; |
} |
return psp; |
} |
static void driDestroyScreen(__DRIscreen *psp) |
{ |
if (psp) { |
driDriverAPI.DestroyScreen(psp); |
free(psp); |
} |
} |
static const __DRIextension **driGetExtensions(__DRIscreen *psp) |
{ |
return psp->extensions; |
} |
/** |
* Context functions |
*/ |
static __DRIcontext * |
driCreateContextAttribs(__DRIscreen *screen, int api, |
const __DRIconfig *config, |
__DRIcontext *shared, |
unsigned num_attribs, |
const uint32_t *attribs, |
unsigned *error, |
void *data) |
{ |
__DRIcontext *pcp; |
const struct gl_config *modes = (config != NULL) ? &config->modes : NULL; |
void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; |
gl_api mesa_api; |
unsigned major_version = 1; |
unsigned minor_version = 0; |
uint32_t flags = 0; |
/* Either num_attribs is zero and attribs is NULL, or num_attribs is not |
* zero and attribs is not NULL. |
*/ |
assert((num_attribs == 0) == (attribs == NULL)); |
switch (api) { |
case __DRI_API_OPENGL: |
mesa_api = API_OPENGL_COMPAT; |
break; |
case __DRI_API_GLES: |
mesa_api = API_OPENGLES; |
break; |
case __DRI_API_GLES2: |
case __DRI_API_GLES3: |
mesa_api = API_OPENGLES2; |
break; |
case __DRI_API_OPENGL_CORE: |
mesa_api = API_OPENGL_CORE; |
break; |
default: |
*error = __DRI_CTX_ERROR_BAD_API; |
return NULL; |
} |
for (unsigned i = 0; i < num_attribs; i++) { |
switch (attribs[i * 2]) { |
case __DRI_CTX_ATTRIB_MAJOR_VERSION: |
major_version = attribs[i * 2 + 1]; |
break; |
case __DRI_CTX_ATTRIB_MINOR_VERSION: |
minor_version = attribs[i * 2 + 1]; |
break; |
case __DRI_CTX_ATTRIB_FLAGS: |
flags = attribs[i * 2 + 1]; |
break; |
default: |
/* We can't create a context that satisfies the requirements of an |
* attribute that we don't understand. Return failure. |
*/ |
return NULL; |
} |
} |
/* Mesa does not support the GL_ARB_compatibilty extension or the |
* compatibility profile. This means that we treat a API_OPENGL_COMPAT 3.1 as |
* API_OPENGL_CORE and reject API_OPENGL_COMPAT 3.2+. |
*/ |
if (mesa_api == API_OPENGL_COMPAT && major_version == 3 && minor_version == 1) |
mesa_api = API_OPENGL_CORE; |
if (mesa_api == API_OPENGL_COMPAT |
&& ((major_version > 3) |
|| (major_version == 3 && minor_version >= 2))) { |
*error = __DRI_CTX_ERROR_BAD_API; |
return NULL; |
} |
/* There are no forward-compatible contexts before OpenGL 3.0. The |
* GLX_ARB_create_context spec says: |
* |
* "Forward-compatible contexts are defined only for OpenGL versions |
* 3.0 and later." |
* |
* Moreover, Mesa can't fulfill the requirements of a forward-looking |
* context. Return failure if a forward-looking context is requested. |
* |
* In Mesa, a debug context is the same as a regular context. |
*/ |
if (major_version >= 3) { |
if ((flags & ~__DRI_CTX_FLAG_DEBUG) != 0) |
return NULL; |
} |
pcp = CALLOC_STRUCT(__DRIcontextRec); |
if (!pcp) |
return NULL; |
pcp->loaderPrivate = data; |
pcp->driScreenPriv = screen; |
pcp->driDrawablePriv = NULL; |
pcp->driReadablePriv = NULL; |
if (!driDriverAPI.CreateContext(mesa_api, modes, pcp, |
major_version, minor_version, |
flags, error, shareCtx)) { |
free(pcp); |
return NULL; |
} |
return pcp; |
} |
static __DRIcontext * |
driCreateNewContextForAPI(__DRIscreen *psp, int api, |
const __DRIconfig *config, |
__DRIcontext *shared, void *data) |
{ |
unsigned error; |
return driCreateContextAttribs(psp, api, config, shared, 0, NULL, |
&error, data); |
} |
static __DRIcontext * |
driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config, |
__DRIcontext *shared, void *data) |
{ |
return driCreateNewContextForAPI(psp, __DRI_API_OPENGL, |
config, shared, data); |
} |
static void |
driDestroyContext(__DRIcontext *pcp) |
{ |
if (pcp) { |
driDriverAPI.DestroyContext(pcp); |
free(pcp); |
} |
} |
static int |
driCopyContext(__DRIcontext *dst, __DRIcontext *src, unsigned long mask) |
{ |
return GL_FALSE; |
} |
static void dri_get_drawable(__DRIdrawable *pdp); |
static void dri_put_drawable(__DRIdrawable *pdp); |
static int driBindContext(__DRIcontext *pcp, |
__DRIdrawable *pdp, |
__DRIdrawable *prp) |
{ |
/* Bind the drawable to the context */ |
if (pcp) { |
pcp->driDrawablePriv = pdp; |
pcp->driReadablePriv = prp; |
if (pdp) { |
pdp->driContextPriv = pcp; |
dri_get_drawable(pdp); |
} |
if (prp && pdp != prp) { |
dri_get_drawable(prp); |
} |
} |
return driDriverAPI.MakeCurrent(pcp, pdp, prp); |
} |
static int driUnbindContext(__DRIcontext *pcp) |
{ |
__DRIdrawable *pdp; |
__DRIdrawable *prp; |
if (pcp == NULL) |
return GL_FALSE; |
pdp = pcp->driDrawablePriv; |
prp = pcp->driReadablePriv; |
/* already unbound */ |
if (!pdp && !prp) |
return GL_TRUE; |
driDriverAPI.UnbindContext(pcp); |
dri_put_drawable(pdp); |
if (prp != pdp) { |
dri_put_drawable(prp); |
} |
pcp->driDrawablePriv = NULL; |
pcp->driReadablePriv = NULL; |
return GL_TRUE; |
} |
/** |
* Drawable functions |
*/ |
static void dri_get_drawable(__DRIdrawable *pdp) |
{ |
pdp->refcount++; |
} |
static void dri_put_drawable(__DRIdrawable *pdp) |
{ |
if (pdp) { |
pdp->refcount--; |
if (pdp->refcount) |
return; |
driDriverAPI.DestroyBuffer(pdp); |
free(pdp); |
} |
} |
static __DRIdrawable * |
driCreateNewDrawable(__DRIscreen *psp, |
const __DRIconfig *config, void *data) |
{ |
__DRIdrawable *pdp; |
pdp = CALLOC_STRUCT(__DRIdrawableRec); |
if (!pdp) |
return NULL; |
pdp->loaderPrivate = data; |
pdp->driScreenPriv = psp; |
pdp->driContextPriv = NULL; |
dri_get_drawable(pdp); |
if (!driDriverAPI.CreateBuffer(psp, pdp, &config->modes, GL_FALSE)) { |
free(pdp); |
return NULL; |
} |
pdp->lastStamp = 1; /* const */ |
return pdp; |
} |
static void |
driDestroyDrawable(__DRIdrawable *pdp) |
{ |
dri_put_drawable(pdp); |
} |
static void driSwapBuffers(__DRIdrawable *pdp) |
{ |
driDriverAPI.SwapBuffers(pdp); |
} |
const __DRIcoreExtension driCoreExtension = { |
{ __DRI_CORE, __DRI_CORE_VERSION }, |
NULL, /* driCreateNewScreen */ |
driDestroyScreen, |
driGetExtensions, |
driGetConfigAttrib, |
driIndexConfigAttrib, |
NULL, /* driCreateNewDrawable */ |
driDestroyDrawable, |
driSwapBuffers, |
driCreateNewContext, |
driCopyContext, |
driDestroyContext, |
driBindContext, |
driUnbindContext |
}; |
const __DRIswrastExtension driSWRastExtension = { |
{ __DRI_SWRAST, __DRI_SWRAST_VERSION }, |
driCreateNewScreen, |
driCreateNewDrawable, |
driCreateNewContextForAPI, |
driCreateContextAttribs |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/mmio.h |
---|
0,0 → 1,62 |
/* |
* (C) Copyright IBM Corporation 2004 |
* 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 |
* on 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 |
* IBM AND/OR THEIR 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. |
*/ |
/** |
* \file mmio.h |
* Functions for properly handling memory mapped IO on various platforms. |
* |
* \author Ian Romanick <idr@us.ibm.com> |
*/ |
#ifndef MMIO_H |
#define MMIO_H |
#include "main/glheader.h" |
#if defined( __powerpc__ ) |
static INLINE uint32_t |
read_MMIO_LE32( volatile void * base, unsigned long offset ) |
{ |
uint32_t val; |
__asm__ __volatile__( "lwbrx %0, %1, %2 ; eieio" |
: "=r" (val) |
: "b" (base), "r" (offset) ); |
return val; |
} |
#else |
static INLINE uint32_t |
read_MMIO_LE32( volatile void * base, unsigned long offset ) |
{ |
volatile uint32_t * p = (volatile uint32_t *) (((volatile char *) base) + offset); |
return LE32_TO_CPU( p[0] ); |
} |
#endif |
#endif /* MMIO_H */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/utils.c |
---|
0,0 → 1,469 |
/* |
* (C) Copyright IBM Corporation 2002, 2004 |
* 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 |
* on 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 |
* VA LINUX SYSTEM, IBM AND/OR THEIR 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. |
*/ |
/** |
* \file utils.c |
* Utility functions for DRI drivers. |
* |
* \author Ian Romanick <idr@us.ibm.com> |
*/ |
#include <string.h> |
#include <stdlib.h> |
#include <stdbool.h> |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/cpuinfo.h" |
#include "main/extensions.h" |
#include "utils.h" |
unsigned |
driParseDebugString( const char * debug, |
const struct dri_debug_control * control ) |
{ |
unsigned flag; |
flag = 0; |
if ( debug != NULL ) { |
while( control->string != NULL ) { |
if ( !strcmp( debug, "all" ) || |
strstr( debug, control->string ) != NULL ) { |
flag |= control->flag; |
} |
control++; |
} |
} |
return flag; |
} |
/** |
* Create the \c GL_RENDERER string for DRI drivers. |
* |
* Almost all DRI drivers use a \c GL_RENDERER string of the form: |
* |
* "Mesa DRI <chip> <driver date> <AGP speed) <CPU information>" |
* |
* Using the supplied chip name, driver data, and AGP speed, this function |
* creates the string. |
* |
* \param buffer Buffer to hold the \c GL_RENDERER string. |
* \param hardware_name Name of the hardware. |
* \param agp_mode AGP mode (speed). |
* |
* \returns |
* The length of the string stored in \c buffer. This does \b not include |
* the terminating \c NUL character. |
*/ |
unsigned |
driGetRendererString( char * buffer, const char * hardware_name, |
GLuint agp_mode ) |
{ |
unsigned offset; |
char *cpu; |
offset = sprintf( buffer, "Mesa DRI %s", hardware_name ); |
/* Append any AGP-specific information. |
*/ |
switch ( agp_mode ) { |
case 1: |
case 2: |
case 4: |
case 8: |
offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode ); |
break; |
default: |
break; |
} |
/* Append any CPU-specific information. |
*/ |
cpu = _mesa_get_cpu_string(); |
if (cpu) { |
offset += sprintf(buffer + offset, " %s", cpu); |
free(cpu); |
} |
return offset; |
} |
/** |
* Creates a set of \c struct gl_config that a driver will expose. |
* |
* A set of \c struct gl_config will be created based on the supplied |
* parameters. The number of modes processed will be 2 * |
* \c num_depth_stencil_bits * \c num_db_modes. |
* |
* For the most part, data is just copied from \c depth_bits, \c stencil_bits, |
* \c db_modes, and \c visType into each \c struct gl_config element. |
* However, the meanings of \c fb_format and \c fb_type require further |
* explanation. The \c fb_format specifies which color components are in |
* each pixel and what the default order is. For example, \c GL_RGB specifies |
* that red, green, blue are available and red is in the "most significant" |
* position and blue is in the "least significant". The \c fb_type specifies |
* the bit sizes of each component and the actual ordering. For example, if |
* \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11] |
* are the blue value, bits [10:5] are the green value, and bits [4:0] are |
* the red value. |
* |
* One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either |
* of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the |
* \c struct gl_config structure is \b identical to the \c GL_RGBA or |
* \c GL_BGRA case, except the \c alphaMask is zero. This means that, as |
* far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8 |
* still uses 32-bits. |
* |
* If in doubt, look at the tables used in the function. |
* |
* \param ptr_to_modes Pointer to a pointer to a linked list of |
* \c struct gl_config. Upon completion, a pointer to |
* the next element to be process will be stored here. |
* If the function fails and returns \c GL_FALSE, this |
* value will be unmodified, but some elements in the |
* linked list may be modified. |
* \param format Mesa gl_format enum describing the pixel format |
* \param depth_bits Array of depth buffer sizes to be exposed. |
* \param stencil_bits Array of stencil buffer sizes to be exposed. |
* \param num_depth_stencil_bits Number of entries in both \c depth_bits and |
* \c stencil_bits. |
* \param db_modes Array of buffer swap modes. If an element has a |
* value of \c GLX_NONE, then it represents a |
* single-buffered mode. Other valid values are |
* \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and |
* \c GLX_SWAP_UNDEFINED_OML. See the |
* GLX_OML_swap_method extension spec for more details. |
* \param num_db_modes Number of entries in \c db_modes. |
* \param msaa_samples Array of msaa sample count. 0 represents a visual |
* without a multisample buffer. |
* \param num_msaa_modes Number of entries in \c msaa_samples. |
* \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or |
* \c GLX_DIRECT_COLOR. |
* |
* \returns |
* Pointer to any array of pointers to the \c __DRIconfig structures created |
* for the specified formats. If there is an error, \c NULL is returned. |
* Currently the only cause of failure is a bad parameter (i.e., unsupported |
* \c format). |
*/ |
__DRIconfig ** |
driCreateConfigs(gl_format format, |
const uint8_t * depth_bits, const uint8_t * stencil_bits, |
unsigned num_depth_stencil_bits, |
const GLenum * db_modes, unsigned num_db_modes, |
const uint8_t * msaa_samples, unsigned num_msaa_modes, |
GLboolean enable_accum) |
{ |
static const uint32_t masks_table[][4] = { |
/* MESA_FORMAT_RGB565 */ |
{ 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, |
/* MESA_FORMAT_XRGB8888 */ |
{ 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, |
/* MESA_FORMAT_ARGB8888 */ |
{ 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, |
}; |
const uint32_t * masks; |
__DRIconfig **configs, **c; |
struct gl_config *modes; |
unsigned i, j, k, h; |
unsigned num_modes; |
unsigned num_accum_bits = (enable_accum) ? 2 : 1; |
int red_bits; |
int green_bits; |
int blue_bits; |
int alpha_bits; |
bool is_srgb; |
switch (format) { |
case MESA_FORMAT_RGB565: |
masks = masks_table[0]; |
break; |
case MESA_FORMAT_XRGB8888: |
masks = masks_table[1]; |
break; |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_SARGB8: |
masks = masks_table[2]; |
break; |
default: |
fprintf(stderr, "[%s:%u] Unknown framebuffer type %s (%d).\n", |
__FUNCTION__, __LINE__, |
_mesa_get_format_name(format), format); |
return NULL; |
} |
red_bits = _mesa_get_format_bits(format, GL_RED_BITS); |
green_bits = _mesa_get_format_bits(format, GL_GREEN_BITS); |
blue_bits = _mesa_get_format_bits(format, GL_BLUE_BITS); |
alpha_bits = _mesa_get_format_bits(format, GL_ALPHA_BITS); |
is_srgb = _mesa_get_format_color_encoding(format) == GL_SRGB; |
num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes; |
configs = calloc(1, (num_modes + 1) * sizeof *configs); |
if (configs == NULL) |
return NULL; |
c = configs; |
for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) { |
for ( i = 0 ; i < num_db_modes ; i++ ) { |
for ( h = 0 ; h < num_msaa_modes; h++ ) { |
for ( j = 0 ; j < num_accum_bits ; j++ ) { |
*c = malloc (sizeof **c); |
modes = &(*c)->modes; |
c++; |
memset(modes, 0, sizeof *modes); |
modes->redBits = red_bits; |
modes->greenBits = green_bits; |
modes->blueBits = blue_bits; |
modes->alphaBits = alpha_bits; |
modes->redMask = masks[0]; |
modes->greenMask = masks[1]; |
modes->blueMask = masks[2]; |
modes->alphaMask = masks[3]; |
modes->rgbBits = modes->redBits + modes->greenBits |
+ modes->blueBits + modes->alphaBits; |
modes->accumRedBits = 16 * j; |
modes->accumGreenBits = 16 * j; |
modes->accumBlueBits = 16 * j; |
modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0; |
modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG; |
modes->stencilBits = stencil_bits[k]; |
modes->depthBits = depth_bits[k]; |
modes->transparentPixel = GLX_NONE; |
modes->transparentRed = GLX_DONT_CARE; |
modes->transparentGreen = GLX_DONT_CARE; |
modes->transparentBlue = GLX_DONT_CARE; |
modes->transparentAlpha = GLX_DONT_CARE; |
modes->transparentIndex = GLX_DONT_CARE; |
modes->rgbMode = GL_TRUE; |
if ( db_modes[i] == GLX_NONE ) { |
modes->doubleBufferMode = GL_FALSE; |
} |
else { |
modes->doubleBufferMode = GL_TRUE; |
modes->swapMethod = db_modes[i]; |
} |
modes->samples = msaa_samples[h]; |
modes->sampleBuffers = modes->samples ? 1 : 0; |
modes->haveAccumBuffer = ((modes->accumRedBits + |
modes->accumGreenBits + |
modes->accumBlueBits + |
modes->accumAlphaBits) > 0); |
modes->haveDepthBuffer = (modes->depthBits > 0); |
modes->haveStencilBuffer = (modes->stencilBits > 0); |
modes->bindToTextureRgb = GL_TRUE; |
modes->bindToTextureRgba = GL_TRUE; |
modes->bindToMipmapTexture = GL_FALSE; |
modes->bindToTextureTargets = |
__DRI_ATTRIB_TEXTURE_1D_BIT | |
__DRI_ATTRIB_TEXTURE_2D_BIT | |
__DRI_ATTRIB_TEXTURE_RECTANGLE_BIT; |
modes->sRGBCapable = is_srgb; |
} |
} |
} |
} |
*c = NULL; |
return configs; |
} |
__DRIconfig **driConcatConfigs(__DRIconfig **a, |
__DRIconfig **b) |
{ |
__DRIconfig **all; |
int i, j, index; |
if (a == NULL || a[0] == NULL) |
return b; |
else if (b == NULL || b[0] == NULL) |
return a; |
i = 0; |
while (a[i] != NULL) |
i++; |
j = 0; |
while (b[j] != NULL) |
j++; |
all = malloc((i + j + 1) * sizeof *all); |
index = 0; |
for (i = 0; a[i] != NULL; i++) |
all[index++] = a[i]; |
for (j = 0; b[j] != NULL; j++) |
all[index++] = b[j]; |
all[index++] = NULL; |
free(a); |
free(b); |
return all; |
} |
#define __ATTRIB(attrib, field) \ |
{ attrib, offsetof(struct gl_config, field) } |
static const struct { unsigned int attrib, offset; } attribMap[] = { |
__ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), |
__ATTRIB(__DRI_ATTRIB_LEVEL, level), |
__ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), |
__ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), |
__ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), |
__ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), |
__ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), |
__ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), |
__ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), |
__ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), |
__ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), |
__ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), |
__ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), |
__ATTRIB(__DRI_ATTRIB_SAMPLES, samples), |
__ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), |
__ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), |
__ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), |
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), |
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel), |
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), |
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), |
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), |
__ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), |
__ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), |
__ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), |
__ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), |
__ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), |
__ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), |
__ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), |
__ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), |
__ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), |
__ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), |
__ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), |
__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), |
__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), |
__ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture), |
__ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS, bindToTextureTargets), |
__ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), |
__ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable), |
/* The struct field doesn't matter here, these are handled by the |
* switch in driGetConfigAttribIndex. We need them in the array |
* so the iterator includes them though.*/ |
__ATTRIB(__DRI_ATTRIB_RENDER_TYPE, level), |
__ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT, level), |
__ATTRIB(__DRI_ATTRIB_SWAP_METHOD, level) |
}; |
/** |
* Return the value of a configuration attribute. The attribute is |
* indicated by the index. |
*/ |
static int |
driGetConfigAttribIndex(const __DRIconfig *config, |
unsigned int index, unsigned int *value) |
{ |
switch (attribMap[index].attrib) { |
case __DRI_ATTRIB_RENDER_TYPE: |
/* no support for color index mode */ |
*value = __DRI_ATTRIB_RGBA_BIT; |
break; |
case __DRI_ATTRIB_CONFIG_CAVEAT: |
if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG) |
*value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG; |
else if (config->modes.visualRating == GLX_SLOW_CONFIG) |
*value = __DRI_ATTRIB_SLOW_BIT; |
else |
*value = 0; |
break; |
case __DRI_ATTRIB_SWAP_METHOD: |
/* XXX no return value??? */ |
break; |
default: |
/* any other int-sized field */ |
*value = *(unsigned int *) |
((char *) &config->modes + attribMap[index].offset); |
break; |
} |
return GL_TRUE; |
} |
/** |
* Get the value of a configuration attribute. |
* \param attrib the attribute (one of the _DRI_ATTRIB_x tokens) |
* \param value returns the attribute's value |
* \return 1 for success, 0 for failure |
*/ |
int |
driGetConfigAttrib(const __DRIconfig *config, |
unsigned int attrib, unsigned int *value) |
{ |
int i; |
for (i = 0; i < ARRAY_SIZE(attribMap); i++) |
if (attribMap[i].attrib == attrib) |
return driGetConfigAttribIndex(config, i, value); |
return GL_FALSE; |
} |
/** |
* Get a configuration attribute name and value, given an index. |
* \param index which field of the __DRIconfig to query |
* \param attrib returns the attribute name (one of the _DRI_ATTRIB_x tokens) |
* \param value returns the attribute's value |
* \return 1 for success, 0 for failure |
*/ |
int |
driIndexConfigAttrib(const __DRIconfig *config, int index, |
unsigned int *attrib, unsigned int *value) |
{ |
if (index >= 0 && index < ARRAY_SIZE(attribMap)) { |
*attrib = attribMap[index].attrib; |
return driGetConfigAttribIndex(config, index, value); |
} |
return GL_FALSE; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/utils.h |
---|
0,0 → 1,68 |
/* |
* (C) Copyright IBM Corporation 2002, 2004 |
* 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 |
* on 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 |
* VA LINUX SYSTEM, IBM AND/OR THEIR 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: |
* Ian Romanick <idr@us.ibm.com> |
*/ |
#ifndef DRI_DEBUG_H |
#define DRI_DEBUG_H |
#include <GL/gl.h> |
#include <GL/internal/dri_interface.h> |
#include "main/context.h" |
struct dri_debug_control { |
const char * string; |
unsigned flag; |
}; |
extern unsigned driParseDebugString( const char * debug, |
const struct dri_debug_control * control ); |
extern unsigned driGetRendererString( char * buffer, |
const char * hardware_name, GLuint agp_mode ); |
struct __DRIconfigRec { |
struct gl_config modes; |
}; |
extern __DRIconfig ** |
driCreateConfigs(gl_format format, |
const uint8_t * depth_bits, const uint8_t * stencil_bits, |
unsigned num_depth_stencil_bits, |
const GLenum * db_modes, unsigned num_db_modes, |
const uint8_t * msaa_samples, unsigned num_msaa_modes, |
GLboolean enable_accum); |
__DRIconfig **driConcatConfigs(__DRIconfig **a, |
__DRIconfig **b); |
int |
driGetConfigAttrib(const __DRIconfig *config, |
unsigned int attrib, unsigned int *value); |
int |
driIndexConfigAttrib(const __DRIconfig *config, int index, |
unsigned int *attrib, unsigned int *value); |
#endif /* DRI_DEBUG_H */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlconfig.c |
---|
0,0 → 1,1043 |
/* |
* XML DRI client-side driver configuration |
* Copyright (C) 2003 Felix Kuehling |
* |
* 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 |
* FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS 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. |
* |
*/ |
/** |
* \file xmlconfig.c |
* \brief Driver-independent client-side part of the XML configuration |
* \author Felix Kuehling |
*/ |
#include "main/glheader.h" |
#include <string.h> |
#include <assert.h> |
#include <expat.h> |
#include <fcntl.h> |
#include <unistd.h> |
#include <errno.h> |
#include "main/imports.h" |
#include "utils.h" |
#include "xmlconfig.h" |
#undef GET_PROGRAM_NAME |
#if (defined(__GNU_LIBRARY__) || defined(__GLIBC__)) && !defined(__UCLIBC__) |
# if !defined(__GLIBC__) || (__GLIBC__ < 2) |
/* These aren't declared in any libc5 header */ |
extern char *program_invocation_name, *program_invocation_short_name; |
# endif |
# define GET_PROGRAM_NAME() program_invocation_short_name |
#elif defined(__FreeBSD__) && (__FreeBSD__ >= 2) |
# include <osreldate.h> |
# if (__FreeBSD_version >= 440000) |
# include <stdlib.h> |
# define GET_PROGRAM_NAME() getprogname() |
# endif |
#elif defined(__NetBSD__) && defined(__NetBSD_Version) && (__NetBSD_Version >= 106000100) |
# include <stdlib.h> |
# define GET_PROGRAM_NAME() getprogname() |
#elif defined(__APPLE__) |
# include <stdlib.h> |
# define GET_PROGRAM_NAME() getprogname() |
#elif defined(__sun) |
/* Solaris has getexecname() which returns the full path - return just |
the basename to match BSD getprogname() */ |
# include <stdlib.h> |
# include <libgen.h> |
static const char *__getProgramName () { |
static const char *progname; |
if (progname == NULL) { |
const char *e = getexecname(); |
if (e != NULL) { |
/* Have to make a copy since getexecname can return a readonly |
string, but basename expects to be able to modify its arg. */ |
char *n = strdup(e); |
if (n != NULL) { |
progname = basename(n); |
} |
} |
} |
return progname; |
} |
# define GET_PROGRAM_NAME() __getProgramName() |
#endif |
#if !defined(GET_PROGRAM_NAME) |
# if defined(__OpenBSD__) || defined(NetBSD) || defined(__UCLIBC__) || defined(ANDROID) |
/* This is a hack. It's said to work on OpenBSD, NetBSD and GNU. |
* Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's |
* used as a last resort, if there is no documented facility available. */ |
static const char *__getProgramName () { |
extern const char *__progname; |
char * arg = strrchr(__progname, '/'); |
if (arg) |
return arg+1; |
else |
return __progname; |
} |
# define GET_PROGRAM_NAME() __getProgramName() |
# else |
# define GET_PROGRAM_NAME() "" |
# warning "Per application configuration won't work with your OS version." |
# endif |
#endif |
/** \brief Find an option in an option cache with the name as key */ |
static GLuint findOption (const driOptionCache *cache, const char *name) { |
GLuint len = strlen (name); |
GLuint size = 1 << cache->tableSize, mask = size - 1; |
GLuint hash = 0; |
GLuint i, shift; |
/* compute a hash from the variable length name */ |
for (i = 0, shift = 0; i < len; ++i, shift = (shift+8) & 31) |
hash += (GLuint)name[i] << shift; |
hash *= hash; |
hash = (hash >> (16-cache->tableSize/2)) & mask; |
/* this is just the starting point of the linear search for the option */ |
for (i = 0; i < size; ++i, hash = (hash+1) & mask) { |
/* if we hit an empty entry then the option is not defined (yet) */ |
if (cache->info[hash].name == 0) |
break; |
else if (!strcmp (name, cache->info[hash].name)) |
break; |
} |
/* this assertion fails if the hash table is full */ |
assert (i < size); |
return hash; |
} |
/** \brief Count the real number of options in an option cache */ |
static GLuint countOptions (const driOptionCache *cache) { |
GLuint size = 1 << cache->tableSize; |
GLuint i, count = 0; |
for (i = 0; i < size; ++i) |
if (cache->info[i].name) |
count++; |
return count; |
} |
/** \brief Like strdup but using malloc and with error checking. */ |
#define XSTRDUP(dest,source) do { \ |
GLuint len = strlen (source); \ |
if (!(dest = malloc(len+1))) { \ |
fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \ |
abort(); \ |
} \ |
memcpy (dest, source, len+1); \ |
} while (0) |
static int compare (const void *a, const void *b) { |
return strcmp (*(char *const*)a, *(char *const*)b); |
} |
/** \brief Binary search in a string array. */ |
static GLuint bsearchStr (const XML_Char *name, |
const XML_Char *elems[], GLuint count) { |
const XML_Char **found; |
found = bsearch (&name, elems, count, sizeof (XML_Char *), compare); |
if (found) |
return found - elems; |
else |
return count; |
} |
/** \brief Locale-independent integer parser. |
* |
* Works similar to strtol. Leading space is NOT skipped. The input |
* number may have an optional sign. Radix is specified by base. If |
* base is 0 then decimal is assumed unless the input number is |
* prefixed by 0x or 0X for hexadecimal or 0 for octal. After |
* returning tail points to the first character that is not part of |
* the integer number. If no number was found then tail points to the |
* start of the input string. */ |
static GLint strToI (const XML_Char *string, const XML_Char **tail, int base) { |
GLint radix = base == 0 ? 10 : base; |
GLint result = 0; |
GLint sign = 1; |
GLboolean numberFound = GL_FALSE; |
const XML_Char *start = string; |
assert (radix >= 2 && radix <= 36); |
if (*string == '-') { |
sign = -1; |
string++; |
} else if (*string == '+') |
string++; |
if (base == 0 && *string == '0') { |
numberFound = GL_TRUE; |
if (*(string+1) == 'x' || *(string+1) == 'X') { |
radix = 16; |
string += 2; |
} else { |
radix = 8; |
string++; |
} |
} |
do { |
GLint digit = -1; |
if (radix <= 10) { |
if (*string >= '0' && *string < '0' + radix) |
digit = *string - '0'; |
} else { |
if (*string >= '0' && *string <= '9') |
digit = *string - '0'; |
else if (*string >= 'a' && *string < 'a' + radix - 10) |
digit = *string - 'a' + 10; |
else if (*string >= 'A' && *string < 'A' + radix - 10) |
digit = *string - 'A' + 10; |
} |
if (digit != -1) { |
numberFound = GL_TRUE; |
result = radix*result + digit; |
string++; |
} else |
break; |
} while (GL_TRUE); |
*tail = numberFound ? string : start; |
return sign * result; |
} |
/** \brief Locale-independent floating-point parser. |
* |
* Works similar to strtod. Leading space is NOT skipped. The input |
* number may have an optional sign. '.' is interpreted as decimal |
* point and may occur at most once. Optionally the number may end in |
* [eE]<exponent>, where <exponent> is an integer as recognized by |
* strToI. In that case the result is number * 10^exponent. After |
* returning tail points to the first character that is not part of |
* the floating point number. If no number was found then tail points |
* to the start of the input string. |
* |
* Uses two passes for maximum accuracy. */ |
static GLfloat strToF (const XML_Char *string, const XML_Char **tail) { |
GLint nDigits = 0, pointPos, exponent; |
GLfloat sign = 1.0f, result = 0.0f, scale; |
const XML_Char *start = string, *numStart; |
/* sign */ |
if (*string == '-') { |
sign = -1.0f; |
string++; |
} else if (*string == '+') |
string++; |
/* first pass: determine position of decimal point, number of |
* digits, exponent and the end of the number. */ |
numStart = string; |
while (*string >= '0' && *string <= '9') { |
string++; |
nDigits++; |
} |
pointPos = nDigits; |
if (*string == '.') { |
string++; |
while (*string >= '0' && *string <= '9') { |
string++; |
nDigits++; |
} |
} |
if (nDigits == 0) { |
/* no digits, no number */ |
*tail = start; |
return 0.0f; |
} |
*tail = string; |
if (*string == 'e' || *string == 'E') { |
const XML_Char *expTail; |
exponent = strToI (string+1, &expTail, 10); |
if (expTail == string+1) |
exponent = 0; |
else |
*tail = expTail; |
} else |
exponent = 0; |
string = numStart; |
/* scale of the first digit */ |
scale = sign * (GLfloat)pow (10.0, (GLdouble)(pointPos-1 + exponent)); |
/* second pass: parse digits */ |
do { |
if (*string != '.') { |
assert (*string >= '0' && *string <= '9'); |
result += scale * (GLfloat)(*string - '0'); |
scale *= 0.1f; |
nDigits--; |
} |
string++; |
} while (nDigits > 0); |
return result; |
} |
/** \brief Parse a value of a given type. */ |
static GLboolean parseValue (driOptionValue *v, driOptionType type, |
const XML_Char *string) { |
const XML_Char *tail = NULL; |
/* skip leading white-space */ |
string += strspn (string, " \f\n\r\t\v"); |
switch (type) { |
case DRI_BOOL: |
if (!strcmp (string, "false")) { |
v->_bool = GL_FALSE; |
tail = string + 5; |
} else if (!strcmp (string, "true")) { |
v->_bool = GL_TRUE; |
tail = string + 4; |
} |
else |
return GL_FALSE; |
break; |
case DRI_ENUM: /* enum is just a special integer */ |
case DRI_INT: |
v->_int = strToI (string, &tail, 0); |
break; |
case DRI_FLOAT: |
v->_float = strToF (string, &tail); |
break; |
} |
if (tail == string) |
return GL_FALSE; /* empty string (or containing only white-space) */ |
/* skip trailing white space */ |
if (*tail) |
tail += strspn (tail, " \f\n\r\t\v"); |
if (*tail) |
return GL_FALSE; /* something left over that is not part of value */ |
return GL_TRUE; |
} |
/** \brief Parse a list of ranges of type info->type. */ |
static GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) { |
XML_Char *cp, *range; |
GLuint nRanges, i; |
driOptionRange *ranges; |
XSTRDUP (cp, string); |
/* pass 1: determine the number of ranges (number of commas + 1) */ |
range = cp; |
for (nRanges = 1; *range; ++range) |
if (*range == ',') |
++nRanges; |
if ((ranges = malloc(nRanges*sizeof(driOptionRange))) == NULL) { |
fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); |
abort(); |
} |
/* pass 2: parse all ranges into preallocated array */ |
range = cp; |
for (i = 0; i < nRanges; ++i) { |
XML_Char *end, *sep; |
assert (range); |
end = strchr (range, ','); |
if (end) |
*end = '\0'; |
sep = strchr (range, ':'); |
if (sep) { /* non-empty interval */ |
*sep = '\0'; |
if (!parseValue (&ranges[i].start, info->type, range) || |
!parseValue (&ranges[i].end, info->type, sep+1)) |
break; |
if (info->type == DRI_INT && |
ranges[i].start._int > ranges[i].end._int) |
break; |
if (info->type == DRI_FLOAT && |
ranges[i].start._float > ranges[i].end._float) |
break; |
} else { /* empty interval */ |
if (!parseValue (&ranges[i].start, info->type, range)) |
break; |
ranges[i].end = ranges[i].start; |
} |
if (end) |
range = end+1; |
else |
range = NULL; |
} |
free(cp); |
if (i < nRanges) { |
free(ranges); |
return GL_FALSE; |
} else |
assert (range == NULL); |
info->nRanges = nRanges; |
info->ranges = ranges; |
return GL_TRUE; |
} |
/** \brief Check if a value is in one of info->ranges. */ |
static GLboolean checkValue (const driOptionValue *v, const driOptionInfo *info) { |
GLuint i; |
assert (info->type != DRI_BOOL); /* should be caught by the parser */ |
if (info->nRanges == 0) |
return GL_TRUE; |
switch (info->type) { |
case DRI_ENUM: /* enum is just a special integer */ |
case DRI_INT: |
for (i = 0; i < info->nRanges; ++i) |
if (v->_int >= info->ranges[i].start._int && |
v->_int <= info->ranges[i].end._int) |
return GL_TRUE; |
break; |
case DRI_FLOAT: |
for (i = 0; i < info->nRanges; ++i) |
if (v->_float >= info->ranges[i].start._float && |
v->_float <= info->ranges[i].end._float) |
return GL_TRUE; |
break; |
default: |
assert (0); /* should never happen */ |
} |
return GL_FALSE; |
} |
/** |
* Print message to \c stderr if the \c LIBGL_DEBUG environment variable |
* is set. |
* |
* Is called from the drivers. |
* |
* \param f \c printf like format string. |
*/ |
static void |
__driUtilMessage(const char *f, ...) |
{ |
va_list args; |
if (getenv("LIBGL_DEBUG")) { |
fprintf(stderr, "libGL: "); |
va_start(args, f); |
vfprintf(stderr, f, args); |
va_end(args); |
fprintf(stderr, "\n"); |
} |
} |
/** \brief Output a warning message. */ |
#define XML_WARNING1(msg) do {\ |
__driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \ |
(int) XML_GetCurrentLineNumber(data->parser), \ |
(int) XML_GetCurrentColumnNumber(data->parser)); \ |
} while (0) |
#define XML_WARNING(msg,args...) do { \ |
__driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \ |
(int) XML_GetCurrentLineNumber(data->parser), \ |
(int) XML_GetCurrentColumnNumber(data->parser), \ |
args); \ |
} while (0) |
/** \brief Output an error message. */ |
#define XML_ERROR1(msg) do { \ |
__driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \ |
(int) XML_GetCurrentLineNumber(data->parser), \ |
(int) XML_GetCurrentColumnNumber(data->parser)); \ |
} while (0) |
#define XML_ERROR(msg,args...) do { \ |
__driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \ |
(int) XML_GetCurrentLineNumber(data->parser), \ |
(int) XML_GetCurrentColumnNumber(data->parser), \ |
args); \ |
} while (0) |
/** \brief Output a fatal error message and abort. */ |
#define XML_FATAL1(msg) do { \ |
fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \ |
data->name, \ |
(int) XML_GetCurrentLineNumber(data->parser), \ |
(int) XML_GetCurrentColumnNumber(data->parser)); \ |
abort();\ |
} while (0) |
#define XML_FATAL(msg,args...) do { \ |
fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \ |
data->name, \ |
(int) XML_GetCurrentLineNumber(data->parser), \ |
(int) XML_GetCurrentColumnNumber(data->parser), \ |
args); \ |
abort();\ |
} while (0) |
/** \brief Parser context for __driConfigOptions. */ |
struct OptInfoData { |
const char *name; |
XML_Parser parser; |
driOptionCache *cache; |
GLboolean inDriInfo; |
GLboolean inSection; |
GLboolean inDesc; |
GLboolean inOption; |
GLboolean inEnum; |
int curOption; |
}; |
/** \brief Elements in __driConfigOptions. */ |
enum OptInfoElem { |
OI_DESCRIPTION = 0, OI_DRIINFO, OI_ENUM, OI_OPTION, OI_SECTION, OI_COUNT |
}; |
static const XML_Char *OptInfoElems[] = { |
"description", "driinfo", "enum", "option", "section" |
}; |
/** \brief Parse attributes of an enum element. |
* |
* We're not actually interested in the data. Just make sure this is ok |
* for external configuration tools. |
*/ |
static void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) { |
GLuint i; |
const XML_Char *value = NULL, *text = NULL; |
driOptionValue v; |
GLuint opt = data->curOption; |
for (i = 0; attr[i]; i += 2) { |
if (!strcmp (attr[i], "value")) value = attr[i+1]; |
else if (!strcmp (attr[i], "text")) text = attr[i+1]; |
else XML_FATAL("illegal enum attribute: %s.", attr[i]); |
} |
if (!value) XML_FATAL1 ("value attribute missing in enum."); |
if (!text) XML_FATAL1 ("text attribute missing in enum."); |
if (!parseValue (&v, data->cache->info[opt].type, value)) |
XML_FATAL ("illegal enum value: %s.", value); |
if (!checkValue (&v, &data->cache->info[opt])) |
XML_FATAL ("enum value out of valid range: %s.", value); |
} |
/** \brief Parse attributes of a description element. |
* |
* We're not actually interested in the data. Just make sure this is ok |
* for external configuration tools. |
*/ |
static void parseDescAttr (struct OptInfoData *data, const XML_Char **attr) { |
GLuint i; |
const XML_Char *lang = NULL, *text = NULL; |
for (i = 0; attr[i]; i += 2) { |
if (!strcmp (attr[i], "lang")) lang = attr[i+1]; |
else if (!strcmp (attr[i], "text")) text = attr[i+1]; |
else XML_FATAL("illegal description attribute: %s.", attr[i]); |
} |
if (!lang) XML_FATAL1 ("lang attribute missing in description."); |
if (!text) XML_FATAL1 ("text attribute missing in description."); |
} |
/** \brief Parse attributes of an option element. */ |
static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) { |
enum OptAttr {OA_DEFAULT = 0, OA_NAME, OA_TYPE, OA_VALID, OA_COUNT}; |
static const XML_Char *optAttr[] = {"default", "name", "type", "valid"}; |
const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL}; |
const char *defaultVal; |
driOptionCache *cache = data->cache; |
GLuint opt, i; |
for (i = 0; attr[i]; i += 2) { |
GLuint attrName = bsearchStr (attr[i], optAttr, OA_COUNT); |
if (attrName >= OA_COUNT) |
XML_FATAL ("illegal option attribute: %s", attr[i]); |
attrVal[attrName] = attr[i+1]; |
} |
if (!attrVal[OA_NAME]) XML_FATAL1 ("name attribute missing in option."); |
if (!attrVal[OA_TYPE]) XML_FATAL1 ("type attribute missing in option."); |
if (!attrVal[OA_DEFAULT]) XML_FATAL1 ("default attribute missing in option."); |
opt = findOption (cache, attrVal[OA_NAME]); |
if (cache->info[opt].name) |
XML_FATAL ("option %s redefined.", attrVal[OA_NAME]); |
data->curOption = opt; |
XSTRDUP (cache->info[opt].name, attrVal[OA_NAME]); |
if (!strcmp (attrVal[OA_TYPE], "bool")) |
cache->info[opt].type = DRI_BOOL; |
else if (!strcmp (attrVal[OA_TYPE], "enum")) |
cache->info[opt].type = DRI_ENUM; |
else if (!strcmp (attrVal[OA_TYPE], "int")) |
cache->info[opt].type = DRI_INT; |
else if (!strcmp (attrVal[OA_TYPE], "float")) |
cache->info[opt].type = DRI_FLOAT; |
else |
XML_FATAL ("illegal type in option: %s.", attrVal[OA_TYPE]); |
defaultVal = getenv (cache->info[opt].name); |
if (defaultVal != NULL) { |
/* don't use XML_WARNING, we want the user to see this! */ |
fprintf (stderr, |
"ATTENTION: default value of option %s overridden by environment.\n", |
cache->info[opt].name); |
} else |
defaultVal = attrVal[OA_DEFAULT]; |
if (!parseValue (&cache->values[opt], cache->info[opt].type, defaultVal)) |
XML_FATAL ("illegal default value for %s: %s.", cache->info[opt].name, defaultVal); |
if (attrVal[OA_VALID]) { |
if (cache->info[opt].type == DRI_BOOL) |
XML_FATAL1 ("boolean option with valid attribute."); |
if (!parseRanges (&cache->info[opt], attrVal[OA_VALID])) |
XML_FATAL ("illegal valid attribute: %s.", attrVal[OA_VALID]); |
if (!checkValue (&cache->values[opt], &cache->info[opt])) |
XML_FATAL ("default value out of valid range '%s': %s.", |
attrVal[OA_VALID], defaultVal); |
} else if (cache->info[opt].type == DRI_ENUM) { |
XML_FATAL1 ("valid attribute missing in option (mandatory for enums)."); |
} else { |
cache->info[opt].nRanges = 0; |
cache->info[opt].ranges = NULL; |
} |
} |
/** \brief Handler for start element events. */ |
static void optInfoStartElem (void *userData, const XML_Char *name, |
const XML_Char **attr) { |
struct OptInfoData *data = (struct OptInfoData *)userData; |
enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT); |
switch (elem) { |
case OI_DRIINFO: |
if (data->inDriInfo) |
XML_FATAL1 ("nested <driinfo> elements."); |
if (attr[0]) |
XML_FATAL1 ("attributes specified on <driinfo> element."); |
data->inDriInfo = GL_TRUE; |
break; |
case OI_SECTION: |
if (!data->inDriInfo) |
XML_FATAL1 ("<section> must be inside <driinfo>."); |
if (data->inSection) |
XML_FATAL1 ("nested <section> elements."); |
if (attr[0]) |
XML_FATAL1 ("attributes specified on <section> element."); |
data->inSection = GL_TRUE; |
break; |
case OI_DESCRIPTION: |
if (!data->inSection && !data->inOption) |
XML_FATAL1 ("<description> must be inside <description> or <option."); |
if (data->inDesc) |
XML_FATAL1 ("nested <description> elements."); |
data->inDesc = GL_TRUE; |
parseDescAttr (data, attr); |
break; |
case OI_OPTION: |
if (!data->inSection) |
XML_FATAL1 ("<option> must be inside <section>."); |
if (data->inDesc) |
XML_FATAL1 ("<option> nested in <description> element."); |
if (data->inOption) |
XML_FATAL1 ("nested <option> elements."); |
data->inOption = GL_TRUE; |
parseOptInfoAttr (data, attr); |
break; |
case OI_ENUM: |
if (!(data->inOption && data->inDesc)) |
XML_FATAL1 ("<enum> must be inside <option> and <description>."); |
if (data->inEnum) |
XML_FATAL1 ("nested <enum> elements."); |
data->inEnum = GL_TRUE; |
parseEnumAttr (data, attr); |
break; |
default: |
XML_FATAL ("unknown element: %s.", name); |
} |
} |
/** \brief Handler for end element events. */ |
static void optInfoEndElem (void *userData, const XML_Char *name) { |
struct OptInfoData *data = (struct OptInfoData *)userData; |
enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT); |
switch (elem) { |
case OI_DRIINFO: |
data->inDriInfo = GL_FALSE; |
break; |
case OI_SECTION: |
data->inSection = GL_FALSE; |
break; |
case OI_DESCRIPTION: |
data->inDesc = GL_FALSE; |
break; |
case OI_OPTION: |
data->inOption = GL_FALSE; |
break; |
case OI_ENUM: |
data->inEnum = GL_FALSE; |
break; |
default: |
assert (0); /* should have been caught by StartElem */ |
} |
} |
void driParseOptionInfo (driOptionCache *info, |
const char *configOptions, GLuint nConfigOptions) { |
XML_Parser p; |
int status; |
struct OptInfoData userData; |
struct OptInfoData *data = &userData; |
GLuint realNoptions; |
/* determine hash table size and allocate memory: |
* 3/2 of the number of options, rounded up, so there remains always |
* at least one free entry. This is needed for detecting undefined |
* options in configuration files without getting a hash table overflow. |
* Round this up to a power of two. */ |
GLuint minSize = (nConfigOptions*3 + 1) / 2; |
GLuint size, log2size; |
for (size = 1, log2size = 0; size < minSize; size <<= 1, ++log2size); |
info->tableSize = log2size; |
info->info = calloc(size, sizeof (driOptionInfo)); |
info->values = calloc(size, sizeof (driOptionValue)); |
if (info->info == NULL || info->values == NULL) { |
fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); |
abort(); |
} |
p = XML_ParserCreate ("UTF-8"); /* always UTF-8 */ |
XML_SetElementHandler (p, optInfoStartElem, optInfoEndElem); |
XML_SetUserData (p, data); |
userData.name = "__driConfigOptions"; |
userData.parser = p; |
userData.cache = info; |
userData.inDriInfo = GL_FALSE; |
userData.inSection = GL_FALSE; |
userData.inDesc = GL_FALSE; |
userData.inOption = GL_FALSE; |
userData.inEnum = GL_FALSE; |
userData.curOption = -1; |
status = XML_Parse (p, configOptions, strlen (configOptions), 1); |
if (!status) |
XML_FATAL ("%s.", XML_ErrorString(XML_GetErrorCode(p))); |
XML_ParserFree (p); |
/* Check if the actual number of options matches nConfigOptions. |
* A mismatch is not fatal (a hash table overflow would be) but we |
* want the driver developer's attention anyway. */ |
realNoptions = countOptions (info); |
if (realNoptions != nConfigOptions) { |
fprintf (stderr, |
"Error: nConfigOptions (%u) does not match the actual number of options in\n" |
" __driConfigOptions (%u).\n", |
nConfigOptions, realNoptions); |
} |
} |
/** \brief Parser context for configuration files. */ |
struct OptConfData { |
const char *name; |
XML_Parser parser; |
driOptionCache *cache; |
GLint screenNum; |
const char *driverName, *execName; |
GLuint ignoringDevice; |
GLuint ignoringApp; |
GLuint inDriConf; |
GLuint inDevice; |
GLuint inApp; |
GLuint inOption; |
}; |
/** \brief Elements in configuration files. */ |
enum OptConfElem { |
OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_OPTION, OC_COUNT |
}; |
static const XML_Char *OptConfElems[] = { |
"application", "device", "driconf", "option" |
}; |
/** \brief Parse attributes of a device element. */ |
static void parseDeviceAttr (struct OptConfData *data, const XML_Char **attr) { |
GLuint i; |
const XML_Char *driver = NULL, *screen = NULL; |
for (i = 0; attr[i]; i += 2) { |
if (!strcmp (attr[i], "driver")) driver = attr[i+1]; |
else if (!strcmp (attr[i], "screen")) screen = attr[i+1]; |
else XML_WARNING("unknown device attribute: %s.", attr[i]); |
} |
if (driver && strcmp (driver, data->driverName)) |
data->ignoringDevice = data->inDevice; |
else if (screen) { |
driOptionValue screenNum; |
if (!parseValue (&screenNum, DRI_INT, screen)) |
XML_WARNING("illegal screen number: %s.", screen); |
else if (screenNum._int != data->screenNum) |
data->ignoringDevice = data->inDevice; |
} |
} |
/** \brief Parse attributes of an application element. */ |
static void parseAppAttr (struct OptConfData *data, const XML_Char **attr) { |
GLuint i; |
const XML_Char *exec = NULL; |
for (i = 0; attr[i]; i += 2) { |
if (!strcmp (attr[i], "name")) /* not needed here */; |
else if (!strcmp (attr[i], "executable")) exec = attr[i+1]; |
else XML_WARNING("unknown application attribute: %s.", attr[i]); |
} |
if (exec && strcmp (exec, data->execName)) |
data->ignoringApp = data->inApp; |
} |
/** \brief Parse attributes of an option element. */ |
static void parseOptConfAttr (struct OptConfData *data, const XML_Char **attr) { |
GLuint i; |
const XML_Char *name = NULL, *value = NULL; |
for (i = 0; attr[i]; i += 2) { |
if (!strcmp (attr[i], "name")) name = attr[i+1]; |
else if (!strcmp (attr[i], "value")) value = attr[i+1]; |
else XML_WARNING("unknown option attribute: %s.", attr[i]); |
} |
if (!name) XML_WARNING1 ("name attribute missing in option."); |
if (!value) XML_WARNING1 ("value attribute missing in option."); |
if (name && value) { |
driOptionCache *cache = data->cache; |
GLuint opt = findOption (cache, name); |
if (cache->info[opt].name == NULL) |
/* don't use XML_WARNING, drirc defines options for all drivers, |
* but not all drivers support them */ |
return; |
else if (getenv (cache->info[opt].name)) |
/* don't use XML_WARNING, we want the user to see this! */ |
fprintf (stderr, "ATTENTION: option value of option %s ignored.\n", |
cache->info[opt].name); |
else if (!parseValue (&cache->values[opt], cache->info[opt].type, value)) |
XML_WARNING ("illegal option value: %s.", value); |
} |
} |
/** \brief Handler for start element events. */ |
static void optConfStartElem (void *userData, const XML_Char *name, |
const XML_Char **attr) { |
struct OptConfData *data = (struct OptConfData *)userData; |
enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT); |
switch (elem) { |
case OC_DRICONF: |
if (data->inDriConf) |
XML_WARNING1 ("nested <driconf> elements."); |
if (attr[0]) |
XML_WARNING1 ("attributes specified on <driconf> element."); |
data->inDriConf++; |
break; |
case OC_DEVICE: |
if (!data->inDriConf) |
XML_WARNING1 ("<device> should be inside <driconf>."); |
if (data->inDevice) |
XML_WARNING1 ("nested <device> elements."); |
data->inDevice++; |
if (!data->ignoringDevice && !data->ignoringApp) |
parseDeviceAttr (data, attr); |
break; |
case OC_APPLICATION: |
if (!data->inDevice) |
XML_WARNING1 ("<application> should be inside <device>."); |
if (data->inApp) |
XML_WARNING1 ("nested <application> elements."); |
data->inApp++; |
if (!data->ignoringDevice && !data->ignoringApp) |
parseAppAttr (data, attr); |
break; |
case OC_OPTION: |
if (!data->inApp) |
XML_WARNING1 ("<option> should be inside <application>."); |
if (data->inOption) |
XML_WARNING1 ("nested <option> elements."); |
data->inOption++; |
if (!data->ignoringDevice && !data->ignoringApp) |
parseOptConfAttr (data, attr); |
break; |
default: |
XML_WARNING ("unknown element: %s.", name); |
} |
} |
/** \brief Handler for end element events. */ |
static void optConfEndElem (void *userData, const XML_Char *name) { |
struct OptConfData *data = (struct OptConfData *)userData; |
enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT); |
switch (elem) { |
case OC_DRICONF: |
data->inDriConf--; |
break; |
case OC_DEVICE: |
if (data->inDevice-- == data->ignoringDevice) |
data->ignoringDevice = 0; |
break; |
case OC_APPLICATION: |
if (data->inApp-- == data->ignoringApp) |
data->ignoringApp = 0; |
break; |
case OC_OPTION: |
data->inOption--; |
break; |
default: |
/* unknown element, warning was produced on start tag */; |
} |
} |
/** \brief Initialize an option cache based on info */ |
static void initOptionCache (driOptionCache *cache, const driOptionCache *info) { |
cache->info = info->info; |
cache->tableSize = info->tableSize; |
cache->values = malloc((1<<info->tableSize) * sizeof (driOptionValue)); |
if (cache->values == NULL) { |
fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); |
abort(); |
} |
memcpy (cache->values, info->values, |
(1<<info->tableSize) * sizeof (driOptionValue)); |
} |
/** \brief Parse the named configuration file */ |
static void parseOneConfigFile (XML_Parser p) { |
#define BUF_SIZE 0x1000 |
struct OptConfData *data = (struct OptConfData *)XML_GetUserData (p); |
int status; |
int fd; |
if ((fd = open (data->name, O_RDONLY)) == -1) { |
__driUtilMessage ("Can't open configuration file %s: %s.", |
data->name, strerror (errno)); |
return; |
} |
while (1) { |
int bytesRead; |
void *buffer = XML_GetBuffer (p, BUF_SIZE); |
if (!buffer) { |
__driUtilMessage ("Can't allocate parser buffer."); |
break; |
} |
bytesRead = read (fd, buffer, BUF_SIZE); |
if (bytesRead == -1) { |
__driUtilMessage ("Error reading from configuration file %s: %s.", |
data->name, strerror (errno)); |
break; |
} |
status = XML_ParseBuffer (p, bytesRead, bytesRead == 0); |
if (!status) { |
XML_ERROR ("%s.", XML_ErrorString(XML_GetErrorCode(p))); |
break; |
} |
if (bytesRead == 0) |
break; |
} |
close (fd); |
#undef BUF_SIZE |
} |
void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info, |
GLint screenNum, const char *driverName) { |
char *filenames[2] = {"/etc/drirc", NULL}; |
char *home; |
GLuint i; |
struct OptConfData userData; |
initOptionCache (cache, info); |
userData.cache = cache; |
userData.screenNum = screenNum; |
userData.driverName = driverName; |
userData.execName = GET_PROGRAM_NAME(); |
if ((home = getenv ("HOME"))) { |
GLuint len = strlen (home); |
filenames[1] = malloc(len + 7+1); |
if (filenames[1] == NULL) |
__driUtilMessage ("Can't allocate memory for %s/.drirc.", home); |
else { |
memcpy (filenames[1], home, len); |
memcpy (filenames[1] + len, "/.drirc", 7+1); |
} |
} |
for (i = 0; i < 2; ++i) { |
XML_Parser p; |
if (filenames[i] == NULL) |
continue; |
p = XML_ParserCreate (NULL); /* use encoding specified by file */ |
XML_SetElementHandler (p, optConfStartElem, optConfEndElem); |
XML_SetUserData (p, &userData); |
userData.parser = p; |
userData.name = filenames[i]; |
userData.ignoringDevice = 0; |
userData.ignoringApp = 0; |
userData.inDriConf = 0; |
userData.inDevice = 0; |
userData.inApp = 0; |
userData.inOption = 0; |
parseOneConfigFile (p); |
XML_ParserFree (p); |
} |
free(filenames[1]); |
} |
void driDestroyOptionInfo (driOptionCache *info) { |
driDestroyOptionCache (info); |
if (info->info) { |
GLuint i, size = 1 << info->tableSize; |
for (i = 0; i < size; ++i) { |
if (info->info[i].name) { |
free(info->info[i].name); |
free(info->info[i].ranges); |
} |
} |
free(info->info); |
} |
} |
void driDestroyOptionCache (driOptionCache *cache) { |
free(cache->values); |
} |
GLboolean driCheckOption (const driOptionCache *cache, const char *name, |
driOptionType type) { |
GLuint i = findOption (cache, name); |
return cache->info[i].name != NULL && cache->info[i].type == type; |
} |
GLboolean driQueryOptionb (const driOptionCache *cache, const char *name) { |
GLuint i = findOption (cache, name); |
/* make sure the option is defined and has the correct type */ |
assert (cache->info[i].name != NULL); |
assert (cache->info[i].type == DRI_BOOL); |
return cache->values[i]._bool; |
} |
GLint driQueryOptioni (const driOptionCache *cache, const char *name) { |
GLuint i = findOption (cache, name); |
/* make sure the option is defined and has the correct type */ |
assert (cache->info[i].name != NULL); |
assert (cache->info[i].type == DRI_INT || cache->info[i].type == DRI_ENUM); |
return cache->values[i]._int; |
} |
GLfloat driQueryOptionf (const driOptionCache *cache, const char *name) { |
GLuint i = findOption (cache, name); |
/* make sure the option is defined and has the correct type */ |
assert (cache->info[i].name != NULL); |
assert (cache->info[i].type == DRI_FLOAT); |
return cache->values[i]._float; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlconfig.h |
---|
0,0 → 1,124 |
/* |
* XML DRI client-side driver configuration |
* Copyright (C) 2003 Felix Kuehling |
* |
* 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 |
* FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS 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. |
* |
*/ |
/** |
* \file xmlconfig.h |
* \brief Driver-independent client-side part of the XML configuration |
* \author Felix Kuehling |
*/ |
#ifndef __XMLCONFIG_H |
#define __XMLCONFIG_H |
/** \brief Option data types */ |
typedef enum driOptionType { |
DRI_BOOL, DRI_ENUM, DRI_INT, DRI_FLOAT |
} driOptionType; |
/** \brief Option value */ |
typedef union driOptionValue { |
GLboolean _bool; /**< \brief Boolean */ |
GLint _int; /**< \brief Integer or Enum */ |
GLfloat _float; /**< \brief Floating-point */ |
} driOptionValue; |
/** \brief Single range of valid values |
* |
* For empty ranges (a single value) start == end */ |
typedef struct driOptionRange { |
driOptionValue start; /**< \brief Start */ |
driOptionValue end; /**< \brief End */ |
} driOptionRange; |
/** \brief Information about an option */ |
typedef struct driOptionInfo { |
char *name; /**< \brief Name */ |
driOptionType type; /**< \brief Type */ |
driOptionRange *ranges; /**< \brief Array of ranges */ |
GLuint nRanges; /**< \brief Number of ranges */ |
} driOptionInfo; |
/** \brief Option cache |
* |
* \li One in <driver>Screen caching option info and the default values |
* \li One in each <driver>Context with the actual values for that context */ |
typedef struct driOptionCache { |
driOptionInfo *info; |
/**< \brief Array of option infos |
* |
* Points to the same array in the screen and all contexts */ |
driOptionValue *values; |
/**< \brief Array of option values |
* |
* \li Default values in screen |
* \li Actual values in contexts |
*/ |
GLuint tableSize; |
/**< \brief Size of the arrays |
* |
* Depending on the hash function this may differ from __driNConfigOptions. |
* In the current implementation it's not actually a size but log2(size). |
* The value is the same in the screen and all contexts. */ |
} driOptionCache; |
/** \brief Parse XML option info from configOptions |
* |
* To be called in <driver>CreateScreen |
* |
* \param info pointer to a driOptionCache that will store the option info |
* \param configOptions XML document describing available configuration opts |
* \param nConfigOptions number of options, used to choose a hash table size |
* |
* For the option information to be available to external configuration tools |
* it must be a public symbol __driConfigOptions. It is also passed as a |
* parameter to driParseOptionInfo in order to avoid driver-independent code |
* depending on symbols in driver-specific code. */ |
void driParseOptionInfo (driOptionCache *info, |
const char *configOptions, GLuint nConfigOptions); |
/** \brief Initialize option cache from info and parse configuration files |
* |
* To be called in <driver>CreateContext. screenNum and driverName select |
* device sections. */ |
void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info, |
GLint screenNum, const char *driverName); |
/** \brief Destroy option info |
* |
* To be called in <driver>DestroyScreen */ |
void driDestroyOptionInfo (driOptionCache *info); |
/** \brief Destroy option cache |
* |
* To be called in <driver>DestroyContext */ |
void driDestroyOptionCache (driOptionCache *cache); |
/** \brief Check if there exists a certain option */ |
GLboolean driCheckOption (const driOptionCache *cache, const char *name, |
driOptionType type); |
/** \brief Query a boolean option value */ |
GLboolean driQueryOptionb (const driOptionCache *cache, const char *name); |
/** \brief Query an integer option value */ |
GLint driQueryOptioni (const driOptionCache *cache, const char *name); |
/** \brief Query a floating-point option value */ |
GLfloat driQueryOptionf (const driOptionCache *cache, const char *name); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlpool/Makefile.am |
---|
0,0 → 1,94 |
# Convenient makefile for managing translations. |
# Prerequisites: |
# - GNU gettext |
# - Python |
# Adding new translations |
# ----------------------- |
# To start working on a new translation edit the POS=... line |
# below. If you want to add for example a french translation, add |
# fr.po. |
# Then run "make po" to generate a fresh .po file from translatable |
# strings in t_options.h. Now you can edit the new .po file (fr.po in |
# the example above) to translate the strings. Please make sure that |
# your editor encodes the file in UTF-8. |
# Updating existing translations |
# ------------------------------ |
# Run "make po" to update .po files with new translatable strings from |
# t_options.h. Now you can edit the .po files you're interested |
# in. Please make sure that your editor encodes the file in UTF-8. |
# Updating options.h |
# ------------------ |
# Finally run "make" to generate options.h from t_options.h with all |
# translations. Now you can rebuild the drivers. Any common options |
# used by the drivers will have option descriptions with the latest |
# translations. |
# Publishing translations |
# ----------------------- |
# To get your translation(s) into Mesa CVS, please send me your |
# <lang>.po file. |
# More information: |
# - info gettext |
# The set of supported languages. Add languages as needed. |
POS=de.po es.po nl.po fr.po sv.po |
# |
# Don't change anything below, unless you know what you're doing. |
# |
LANGS=$(POS:%.po=%) |
MOS=$(POS:%.po=%/LC_MESSAGES/options.mo) |
POT=xmlpool.pot |
.PHONY: all clean pot po mo |
BUILT_SOURCES = options.h |
# All generated files are cleaned up. |
clean: |
-rm -f $(POT) options.h *~ |
-rm -rf $(LANGS) |
# Default target options.h |
options.h: LOCALEDIR := . |
options.h: t_options.h $(MOS) |
$(AM_V_GEN) $(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/gen_xmlpool.py $(srcdir)/t_options.h $(LOCALEDIR) $(LANGS) > options.h |
# Update .mo files from the corresponding .po files. |
%/LC_MESSAGES/options.mo: %.po |
@mo="$@"; \ |
lang=$${mo%%/*}; \ |
echo "Updating ($$lang) $@ from $?."; \ |
mkdir -p $$lang/LC_MESSAGES; \ |
msgfmt -o $@ $? |
# Use this target to create or update .po files with new messages in |
# driconf.py. |
po: $(POT) |
@for po in $(POS); do \ |
if [ -f $$po ]; then \ |
echo "Merging new strings from $(POT) into $@."; \ |
mv $$po $$po~; \ |
msgmerge -o $$po $$po~ $(POT); \ |
else \ |
echo "Initializing $$po from $(POT)."; \ |
msginit -i $(POT) -o $$po~ --locale=$*; \ |
sed -e 's/charset=.*\\n/charset=UTF-8\\n/' $$po~ > $$po; \ |
fi \ |
done |
pot: $(POT) |
# Extract message catalog from driconf.py. |
$(POT): t_options.h |
xgettext -L C --from-code utf-8 -o $(POT) t_options.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlpool/Makefile.in |
---|
0,0 → 1,690 |
# 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@ |
# Convenient makefile for managing translations. |
# Prerequisites: |
# - GNU gettext |
# - Python |
# Adding new translations |
# ----------------------- |
# To start working on a new translation edit the POS=... line |
# below. If you want to add for example a french translation, add |
# fr.po. |
# Then run "make po" to generate a fresh .po file from translatable |
# strings in t_options.h. Now you can edit the new .po file (fr.po in |
# the example above) to translate the strings. Please make sure that |
# your editor encodes the file in UTF-8. |
# Updating existing translations |
# ------------------------------ |
# Run "make po" to update .po files with new translatable strings from |
# t_options.h. Now you can edit the .po files you're interested |
# in. Please make sure that your editor encodes the file in UTF-8. |
# Updating options.h |
# ------------------ |
# Finally run "make" to generate options.h from t_options.h with all |
# translations. Now you can rebuild the drivers. Any common options |
# used by the drivers will have option descriptions with the latest |
# translations. |
# Publishing translations |
# ----------------------- |
# To get your translation(s) into Mesa CVS, please send me your |
# <lang>.po file. |
# More information: |
# - info gettext |
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@ |
subdir = src/mesa/drivers/dri/common/xmlpool |
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am |
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 = |
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 = |
SOURCES = |
DIST_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) |
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@ |
# The set of supported languages. Add languages as needed. |
POS = de.po es.po nl.po fr.po sv.po |
# |
# Don't change anything below, unless you know what you're doing. |
# |
LANGS = $(POS:%.po=%) |
MOS = $(POS:%.po=%/LC_MESSAGES/options.mo) |
POT = xmlpool.pot |
BUILT_SOURCES = options.h |
all: $(BUILT_SOURCES) |
$(MAKE) $(AM_MAKEFLAGS) all-am |
.SUFFIXES: |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(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/mesa/drivers/dri/common/xmlpool/Makefile'; \ |
$(am__cd) $(top_srcdir) && \ |
$(AUTOMAKE) --foreign src/mesa/drivers/dri/common/xmlpool/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_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): |
mostlyclean-libtool: |
-rm -f *.lo |
clean-libtool: |
-rm -rf .libs _libs |
tags TAGS: |
ctags CTAGS: |
cscope cscopelist: |
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: $(BUILT_SOURCES) |
$(MAKE) $(AM_MAKEFLAGS) check-am |
all-am: Makefile |
installdirs: |
install: $(BUILT_SOURCES) |
$(MAKE) $(AM_MAKEFLAGS) 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." |
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) |
clean-am: clean-generic clean-libtool mostlyclean-am |
distclean: distclean-am |
-rm -f Makefile |
distclean-am: clean-am distclean-generic |
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 -f Makefile |
maintainer-clean-am: distclean-am maintainer-clean-generic |
mostlyclean: mostlyclean-am |
mostlyclean-am: mostlyclean-generic mostlyclean-libtool |
pdf: pdf-am |
pdf-am: |
ps: ps-am |
ps-am: |
uninstall-am: |
.MAKE: all check install install-am install-strip |
.PHONY: all all-am check check-am clean clean-generic clean-libtool \ |
cscopelist-am ctags-am distclean distclean-generic \ |
distclean-libtool 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-generic mostlyclean-libtool pdf pdf-am ps ps-am \ |
tags-am uninstall uninstall-am |
.PHONY: all clean pot po mo |
# All generated files are cleaned up. |
clean: |
-rm -f $(POT) options.h *~ |
-rm -rf $(LANGS) |
# Default target options.h |
options.h: LOCALEDIR := . |
options.h: t_options.h $(MOS) |
$(AM_V_GEN) $(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/gen_xmlpool.py $(srcdir)/t_options.h $(LOCALEDIR) $(LANGS) > options.h |
# Update .mo files from the corresponding .po files. |
%/LC_MESSAGES/options.mo: %.po |
@mo="$@"; \ |
lang=$${mo%%/*}; \ |
echo "Updating ($$lang) $@ from $?."; \ |
mkdir -p $$lang/LC_MESSAGES; \ |
msgfmt -o $@ $? |
# Use this target to create or update .po files with new messages in |
# driconf.py. |
po: $(POT) |
@for po in $(POS); do \ |
if [ -f $$po ]; then \ |
echo "Merging new strings from $(POT) into $@."; \ |
mv $$po $$po~; \ |
msgmerge -o $$po $$po~ $(POT); \ |
else \ |
echo "Initializing $$po from $(POT)."; \ |
msginit -i $(POT) -o $$po~ --locale=$*; \ |
sed -e 's/charset=.*\\n/charset=UTF-8\\n/' $$po~ > $$po; \ |
fi \ |
done |
pot: $(POT) |
# Extract message catalog from driconf.py. |
$(POT): t_options.h |
xgettext -L C --from-code utf-8 -o $(POT) t_options.h |
# 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/src/mesa/drivers/dri/common/xmlpool/SConscript |
---|
0,0 → 1,14 |
Import('*') |
from sys import executable as python_cmd |
LOCALEDIR = env.Dir('.').srcnode().abspath |
xmlpool_options, = env.CodeGenerate( |
target = 'options.h', |
script = 'gen_xmlpool.py', |
source = ['t_options.h'], |
command = python_cmd + ' $SCRIPT $SOURCE ' + LOCALEDIR + ' > $TARGET' |
) |
Export('xmlpool_options') |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlpool/de.po |
---|
0,0 → 1,277 |
# German translations for DRI driver options. |
# Copyright (C) 2005 Felix Kuehling |
# This file is distributed under the same license as the Mesa package. |
# Felix Kuehling <fxkuehl@gmx.de>, 2005. |
# |
msgid "" |
msgstr "" |
"Project-Id-Version: Mesa 6.3\n" |
"Report-Msgid-Bugs-To: \n" |
"POT-Creation-Date: 2011-08-30 11:40+0200\n" |
"PO-Revision-Date: 2005-04-11 01:34+0200\n" |
"Last-Translator: Felix Kuehling <fxkuehl@gmx.de>\n" |
"Language-Team: German <de@li.org>\n" |
"Language: de\n" |
"MIME-Version: 1.0\n" |
"Content-Type: text/plain; charset=UTF-8\n" |
"Content-Transfer-Encoding: 8bit\n" |
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
#: t_options.h:53 |
msgid "Debugging" |
msgstr "Fehlersuche" |
#: t_options.h:57 |
msgid "Disable 3D acceleration" |
msgstr "3D-Beschleunigung abschalten" |
#: t_options.h:62 |
msgid "Show performance boxes" |
msgstr "Zeige Performanceboxen" |
#: t_options.h:69 |
msgid "Image Quality" |
msgstr "Bildqualität" |
#: t_options.h:82 |
msgid "Texture color depth" |
msgstr "Texturfarbtiefe" |
#: t_options.h:83 |
msgid "Prefer frame buffer color depth" |
msgstr "Bevorzuge Farbtiefe des Framebuffers" |
#: t_options.h:84 |
msgid "Prefer 32 bits per texel" |
msgstr "Bevorzuge 32 bits pro Texel" |
#: t_options.h:85 |
msgid "Prefer 16 bits per texel" |
msgstr "Bevorzuge 16 bits pro Texel" |
#: t_options.h:86 |
msgid "Force 16 bits per texel" |
msgstr "Erzwinge 16 bits pro Texel" |
#: t_options.h:92 |
msgid "Initial maximum value for anisotropic texture filtering" |
msgstr "Initialer Maximalwert für anisotropische Texturfilterung" |
#: t_options.h:97 |
msgid "Forbid negative texture LOD bias" |
msgstr "Verbiete negative Textur-Detailgradverschiebung" |
#: t_options.h:102 |
msgid "" |
"Enable S3TC texture compression even if software support is not available" |
msgstr "" |
"Aktiviere S3TC Texturkomprimierung auch wenn die nötige " |
"Softwareunterstützung fehlt" |
#: t_options.h:109 |
msgid "Initial color reduction method" |
msgstr "Initiale Farbreduktionsmethode" |
#: t_options.h:110 |
msgid "Round colors" |
msgstr "Farben runden" |
#: t_options.h:111 |
msgid "Dither colors" |
msgstr "Farben rastern" |
#: t_options.h:119 |
msgid "Color rounding method" |
msgstr "Farbrundungsmethode" |
#: t_options.h:120 |
msgid "Round color components downward" |
msgstr "Farbkomponenten abrunden" |
#: t_options.h:121 |
msgid "Round to nearest color" |
msgstr "Zur ähnlichsten Farbe runden" |
#: t_options.h:130 |
msgid "Color dithering method" |
msgstr "Farbrasterungsmethode" |
#: t_options.h:131 |
msgid "Horizontal error diffusion" |
msgstr "Horizontale Fehlerstreuung" |
#: t_options.h:132 |
msgid "Horizontal error diffusion, reset error at line start" |
msgstr "Horizontale Fehlerstreuung, Fehler am Zeilenanfang zurücksetzen" |
#: t_options.h:133 |
msgid "Ordered 2D color dithering" |
msgstr "Geordnete 2D Farbrasterung" |
#: t_options.h:139 |
msgid "Floating point depth buffer" |
msgstr "Fließkomma z-Puffer" |
#: t_options.h:145 |
msgid "Performance" |
msgstr "Leistung" |
#: t_options.h:153 |
msgid "TCL mode (Transformation, Clipping, Lighting)" |
msgstr "TCL-Modus (Transformation, Clipping, Licht)" |
#: t_options.h:154 |
msgid "Use software TCL pipeline" |
msgstr "Benutze die Software-TCL-Pipeline" |
#: t_options.h:155 |
msgid "Use hardware TCL as first TCL pipeline stage" |
msgstr "Benutze Hardware TCL als erste Stufe der TCL-Pipeline" |
#: t_options.h:156 |
msgid "Bypass the TCL pipeline" |
msgstr "Umgehe die TCL-Pipeline" |
#: t_options.h:157 |
msgid "" |
"Bypass the TCL pipeline with state-based machine code generated on-the-fly" |
msgstr "" |
"Umgehe die TCL-Pipeline mit zur Laufzeit erzeugtem, zustandsbasiertem " |
"Maschinencode" |
#: t_options.h:166 |
msgid "Method to limit rendering latency" |
msgstr "Methode zur Begrenzung der Bildverzögerung" |
#: t_options.h:167 |
msgid "Busy waiting for the graphics hardware" |
msgstr "Aktives Warten auf die Grafikhardware" |
#: t_options.h:168 |
msgid "Sleep for brief intervals while waiting for the graphics hardware" |
msgstr "Kurze Schlafintervalle beim Warten auf die Grafikhardware" |
#: t_options.h:169 |
msgid "Let the graphics hardware emit a software interrupt and sleep" |
msgstr "" |
"Die Grafikhardware eine Softwareunterbrechnung erzeugen lassen und schlafen" |
#: t_options.h:179 |
msgid "Synchronization with vertical refresh (swap intervals)" |
msgstr "Synchronisation mit der vertikalen Bildwiederholung" |
#: t_options.h:180 |
msgid "Never synchronize with vertical refresh, ignore application's choice" |
msgstr "" |
"Niemals mit der Bildwiederholung synchronisieren, Anweisungen der Anwendung " |
"ignorieren" |
#: t_options.h:181 |
msgid "Initial swap interval 0, obey application's choice" |
msgstr "Initiales Bildinterval 0, Anweisungen der Anwendung gehorchen" |
#: t_options.h:182 |
msgid "Initial swap interval 1, obey application's choice" |
msgstr "Initiales Bildinterval 1, Anweisungen der Anwendung gehorchen" |
#: t_options.h:183 |
msgid "" |
"Always synchronize with vertical refresh, application chooses the minimum " |
"swap interval" |
msgstr "" |
"Immer mit der Bildwiederholung synchronisieren, Anwendung wählt das minimale " |
"Bildintervall" |
#: t_options.h:191 |
msgid "Use HyperZ to boost performance" |
msgstr "HyperZ zur Leistungssteigerung verwenden" |
#: t_options.h:196 |
msgid "A post-processing filter to cel-shade the output" |
msgstr "Nachbearbeitungsfilter für Cell Shading" |
#: t_options.h:201 |
msgid "A post-processing filter to remove the red channel" |
msgstr "Nachbearbeitungsfilter zum Entfernen des Rotkanals" |
#: t_options.h:206 |
msgid "A post-processing filter to remove the green channel" |
msgstr "Nachbearbeitungsfilter zum Entfernen des Grünkanals" |
#: t_options.h:211 |
msgid "A post-processing filter to remove the blue channel" |
msgstr "Nachbearbeitungsfilter zum Entfernen des Blaukanals" |
#: t_options.h:216 |
msgid "" |
"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " |
"default quality" |
msgstr "Morphologische Kantenglättung (Anti-Aliasing) basierend auf " |
"Jimenez' MLAA. 0 für deaktiviert, 8 für Standardqualität" |
#: t_options.h:221 |
msgid "" |
"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " |
"default quality. Color version, usable with 2d GL apps" |
msgstr "Morphologische Kantenglättung (Anti-Aliasing) basierend auf " |
"Jimenez' MLAA. 0 für deaktiviert, 8 für Standardqualität. " |
"Farbversion, für 2D-Anwendungen" |
#: t_options.h:226 |
msgid "Number of texture units used" |
msgstr "Anzahl der benutzten Textureinheiten" |
#: t_options.h:231 |
msgid "Support larger textures not guaranteed to fit into graphics memory" |
msgstr "" |
"Unterstütze grosse Texturen die evtl. nicht in den Grafikspeicher passen" |
#: t_options.h:232 |
msgid "No" |
msgstr "Nein" |
#: t_options.h:233 |
msgid "At least 1 texture must fit under worst-case assumptions" |
msgstr "Mindestens 1 Textur muss auch im schlechtesten Fall Platz haben" |
#: t_options.h:234 |
msgid "Announce hardware limits" |
msgstr "Benutze Hardware-Limits" |
#: t_options.h:240 |
msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" |
msgstr "" |
"Texturfilterqualität versus -geschwindigkeit, auch bekannt als „brilineare“ " |
"Texturfilterung" |
#: t_options.h:248 |
msgid "Used types of texture memory" |
msgstr "Benutzte Arten von Texturspeicher" |
#: t_options.h:249 |
msgid "All available memory" |
msgstr "Aller verfügbarer Speicher" |
#: t_options.h:250 |
msgid "Only card memory (if available)" |
msgstr "Nur Grafikspeicher (falls verfügbar)" |
#: t_options.h:251 |
msgid "Only GART (AGP/PCIE) memory (if available)" |
msgstr "Nur GART-Speicher (AGP/PCIE) (falls verfügbar)" |
#: t_options.h:259 |
msgid "Features that are not hardware-accelerated" |
msgstr "Funktionalität, die nicht hardwarebeschleunigt ist" |
#: t_options.h:263 |
msgid "Enable extension GL_ARB_vertex_program" |
msgstr "Erweiterung GL_ARB_vertex_program aktivieren" |
#: t_options.h:273 |
msgid "Enable flushing batchbuffer after each draw call" |
msgstr "Aktiviere sofortige Leerung des Stapelpuffers nach jedem Zeichenaufruf" |
#: t_options.h:278 |
msgid "Enable flushing GPU caches with each draw call" |
msgstr "Aktiviere sofortige Leerung der GPU-Zwischenspeicher mit jedem Zeichenaufruf" |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlpool/es.po |
---|
0,0 → 1,214 |
# translation of es.po to Spanish |
# Spanish translations for PACKAGE package. |
# Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER |
# This file is distributed under the same license as the PACKAGE package. |
# David <deifo@ono.com>, 2005. |
# David Rubio Miguélez <deifo@ono.com>, 2005. |
# |
msgid "" |
msgstr "" |
"Project-Id-Version: es\n" |
"Report-Msgid-Bugs-To: \n" |
"POT-Creation-Date: 2005-04-12 12:18+0200\n" |
"PO-Revision-Date: 2005-04-12 20:26+0200\n" |
"Last-Translator: David Rubio Miguélez <deifo@ono.com>\n" |
"Language-Team: Spanish <es@li.org>\n" |
"MIME-Version: 1.0\n" |
"Content-Type: text/plain; charset=UTF-8\n" |
"Content-Transfer-Encoding: 8bit\n" |
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
"X-Generator: KBabel 1.10\n" |
#: t_options.h:53 |
msgid "Debugging" |
msgstr "Depurando" |
#: t_options.h:57 |
msgid "Disable 3D acceleration" |
msgstr "Desactivar aceleración 3D" |
#: t_options.h:62 |
msgid "Show performance boxes" |
msgstr "Mostrar cajas de rendimiento" |
#: t_options.h:69 |
msgid "Image Quality" |
msgstr "Calidad de imagen" |
#: t_options.h:77 |
msgid "Texture color depth" |
msgstr "Profundidad de color de textura" |
#: t_options.h:78 |
msgid "Prefer frame buffer color depth" |
msgstr "Preferir profundidad de color del \"framebuffer\"" |
#: t_options.h:79 |
msgid "Prefer 32 bits per texel" |
msgstr "Preferir 32 bits por texel" |
#: t_options.h:80 |
msgid "Prefer 16 bits per texel" |
msgstr "Preferir 16 bits por texel" |
#: t_options.h:81 |
msgid "Force 16 bits per texel" |
msgstr "Forzar a 16 bits por texel" |
#: t_options.h:87 |
msgid "Initial maximum value for anisotropic texture filtering" |
msgstr "Valor máximo inicial para filtrado anisotrópico de textura" |
#: t_options.h:92 |
msgid "Forbid negative texture LOD bias" |
msgstr "Prohibir valores negativos de Nivel De Detalle (LOD) de texturas" |
#: t_options.h:97 |
msgid "Enable S3TC texture compression even if software support is not available" |
msgstr "Activar la compresión de texturas S3TC incluso si el soporte por software no está disponible" |
#: t_options.h:104 |
msgid "Initial color reduction method" |
msgstr "Método inicial de reducción de color" |
#: t_options.h:105 |
msgid "Round colors" |
msgstr "Colores redondeados" |
#: t_options.h:106 |
msgid "Dither colors" |
msgstr "Colores suavizados" |
#: t_options.h:114 |
msgid "Color rounding method" |
msgstr "Método de redondeo de colores" |
#: t_options.h:115 |
msgid "Round color components downward" |
msgstr "Redondear hacia abajo los componentes de color" |
#: t_options.h:116 |
msgid "Round to nearest color" |
msgstr "Redondear al color más cercano" |
#: t_options.h:125 |
msgid "Color dithering method" |
msgstr "Método de suavizado de color" |
#: t_options.h:126 |
msgid "Horizontal error diffusion" |
msgstr "Difusión de error horizontal" |
#: t_options.h:127 |
msgid "Horizontal error diffusion, reset error at line start" |
msgstr "Difusión de error horizontal, reiniciar error al comienzo de línea" |
#: t_options.h:128 |
msgid "Ordered 2D color dithering" |
msgstr "Suavizado de color 2D ordenado" |
#: t_options.h:134 |
msgid "Floating point depth buffer" |
msgstr "Búfer de profundidad en coma flotante" |
#: t_options.h:140 |
msgid "Performance" |
msgstr "Rendimiento" |
#: t_options.h:148 |
msgid "TCL mode (Transformation, Clipping, Lighting)" |
msgstr "Modo TCL (Transformación, Recorte, Iluminación)" |
#: t_options.h:149 |
msgid "Use software TCL pipeline" |
msgstr "Usar tubería TCL por software" |
#: t_options.h:150 |
msgid "Use hardware TCL as first TCL pipeline stage" |
msgstr "Usar TCL por hardware en la primera fase de la tubería TCL" |
#: t_options.h:151 |
msgid "Bypass the TCL pipeline" |
msgstr "Pasar por alto la tubería TCL" |
#: t_options.h:152 |
msgid "Bypass the TCL pipeline with state-based machine code generated on-the-fly" |
msgstr "Pasar por alto la tubería TCL con código máquina basado en estados generado al vuelo" |
#: t_options.h:161 |
msgid "Method to limit rendering latency" |
msgstr "Método para limitar la latencia de rénder" |
#: t_options.h:162 |
msgid "Busy waiting for the graphics hardware" |
msgstr "Esperar activamente al hardware gráfico" |
#: t_options.h:163 |
msgid "Sleep for brief intervals while waiting for the graphics hardware" |
msgstr "Dormir en intervalos cortos mientras se espera al hardware gráfico" |
#: t_options.h:164 |
msgid "Let the graphics hardware emit a software interrupt and sleep" |
msgstr "Permitir que el hardware gráfico emita una interrupción de software y duerma" |
#: t_options.h:174 |
msgid "Synchronization with vertical refresh (swap intervals)" |
msgstr "Sincronización con el refresco vertical (intervalos de intercambio)" |
#: t_options.h:175 |
msgid "Never synchronize with vertical refresh, ignore application's choice" |
msgstr "No sincronizar nunca con el refresco vertical, ignorar la elección de la aplicación" |
#: t_options.h:176 |
msgid "Initial swap interval 0, obey application's choice" |
msgstr "Intervalo de intercambio inicial 0, obedecer la elección de la aplicación" |
#: t_options.h:177 |
msgid "Initial swap interval 1, obey application's choice" |
msgstr "Intervalo de intercambio inicial 1, obedecer la elección de la aplicación" |
#: t_options.h:178 |
msgid "" |
"Always synchronize with vertical refresh, application chooses the minimum " |
"swap interval" |
msgstr "Sincronizar siempre con el refresco vertical, la aplicación elige el intervalo de intercambio mínimo" |
#: t_options.h:186 |
msgid "Use HyperZ to boost performance" |
msgstr "Usar HyperZ para potenciar rendimiento" |
#: t_options.h:191 |
msgid "Number of texture units used" |
msgstr "Número de unidades de textura usadas" |
#: t_options.h:196 |
msgid "Enable hack to allow larger textures with texture compression on radeon/r200" |
msgstr "Activar \"hack\" para permitir texturas más grandes con compresión de textura activada en la Radeon/r200" |
#: t_options.h:201 |
msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" |
msgstr "Calidad de filtrado de textura vs. velocidad, alias filtrado \"brilinear\" de textura" |
#: t_options.h:209 |
msgid "Used types of texture memory" |
msgstr "Tipos de memoria de textura usados" |
#: t_options.h:210 |
msgid "All available memory" |
msgstr "Toda la memoria disponible" |
#: t_options.h:211 |
msgid "Only card memory (if available)" |
msgstr "Sólo la memoria de la tarjeta (si disponible)" |
#: t_options.h:212 |
msgid "Only GART (AGP/PCIE) memory (if available)" |
msgstr "Sólo memoria GART (AGP/PCIE) (si disponible)" |
#: t_options.h:220 |
msgid "Features that are not hardware-accelerated" |
msgstr "Características no aceleradas por hardware" |
#: t_options.h:224 |
msgid "Enable extension GL_ARB_vertex_program" |
msgstr "Activar la extensión GL_ARB_vertex_program" |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlpool/fr.po |
---|
0,0 → 1,221 |
# French translations for DRI driver options. |
# Copyright (C) 2005 Stephane Marchesin |
# This file is distributed under the same license as the Mesa package. |
# Stephane Marchesin <marchesin@icps.u-strasbg.fr>, 2005. |
# |
msgid "" |
msgstr "" |
"Project-Id-Version: Mesa 6.3\n" |
"Report-Msgid-Bugs-To: \n" |
"POT-Creation-Date: 2005-04-11 23:19+0200\n" |
"PO-Revision-Date: 2005-04-11 01:34+0200\n" |
"Last-Translator: Stephane Marchesin <marchesin@icps.u-strasbg.fr>\n" |
"Language-Team: French <fr@li.org>\n" |
"MIME-Version: 1.0\n" |
"Content-Type: text/plain; charset=UTF-8\n" |
"Content-Transfer-Encoding: 8bit\n" |
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
#: t_options.h:53 |
msgid "Debugging" |
msgstr "Debogage" |
#: t_options.h:57 |
msgid "Disable 3D acceleration" |
msgstr "Désactiver l'accélération 3D" |
#: t_options.h:62 |
msgid "Show performance boxes" |
msgstr "Afficher les boîtes de performance" |
#: t_options.h:69 |
msgid "Image Quality" |
msgstr "Qualité d'image" |
#: t_options.h:77 |
msgid "Texture color depth" |
msgstr "Profondeur de texture" |
#: t_options.h:78 |
msgid "Prefer frame buffer color depth" |
msgstr "Profondeur de couleur" |
#: t_options.h:79 |
msgid "Prefer 32 bits per texel" |
msgstr "Préférer 32 bits par texel" |
#: t_options.h:80 |
msgid "Prefer 16 bits per texel" |
msgstr "Prérérer 16 bits par texel" |
#: t_options.h:81 |
msgid "Force 16 bits per texel" |
msgstr "Forcer 16 bits par texel" |
#: t_options.h:87 |
msgid "Initial maximum value for anisotropic texture filtering" |
msgstr "Valeur maximale initiale pour le filtrage anisotropique de texture" |
#: t_options.h:92 |
msgid "Forbid negative texture LOD bias" |
msgstr "Interdire le LOD bias negatif" |
#: t_options.h:97 |
msgid "" |
"Enable S3TC texture compression even if software support is not available" |
msgstr "" |
"Activer la compression de texture S3TC même si le support logiciel est absent" |
#: t_options.h:104 |
msgid "Initial color reduction method" |
msgstr "Technique de réduction de couleurs" |
#: t_options.h:105 |
msgid "Round colors" |
msgstr "Arrondir les valeurs de couleur" |
#: t_options.h:106 |
msgid "Dither colors" |
msgstr "Tramer les couleurs" |
#: t_options.h:114 |
msgid "Color rounding method" |
msgstr "Méthode d'arrondi des couleurs" |
#: t_options.h:115 |
msgid "Round color components downward" |
msgstr "Arrondi à l'inférieur" |
#: t_options.h:116 |
msgid "Round to nearest color" |
msgstr "Arrondi au plus proche" |
#: t_options.h:125 |
msgid "Color dithering method" |
msgstr "Méthode de tramage" |
#: t_options.h:126 |
msgid "Horizontal error diffusion" |
msgstr "Diffusion d'erreur horizontale" |
#: t_options.h:127 |
msgid "Horizontal error diffusion, reset error at line start" |
msgstr "Diffusion d'erreur horizontale, réinitialisé pour chaque ligne" |
#: t_options.h:128 |
msgid "Ordered 2D color dithering" |
msgstr "Tramage ordonné des couleurs" |
#: t_options.h:134 |
msgid "Floating point depth buffer" |
msgstr "Z-buffer en virgule flottante" |
#: t_options.h:140 |
msgid "Performance" |
msgstr "Performance" |
#: t_options.h:148 |
msgid "TCL mode (Transformation, Clipping, Lighting)" |
msgstr "Mode de TCL (Transformation, Clipping, Eclairage)" |
#: t_options.h:149 |
msgid "Use software TCL pipeline" |
msgstr "Utiliser un pipeline TCL logiciel" |
#: t_options.h:150 |
msgid "Use hardware TCL as first TCL pipeline stage" |
msgstr "Utiliser le TCL matériel pour le premier niveau de pipeline" |
#: t_options.h:151 |
msgid "Bypass the TCL pipeline" |
msgstr "Court-circuiter le pipeline TCL" |
#: t_options.h:152 |
msgid "" |
"Bypass the TCL pipeline with state-based machine code generated on-the-fly" |
msgstr "" |
"Court-circuiter le pipeline TCL par une machine à états qui génère le code" |
"de TCL à la volée" |
#: t_options.h:161 |
msgid "Method to limit rendering latency" |
msgstr "Méthode d'attente de la carte graphique" |
#: t_options.h:162 |
msgid "Busy waiting for the graphics hardware" |
msgstr "Attente active de la carte graphique" |
#: t_options.h:163 |
msgid "Sleep for brief intervals while waiting for the graphics hardware" |
msgstr "Attente utilisant usleep()" |
#: t_options.h:164 |
msgid "Let the graphics hardware emit a software interrupt and sleep" |
msgstr "Utiliser les interruptions" |
#: t_options.h:174 |
msgid "Synchronization with vertical refresh (swap intervals)" |
msgstr "Synchronisation de l'affichage avec le balayage vertical" |
#: t_options.h:175 |
msgid "Never synchronize with vertical refresh, ignore application's choice" |
msgstr "Ne jamais synchroniser avec le balayage vertical, ignorer le choix de l'application" |
#: t_options.h:176 |
msgid "Initial swap interval 0, obey application's choice" |
msgstr "Ne pas synchroniser avec le balayage vertical par défaut, mais obéir au choix de l'application" |
#: t_options.h:177 |
msgid "Initial swap interval 1, obey application's choice" |
msgstr "Synchroniser avec le balayage vertical par défaut, mais obéir au choix de l'application" |
#: t_options.h:178 |
msgid "" |
"Always synchronize with vertical refresh, application chooses the minimum " |
"swap interval" |
msgstr "" |
"Toujours synchroniser avec le balayage vertical, l'application choisit l'intervalle minimal" |
#: t_options.h:186 |
msgid "Use HyperZ to boost performance" |
msgstr "Utiliser le HyperZ pour améliorer les performances" |
#: t_options.h:191 |
msgid "Number of texture units used" |
msgstr "Nombre d'unités de texture" |
#: t_options.h:196 |
msgid "" |
"Enable hack to allow larger textures with texture compression on radeon/r200" |
msgstr "" |
"Activer le hack permettant l'utilisation de textures de grande taille avec la " |
"compression de textures sur radeon/r200" |
#: t_options.h:201 |
msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" |
msgstr "" |
"Qualité/performance du filtrage trilinéaire de texture (filtrage brilinéaire)" |
#: t_options.h:209 |
msgid "Used types of texture memory" |
msgstr "Types de mémoire de texture" |
#: t_options.h:210 |
msgid "All available memory" |
msgstr "Utiliser toute la mémoire disponible" |
#: t_options.h:211 |
msgid "Only card memory (if available)" |
msgstr "Utiliser uniquement la mémoire graphique (si disponible)" |
#: t_options.h:212 |
msgid "Only GART (AGP/PCIE) memory (if available)" |
msgstr "Utiliser uniquement la mémoire GART (AGP/PCIE) (si disponible)" |
#: t_options.h:220 |
msgid "Features that are not hardware-accelerated" |
msgstr "Fonctionnalités ne bénéficiant pas d'une accélération matérielle" |
#: t_options.h:224 |
msgid "Enable extension GL_ARB_vertex_program" |
msgstr "Activer l'extension GL_ARB_vertex_program" |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py |
---|
0,0 → 1,204 |
#!/usr/bin/python |
# |
# Usage: |
# gen_xmlpool.py /path/to/t_option.h localedir lang lang lang ... |
# |
# For each given language, this script expects to find a .mo file at |
# `{localedir}/{language}/LC_MESSAGES/options.mo`. |
# |
import sys |
import gettext |
import re |
# Path to t_options.h |
template_header_path = sys.argv[1] |
localedir = sys.argv[2] |
# List of supported languages |
languages = sys.argv[3:] |
# Escape special characters in C strings |
def escapeCString (s): |
escapeSeqs = {'\a' : '\\a', '\b' : '\\b', '\f' : '\\f', '\n' : '\\n', |
'\r' : '\\r', '\t' : '\\t', '\v' : '\\v', '\\' : '\\\\'} |
# " -> '' is a hack. Quotes (") aren't possible in XML attributes. |
# Better use Unicode characters for typographic quotes in option |
# descriptions and translations. |
i = 0 |
r = '' |
while i < len(s): |
# Special case: escape double quote with \u201c or \u201d, depending |
# on whether it's an open or close quote. This is needed because plain |
# double quotes are not possible in XML attributes. |
if s[i] == '"': |
if i == len(s)-1 or s[i+1].isspace(): |
# close quote |
q = u'\u201c' |
else: |
# open quote |
q = u'\u201d' |
r = r + q |
elif escapeSeqs.has_key(s[i]): |
r = r + escapeSeqs[s[i]] |
else: |
r = r + s[i] |
i = i + 1 |
return r |
# Expand escape sequences in C strings (needed for gettext lookup) |
def expandCString (s): |
escapeSeqs = {'a' : '\a', 'b' : '\b', 'f' : '\f', 'n' : '\n', |
'r' : '\r', 't' : '\t', 'v' : '\v', |
'"' : '"', '\\' : '\\'} |
i = 0 |
escape = False |
hexa = False |
octa = False |
num = 0 |
digits = 0 |
r = '' |
while i < len(s): |
if not escape: |
if s[i] == '\\': |
escape = True |
else: |
r = r + s[i] |
elif hexa: |
if (s[i] >= '0' and s[i] <= '9') or \ |
(s[i] >= 'a' and s[i] <= 'f') or \ |
(s[i] >= 'A' and s[i] <= 'F'): |
num = num * 16 + int(s[i],16) |
digits = digits + 1 |
else: |
digits = 2 |
if digits >= 2: |
hexa = False |
escape = False |
r = r + chr(num) |
elif octa: |
if s[i] >= '0' and s[i] <= '7': |
num = num * 8 + int(s[i],8) |
digits = digits + 1 |
else: |
digits = 3 |
if digits >= 3: |
octa = False |
escape = False |
r = r + chr(num) |
else: |
if escapeSeqs.has_key(s[i]): |
r = r + escapeSeqs[s[i]] |
escape = False |
elif s[i] >= '0' and s[i] <= '7': |
octa = True |
num = int(s[i],8) |
if num <= 3: |
digits = 1 |
else: |
digits = 2 |
elif s[i] == 'x' or s[i] == 'X': |
hexa = True |
num = 0 |
digits = 0 |
else: |
r = r + s[i] |
escape = False |
i = i + 1 |
return r |
# Expand matches. The first match is always a DESC or DESC_BEGIN match. |
# Subsequent matches are ENUM matches. |
# |
# DESC, DESC_BEGIN format: \1 \2=<lang> \3 \4=gettext(" \5=<text> \6=") \7 |
# ENUM format: \1 \2=gettext(" \3=<text> \4=") \5 |
def expandMatches (matches, translations, end=None): |
assert len(matches) > 0 |
nTranslations = len(translations) |
i = 0 |
# Expand the description+enums for all translations |
for lang,trans in translations: |
i = i + 1 |
# Make sure that all but the last line of a simple description |
# are extended with a backslash. |
suffix = '' |
if len(matches) == 1 and i < len(translations) and \ |
not matches[0].expand (r'\7').endswith('\\'): |
suffix = ' \\' |
# Expand the description line. Need to use ugettext in order to allow |
# non-ascii unicode chars in the original English descriptions. |
text = escapeCString (trans.ugettext (unicode (expandCString ( |
matches[0].expand (r'\5')), "utf-8"))).encode("utf-8") |
print matches[0].expand (r'\1' + lang + r'\3"' + text + r'"\7') + suffix |
# Expand any subsequent enum lines |
for match in matches[1:]: |
text = escapeCString (trans.ugettext (unicode (expandCString ( |
match.expand (r'\3')), "utf-8"))).encode("utf-8") |
print match.expand (r'\1"' + text + r'"\5') |
# Expand description end |
if end: |
print end, |
# Compile a list of translation classes to all supported languages. |
# The first translation is always a NullTranslations. |
translations = [("en", gettext.NullTranslations())] |
for lang in languages: |
try: |
trans = gettext.translation ("options", localedir, [lang]) |
except IOError: |
sys.stderr.write ("Warning: language '%s' not found.\n" % lang) |
continue |
translations.append ((lang, trans)) |
# Regular expressions: |
reLibintl_h = re.compile (r'#\s*include\s*<libintl.h>') |
reDESC = re.compile (r'(\s*DRI_CONF_DESC\s*\(\s*)([a-z]+)(\s*,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$') |
reDESC_BEGIN = re.compile (r'(\s*DRI_CONF_DESC_BEGIN\s*\(\s*)([a-z]+)(\s*,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$') |
reENUM = re.compile (r'(\s*DRI_CONF_ENUM\s*\([^,]+,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$') |
reDESC_END = re.compile (r'\s*DRI_CONF_DESC_END') |
# Print a header |
print \ |
"/***********************************************************************\n" \ |
" *** THIS FILE IS GENERATED AUTOMATICALLY. DON'T EDIT! ***\n" \ |
" ***********************************************************************/" |
# Process the options template and generate options.h with all |
# translations. |
template = file (template_header_path, "r") |
descMatches = [] |
for line in template: |
if len(descMatches) > 0: |
matchENUM = reENUM .match (line) |
matchDESC_END = reDESC_END.match (line) |
if matchENUM: |
descMatches.append (matchENUM) |
elif matchDESC_END: |
expandMatches (descMatches, translations, line) |
descMatches = [] |
else: |
sys.stderr.write ( |
"Warning: unexpected line inside description dropped:\n%s\n" \ |
% line) |
continue |
if reLibintl_h.search (line): |
# Ignore (comment out) #include <libintl.h> |
print "/* %s * commented out by gen_xmlpool.py */" % line |
continue |
matchDESC = reDESC .match (line) |
matchDESC_BEGIN = reDESC_BEGIN.match (line) |
if matchDESC: |
assert len(descMatches) == 0 |
expandMatches ([matchDESC], translations) |
elif matchDESC_BEGIN: |
assert len(descMatches) == 0 |
descMatches = [matchDESC_BEGIN] |
else: |
print line, |
if len(descMatches) > 0: |
sys.stderr.write ("Warning: unterminated description at end of file.\n") |
expandMatches (descMatches, translations) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlpool/nl.po |
---|
0,0 → 1,226 |
# Dutch translations for PACKAGE package. |
# Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER |
# This file is distributed under the same license as the PACKAGE package. |
# <manfred.stienstra@dwerg.net>, 2005. |
# |
msgid "" |
msgstr "" |
"Project-Id-Version: PACKAGE VERSION\n" |
"Report-Msgid-Bugs-To: \n" |
"POT-Creation-Date: 2005-04-12 20:09+0200\n" |
"PO-Revision-Date: 2005-04-12 20:09+0200\n" |
"Last-Translator: Manfred Stienstra <manfred.stienstra@dwerg.net>\n" |
"Language-Team: Dutch <vertaling@nl.linux.org>\n" |
"MIME-Version: 1.0\n" |
"Content-Type: text/plain; charset=UTF-8\n" |
"Content-Transfer-Encoding: 8bit\n" |
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
#: t_options.h:53 |
msgid "Debugging" |
msgstr "Debuggen" |
#: t_options.h:57 |
msgid "Disable 3D acceleration" |
msgstr "3D versnelling uitschakelen" |
#: t_options.h:62 |
msgid "Show performance boxes" |
msgstr "Laat prestatie boxjes zien" |
#: t_options.h:69 |
msgid "Image Quality" |
msgstr "Beeldkwaliteit" |
#: t_options.h:77 |
msgid "Texture color depth" |
msgstr "Textuurkleurendiepte" |
#: t_options.h:78 |
msgid "Prefer frame buffer color depth" |
msgstr "Prefereer kaderbufferkleurdiepte" |
#: t_options.h:79 |
msgid "Prefer 32 bits per texel" |
msgstr "Prefereer 32 bits per texel" |
#: t_options.h:80 |
msgid "Prefer 16 bits per texel" |
msgstr "Prefereer 16 bits per texel" |
#: t_options.h:81 |
msgid "Force 16 bits per texel" |
msgstr "Dwing 16 bits per texel af" |
#: t_options.h:87 |
msgid "Initial maximum value for anisotropic texture filtering" |
msgstr "Initïele maximum waarde voor anisotrophische textuur filtering" |
#: t_options.h:92 |
msgid "Forbid negative texture LOD bias" |
msgstr "Verbied negatief niveau detailonderscheid (LOD) van texturen" |
#: t_options.h:97 |
msgid "" |
"Enable S3TC texture compression even if software support is not available" |
msgstr "" |
"Schakel S3TC textuurcompressie in, zelfs als softwareondersteuning niet " |
"aanwezig is" |
#: t_options.h:104 |
msgid "Initial color reduction method" |
msgstr "Initïele kleurreductie methode" |
#: t_options.h:105 |
msgid "Round colors" |
msgstr "Rond kleuren af" |
#: t_options.h:106 |
msgid "Dither colors" |
msgstr "Rasteriseer kleuren" |
#: t_options.h:114 |
msgid "Color rounding method" |
msgstr "Kleurafrondingmethode" |
#: t_options.h:115 |
msgid "Round color components downward" |
msgstr "Rond kleurencomponenten af naar beneden" |
#: t_options.h:116 |
msgid "Round to nearest color" |
msgstr "Rond af naar dichtsbijzijnde kleur" |
#: t_options.h:125 |
msgid "Color dithering method" |
msgstr "Kleurrasteriseringsmethode" |
#: t_options.h:126 |
msgid "Horizontal error diffusion" |
msgstr "Horizontale foutdiffusie" |
#: t_options.h:127 |
msgid "Horizontal error diffusion, reset error at line start" |
msgstr "Horizontale foutdiffusie, zet fout bij lijnbegin terug" |
#: t_options.h:128 |
msgid "Ordered 2D color dithering" |
msgstr "Geordende 2D kleurrasterisering" |
#: t_options.h:134 |
msgid "Floating point depth buffer" |
msgstr "Dieptebuffer als commagetal" |
#: t_options.h:140 |
msgid "Performance" |
msgstr "Prestatie" |
#: t_options.h:148 |
msgid "TCL mode (Transformation, Clipping, Lighting)" |
msgstr "TCL-modus (Transformatie, Clipping, Licht)" |
#: t_options.h:149 |
msgid "Use software TCL pipeline" |
msgstr "Gebruik software TCL pijpleiding" |
#: t_options.h:150 |
msgid "Use hardware TCL as first TCL pipeline stage" |
msgstr "Gebruik hardware TCL as eerste TCL pijpleiding trap" |
#: t_options.h:151 |
msgid "Bypass the TCL pipeline" |
msgstr "Omzeil de TCL pijpleiding" |
#: t_options.h:152 |
msgid "" |
"Bypass the TCL pipeline with state-based machine code generated on-the-fly" |
msgstr "" |
"Omzeil de TCL pijpleiding met staatgebaseerde machinecode die tijdens " |
"executie gegenereerd wordt" |
#: t_options.h:161 |
msgid "Method to limit rendering latency" |
msgstr "Methode om beeldopbouwvertraging te onderdrukken" |
#: t_options.h:162 |
msgid "Busy waiting for the graphics hardware" |
msgstr "Actief wachten voor de grafische hardware" |
#: t_options.h:163 |
msgid "Sleep for brief intervals while waiting for the graphics hardware" |
msgstr "Slaap voor korte intervallen tijdens het wachten op de grafische " |
"hardware" |
#: t_options.h:164 |
msgid "Let the graphics hardware emit a software interrupt and sleep" |
msgstr "Laat de grafische hardware een software onderbreking uitzenden en in " |
"slaap vallen" |
#: t_options.h:174 |
msgid "Synchronization with vertical refresh (swap intervals)" |
msgstr "Synchronisatie met verticale verversing (interval omwisselen)" |
#: t_options.h:175 |
msgid "Never synchronize with vertical refresh, ignore application's choice" |
msgstr "Nooit synchroniseren met verticale verversing, negeer de keuze van de " |
"applicatie" |
#: t_options.h:176 |
msgid "Initial swap interval 0, obey application's choice" |
msgstr "Initïeel omwisselingsinterval 0, honoreer de keuze van de applicatie" |
#: t_options.h:177 |
msgid "Initial swap interval 1, obey application's choice" |
msgstr "Initïeel omwisselingsinterval 1, honoreer de keuze van de applicatie" |
#: t_options.h:178 |
msgid "" |
"Always synchronize with vertical refresh, application chooses the minimum " |
"swap interval" |
msgstr "" |
"Synchroniseer altijd met verticale verversing, de applicatie kiest het " |
"minimum omwisselingsinterval" |
#: t_options.h:186 |
msgid "Use HyperZ to boost performance" |
msgstr "Gebruik HyperZ om de prestaties te verbeteren" |
#: t_options.h:191 |
msgid "Number of texture units used" |
msgstr "Aantal textuureenheden in gebruik" |
#: t_options.h:196 |
msgid "" |
"Enable hack to allow larger textures with texture compression on radeon/r200" |
msgstr "" |
"Schakel hack in om met textuurcompressie grotere texturen toe te staan op " |
"een radeon/r200" |
#: t_options.h:201 |
msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" |
msgstr "Textuurfilterkwaliteit versus -snelheid, ookwel bekend als " |
"“brilineaire” textuurfiltering" |
#: t_options.h:209 |
msgid "Used types of texture memory" |
msgstr "Gebruikte soorten textuurgeheugen" |
#: t_options.h:210 |
msgid "All available memory" |
msgstr "Al het beschikbaar geheugen" |
#: t_options.h:211 |
msgid "Only card memory (if available)" |
msgstr "Alleen geheugen op de kaart (als het aanwezig is)" |
#: t_options.h:212 |
msgid "Only GART (AGP/PCIE) memory (if available)" |
msgstr "Alleen GART (AGP/PCIE) geheugen (als het aanwezig is)" |
#: t_options.h:220 |
msgid "Features that are not hardware-accelerated" |
msgstr "Eigenschappen die niet hardwareversneld zijn" |
#: t_options.h:224 |
msgid "Enable extension GL_ARB_vertex_program" |
msgstr "Zet uitbreiding GL_ARB_vertex_program aan" |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlpool/options.h |
---|
0,0 → 1,327 |
/*********************************************************************** |
*** THIS FILE IS GENERATED AUTOMATICALLY. DON'T EDIT! *** |
***********************************************************************/ |
/* |
* XML DRI client-side driver configuration |
* Copyright (C) 2003 Felix Kuehling |
* |
* 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 |
* FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS 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. |
* |
*/ |
/** |
* \file t_options.h |
* \brief Templates of common options |
* \author Felix Kuehling |
* |
* This file defines macros for common options that can be used to |
* construct driConfigOptions in the drivers. This file is only a |
* template containing English descriptions for options wrapped in |
* gettext(). xgettext can be used to extract translatable |
* strings. These strings can then be translated by anyone familiar |
* with GNU gettext. gen_xmlpool.py takes this template and fills in |
* all the translations. The result (options.h) is included by |
* xmlpool.h which in turn can be included by drivers. |
* |
* The macros used to describe otions in this file are defined in |
* ../xmlpool.h. |
*/ |
/* This is needed for xgettext to extract translatable strings. |
* gen_xmlpool.py will discard this line. */ |
/* #include <libintl.h> |
* commented out by gen_xmlpool.py */ |
/* |
* predefined option sections and options with multi-lingual descriptions |
*/ |
/** |
* \brief Debugging options |
*/ |
#define DRI_CONF_SECTION_DEBUG \ |
DRI_CONF_SECTION_BEGIN \ |
DRI_CONF_DESC(en,"Debugging") |
#define DRI_CONF_NO_RAST(def) \ |
DRI_CONF_OPT_BEGIN_B(no_rast, def) \ |
DRI_CONF_DESC(en,"Disable 3D acceleration") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PERFORMANCE_BOXES(def) \ |
DRI_CONF_OPT_BEGIN_B(performance_boxes, def) \ |
DRI_CONF_DESC(en,"Show performance boxes") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_ALWAYS_FLUSH_BATCH(def) \ |
DRI_CONF_OPT_BEGIN_B(always_flush_batch, def) \ |
DRI_CONF_DESC(en,"Enable flushing batchbuffer after each draw call") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_ALWAYS_FLUSH_CACHE(def) \ |
DRI_CONF_OPT_BEGIN_B(always_flush_cache, def) \ |
DRI_CONF_DESC(en,"Enable flushing GPU caches with each draw call") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DISABLE_THROTTLING(def) \ |
DRI_CONF_OPT_BEGIN_B(disable_throttling, def) \ |
DRI_CONF_DESC(en,"Disable throttling on first batch after flush") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN(def) \ |
DRI_CONF_OPT_BEGIN_B(force_glsl_extensions_warn, def) \ |
DRI_CONF_DESC(en,"Force GLSL extension default behavior to 'warn'") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED(def) \ |
DRI_CONF_OPT_BEGIN_B(disable_blend_func_extended, def) \ |
DRI_CONF_DESC(en,"Disable dual source blending") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS(def) \ |
DRI_CONF_OPT_BEGIN_B(disable_glsl_line_continuations, def) \ |
DRI_CONF_DESC(en,"Disable backslash-based line continuations in GLSL source") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DISABLE_SHADER_BIT_ENCODING(def) \ |
DRI_CONF_OPT_BEGIN_B(disable_shader_bit_encoding, def) \ |
DRI_CONF_DESC(en,"Disable GL_ARB_shader_bit_encoding") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_FORCE_GLSL_VERSION(def) \ |
DRI_CONF_OPT_BEGIN_V(force_glsl_version, int, def, "0:999") \ |
DRI_CONF_DESC(en,"Force a default GLSL version for shaders that lack an explicit #version line") \ |
DRI_CONF_OPT_END |
/** |
* \brief Image quality-related options |
*/ |
#define DRI_CONF_SECTION_QUALITY \ |
DRI_CONF_SECTION_BEGIN \ |
DRI_CONF_DESC(en,"Image Quality") |
#define DRI_CONF_EXCESS_MIPMAP(def) \ |
DRI_CONF_OPT_BEGIN_B(excess_mipmap, def) \ |
DRI_CONF_DESC(en,"Enable extra mipmap level") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_TEXTURE_DEPTH_FB 0 |
#define DRI_CONF_TEXTURE_DEPTH_32 1 |
#define DRI_CONF_TEXTURE_DEPTH_16 2 |
#define DRI_CONF_TEXTURE_DEPTH_FORCE_16 3 |
#define DRI_CONF_TEXTURE_DEPTH(def) \ |
DRI_CONF_OPT_BEGIN_V(texture_depth,enum,def,"0:3") \ |
DRI_CONF_DESC_BEGIN(en,"Texture color depth") \ |
DRI_CONF_ENUM(0,"Prefer frame buffer color depth") \ |
DRI_CONF_ENUM(1,"Prefer 32 bits per texel") \ |
DRI_CONF_ENUM(2,"Prefer 16 bits per texel") \ |
DRI_CONF_ENUM(3,"Force 16 bits per texel") \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DEF_MAX_ANISOTROPY(def,range) \ |
DRI_CONF_OPT_BEGIN_V(def_max_anisotropy,float,def,range) \ |
DRI_CONF_DESC(en,"Initial maximum value for anisotropic texture filtering") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_NO_NEG_LOD_BIAS(def) \ |
DRI_CONF_OPT_BEGIN_B(no_neg_lod_bias, def) \ |
DRI_CONF_DESC(en,"Forbid negative texture LOD bias") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_FORCE_S3TC_ENABLE(def) \ |
DRI_CONF_OPT_BEGIN_B(force_s3tc_enable, def) \ |
DRI_CONF_DESC(en,"Enable S3TC texture compression even if software support is not available") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_COLOR_REDUCTION_ROUND 0 |
#define DRI_CONF_COLOR_REDUCTION_DITHER 1 |
#define DRI_CONF_COLOR_REDUCTION(def) \ |
DRI_CONF_OPT_BEGIN_V(color_reduction,enum,def,"0:1") \ |
DRI_CONF_DESC_BEGIN(en,"Initial color reduction method") \ |
DRI_CONF_ENUM(0,"Round colors") \ |
DRI_CONF_ENUM(1,"Dither colors") \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_ROUND_TRUNC 0 |
#define DRI_CONF_ROUND_ROUND 1 |
#define DRI_CONF_ROUND_MODE(def) \ |
DRI_CONF_OPT_BEGIN_V(round_mode,enum,def,"0:1") \ |
DRI_CONF_DESC_BEGIN(en,"Color rounding method") \ |
DRI_CONF_ENUM(0,"Round color components downward") \ |
DRI_CONF_ENUM(1,"Round to nearest color") \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DITHER_XERRORDIFF 0 |
#define DRI_CONF_DITHER_XERRORDIFFRESET 1 |
#define DRI_CONF_DITHER_ORDERED 2 |
#define DRI_CONF_DITHER_MODE(def) \ |
DRI_CONF_OPT_BEGIN_V(dither_mode,enum,def,"0:2") \ |
DRI_CONF_DESC_BEGIN(en,"Color dithering method") \ |
DRI_CONF_ENUM(0,"Horizontal error diffusion") \ |
DRI_CONF_ENUM(1,"Horizontal error diffusion, reset error at line start") \ |
DRI_CONF_ENUM(2,"Ordered 2D color dithering") \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_FLOAT_DEPTH(def) \ |
DRI_CONF_OPT_BEGIN_B(float_depth, def) \ |
DRI_CONF_DESC(en,"Floating point depth buffer") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_CELSHADE(def) \ |
DRI_CONF_OPT_BEGIN_V(pp_celshade,enum,def,"0:1") \ |
DRI_CONF_DESC(en,"A post-processing filter to cel-shade the output") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_NORED(def) \ |
DRI_CONF_OPT_BEGIN_V(pp_nored,enum,def,"0:1") \ |
DRI_CONF_DESC(en,"A post-processing filter to remove the red channel") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_NOGREEN(def) \ |
DRI_CONF_OPT_BEGIN_V(pp_nogreen,enum,def,"0:1") \ |
DRI_CONF_DESC(en,"A post-processing filter to remove the green channel") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_NOBLUE(def) \ |
DRI_CONF_OPT_BEGIN_V(pp_noblue,enum,def,"0:1") \ |
DRI_CONF_DESC(en,"A post-processing filter to remove the blue channel") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_JIMENEZMLAA(def,min,max) \ |
DRI_CONF_OPT_BEGIN_V(pp_jimenezmlaa,int,def, # min ":" # max ) \ |
DRI_CONF_DESC(en,"Morphological anti-aliasing based on Jimenez\' MLAA. 0 to disable, 8 for default quality") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_JIMENEZMLAA_COLOR(def,min,max) \ |
DRI_CONF_OPT_BEGIN_V(pp_jimenezmlaa_color,int,def, # min ":" # max ) \ |
DRI_CONF_DESC(en,"Morphological anti-aliasing based on Jimenez\' MLAA. 0 to disable, 8 for default quality. Color version, usable with 2d GL apps") \ |
DRI_CONF_OPT_END |
/** |
* \brief Performance-related options |
*/ |
#define DRI_CONF_SECTION_PERFORMANCE \ |
DRI_CONF_SECTION_BEGIN \ |
DRI_CONF_DESC(en,"Performance") |
#define DRI_CONF_TCL_SW 0 |
#define DRI_CONF_TCL_PIPELINED 1 |
#define DRI_CONF_TCL_VTXFMT 2 |
#define DRI_CONF_TCL_CODEGEN 3 |
#define DRI_CONF_TCL_MODE(def) \ |
DRI_CONF_OPT_BEGIN_V(tcl_mode,enum,def,"0:3") \ |
DRI_CONF_DESC_BEGIN(en,"TCL mode (Transformation, Clipping, Lighting)") \ |
DRI_CONF_ENUM(0,"Use software TCL pipeline") \ |
DRI_CONF_ENUM(1,"Use hardware TCL as first TCL pipeline stage") \ |
DRI_CONF_ENUM(2,"Bypass the TCL pipeline") \ |
DRI_CONF_ENUM(3,"Bypass the TCL pipeline with state-based machine code generated on-the-fly") \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_FTHROTTLE_BUSY 0 |
#define DRI_CONF_FTHROTTLE_USLEEPS 1 |
#define DRI_CONF_FTHROTTLE_IRQS 2 |
#define DRI_CONF_FTHROTTLE_MODE(def) \ |
DRI_CONF_OPT_BEGIN_V(fthrottle_mode,enum,def,"0:2") \ |
DRI_CONF_DESC_BEGIN(en,"Method to limit rendering latency") \ |
DRI_CONF_ENUM(0,"Busy waiting for the graphics hardware") \ |
DRI_CONF_ENUM(1,"Sleep for brief intervals while waiting for the graphics hardware") \ |
DRI_CONF_ENUM(2,"Let the graphics hardware emit a software interrupt and sleep") \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_VBLANK_NEVER 0 |
#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1 |
#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2 |
#define DRI_CONF_VBLANK_ALWAYS_SYNC 3 |
#define DRI_CONF_VBLANK_MODE(def) \ |
DRI_CONF_OPT_BEGIN_V(vblank_mode,enum,def,"0:3") \ |
DRI_CONF_DESC_BEGIN(en,"Synchronization with vertical refresh (swap intervals)") \ |
DRI_CONF_ENUM(0,"Never synchronize with vertical refresh, ignore application's choice") \ |
DRI_CONF_ENUM(1,"Initial swap interval 0, obey application's choice") \ |
DRI_CONF_ENUM(2,"Initial swap interval 1, obey application's choice") \ |
DRI_CONF_ENUM(3,"Always synchronize with vertical refresh, application chooses the minimum swap interval") \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_HYPERZ_DISABLED 0 |
#define DRI_CONF_HYPERZ_ENABLED 1 |
#define DRI_CONF_HYPERZ(def) \ |
DRI_CONF_OPT_BEGIN_B(hyperz, def) \ |
DRI_CONF_DESC(en,"Use HyperZ to boost performance") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_MAX_TEXTURE_UNITS(def,min,max) \ |
DRI_CONF_OPT_BEGIN_V(texture_units,int,def, # min ":" # max ) \ |
DRI_CONF_DESC(en,"Number of texture units used") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_TEXTURE_BLEND_QUALITY(def,range) \ |
DRI_CONF_OPT_BEGIN_V(texture_blend_quality,float,def,range) \ |
DRI_CONF_DESC(en,"Texture filtering quality vs. speed, AKA “brilinear” texture filtering") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_TEXTURE_HEAPS_ALL 0 |
#define DRI_CONF_TEXTURE_HEAPS_CARD 1 |
#define DRI_CONF_TEXTURE_HEAPS_GART 2 |
#define DRI_CONF_TEXTURE_HEAPS(def) \ |
DRI_CONF_OPT_BEGIN_V(texture_heaps,enum,def,"0:2") \ |
DRI_CONF_DESC_BEGIN(en,"Used types of texture memory") \ |
DRI_CONF_ENUM(0,"All available memory") \ |
DRI_CONF_ENUM(1,"Only card memory (if available)") \ |
DRI_CONF_ENUM(2,"Only GART (AGP/PCIE) memory (if available)") \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
/** |
* \brief Software-fallback options. To allow using features (like |
* GL_ARB_vertex_program) on GPUs that don't otherwise support the feature. |
*/ |
#define DRI_CONF_SECTION_SOFTWARE \ |
DRI_CONF_SECTION_BEGIN \ |
DRI_CONF_DESC(en,"Features that are not hardware-accelerated") |
#define DRI_CONF_ARB_VERTEX_PROGRAM(def) \ |
DRI_CONF_OPT_BEGIN_B(arb_vertex_program, def) \ |
DRI_CONF_DESC(en,"Enable extension GL_ARB_vertex_program") \ |
DRI_CONF_OPT_END |
/** |
* \brief Miscellaneous configuration options |
*/ |
#define DRI_CONF_SECTION_MISCELLANEOUS \ |
DRI_CONF_SECTION_BEGIN \ |
DRI_CONF_DESC(en,"Miscellaneous") |
#define DRI_CONF_ALWAYS_HAVE_DEPTH_BUFFER(def) \ |
DRI_CONF_OPT_BEGIN_B(always_have_depth_buffer, def) \ |
DRI_CONF_DESC(en,"Create all visuals with a depth buffer") \ |
DRI_CONF_OPT_END |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlpool/sv.po |
---|
0,0 → 1,221 |
# Swedish translation of DRI driver options. |
# Copyright (C) Free Software Foundation, Inc. |
# This file is distributed under the same license as the Mesa package. |
# Daniel Nylander <po@danielnylander.se>, 2006. |
# |
msgid "" |
msgstr "" |
"Project-Id-Version: Mesa DRI\n" |
"Report-Msgid-Bugs-To: \n" |
"POT-Creation-Date: 2005-04-11 23:19+0200\n" |
"PO-Revision-Date: 2006-09-18 10:56+0100\n" |
"Last-Translator: Daniel Nylander <po@danielnylander.se>\n" |
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" |
"MIME-Version: 1.0\n" |
"Content-Type: text/plain; charset=UTF-8\n" |
"Content-Transfer-Encoding: 8bit\n" |
"Plural-Forms: nplurals=2; plural=(n != 1);\n" |
#: t_options.h:53 |
msgid "Debugging" |
msgstr "Felsökning" |
#: t_options.h:57 |
msgid "Disable 3D acceleration" |
msgstr "Inaktivera 3D-accelerering" |
#: t_options.h:62 |
msgid "Show performance boxes" |
msgstr "Visa prestandarutor" |
#: t_options.h:69 |
msgid "Image Quality" |
msgstr "Bildkvalitet" |
#: t_options.h:77 |
msgid "Texture color depth" |
msgstr "Färgdjup för texturer" |
#: t_options.h:78 |
msgid "Prefer frame buffer color depth" |
msgstr "Föredra färgdjupet för framebuffer" |
#: t_options.h:79 |
msgid "Prefer 32 bits per texel" |
msgstr "Föredra 32 bitar per texel" |
#: t_options.h:80 |
msgid "Prefer 16 bits per texel" |
msgstr "Föredra 16 bitar per texel" |
#: t_options.h:81 |
msgid "Force 16 bits per texel" |
msgstr "Tvinga 16 bitar per texel" |
#: t_options.h:87 |
msgid "Initial maximum value for anisotropic texture filtering" |
msgstr "Initialt maximalt värde för anisotropisk texturfiltrering" |
#: t_options.h:92 |
msgid "Forbid negative texture LOD bias" |
msgstr "Förbjud negativ LOD-kompensation för texturer" |
#: t_options.h:97 |
msgid "Enable S3TC texture compression even if software support is not available" |
msgstr "Aktivera S3TC-texturkomprimering även om programvarustöd saknas" |
#: t_options.h:104 |
msgid "Initial color reduction method" |
msgstr "Initial färgminskningsmetod" |
#: t_options.h:105 |
msgid "Round colors" |
msgstr "Avrunda färger" |
#: t_options.h:106 |
msgid "Dither colors" |
msgstr "Utjämna färger" |
#: t_options.h:114 |
msgid "Color rounding method" |
msgstr "Färgavrundningsmetod" |
#: t_options.h:115 |
msgid "Round color components downward" |
msgstr "Avrunda färdkomponenter nedåt" |
#: t_options.h:116 |
msgid "Round to nearest color" |
msgstr "Avrunda till närmsta färg" |
#: t_options.h:125 |
msgid "Color dithering method" |
msgstr "Färgutjämningsmetod" |
#: t_options.h:126 |
msgid "Horizontal error diffusion" |
msgstr "Horisontell felspridning" |
#: t_options.h:127 |
msgid "Horizontal error diffusion, reset error at line start" |
msgstr "Horisontell felspridning, återställ fel vid radbörjan" |
#: t_options.h:128 |
msgid "Ordered 2D color dithering" |
msgstr "Ordnad 2D-färgutjämning" |
#: t_options.h:134 |
msgid "Floating point depth buffer" |
msgstr "Buffert för flytande punktdjup" |
#: t_options.h:140 |
msgid "Performance" |
msgstr "Prestanda" |
#: t_options.h:148 |
msgid "TCL mode (Transformation, Clipping, Lighting)" |
msgstr "TCL-läge (Transformation, Clipping, Lighting)" |
#: t_options.h:149 |
msgid "Use software TCL pipeline" |
msgstr "Använd programvaru-TCL-rörledning" |
#: t_options.h:150 |
msgid "Use hardware TCL as first TCL pipeline stage" |
msgstr "Använd maskinvaru-TCL som första TCL-rörledningssteg" |
#: t_options.h:151 |
msgid "Bypass the TCL pipeline" |
msgstr "Kringgå TCL-rörledningen" |
#: t_options.h:152 |
msgid "Bypass the TCL pipeline with state-based machine code generated on-the-fly" |
msgstr "Kringgå TCL-rörledningen med tillståndsbaserad maskinkod som direktgenereras" |
#: t_options.h:161 |
msgid "Method to limit rendering latency" |
msgstr "Metod för att begränsa renderingslatens" |
#: t_options.h:162 |
msgid "Busy waiting for the graphics hardware" |
msgstr "Upptagen med att vänta på grafikhårdvaran" |
#: t_options.h:163 |
msgid "Sleep for brief intervals while waiting for the graphics hardware" |
msgstr "Sov i korta intervall under väntan på grafikhårdvaran" |
#: t_options.h:164 |
msgid "Let the graphics hardware emit a software interrupt and sleep" |
msgstr "Låt grafikhårdvaran sända ut ett programvaruavbrott och sov" |
#: t_options.h:174 |
msgid "Synchronization with vertical refresh (swap intervals)" |
msgstr "Synkronisering med vertikal uppdatering (växlingsintervall)" |
#: t_options.h:175 |
msgid "Never synchronize with vertical refresh, ignore application's choice" |
msgstr "Synkronisera aldrig med vertikal uppdatering, ignorera programmets val" |
#: t_options.h:176 |
msgid "Initial swap interval 0, obey application's choice" |
msgstr "Initialt växlingsintervall 0, följ programmets val" |
#: t_options.h:177 |
msgid "Initial swap interval 1, obey application's choice" |
msgstr "Initialt växlingsintervall 1, följ programmets val" |
#: t_options.h:178 |
msgid "Always synchronize with vertical refresh, application chooses the minimum swap interval" |
msgstr "Synkronisera alltid med vertikal uppdatering, programmet väljer den minsta växlingsintervallen" |
#: t_options.h:186 |
msgid "Use HyperZ to boost performance" |
msgstr "Använd HyperZ för att maximera prestandan" |
#: t_options.h:191 |
msgid "Number of texture units used" |
msgstr "Antal använda texturenheter" |
#: t_options.h:196 |
msgid "Support larger textures not guaranteed to fit into graphics memory" |
msgstr "Stöd för större texturer är inte garanterat att passa i grafikminnet" |
#: t_options.h:197 |
msgid "No" |
msgstr "Nej" |
#: t_options.h:198 |
msgid "At least 1 texture must fit under worst-case assumptions" |
msgstr "Åtminstone en textur måste passa för antaget sämsta förhållande" |
#: t_options.h:199 |
msgid "Announce hardware limits" |
msgstr "Annonsera hårdvarubegränsningar" |
#: t_options.h:205 |
msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" |
msgstr "Texturfiltreringskvalitet mot hastighet, även kallad \"brilinear\"-texturfiltrering" |
#: t_options.h:213 |
msgid "Used types of texture memory" |
msgstr "Använda typer av texturminne" |
#: t_options.h:214 |
msgid "All available memory" |
msgstr "Allt tillgängligt minne" |
#: t_options.h:215 |
msgid "Only card memory (if available)" |
msgstr "Endast kortminne (om tillgängligt)" |
#: t_options.h:216 |
msgid "Only GART (AGP/PCIE) memory (if available)" |
msgstr "Endast GART-minne (AGP/PCIE) (om tillgängligt)" |
#: t_options.h:224 |
msgid "Features that are not hardware-accelerated" |
msgstr "Funktioner som inte är hårdvaruaccelererade" |
#: t_options.h:228 |
msgid "Enable extension GL_ARB_vertex_program" |
msgstr "Aktivera tillägget GL_ARB_vertex_program" |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlpool/t_options.h |
---|
0,0 → 1,323 |
/* |
* XML DRI client-side driver configuration |
* Copyright (C) 2003 Felix Kuehling |
* |
* 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 |
* FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS 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. |
* |
*/ |
/** |
* \file t_options.h |
* \brief Templates of common options |
* \author Felix Kuehling |
* |
* This file defines macros for common options that can be used to |
* construct driConfigOptions in the drivers. This file is only a |
* template containing English descriptions for options wrapped in |
* gettext(). xgettext can be used to extract translatable |
* strings. These strings can then be translated by anyone familiar |
* with GNU gettext. gen_xmlpool.py takes this template and fills in |
* all the translations. The result (options.h) is included by |
* xmlpool.h which in turn can be included by drivers. |
* |
* The macros used to describe otions in this file are defined in |
* ../xmlpool.h. |
*/ |
/* This is needed for xgettext to extract translatable strings. |
* gen_xmlpool.py will discard this line. */ |
#include <libintl.h> |
/* |
* predefined option sections and options with multi-lingual descriptions |
*/ |
/** |
* \brief Debugging options |
*/ |
#define DRI_CONF_SECTION_DEBUG \ |
DRI_CONF_SECTION_BEGIN \ |
DRI_CONF_DESC(en,gettext("Debugging")) |
#define DRI_CONF_NO_RAST(def) \ |
DRI_CONF_OPT_BEGIN_B(no_rast, def) \ |
DRI_CONF_DESC(en,gettext("Disable 3D acceleration")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PERFORMANCE_BOXES(def) \ |
DRI_CONF_OPT_BEGIN_B(performance_boxes, def) \ |
DRI_CONF_DESC(en,gettext("Show performance boxes")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_ALWAYS_FLUSH_BATCH(def) \ |
DRI_CONF_OPT_BEGIN_B(always_flush_batch, def) \ |
DRI_CONF_DESC(en,gettext("Enable flushing batchbuffer after each draw call")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_ALWAYS_FLUSH_CACHE(def) \ |
DRI_CONF_OPT_BEGIN_B(always_flush_cache, def) \ |
DRI_CONF_DESC(en,gettext("Enable flushing GPU caches with each draw call")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DISABLE_THROTTLING(def) \ |
DRI_CONF_OPT_BEGIN_B(disable_throttling, def) \ |
DRI_CONF_DESC(en,gettext("Disable throttling on first batch after flush")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN(def) \ |
DRI_CONF_OPT_BEGIN_B(force_glsl_extensions_warn, def) \ |
DRI_CONF_DESC(en,gettext("Force GLSL extension default behavior to 'warn'")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED(def) \ |
DRI_CONF_OPT_BEGIN_B(disable_blend_func_extended, def) \ |
DRI_CONF_DESC(en,gettext("Disable dual source blending")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS(def) \ |
DRI_CONF_OPT_BEGIN_B(disable_glsl_line_continuations, def) \ |
DRI_CONF_DESC(en,gettext("Disable backslash-based line continuations in GLSL source")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DISABLE_SHADER_BIT_ENCODING(def) \ |
DRI_CONF_OPT_BEGIN_B(disable_shader_bit_encoding, def) \ |
DRI_CONF_DESC(en,gettext("Disable GL_ARB_shader_bit_encoding")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_FORCE_GLSL_VERSION(def) \ |
DRI_CONF_OPT_BEGIN_V(force_glsl_version, int, def, "0:999") \ |
DRI_CONF_DESC(en,gettext("Force a default GLSL version for shaders that lack an explicit #version line")) \ |
DRI_CONF_OPT_END |
/** |
* \brief Image quality-related options |
*/ |
#define DRI_CONF_SECTION_QUALITY \ |
DRI_CONF_SECTION_BEGIN \ |
DRI_CONF_DESC(en,gettext("Image Quality")) |
#define DRI_CONF_EXCESS_MIPMAP(def) \ |
DRI_CONF_OPT_BEGIN_B(excess_mipmap, def) \ |
DRI_CONF_DESC(en,"Enable extra mipmap level") \ |
DRI_CONF_OPT_END |
#define DRI_CONF_TEXTURE_DEPTH_FB 0 |
#define DRI_CONF_TEXTURE_DEPTH_32 1 |
#define DRI_CONF_TEXTURE_DEPTH_16 2 |
#define DRI_CONF_TEXTURE_DEPTH_FORCE_16 3 |
#define DRI_CONF_TEXTURE_DEPTH(def) \ |
DRI_CONF_OPT_BEGIN_V(texture_depth,enum,def,"0:3") \ |
DRI_CONF_DESC_BEGIN(en,gettext("Texture color depth")) \ |
DRI_CONF_ENUM(0,gettext("Prefer frame buffer color depth")) \ |
DRI_CONF_ENUM(1,gettext("Prefer 32 bits per texel")) \ |
DRI_CONF_ENUM(2,gettext("Prefer 16 bits per texel")) \ |
DRI_CONF_ENUM(3,gettext("Force 16 bits per texel")) \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DEF_MAX_ANISOTROPY(def,range) \ |
DRI_CONF_OPT_BEGIN_V(def_max_anisotropy,float,def,range) \ |
DRI_CONF_DESC(en,gettext("Initial maximum value for anisotropic texture filtering")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_NO_NEG_LOD_BIAS(def) \ |
DRI_CONF_OPT_BEGIN_B(no_neg_lod_bias, def) \ |
DRI_CONF_DESC(en,gettext("Forbid negative texture LOD bias")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_FORCE_S3TC_ENABLE(def) \ |
DRI_CONF_OPT_BEGIN_B(force_s3tc_enable, def) \ |
DRI_CONF_DESC(en,gettext("Enable S3TC texture compression even if software support is not available")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_COLOR_REDUCTION_ROUND 0 |
#define DRI_CONF_COLOR_REDUCTION_DITHER 1 |
#define DRI_CONF_COLOR_REDUCTION(def) \ |
DRI_CONF_OPT_BEGIN_V(color_reduction,enum,def,"0:1") \ |
DRI_CONF_DESC_BEGIN(en,gettext("Initial color reduction method")) \ |
DRI_CONF_ENUM(0,gettext("Round colors")) \ |
DRI_CONF_ENUM(1,gettext("Dither colors")) \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_ROUND_TRUNC 0 |
#define DRI_CONF_ROUND_ROUND 1 |
#define DRI_CONF_ROUND_MODE(def) \ |
DRI_CONF_OPT_BEGIN_V(round_mode,enum,def,"0:1") \ |
DRI_CONF_DESC_BEGIN(en,gettext("Color rounding method")) \ |
DRI_CONF_ENUM(0,gettext("Round color components downward")) \ |
DRI_CONF_ENUM(1,gettext("Round to nearest color")) \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_DITHER_XERRORDIFF 0 |
#define DRI_CONF_DITHER_XERRORDIFFRESET 1 |
#define DRI_CONF_DITHER_ORDERED 2 |
#define DRI_CONF_DITHER_MODE(def) \ |
DRI_CONF_OPT_BEGIN_V(dither_mode,enum,def,"0:2") \ |
DRI_CONF_DESC_BEGIN(en,gettext("Color dithering method")) \ |
DRI_CONF_ENUM(0,gettext("Horizontal error diffusion")) \ |
DRI_CONF_ENUM(1,gettext("Horizontal error diffusion, reset error at line start")) \ |
DRI_CONF_ENUM(2,gettext("Ordered 2D color dithering")) \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_FLOAT_DEPTH(def) \ |
DRI_CONF_OPT_BEGIN_B(float_depth, def) \ |
DRI_CONF_DESC(en,gettext("Floating point depth buffer")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_CELSHADE(def) \ |
DRI_CONF_OPT_BEGIN_V(pp_celshade,enum,def,"0:1") \ |
DRI_CONF_DESC(en,gettext("A post-processing filter to cel-shade the output")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_NORED(def) \ |
DRI_CONF_OPT_BEGIN_V(pp_nored,enum,def,"0:1") \ |
DRI_CONF_DESC(en,gettext("A post-processing filter to remove the red channel")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_NOGREEN(def) \ |
DRI_CONF_OPT_BEGIN_V(pp_nogreen,enum,def,"0:1") \ |
DRI_CONF_DESC(en,gettext("A post-processing filter to remove the green channel")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_NOBLUE(def) \ |
DRI_CONF_OPT_BEGIN_V(pp_noblue,enum,def,"0:1") \ |
DRI_CONF_DESC(en,gettext("A post-processing filter to remove the blue channel")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_JIMENEZMLAA(def,min,max) \ |
DRI_CONF_OPT_BEGIN_V(pp_jimenezmlaa,int,def, # min ":" # max ) \ |
DRI_CONF_DESC(en,gettext("Morphological anti-aliasing based on Jimenez\\\' MLAA. 0 to disable, 8 for default quality")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_PP_JIMENEZMLAA_COLOR(def,min,max) \ |
DRI_CONF_OPT_BEGIN_V(pp_jimenezmlaa_color,int,def, # min ":" # max ) \ |
DRI_CONF_DESC(en,gettext("Morphological anti-aliasing based on Jimenez\\\' MLAA. 0 to disable, 8 for default quality. Color version, usable with 2d GL apps")) \ |
DRI_CONF_OPT_END |
/** |
* \brief Performance-related options |
*/ |
#define DRI_CONF_SECTION_PERFORMANCE \ |
DRI_CONF_SECTION_BEGIN \ |
DRI_CONF_DESC(en,gettext("Performance")) |
#define DRI_CONF_TCL_SW 0 |
#define DRI_CONF_TCL_PIPELINED 1 |
#define DRI_CONF_TCL_VTXFMT 2 |
#define DRI_CONF_TCL_CODEGEN 3 |
#define DRI_CONF_TCL_MODE(def) \ |
DRI_CONF_OPT_BEGIN_V(tcl_mode,enum,def,"0:3") \ |
DRI_CONF_DESC_BEGIN(en,gettext("TCL mode (Transformation, Clipping, Lighting)")) \ |
DRI_CONF_ENUM(0,gettext("Use software TCL pipeline")) \ |
DRI_CONF_ENUM(1,gettext("Use hardware TCL as first TCL pipeline stage")) \ |
DRI_CONF_ENUM(2,gettext("Bypass the TCL pipeline")) \ |
DRI_CONF_ENUM(3,gettext("Bypass the TCL pipeline with state-based machine code generated on-the-fly")) \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_FTHROTTLE_BUSY 0 |
#define DRI_CONF_FTHROTTLE_USLEEPS 1 |
#define DRI_CONF_FTHROTTLE_IRQS 2 |
#define DRI_CONF_FTHROTTLE_MODE(def) \ |
DRI_CONF_OPT_BEGIN_V(fthrottle_mode,enum,def,"0:2") \ |
DRI_CONF_DESC_BEGIN(en,gettext("Method to limit rendering latency")) \ |
DRI_CONF_ENUM(0,gettext("Busy waiting for the graphics hardware")) \ |
DRI_CONF_ENUM(1,gettext("Sleep for brief intervals while waiting for the graphics hardware")) \ |
DRI_CONF_ENUM(2,gettext("Let the graphics hardware emit a software interrupt and sleep")) \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_VBLANK_NEVER 0 |
#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1 |
#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2 |
#define DRI_CONF_VBLANK_ALWAYS_SYNC 3 |
#define DRI_CONF_VBLANK_MODE(def) \ |
DRI_CONF_OPT_BEGIN_V(vblank_mode,enum,def,"0:3") \ |
DRI_CONF_DESC_BEGIN(en,gettext("Synchronization with vertical refresh (swap intervals)")) \ |
DRI_CONF_ENUM(0,gettext("Never synchronize with vertical refresh, ignore application's choice")) \ |
DRI_CONF_ENUM(1,gettext("Initial swap interval 0, obey application's choice")) \ |
DRI_CONF_ENUM(2,gettext("Initial swap interval 1, obey application's choice")) \ |
DRI_CONF_ENUM(3,gettext("Always synchronize with vertical refresh, application chooses the minimum swap interval")) \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
#define DRI_CONF_HYPERZ_DISABLED 0 |
#define DRI_CONF_HYPERZ_ENABLED 1 |
#define DRI_CONF_HYPERZ(def) \ |
DRI_CONF_OPT_BEGIN_B(hyperz, def) \ |
DRI_CONF_DESC(en,gettext("Use HyperZ to boost performance")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_MAX_TEXTURE_UNITS(def,min,max) \ |
DRI_CONF_OPT_BEGIN_V(texture_units,int,def, # min ":" # max ) \ |
DRI_CONF_DESC(en,gettext("Number of texture units used")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_TEXTURE_BLEND_QUALITY(def,range) \ |
DRI_CONF_OPT_BEGIN_V(texture_blend_quality,float,def,range) \ |
DRI_CONF_DESC(en,gettext("Texture filtering quality vs. speed, AKA “brilinear” texture filtering")) \ |
DRI_CONF_OPT_END |
#define DRI_CONF_TEXTURE_HEAPS_ALL 0 |
#define DRI_CONF_TEXTURE_HEAPS_CARD 1 |
#define DRI_CONF_TEXTURE_HEAPS_GART 2 |
#define DRI_CONF_TEXTURE_HEAPS(def) \ |
DRI_CONF_OPT_BEGIN_V(texture_heaps,enum,def,"0:2") \ |
DRI_CONF_DESC_BEGIN(en,gettext("Used types of texture memory")) \ |
DRI_CONF_ENUM(0,gettext("All available memory")) \ |
DRI_CONF_ENUM(1,gettext("Only card memory (if available)")) \ |
DRI_CONF_ENUM(2,gettext("Only GART (AGP/PCIE) memory (if available)")) \ |
DRI_CONF_DESC_END \ |
DRI_CONF_OPT_END |
/** |
* \brief Software-fallback options. To allow using features (like |
* GL_ARB_vertex_program) on GPUs that don't otherwise support the feature. |
*/ |
#define DRI_CONF_SECTION_SOFTWARE \ |
DRI_CONF_SECTION_BEGIN \ |
DRI_CONF_DESC(en,gettext("Features that are not hardware-accelerated")) |
#define DRI_CONF_ARB_VERTEX_PROGRAM(def) \ |
DRI_CONF_OPT_BEGIN_B(arb_vertex_program, def) \ |
DRI_CONF_DESC(en,gettext("Enable extension GL_ARB_vertex_program")) \ |
DRI_CONF_OPT_END |
/** |
* \brief Miscellaneous configuration options |
*/ |
#define DRI_CONF_SECTION_MISCELLANEOUS \ |
DRI_CONF_SECTION_BEGIN \ |
DRI_CONF_DESC(en,gettext("Miscellaneous")) |
#define DRI_CONF_ALWAYS_HAVE_DEPTH_BUFFER(def) \ |
DRI_CONF_OPT_BEGIN_B(always_have_depth_buffer, def) \ |
DRI_CONF_DESC(en,gettext("Create all visuals with a depth buffer")) \ |
DRI_CONF_OPT_END |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/common/xmlpool.h |
---|
0,0 → 1,105 |
/* |
* XML DRI client-side driver configuration |
* Copyright (C) 2003 Felix Kuehling |
* |
* 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 |
* FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS 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. |
* |
*/ |
/** |
* \file xmlpool.h |
* \brief Pool of common options |
* \author Felix Kuehling |
* |
* This file defines macros that can be used to construct |
* driConfigOptions in the drivers. Common options are defined in |
* xmlpool/t_options.h from which xmlpool/options.h is generated with |
* translations. This file defines generic helper macros and includes |
* xmlpool/options.h. |
*/ |
#ifndef __XMLPOOL_H |
#define __XMLPOOL_H |
/* |
* generic macros |
*/ |
/** \brief Begin __driConfigOptions */ |
#define DRI_CONF_BEGIN \ |
"<driinfo>\n" |
/** \brief End __driConfigOptions */ |
#define DRI_CONF_END \ |
"</driinfo>\n" |
/** \brief Begin a section of related options */ |
#define DRI_CONF_SECTION_BEGIN \ |
"<section>\n" |
/** \brief End a section of related options */ |
#define DRI_CONF_SECTION_END \ |
"</section>\n" |
/** \brief Begin an option definition */ |
#define DRI_CONF_OPT_BEGIN(name,type,def) \ |
"<option name=\""#name"\" type=\""#type"\" default=\""#def"\">\n" |
/** |
* \brief Begin a boolean option definition, with the default value passed in |
* as a string |
*/ |
#define DRI_CONF_OPT_BEGIN_B(name,def) \ |
"<option name=\""#name"\" type=\"bool\" default="#def">\n" |
/** \brief Begin an option definition with quoted default value */ |
#define DRI_CONF_OPT_BEGIN_Q(name,type,def) \ |
"<option name=\""#name"\" type=\""#type"\" default="#def">\n" |
/** \brief Begin an option definition with restrictions on valid values */ |
#define DRI_CONF_OPT_BEGIN_V(name,type,def,valid) \ |
"<option name=\""#name"\" type=\""#type"\" default=\""#def"\" valid=\""valid"\">\n" |
/** \brief End an option description */ |
#define DRI_CONF_OPT_END \ |
"</option>\n" |
/** \brief A verbal description in a specified language (empty version) */ |
#define DRI_CONF_DESC(lang,text) \ |
"<description lang=\""#lang"\" text=\""text"\"/>\n" |
/** \brief A verbal description in a specified language */ |
#define DRI_CONF_DESC_BEGIN(lang,text) \ |
"<description lang=\""#lang"\" text=\""text"\">\n" |
/** \brief End a description */ |
#define DRI_CONF_DESC_END \ |
"</description>\n" |
/** \brief A verbal description of an enum value */ |
#define DRI_CONF_ENUM(value,text) \ |
"<enum value=\""#value"\" text=\""text"\"/>\n" |
/* |
* Predefined option sections and options with multi-lingual descriptions |
* are now automatically generated. |
*/ |
#include "xmlpool/options.h" |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/dri.pc.in |
---|
0,0 → 1,11 |
prefix=@prefix@ |
exec_prefix=@exec_prefix@ |
libdir=@libdir@ |
includedir=@includedir@ |
dridriverdir=@DRI_DRIVER_INSTALL_DIR@ |
Name: dri |
Description: Direct Rendering Infrastructure |
Version: @VERSION@ |
Requires.private: @DRI_PC_REQ_PRIV@ |
Cflags: -I${includedir} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/Android.mk |
---|
0,0 → 1,58 |
# |
# Copyright (C) 2011 Intel Corporation |
# Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com> |
# Copyright (C) 2010-2011 LunarG |
# |
# 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) |
include $(CLEAR_VARS) |
LOCAL_MODULE := i915_dri |
LOCAL_MODULE_PATH := $(MESA_DRI_MODULE_PATH) |
LOCAL_UNSTRIPPED_PATH := $(MESA_DRI_MODULE_UNSTRIPPED_PATH) |
# Import variables i915_*. |
include $(LOCAL_PATH)/Makefile.sources |
LOCAL_CFLAGS := \ |
$(MESA_DRI_CFLAGS) \ |
-DI915 |
LOCAL_C_INCLUDES := \ |
$(addprefix $(MESA_TOP)/,$(i915_INCLUDES)) \ |
$(MESA_DRI_C_INCLUDES) \ |
$(DRM_TOP)/intel |
LOCAL_SRC_FILES := \ |
$(i915_C_FILES) |
LOCAL_WHOLE_STATIC_LIBRARIES := \ |
$(MESA_DRI_WHOLE_STATIC_LIBRARIES) |
LOCAL_SHARED_LIBRARIES := \ |
$(MESA_DRI_SHARED_LIBRARIES) \ |
libdrm_intel |
LOCAL_GENERATED_SOURCES := \ |
$(MESA_DRI_OPTIONS_H) |
include $(MESA_COMMON_MK) |
include $(BUILD_SHARED_LIBRARY) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/Makefile.am |
---|
0,0 → 1,65 |
# Copyright © 2012 Matt Turner <mattst88@gmail.com> |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
# copy of this software and associated documentation files (the "Software"), |
# to deal in the Software without restriction, including without limitation |
# the rights to use, copy, modify, merge, publish, distribute, sublicense, |
# and/or sell copies of the Software, and to permit persons to whom the |
# Software is furnished to do so, subject to the following conditions: |
# |
# The above copyright notice and this permission notice (including the next |
# paragraph) shall be included in all copies or substantial portions of the |
# Software. |
# |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
# IN THE SOFTWARE. |
include Makefile.sources |
AM_CFLAGS = \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
-I$(top_srcdir)/src/mesa/drivers/dri/common \ |
-I$(top_srcdir)/src/mesa/drivers/dri/intel/server \ |
-I$(top_builddir)/src/mesa/drivers/dri/common \ |
$(DEFINES) \ |
$(VISIBILITY_CFLAGS) \ |
$(INTEL_CFLAGS) |
if HAVE_OPENGL_ES1 |
AM_CFLAGS += \ |
-DFEATURE_ES1=1 |
endif |
if HAVE_OPENGL_ES2 |
AM_CFLAGS += \ |
-DFEATURE_ES2=1 |
endif |
dridir = $(DRI_DRIVER_INSTALL_DIR) |
if HAVE_I915_DRI |
dri_LTLIBRARIES = i915_dri.la |
endif |
i915_dri_la_SOURCES = $(i915_FILES) |
i915_dri_la_LDFLAGS = -module -avoid-version -shared |
i915_dri_la_LIBADD = \ |
../common/libdricommon.la \ |
$(DRI_LIB_DEPS) \ |
$(INTEL_LIBS) |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
all-local: i915_dri.la |
$(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
ln -f .libs/i915_dri.so $(top_builddir)/$(LIB_DIR)/i915_dri.so; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/Makefile.in |
---|
0,0 → 1,949 |
# 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 Matt Turner <mattst88@gmail.com> |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
# copy of this software and associated documentation files (the "Software"), |
# to deal in the Software without restriction, including without limitation |
# the rights to use, copy, modify, merge, publish, distribute, 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 = $(srcdir)/Makefile.sources $(srcdir)/Makefile.in \ |
$(srcdir)/Makefile.am $(top_srcdir)/bin/depcomp |
@HAVE_OPENGL_ES1_TRUE@am__append_1 = \ |
@HAVE_OPENGL_ES1_TRUE@ -DFEATURE_ES1=1 |
@HAVE_OPENGL_ES2_TRUE@am__append_2 = \ |
@HAVE_OPENGL_ES2_TRUE@ -DFEATURE_ES2=1 |
subdir = src/mesa/drivers/dri/i915 |
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 = |
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; |
am__vpath_adj = case $$p in \ |
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |
*) f=$$p;; \ |
esac; |
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; |
am__install_max = 40 |
am__nobase_strip_setup = \ |
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` |
am__nobase_strip = \ |
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" |
am__nobase_list = $(am__nobase_strip_setup); \ |
for p in $$list; do echo "$$p $$p"; done | \ |
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ |
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ |
if (++n[$$2] == $(am__install_max)) \ |
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ |
END { for (dir in files) print dir, files[dir] }' |
am__base_list = \ |
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ |
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' |
am__uninstall_files_from_dir = { \ |
test -z "$$files" \ |
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ |
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \ |
$(am__cd) "$$dir" && rm -f $$files; }; \ |
} |
am__installdirs = "$(DESTDIR)$(dridir)" |
LTLIBRARIES = $(dri_LTLIBRARIES) |
am__DEPENDENCIES_1 = |
i915_dri_la_DEPENDENCIES = ../common/libdricommon.la \ |
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) |
am__objects_1 = i830_context.lo i830_state.lo i830_texblend.lo \ |
i830_texstate.lo i830_vtbl.lo intel_render.lo intel_regions.lo \ |
intel_buffer_objects.lo intel_batchbuffer.lo intel_clear.lo \ |
intel_extensions.lo intel_mipmap_tree.lo intel_tex_layout.lo \ |
intel_tex_image.lo intel_tex_subimage.lo intel_tex_copy.lo \ |
intel_tex_validate.lo intel_tex.lo intel_pixel.lo \ |
intel_pixel_bitmap.lo intel_pixel_copy.lo intel_pixel_draw.lo \ |
intel_pixel_read.lo intel_buffers.lo intel_blit.lo \ |
i915_tex_layout.lo i915_texstate.lo i915_context.lo \ |
i915_debug_fp.lo i915_fragprog.lo i915_program.lo \ |
i915_state.lo i915_vtbl.lo intel_context.lo intel_screen.lo \ |
intel_state.lo intel_syncobj.lo intel_tris.lo intel_fbo.lo |
am_i915_dri_la_OBJECTS = $(am__objects_1) |
i915_dri_la_OBJECTS = $(am_i915_dri_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 = |
i915_dri_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ |
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ |
$(i915_dri_la_LDFLAGS) $(LDFLAGS) -o $@ |
@HAVE_I915_DRI_TRUE@am_i915_dri_la_rpath = -rpath $(dridir) |
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 = $(i915_dri_la_SOURCES) |
DIST_SOURCES = $(i915_dri_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@ |
# Paths are relative to TOP. |
i915_INCLUDES = \ |
src/mesa/drivers/dri/intel |
i915_FILES = \ |
i830_context.c \ |
i830_state.c \ |
i830_texblend.c \ |
i830_texstate.c \ |
i830_vtbl.c \ |
intel_render.c \ |
intel_regions.c \ |
intel_buffer_objects.c \ |
intel_batchbuffer.c \ |
intel_clear.c \ |
intel_extensions.c \ |
intel_mipmap_tree.c \ |
intel_tex_layout.c \ |
intel_tex_image.c \ |
intel_tex_subimage.c \ |
intel_tex_copy.c \ |
intel_tex_validate.c \ |
intel_tex.c \ |
intel_pixel.c \ |
intel_pixel_bitmap.c \ |
intel_pixel_copy.c \ |
intel_pixel_draw.c \ |
intel_pixel_read.c \ |
intel_buffers.c \ |
intel_blit.c \ |
i915_tex_layout.c \ |
i915_texstate.c \ |
i915_context.c \ |
i915_debug_fp.c \ |
i915_fragprog.c \ |
i915_program.c \ |
i915_state.c \ |
i915_vtbl.c \ |
intel_context.c \ |
intel_screen.c \ |
intel_state.c \ |
intel_syncobj.c \ |
intel_tris.c \ |
intel_fbo.c |
AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi -I$(top_srcdir)/src/mesa/ \ |
-I$(top_srcdir)/src/mesa/drivers/dri/common \ |
-I$(top_srcdir)/src/mesa/drivers/dri/intel/server \ |
-I$(top_builddir)/src/mesa/drivers/dri/common $(DEFINES) \ |
$(VISIBILITY_CFLAGS) $(INTEL_CFLAGS) $(am__append_1) \ |
$(am__append_2) |
dridir = $(DRI_DRIVER_INSTALL_DIR) |
@HAVE_I915_DRI_TRUE@dri_LTLIBRARIES = i915_dri.la |
i915_dri_la_SOURCES = $(i915_FILES) |
i915_dri_la_LDFLAGS = -module -avoid-version -shared |
i915_dri_la_LIBADD = \ |
../common/libdricommon.la \ |
$(DRI_LIB_DEPS) \ |
$(INTEL_LIBS) |
all: all-am |
.SUFFIXES: |
.SUFFIXES: .c .lo .o .obj |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(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/mesa/drivers/dri/i915/Makefile'; \ |
$(am__cd) $(top_srcdir) && \ |
$(AUTOMAKE) --foreign src/mesa/drivers/dri/i915/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; |
$(srcdir)/Makefile.sources: |
$(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): |
install-driLTLIBRARIES: $(dri_LTLIBRARIES) |
@$(NORMAL_INSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
list2=; for p in $$list; do \ |
if test -f $$p; then \ |
list2="$$list2 $$p"; \ |
else :; fi; \ |
done; \ |
test -z "$$list2" || { \ |
echo " $(MKDIR_P) '$(DESTDIR)$(dridir)'"; \ |
$(MKDIR_P) "$(DESTDIR)$(dridir)" || exit 1; \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(dridir)'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(dridir)"; \ |
} |
uninstall-driLTLIBRARIES: |
@$(NORMAL_UNINSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
for p in $$list; do \ |
$(am__strip_dir) \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(dridir)/$$f'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(dridir)/$$f"; \ |
done |
clean-driLTLIBRARIES: |
-test -z "$(dri_LTLIBRARIES)" || rm -f $(dri_LTLIBRARIES) |
@list='$(dri_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}; \ |
} |
i915_dri.la: $(i915_dri_la_OBJECTS) $(i915_dri_la_DEPENDENCIES) $(EXTRA_i915_dri_la_DEPENDENCIES) |
$(AM_V_CCLD)$(i915_dri_la_LINK) $(am_i915_dri_la_rpath) $(i915_dri_la_OBJECTS) $(i915_dri_la_LIBADD) $(LIBS) |
mostlyclean-compile: |
-rm -f *.$(OBJEXT) |
distclean-compile: |
-rm -f *.tab.c |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i830_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i830_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i830_texblend.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i830_texstate.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i830_vtbl.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i915_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i915_debug_fp.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i915_fragprog.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i915_program.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i915_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i915_tex_layout.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i915_texstate.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i915_vtbl.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_batchbuffer.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_blit.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_buffer_objects.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_buffers.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_clear.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_extensions.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_fbo.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_mipmap_tree.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_pixel.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_pixel_bitmap.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_pixel_copy.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_pixel_draw.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_pixel_read.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_regions.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_render.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_screen.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_syncobj.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tex.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tex_copy.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tex_image.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tex_layout.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tex_subimage.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tex_validate.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tris.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) all-local |
installdirs: |
for dir in "$(DESTDIR)$(dridir)"; do \ |
test -z "$$dir" || $(MKDIR_P) "$$dir"; \ |
done |
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-driLTLIBRARIES clean-generic clean-libtool \ |
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-driLTLIBRARIES |
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: uninstall-driLTLIBRARIES |
.MAKE: install-am install-strip |
.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \ |
clean-driLTLIBRARIES clean-generic clean-libtool 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-driLTLIBRARIES 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 \ |
uninstall-driLTLIBRARIES |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
all-local: i915_dri.la |
$(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
ln -f .libs/i915_dri.so $(top_builddir)/$(LIB_DIR)/i915_dri.so; |
# 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/src/mesa/drivers/dri/i915/Makefile.sources |
---|
0,0 → 1,44 |
# Paths are relative to TOP. |
i915_INCLUDES = \ |
src/mesa/drivers/dri/intel |
i915_FILES = \ |
i830_context.c \ |
i830_state.c \ |
i830_texblend.c \ |
i830_texstate.c \ |
i830_vtbl.c \ |
intel_render.c \ |
intel_regions.c \ |
intel_buffer_objects.c \ |
intel_batchbuffer.c \ |
intel_clear.c \ |
intel_extensions.c \ |
intel_mipmap_tree.c \ |
intel_tex_layout.c \ |
intel_tex_image.c \ |
intel_tex_subimage.c \ |
intel_tex_copy.c \ |
intel_tex_validate.c \ |
intel_tex.c \ |
intel_pixel.c \ |
intel_pixel_bitmap.c \ |
intel_pixel_copy.c \ |
intel_pixel_draw.c \ |
intel_pixel_read.c \ |
intel_buffers.c \ |
intel_blit.c \ |
i915_tex_layout.c \ |
i915_texstate.c \ |
i915_context.c \ |
i915_debug_fp.c \ |
i915_fragprog.c \ |
i915_program.c \ |
i915_state.c \ |
i915_vtbl.c \ |
intel_context.c \ |
intel_screen.c \ |
intel_state.c \ |
intel_syncobj.c \ |
intel_tris.c \ |
intel_fbo.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i830_context.c |
---|
0,0 → 1,132 |
/************************************************************************** |
* |
* 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 "i830_context.h" |
#include "main/api_exec.h" |
#include "main/imports.h" |
#include "main/version.h" |
#include "main/vtxfmt.h" |
#include "tnl/tnl.h" |
#include "tnl/t_vertex.h" |
#include "tnl/t_context.h" |
#include "tnl/t_pipeline.h" |
#include "intel_tris.h" |
#include "../glsl/ralloc.h" |
/*************************************** |
* Mesa's Driver Functions |
***************************************/ |
static void |
i830InitDriverFunctions(struct dd_function_table *functions) |
{ |
intelInitDriverFunctions(functions); |
i830InitStateFuncs(functions); |
} |
extern const struct tnl_pipeline_stage *intel_pipeline[]; |
bool |
i830CreateContext(int api, |
const struct gl_config * mesaVis, |
__DRIcontext * driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
unsigned *error, |
void *sharedContextPrivate) |
{ |
struct dd_function_table functions; |
struct i830_context *i830 = rzalloc(NULL, struct i830_context); |
struct intel_context *intel = &i830->intel; |
struct gl_context *ctx = &intel->ctx; |
if (!i830) { |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
return false; |
} |
i830InitVtbl(i830); |
i830InitDriverFunctions(&functions); |
if (!intelInitContext(intel, __DRI_API_OPENGL, |
major_version, minor_version, |
mesaVis, driContextPriv, |
sharedContextPrivate, &functions, |
error)) { |
ralloc_free(i830); |
return false; |
} |
intel_init_texture_formats(ctx); |
_math_matrix_ctr(&intel->ViewportMatrix); |
/* Initialize swrast, tnl driver tables: */ |
intelInitTriFuncs(ctx); |
/* Install the customized pipeline: */ |
_tnl_destroy_pipeline(ctx); |
_tnl_install_pipeline(ctx, intel_pipeline); |
if (intel->no_rast) |
FALLBACK(intel, INTEL_FALLBACK_USER, 1); |
intel->ctx.Const.MaxTextureUnits = I830_TEX_UNITS; |
intel->ctx.Const.FragmentProgram.MaxTextureImageUnits = I830_TEX_UNITS; |
intel->ctx.Const.MaxTextureCoordUnits = I830_TEX_UNITS; |
/* Advertise the full hardware capabilities. The new memory |
* manager should cope much better with overload situations: |
*/ |
ctx->Const.MaxTextureLevels = 12; |
ctx->Const.Max3DTextureLevels = 9; |
ctx->Const.MaxCubeTextureLevels = 11; |
ctx->Const.MaxTextureRectSize = (1 << 11); |
ctx->Const.MaxTextureUnits = I830_TEX_UNITS; |
ctx->Const.MaxTextureMaxAnisotropy = 2.0; |
ctx->Const.MaxDrawBuffers = 1; |
ctx->Const.QueryCounterBits.SamplesPassed = 0; |
_tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12, |
18 * sizeof(GLfloat)); |
intel->verts = TNL_CONTEXT(ctx)->clipspace.vertex_buf; |
i830InitState(i830); |
_tnl_allow_vertex_fog(ctx, 1); |
_tnl_allow_pixel_fog(ctx, 0); |
_mesa_compute_version(ctx); |
_mesa_initialize_dispatch_tables(ctx); |
_mesa_initialize_vbo_vtxfmt(ctx); |
return true; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i830_context.h |
---|
0,0 → 1,224 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef I830CONTEXT_INC |
#define I830CONTEXT_INC |
#include "intel_context.h" |
#define I830_FALLBACK_TEXTURE 0x1000 |
#define I830_FALLBACK_COLORMASK 0x2000 |
#define I830_FALLBACK_STENCIL 0x4000 |
#define I830_FALLBACK_STIPPLE 0x8000 |
#define I830_FALLBACK_LOGICOP 0x20000 |
#define I830_FALLBACK_DRAW_OFFSET 0x200000 |
#define I830_UPLOAD_CTX 0x1 |
#define I830_UPLOAD_BUFFERS 0x2 |
#define I830_UPLOAD_STIPPLE 0x4 |
#define I830_UPLOAD_INVARIENT 0x8 |
#define I830_UPLOAD_RASTER_RULES 0x10 |
#define I830_UPLOAD_TEX(i) (0x10<<(i)) |
#define I830_UPLOAD_TEXBLEND(i) (0x100<<(i)) |
#define I830_UPLOAD_TEX_ALL (0x0f0) |
#define I830_UPLOAD_TEXBLEND_ALL (0xf00) |
/* State structure offsets - these will probably disappear. |
*/ |
#define I830_DESTREG_CBUFADDR0 0 |
#define I830_DESTREG_CBUFADDR1 1 |
#define I830_DESTREG_DBUFADDR0 2 |
#define I830_DESTREG_DBUFADDR1 3 |
#define I830_DESTREG_DV0 4 |
#define I830_DESTREG_DV1 5 |
#define I830_DESTREG_SENABLE 6 |
#define I830_DESTREG_SR0 7 |
#define I830_DESTREG_SR1 8 |
#define I830_DESTREG_SR2 9 |
#define I830_DESTREG_DRAWRECT0 10 |
#define I830_DESTREG_DRAWRECT1 11 |
#define I830_DESTREG_DRAWRECT2 12 |
#define I830_DESTREG_DRAWRECT3 13 |
#define I830_DESTREG_DRAWRECT4 14 |
#define I830_DESTREG_DRAWRECT5 15 |
#define I830_DEST_SETUP_SIZE 16 |
#define I830_CTXREG_STATE1 0 |
#define I830_CTXREG_STATE2 1 |
#define I830_CTXREG_STATE3 2 |
#define I830_CTXREG_STATE4 3 |
#define I830_CTXREG_STATE5 4 |
#define I830_CTXREG_IALPHAB 5 |
#define I830_CTXREG_STENCILTST 6 |
#define I830_CTXREG_ENABLES_1 7 |
#define I830_CTXREG_ENABLES_2 8 |
#define I830_CTXREG_AA 9 |
#define I830_CTXREG_FOGCOLOR 10 |
#define I830_CTXREG_BLENDCOLOR0 11 |
#define I830_CTXREG_BLENDCOLOR1 12 |
#define I830_CTXREG_VF 13 |
#define I830_CTXREG_VF2 14 |
#define I830_CTXREG_MCSB0 15 |
#define I830_CTXREG_MCSB1 16 |
#define I830_CTX_SETUP_SIZE 17 |
#define I830_STPREG_ST0 0 |
#define I830_STPREG_ST1 1 |
#define I830_STP_SETUP_SIZE 2 |
#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */ |
#define I830_TEXREG_TM0S1 1 |
#define I830_TEXREG_TM0S2 2 |
#define I830_TEXREG_TM0S3 3 |
#define I830_TEXREG_TM0S4 4 |
#define I830_TEXREG_MCS 5 /* _3DSTATE_MAP_COORD_SETS */ |
#define I830_TEXREG_CUBE 6 /* _3DSTATE_MAP_SUBE */ |
#define I830_TEX_SETUP_SIZE 7 |
#define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */ |
enum { |
I830_RASTER_RULES, |
I830_RASTER_RULES_SIZE |
}; |
struct i830_texture_object |
{ |
struct intel_texture_object intel; |
GLuint Setup[I830_TEX_SETUP_SIZE]; |
}; |
#define I830_TEX_UNITS 4 |
struct i830_hw_state |
{ |
GLuint Ctx[I830_CTX_SETUP_SIZE]; |
GLuint Buffer[I830_DEST_SETUP_SIZE]; |
GLuint Stipple[I830_STP_SETUP_SIZE]; |
GLuint RasterRules[I830_RASTER_RULES_SIZE]; |
GLuint Tex[I830_TEX_UNITS][I830_TEX_SETUP_SIZE]; |
GLuint TexBlend[I830_TEX_UNITS][I830_TEXBLEND_SIZE]; |
GLuint TexBlendWordsUsed[I830_TEX_UNITS]; |
struct intel_region *draw_region; |
struct intel_region *depth_region; |
/* Regions aren't actually that appropriate here as the memory may |
* be from a PBO or FBO. Will have to do this for draw and depth for |
* FBO's... |
*/ |
drm_intel_bo *tex_buffer[I830_TEX_UNITS]; |
GLuint tex_offset[I830_TEX_UNITS]; |
GLuint emitted; /* I810_UPLOAD_* */ |
GLuint active; |
}; |
struct i830_context |
{ |
struct intel_context intel; |
GLuint lodbias_tm0s3[MAX_TEXTURE_UNITS]; |
GLbitfield64 last_index_bitset; |
struct i830_hw_state state; |
}; |
#define I830_STATECHANGE(i830, flag) \ |
do { \ |
INTEL_FIREVERTICES( &i830->intel ); \ |
i830->state.emitted &= ~flag; \ |
} while (0) |
#define I830_ACTIVESTATE(i830, flag, mode) \ |
do { \ |
INTEL_FIREVERTICES( &i830->intel ); \ |
if (mode) \ |
i830->state.active |= flag; \ |
else \ |
i830->state.active &= ~flag; \ |
} while (0) |
/* i830_vtbl.c |
*/ |
extern void i830InitVtbl(struct i830_context *i830); |
extern void |
i830_state_draw_region(struct intel_context *intel, |
struct i830_hw_state *state, |
struct intel_region *color_region, |
struct intel_region *depth_region); |
/* i830_context.c |
*/ |
extern bool |
i830CreateContext(int api, |
const struct gl_config * mesaVis, |
__DRIcontext * driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
unsigned *error, |
void *sharedContextPrivate); |
/* i830_tex.c, i830_texstate.c |
*/ |
extern void i830UpdateTextureState(struct intel_context *intel); |
extern void i830InitTextureFuncs(struct dd_function_table *functions); |
/* i830_texblend.c |
*/ |
extern GLuint i830SetTexEnvCombine(struct i830_context *i830, |
const struct gl_tex_env_combine_state |
*combine, GLint blendUnit, GLuint texel_op, |
GLuint * state, const GLfloat * factor); |
extern void i830EmitTextureBlend(struct i830_context *i830); |
/* i830_state.c |
*/ |
extern void i830InitStateFuncs(struct dd_function_table *functions); |
extern void i830EmitState(struct i830_context *i830); |
extern void i830InitState(struct i830_context *i830); |
extern void i830_update_provoking_vertex(struct gl_context *ctx); |
/*====================================================================== |
* Inline conversion functions. These are better-typed than the |
* macros used previously: |
*/ |
static INLINE struct i830_context * |
i830_context(struct gl_context * ctx) |
{ |
return (struct i830_context *) ctx; |
} |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i830_reg.h |
---|
0,0 → 1,628 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef _I830_REG_H_ |
#define _I830_REG_H_ |
#include "intel_reg.h" |
#define I830_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value) |
#define _3DSTATE_AA_CMD (CMD_3D | (0x06<<24)) |
#define AA_LINE_ECAAR_WIDTH_ENABLE (1<<16) |
#define AA_LINE_ECAAR_WIDTH_0_5 0 |
#define AA_LINE_ECAAR_WIDTH_1_0 (1<<14) |
#define AA_LINE_ECAAR_WIDTH_2_0 (2<<14) |
#define AA_LINE_ECAAR_WIDTH_4_0 (3<<14) |
#define AA_LINE_REGION_WIDTH_ENABLE (1<<8) |
#define AA_LINE_REGION_WIDTH_0_5 0 |
#define AA_LINE_REGION_WIDTH_1_0 (1<<6) |
#define AA_LINE_REGION_WIDTH_2_0 (2<<6) |
#define AA_LINE_REGION_WIDTH_4_0 (3<<6) |
#define AA_LINE_ENABLE ((1<<1) | 1) |
#define AA_LINE_DISABLE (1<<1) |
#define _3DSTATE_COLOR_FACTOR_CMD (CMD_3D | (0x1d<<24) | (0x1<<16)) |
#define _3DSTATE_COLOR_FACTOR_N_CMD(stage) (CMD_3D | (0x1d<<24) | \ |
((0x90+(stage))<<16)) |
#define _3DSTATE_CONST_BLEND_COLOR_CMD (CMD_3D | (0x1d<<24) | (0x88<<16)) |
#define _3DSTATE_DFLT_DIFFUSE_CMD (CMD_3D | (0x1d<<24) | (0x99<<16)) |
#define _3DSTATE_DFLT_SPEC_CMD (CMD_3D | (0x1d<<24) | (0x9a<<16)) |
#define _3DSTATE_DFLT_Z_CMD (CMD_3D | (0x1d<<24) | (0x98<<16)) |
#define _3DSTATE_DST_BUF_VARS_CMD (CMD_3D | (0x1d<<24) | (0x85<<16)) |
/* Dword 1 */ |
#define DSTORG_HORT_BIAS(x) ((x)<<20) |
#define DSTORG_VERT_BIAS(x) ((x)<<16) |
#define COLOR_4_2_2_CHNL_WRT_ALL 0 |
#define COLOR_4_2_2_CHNL_WRT_Y (1<<12) |
#define COLOR_4_2_2_CHNL_WRT_CR (2<<12) |
#define COLOR_4_2_2_CHNL_WRT_CB (3<<12) |
#define COLOR_4_2_2_CHNL_WRT_CRCB (4<<12) |
#define COLR_BUF_8BIT 0 |
#define COLR_BUF_RGB555 (1<<8) |
#define COLR_BUF_RGB565 (2<<8) |
#define COLR_BUF_ARGB8888 (3<<8) |
#define DEPTH_IS_Z 0 |
#define DEPTH_IS_W (1<<6) |
#define DEPTH_FRMT_16_FIXED 0 |
#define DEPTH_FRMT_16_FLOAT (1<<2) |
#define DEPTH_FRMT_24_FIXED_8_OTHER (2<<2) |
#define DEPTH_FRMT_24_FLOAT_8_OTHER (3<<2) |
#define VERT_LINE_STRIDE_1 (1<<1) |
#define VERT_LINE_STRIDE_0 0 |
#define VERT_LINE_STRIDE_OFS_1 1 |
#define VERT_LINE_STRIDE_OFS_0 0 |
#define _3DSTATE_DRAW_RECT_CMD (CMD_3D|(0x1d<<24)|(0x80<<16)|3) |
/* Dword 1 */ |
#define DRAW_RECT_DIS_DEPTH_OFS (1<<30) |
#define DRAW_DITHER_OFS_X(x) ((x)<<26) |
#define DRAW_DITHER_OFS_Y(x) ((x)<<24) |
/* Dword 2 */ |
#define DRAW_YMIN(x) ((x)<<16) |
#define DRAW_XMIN(x) (x) |
/* Dword 3 */ |
#define DRAW_YMAX(x) ((x)<<16) |
#define DRAW_XMAX(x) (x) |
/* Dword 4 */ |
#define DRAW_YORG(x) ((x)<<16) |
#define DRAW_XORG(x) (x) |
#define _3DSTATE_ENABLES_1_CMD (CMD_3D|(0x3<<24)) |
#define ENABLE_LOGIC_OP_MASK ((1<<23)|(1<<22)) |
#define ENABLE_LOGIC_OP ((1<<23)|(1<<22)) |
#define DISABLE_LOGIC_OP (1<<23) |
#define ENABLE_STENCIL_TEST ((1<<21)|(1<<20)) |
#define DISABLE_STENCIL_TEST (1<<21) |
#define ENABLE_DEPTH_BIAS ((1<<11)|(1<<10)) |
#define DISABLE_DEPTH_BIAS (1<<11) |
#define ENABLE_SPEC_ADD_MASK ((1<<9)|(1<<8)) |
#define ENABLE_SPEC_ADD ((1<<9)|(1<<8)) |
#define DISABLE_SPEC_ADD (1<<9) |
#define ENABLE_DIS_FOG_MASK ((1<<7)|(1<<6)) |
#define ENABLE_FOG ((1<<7)|(1<<6)) |
#define DISABLE_FOG (1<<7) |
#define ENABLE_DIS_ALPHA_TEST_MASK ((1<<5)|(1<<4)) |
#define ENABLE_ALPHA_TEST ((1<<5)|(1<<4)) |
#define DISABLE_ALPHA_TEST (1<<5) |
#define ENABLE_DIS_CBLEND_MASK ((1<<3)|(1<<2)) |
#define ENABLE_COLOR_BLEND ((1<<3)|(1<<2)) |
#define DISABLE_COLOR_BLEND (1<<3) |
#define ENABLE_DIS_DEPTH_TEST_MASK ((1<<1)|1) |
#define ENABLE_DEPTH_TEST ((1<<1)|1) |
#define DISABLE_DEPTH_TEST (1<<1) |
/* _3DSTATE_ENABLES_2, p138 */ |
#define _3DSTATE_ENABLES_2_CMD (CMD_3D|(0x4<<24)) |
#define ENABLE_STENCIL_WRITE ((1<<21)|(1<<20)) |
#define DISABLE_STENCIL_WRITE (1<<21) |
#define ENABLE_TEX_CACHE ((1<<17)|(1<<16)) |
#define DISABLE_TEX_CACHE (1<<17) |
#define ENABLE_DITHER ((1<<9)|(1<<8)) |
#define DISABLE_DITHER (1<<9) |
#define ENABLE_COLOR_MASK (1<<10) |
#define WRITEMASK_ALPHA (1<<7) |
#define WRITEMASK_ALPHA_SHIFT 7 |
#define WRITEMASK_RED (1<<6) |
#define WRITEMASK_RED_SHIFT 6 |
#define WRITEMASK_GREEN (1<<5) |
#define WRITEMASK_GREEN_SHIFT 5 |
#define WRITEMASK_BLUE (1<<4) |
#define WRITEMASK_BLUE_SHIFT 4 |
#define WRITEMASK_MASK ((1<<4)|(1<<5)|(1<<6)|(1<<7)) |
#define ENABLE_COLOR_WRITE ((1<<3)|(1<<2)) |
#define DISABLE_COLOR_WRITE (1<<3) |
#define ENABLE_DIS_DEPTH_WRITE_MASK 0x3 |
#define ENABLE_DEPTH_WRITE ((1<<1)|1) |
#define DISABLE_DEPTH_WRITE (1<<1) |
/* _3DSTATE_FOG_COLOR, p139 */ |
#define _3DSTATE_FOG_COLOR_CMD (CMD_3D|(0x15<<24)) |
#define FOG_COLOR_RED(x) ((x)<<16) |
#define FOG_COLOR_GREEN(x) ((x)<<8) |
#define FOG_COLOR_BLUE(x) (x) |
/* _3DSTATE_FOG_MODE, p140 */ |
#define _3DSTATE_FOG_MODE_CMD (CMD_3D|(0x1d<<24)|(0x89<<16)|2) |
/* Dword 1 */ |
#define FOGFUNC_ENABLE (1<<31) |
#define FOGFUNC_VERTEX 0 |
#define FOGFUNC_PIXEL_EXP (1<<28) |
#define FOGFUNC_PIXEL_EXP2 (2<<28) |
#define FOGFUNC_PIXEL_LINEAR (3<<28) |
#define FOGSRC_INDEX_Z (1<<27) |
#define FOGSRC_INDEX_W ((1<<27)|(1<<25)) |
#define FOG_LINEAR_CONST (1<<24) |
#define FOG_CONST_1(x) ((x)<<4) |
#define ENABLE_FOG_DENSITY (1<<23) |
/* Dword 2 */ |
#define FOG_CONST_2(x) (x) |
/* Dword 3 */ |
#define FOG_DENSITY(x) (x) |
/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p142 */ |
#define _3DSTATE_INDPT_ALPHA_BLEND_CMD (CMD_3D|(0x0b<<24)) |
#define ENABLE_INDPT_ALPHA_BLEND ((1<<23)|(1<<22)) |
#define DISABLE_INDPT_ALPHA_BLEND (1<<23) |
#define ALPHA_BLENDFUNC_MASK 0x3f0000 |
#define ENABLE_ALPHA_BLENDFUNC (1<<21) |
#define ABLENDFUNC_ADD 0 |
#define ABLENDFUNC_SUB (1<<16) |
#define ABLENDFUNC_RVSE_SUB (2<<16) |
#define ABLENDFUNC_MIN (3<<16) |
#define ABLENDFUNC_MAX (4<<16) |
#define SRC_DST_ABLEND_MASK 0xfff |
#define ENABLE_SRC_ABLEND_FACTOR (1<<11) |
#define SRC_ABLEND_FACT(x) ((x)<<6) |
#define ENABLE_DST_ABLEND_FACTOR (1<<5) |
#define DST_ABLEND_FACT(x) (x) |
/* _3DSTATE_MAP_BLEND_ARG, p152 */ |
#define _3DSTATE_MAP_BLEND_ARG_CMD(stage) (CMD_3D|(0x0e<<24)|((stage)<<20)) |
#define TEXPIPE_COLOR 0 |
#define TEXPIPE_ALPHA (1<<18) |
#define TEXPIPE_KILL (2<<18) |
#define TEXBLEND_ARG0 0 |
#define TEXBLEND_ARG1 (1<<15) |
#define TEXBLEND_ARG2 (2<<15) |
#define TEXBLEND_ARG3 (3<<15) |
#define TEXBLENDARG_MODIFY_PARMS (1<<6) |
#define TEXBLENDARG_REPLICATE_ALPHA (1<<5) |
#define TEXBLENDARG_INV_ARG (1<<4) |
#define TEXBLENDARG_ONE 0 |
#define TEXBLENDARG_FACTOR 0x01 |
#define TEXBLENDARG_ACCUM 0x02 |
#define TEXBLENDARG_DIFFUSE 0x03 |
#define TEXBLENDARG_SPEC 0x04 |
#define TEXBLENDARG_CURRENT 0x05 |
#define TEXBLENDARG_TEXEL0 0x06 |
#define TEXBLENDARG_TEXEL1 0x07 |
#define TEXBLENDARG_TEXEL2 0x08 |
#define TEXBLENDARG_TEXEL3 0x09 |
#define TEXBLENDARG_FACTOR_N 0x0e |
/* _3DSTATE_MAP_BLEND_OP, p155 */ |
#define _3DSTATE_MAP_BLEND_OP_CMD(stage) (CMD_3D|(0x0d<<24)|((stage)<<20)) |
#if 0 |
# define TEXPIPE_COLOR 0 |
# define TEXPIPE_ALPHA (1<<18) |
# define TEXPIPE_KILL (2<<18) |
#endif |
#define ENABLE_TEXOUTPUT_WRT_SEL (1<<17) |
#define TEXOP_OUTPUT_CURRENT 0 |
#define TEXOP_OUTPUT_ACCUM (1<<15) |
#define ENABLE_TEX_CNTRL_STAGE ((1<<12)|(1<<11)) |
#define DISABLE_TEX_CNTRL_STAGE (1<<12) |
#define TEXOP_SCALE_SHIFT 9 |
#define TEXOP_SCALE_1X (0 << TEXOP_SCALE_SHIFT) |
#define TEXOP_SCALE_2X (1 << TEXOP_SCALE_SHIFT) |
#define TEXOP_SCALE_4X (2 << TEXOP_SCALE_SHIFT) |
#define TEXOP_MODIFY_PARMS (1<<8) |
#define TEXOP_LAST_STAGE (1<<7) |
#define TEXBLENDOP_KILLPIXEL 0x02 |
#define TEXBLENDOP_ARG1 0x01 |
#define TEXBLENDOP_ARG2 0x02 |
#define TEXBLENDOP_MODULATE 0x03 |
#define TEXBLENDOP_ADD 0x06 |
#define TEXBLENDOP_ADDSIGNED 0x07 |
#define TEXBLENDOP_BLEND 0x08 |
#define TEXBLENDOP_BLEND_AND_ADD 0x09 |
#define TEXBLENDOP_SUBTRACT 0x0a |
#define TEXBLENDOP_DOT3 0x0b |
#define TEXBLENDOP_DOT4 0x0c |
#define TEXBLENDOP_MODULATE_AND_ADD 0x0d |
#define TEXBLENDOP_MODULATE_2X_AND_ADD 0x0e |
#define TEXBLENDOP_MODULATE_4X_AND_ADD 0x0f |
/* _3DSTATE_MAP_BUMP_TABLE, p160 TODO */ |
/* _3DSTATE_MAP_COLOR_CHROMA_KEY, p161 TODO */ |
#define _3DSTATE_MAP_COORD_TRANSFORM ((3<<29)|(0x1d<<24)|(0x8c<<16)) |
#define DISABLE_TEX_TRANSFORM (1<<28) |
#define TEXTURE_SET(x) (x<<29) |
#define _3DSTATE_VERTEX_TRANSFORM ((3<<29)|(0x1d<<24)|(0x8b<<16)) |
#define DISABLE_VIEWPORT_TRANSFORM (1<<31) |
#define DISABLE_PERSPECTIVE_DIVIDE (1<<29) |
/* _3DSTATE_MAP_COORD_SET_BINDINGS, p162 */ |
#define _3DSTATE_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16)) |
#define TEXBIND_MASK3 ((1<<15)|(1<<14)|(1<<13)|(1<<12)) |
#define TEXBIND_MASK2 ((1<<11)|(1<<10)|(1<<9)|(1<<8)) |
#define TEXBIND_MASK1 ((1<<7)|(1<<6)|(1<<5)|(1<<4)) |
#define TEXBIND_MASK0 ((1<<3)|(1<<2)|(1<<1)|1) |
#define TEXBIND_SET3(x) ((x)<<12) |
#define TEXBIND_SET2(x) ((x)<<8) |
#define TEXBIND_SET1(x) ((x)<<4) |
#define TEXBIND_SET0(x) (x) |
#define TEXCOORDSRC_KEEP 0 |
#define TEXCOORDSRC_DEFAULT 0x01 |
#define TEXCOORDSRC_VTXSET_0 0x08 |
#define TEXCOORDSRC_VTXSET_1 0x09 |
#define TEXCOORDSRC_VTXSET_2 0x0a |
#define TEXCOORDSRC_VTXSET_3 0x0b |
#define TEXCOORDSRC_VTXSET_4 0x0c |
#define TEXCOORDSRC_VTXSET_5 0x0d |
#define TEXCOORDSRC_VTXSET_6 0x0e |
#define TEXCOORDSRC_VTXSET_7 0x0f |
#define MAP_UNIT(unit) ((unit)<<16) |
#define MAP_UNIT_MASK (0x7<<16) |
/* _3DSTATE_MAP_COORD_SETS, p164 */ |
#define _3DSTATE_MAP_COORD_SET_CMD (CMD_3D|(0x1c<<24)|(0x01<<19)) |
#define ENABLE_TEXCOORD_PARAMS (1<<15) |
#define TEXCOORDS_ARE_NORMAL (1<<14) |
#define TEXCOORDS_ARE_IN_TEXELUNITS 0 |
#define TEXCOORDTYPE_CARTESIAN 0 |
#define TEXCOORDTYPE_HOMOGENEOUS (1<<11) |
#define TEXCOORDTYPE_VECTOR (2<<11) |
#define TEXCOORDTYPE_MASK (0x7<<11) |
#define ENABLE_ADDR_V_CNTL (1<<7) |
#define ENABLE_ADDR_U_CNTL (1<<3) |
#define TEXCOORD_ADDR_V_MODE(x) ((x)<<4) |
#define TEXCOORD_ADDR_U_MODE(x) (x) |
#define TEXCOORDMODE_WRAP 0 |
#define TEXCOORDMODE_MIRROR 1 |
#define TEXCOORDMODE_CLAMP 2 |
#define TEXCOORDMODE_WRAP_SHORTEST 3 |
#define TEXCOORDMODE_CLAMP_BORDER 4 |
#define TEXCOORD_ADDR_V_MASK 0x70 |
#define TEXCOORD_ADDR_U_MASK 0x7 |
/* _3DSTATE_MAP_CUBE, p168 TODO */ |
#define _3DSTATE_MAP_CUBE (CMD_3D|(0x1c<<24)|(0x0a<<19)) |
#define CUBE_NEGX_ENABLE (1<<5) |
#define CUBE_POSX_ENABLE (1<<4) |
#define CUBE_NEGY_ENABLE (1<<3) |
#define CUBE_POSY_ENABLE (1<<2) |
#define CUBE_NEGZ_ENABLE (1<<1) |
#define CUBE_POSZ_ENABLE (1<<0) |
/* _3DSTATE_MODES_1, p190 */ |
#define _3DSTATE_MODES_1_CMD (CMD_3D|(0x08<<24)) |
#define BLENDFUNC_MASK 0x3f0000 |
#define ENABLE_COLR_BLND_FUNC (1<<21) |
#define BLENDFUNC_ADD 0 |
#define BLENDFUNC_SUB (1<<16) |
#define BLENDFUNC_RVRSE_SUB (2<<16) |
#define BLENDFUNC_MIN (3<<16) |
#define BLENDFUNC_MAX (4<<16) |
#define SRC_DST_BLND_MASK 0xfff |
#define ENABLE_SRC_BLND_FACTOR (1<<11) |
#define ENABLE_DST_BLND_FACTOR (1<<5) |
#define SRC_BLND_FACT(x) ((x)<<6) |
#define DST_BLND_FACT(x) (x) |
/* _3DSTATE_MODES_2, p192 */ |
#define _3DSTATE_MODES_2_CMD (CMD_3D|(0x0f<<24)) |
#define ENABLE_GLOBAL_DEPTH_BIAS (1<<22) |
#define GLOBAL_DEPTH_BIAS(x) ((x)<<14) |
#define ENABLE_ALPHA_TEST_FUNC (1<<13) |
#define ENABLE_ALPHA_REF_VALUE (1<<8) |
#define ALPHA_TEST_FUNC(x) ((x)<<9) |
#define ALPHA_REF_VALUE(x) (x) |
#define ALPHA_TEST_REF_MASK 0x3fff |
/* _3DSTATE_MODES_3, p193 */ |
#define _3DSTATE_MODES_3_CMD (CMD_3D|(0x02<<24)) |
#define DEPTH_TEST_FUNC_MASK 0x1f0000 |
#define ENABLE_DEPTH_TEST_FUNC (1<<20) |
/* Uses COMPAREFUNC */ |
#define DEPTH_TEST_FUNC(x) ((x)<<16) |
#define ENABLE_ALPHA_SHADE_MODE (1<<11) |
#define ENABLE_FOG_SHADE_MODE (1<<9) |
#define ENABLE_SPEC_SHADE_MODE (1<<7) |
#define ENABLE_COLOR_SHADE_MODE (1<<5) |
#define ALPHA_SHADE_MODE(x) ((x)<<10) |
#define FOG_SHADE_MODE(x) ((x)<<8) |
#define SPEC_SHADE_MODE(x) ((x)<<6) |
#define COLOR_SHADE_MODE(x) ((x)<<4) |
#define CULLMODE_MASK 0xf |
#define ENABLE_CULL_MODE (1<<3) |
#define CULLMODE_BOTH 0 |
#define CULLMODE_NONE 1 |
#define CULLMODE_CW 2 |
#define CULLMODE_CCW 3 |
#define SHADE_MODE_LINEAR 0 |
#define SHADE_MODE_FLAT 0x1 |
/* _3DSTATE_MODES_4, p195 */ |
#define _3DSTATE_MODES_4_CMD (CMD_3D|(0x16<<24)) |
#define ENABLE_LOGIC_OP_FUNC (1<<23) |
#define LOGIC_OP_FUNC(x) ((x)<<18) |
#define LOGICOP_MASK ((1<<18)|(1<<19)|(1<<20)|(1<<21)) |
#define LOGICOP_CLEAR 0 |
#define LOGICOP_NOR 0x1 |
#define LOGICOP_AND_INV 0x2 |
#define LOGICOP_COPY_INV 0x3 |
#define LOGICOP_AND_RVRSE 0x4 |
#define LOGICOP_INV 0x5 |
#define LOGICOP_XOR 0x6 |
#define LOGICOP_NAND 0x7 |
#define LOGICOP_AND 0x8 |
#define LOGICOP_EQUIV 0x9 |
#define LOGICOP_NOOP 0xa |
#define LOGICOP_OR_INV 0xb |
#define LOGICOP_COPY 0xc |
#define LOGICOP_OR_RVRSE 0xd |
#define LOGICOP_OR 0xe |
#define LOGICOP_SET 0xf |
#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00)) |
#define ENABLE_STENCIL_TEST_MASK (1<<17) |
#define STENCIL_TEST_MASK(x) (((x)&0xff)<<8) |
#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff)) |
#define ENABLE_STENCIL_WRITE_MASK (1<<16) |
#define STENCIL_WRITE_MASK(x) ((x)&0xff) |
/* _3DSTATE_MODES_5, p196 */ |
#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24)) |
#define ENABLE_SPRITE_POINT_TEX (1<<23) |
#define SPRITE_POINT_TEX_ON (1<<22) |
#define SPRITE_POINT_TEX_OFF 0 |
#define FLUSH_RENDER_CACHE (1<<18) |
#define FLUSH_TEXTURE_CACHE (1<<16) |
#define FIXED_LINE_WIDTH_MASK 0xfc00 |
#define ENABLE_FIXED_LINE_WIDTH (1<<15) |
#define FIXED_LINE_WIDTH(x) ((x)<<10) |
#define FIXED_POINT_WIDTH_MASK 0x3ff |
#define ENABLE_FIXED_POINT_WIDTH (1<<9) |
#define FIXED_POINT_WIDTH(x) (x) |
/* _3DSTATE_RASTERIZATION_RULES, p198 */ |
#define _3DSTATE_RASTER_RULES_CMD (CMD_3D|(0x07<<24)) |
#define ENABLE_POINT_RASTER_RULE (1<<15) |
#define OGL_POINT_RASTER_RULE (1<<13) |
#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8) |
#define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5) |
#define ENABLE_TRI_STRIP_PROVOKE_VRTX (1<<2) |
#define LINE_STRIP_PROVOKE_VRTX_MASK (3<<6) |
#define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6) |
#define TRI_FAN_PROVOKE_VRTX_MASK (3<<3) |
#define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3) |
#define TRI_STRIP_PROVOKE_VRTX_MASK (3<<0) |
#define TRI_STRIP_PROVOKE_VRTX(x) (x) |
/* _3DSTATE_SCISSOR_ENABLE, p200 */ |
#define _3DSTATE_SCISSOR_ENABLE_CMD (CMD_3D|(0x1c<<24)|(0x10<<19)) |
#define ENABLE_SCISSOR_RECT ((1<<1) | 1) |
#define DISABLE_SCISSOR_RECT (1<<1) |
/* _3DSTATE_SCISSOR_RECTANGLE_0, p201 */ |
#define _3DSTATE_SCISSOR_RECT_0_CMD (CMD_3D|(0x1d<<24)|(0x81<<16)|1) |
/* Dword 1 */ |
#define SCISSOR_RECT_0_YMIN(x) ((x)<<16) |
#define SCISSOR_RECT_0_XMIN(x) (x) |
/* Dword 2 */ |
#define SCISSOR_RECT_0_YMAX(x) ((x)<<16) |
#define SCISSOR_RECT_0_XMAX(x) (x) |
/* _3DSTATE_STENCIL_TEST, p202 */ |
#define _3DSTATE_STENCIL_TEST_CMD (CMD_3D|(0x09<<24)) |
#define ENABLE_STENCIL_PARMS (1<<23) |
#define STENCIL_OPS_MASK (0xffc000) |
#define STENCIL_FAIL_OP(x) ((x)<<20) |
#define STENCIL_PASS_DEPTH_FAIL_OP(x) ((x)<<17) |
#define STENCIL_PASS_DEPTH_PASS_OP(x) ((x)<<14) |
#define ENABLE_STENCIL_TEST_FUNC_MASK ((1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)) |
#define ENABLE_STENCIL_TEST_FUNC (1<<13) |
/* Uses COMPAREFUNC */ |
#define STENCIL_TEST_FUNC(x) ((x)<<9) |
#define STENCIL_REF_VALUE_MASK ((1<<8)|0xff) |
#define ENABLE_STENCIL_REF_VALUE (1<<8) |
#define STENCIL_REF_VALUE(x) (x) |
/* _3DSTATE_VERTEX_FORMAT, p204 */ |
#define _3DSTATE_VFT0_CMD (CMD_3D|(0x05<<24)) |
#define VFT0_POINT_WIDTH (1<<12) |
#define VFT0_TEX_COUNT_MASK (7<<8) |
#define VFT0_TEX_COUNT_SHIFT 8 |
#define VFT0_TEX_COUNT(x) ((x)<<8) |
#define VFT0_SPEC (1<<7) |
#define VFT0_DIFFUSE (1<<6) |
#define VFT0_DEPTH_OFFSET (1<<5) |
#define VFT0_XYZ (1<<1) |
#define VFT0_XYZW (2<<1) |
#define VFT0_XY (3<<1) |
#define VFT0_XYW (4<<1) |
#define VFT0_XYZW_MASK (7<<1) |
/* _3DSTATE_VERTEX_FORMAT_2, p206 */ |
#define _3DSTATE_VFT1_CMD (CMD_3D|(0x0a<<24)) |
#define VFT1_TEX7_FMT(x) ((x)<<14) |
#define VFT1_TEX6_FMT(x) ((x)<<12) |
#define VFT1_TEX5_FMT(x) ((x)<<10) |
#define VFT1_TEX4_FMT(x) ((x)<<8) |
#define VFT1_TEX3_FMT(x) ((x)<<6) |
#define VFT1_TEX2_FMT(x) ((x)<<4) |
#define VFT1_TEX1_FMT(x) ((x)<<2) |
#define VFT1_TEX0_FMT(x) (x) |
#define VFT1_TEX0_MASK 3 |
#define VFT1_TEX1_SHIFT 2 |
/*New stuff picked up along the way */ |
#define MLC_LOD_BIAS_MASK ((1<<7)-1) |
/* _3DSTATE_VERTEX_TRANSFORM, p207 */ |
#define _3DSTATE_VERTEX_TRANS_CMD (CMD_3D|(0x1d<<24)|(0x8b<<16)|0) |
#define _3DSTATE_VERTEX_TRANS_MTX_CMD (CMD_3D|(0x1d<<24)|(0x8b<<16)|6) |
/* Dword 1 */ |
#define ENABLE_VIEWPORT_TRANSFORM ((1<<31)|(1<<30)) |
#define DISABLE_VIEWPORT_TRANSFORM (1<<31) |
#define ENABLE_PERSP_DIVIDE ((1<<29)|(1<<28)) |
#define DISABLE_PERSP_DIVIDE (1<<29) |
#define VRTX_TRANS_LOAD_MATRICES 0x7421 |
#define VRTX_TRANS_NO_LOAD_MATRICES 0x0000 |
/* Dword 2 -> 7 are matrix elements */ |
/* _3DSTATE_W_STATE, p209 */ |
#define _3DSTATE_W_STATE_CMD (CMD_3D|(0x1d<<24)|(0x8d<<16)|1) |
/* Dword 1 */ |
#define MAGIC_W_STATE_DWORD1 0x00000008 |
/* Dword 2 */ |
#define WFAR_VALUE(x) (x) |
/* Stipple command, carried over from the i810, apparently: |
*/ |
#define _3DSTATE_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) |
#define ST1_ENABLE (1<<16) |
#define ST1_MASK (0xffff) |
#define _3DSTATE_LOAD_STATE_IMMEDIATE_2 ((0x3<<29)|(0x1d<<24)|(0x03<<16)) |
#define LOAD_TEXTURE_MAP0 (1<<11) |
#define LOAD_GLOBAL_COLOR_FACTOR (1<<6) |
#define TM0S0_ADDRESS_MASK 0xfffffffc |
#define TM0S0_USE_FENCE (1<<1) |
#define TM0S1_HEIGHT_SHIFT 21 |
#define TM0S1_WIDTH_SHIFT 10 |
#define TM0S1_PALETTE_SELECT (1<<9) |
#define TM0S1_MAPSURF_FORMAT_MASK (0x7 << 6) |
#define TM0S1_MAPSURF_FORMAT_SHIFT 6 |
#define MAPSURF_8BIT_INDEXED (0<<6) |
#define MAPSURF_8BIT (1<<6) |
#define MAPSURF_16BIT (2<<6) |
#define MAPSURF_32BIT (3<<6) |
#define MAPSURF_411 (4<<6) |
#define MAPSURF_422 (5<<6) |
#define MAPSURF_COMPRESSED (6<<6) |
#define MAPSURF_4BIT_INDEXED (7<<6) |
#define TM0S1_MT_FORMAT_MASK (0x7 << 3) |
#define TM0S1_MT_FORMAT_SHIFT 3 |
#define MT_4BIT_IDX_ARGB8888 (7<<3) /* SURFACE_4BIT_INDEXED */ |
#define MT_8BIT_IDX_RGB565 (0<<3) /* SURFACE_8BIT_INDEXED */ |
#define MT_8BIT_IDX_ARGB1555 (1<<3) |
#define MT_8BIT_IDX_ARGB4444 (2<<3) |
#define MT_8BIT_IDX_AY88 (3<<3) |
#define MT_8BIT_IDX_ABGR8888 (4<<3) |
#define MT_8BIT_IDX_BUMP_88DVDU (5<<3) |
#define MT_8BIT_IDX_BUMP_655LDVDU (6<<3) |
#define MT_8BIT_IDX_ARGB8888 (7<<3) |
#define MT_8BIT_I8 (0<<3) /* SURFACE_8BIT */ |
#define MT_8BIT_L8 (1<<3) |
#define MT_16BIT_RGB565 (0<<3) /* SURFACE_16BIT */ |
#define MT_16BIT_ARGB1555 (1<<3) |
#define MT_16BIT_ARGB4444 (2<<3) |
#define MT_16BIT_AY88 (3<<3) |
#define MT_16BIT_DIB_ARGB1555_8888 (4<<3) |
#define MT_16BIT_BUMP_88DVDU (5<<3) |
#define MT_16BIT_BUMP_655LDVDU (6<<3) |
#define MT_16BIT_DIB_RGB565_8888 (7<<3) |
#define MT_32BIT_ARGB8888 (0<<3) /* SURFACE_32BIT */ |
#define MT_32BIT_ABGR8888 (1<<3) |
#define MT_32BIT_XRGB8888 (2<<3) /* XXX: Guess from i915_reg.h */ |
#define MT_32BIT_BUMP_XLDVDU_8888 (6<<3) |
#define MT_32BIT_DIB_8888 (7<<3) |
#define MT_411_YUV411 (0<<3) /* SURFACE_411 */ |
#define MT_422_YCRCB_SWAPY (0<<3) /* SURFACE_422 */ |
#define MT_422_YCRCB_NORMAL (1<<3) |
#define MT_422_YCRCB_SWAPUV (2<<3) |
#define MT_422_YCRCB_SWAPUVY (3<<3) |
#define MT_COMPRESS_DXT1 (0<<3) /* SURFACE_COMPRESSED */ |
#define MT_COMPRESS_DXT2_3 (1<<3) |
#define MT_COMPRESS_DXT4_5 (2<<3) |
#define MT_COMPRESS_FXT1 (3<<3) |
#define TM0S1_COLORSPACE_CONVERSION (1 << 2) |
#define TM0S1_TILED_SURFACE (1 << 1) |
#define TM0S1_TILE_WALK (1 << 0) |
#define TM0S2_PITCH_SHIFT 21 |
#define TM0S2_CUBE_FACE_ENA_SHIFT 15 |
#define TM0S2_CUBE_FACE_ENA_MASK (1<<15) |
#define TM0S2_MAP_FORMAT (1<<14) |
#define TM0S2_VERTICAL_LINE_STRIDE (1<<13) |
#define TM0S2_VERITCAL_LINE_STRIDE_OFF (1<<12) |
#define TM0S2_OUTPUT_CHAN_SHIFT 10 |
#define TM0S2_OUTPUT_CHAN_MASK (3<<10) |
#define TM0S2_BASE_MIP_LEVEL_SHIFT 1 |
#define TM0S2_LOD_PRECLAMP (1 << 0) |
#define TM0S3_MIP_FILTER_MASK (0x3<<30) |
#define TM0S3_MIP_FILTER_SHIFT 30 |
#define MIPFILTER_NONE 0 |
#define MIPFILTER_NEAREST 1 |
#define MIPFILTER_LINEAR 3 |
#define TM0S3_MAG_FILTER_MASK (0x3<<28) |
#define TM0S3_MAG_FILTER_SHIFT 28 |
#define TM0S3_MIN_FILTER_MASK (0x3<<26) |
#define TM0S3_MIN_FILTER_SHIFT 26 |
#define FILTER_NEAREST 0 |
#define FILTER_LINEAR 1 |
#define FILTER_ANISOTROPIC 2 |
#define TM0S3_LOD_BIAS_SHIFT 17 |
#define TM0S3_LOD_BIAS_MASK (0x1ff<<17) |
#define TM0S3_MAX_MIP_SHIFT 9 |
#define TM0S3_MAX_MIP_MASK (0xff<<9) |
#define TM0S3_MIN_MIP_SHIFT 3 |
#define TM0S3_MIN_MIP_MASK (0x3f<<3) |
#define TM0S3_MIN_MIP_SHIFT_830 5 |
#define TM0S3_MIN_MIP_MASK_830 (0x3f<<5) |
#define TM0S3_KILL_PIXEL (1<<2) |
#define TM0S3_KEYED_FILTER (1<<1) |
#define TM0S3_CHROMA_KEY (1<<0) |
/* _3DSTATE_MAP_TEXEL_STREAM, p188 */ |
#define _3DSTATE_MAP_TEX_STREAM_CMD (CMD_3D|(0x1c<<24)|(0x05<<19)) |
#define DISABLE_TEX_STREAM_BUMP (1<<12) |
#define ENABLE_TEX_STREAM_BUMP ((1<<12)|(1<<11)) |
#define TEX_MODIFY_UNIT_0 0 |
#define TEX_MODIFY_UNIT_1 (1<<8) |
#define ENABLE_TEX_STREAM_COORD_SET (1<<7) |
#define TEX_STREAM_COORD_SET(x) ((x)<<4) |
#define ENABLE_TEX_STREAM_MAP_IDX (1<<3) |
#define TEX_STREAM_MAP_IDX(x) (x) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i830_state.c |
---|
0,0 → 1,1157 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "main/fbobject.h" |
#include "main/dd.h" |
#include "main/state.h" |
#include "drivers/common/driverfuncs.h" |
#include "intel_screen.h" |
#include "intel_batchbuffer.h" |
#include "intel_mipmap_tree.h" |
#include "intel_fbo.h" |
#include "intel_buffers.h" |
#include "i830_context.h" |
#include "i830_reg.h" |
#define FILE_DEBUG_FLAG DEBUG_STATE |
static void |
i830StencilFuncSeparate(struct gl_context * ctx, GLenum face, GLenum func, GLint ref, |
GLuint mask) |
{ |
struct i830_context *i830 = i830_context(ctx); |
int test = intel_translate_compare_func(func); |
mask = mask & 0xff; |
DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(func), ref, mask); |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK; |
i830->state.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK | |
STENCIL_TEST_MASK(mask)); |
i830->state.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_REF_VALUE_MASK | |
ENABLE_STENCIL_TEST_FUNC_MASK); |
i830->state.Ctx[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_REF_VALUE | |
ENABLE_STENCIL_TEST_FUNC | |
STENCIL_REF_VALUE(ref) | |
STENCIL_TEST_FUNC(test)); |
} |
static void |
i830StencilMaskSeparate(struct gl_context * ctx, GLenum face, GLuint mask) |
{ |
struct i830_context *i830 = i830_context(ctx); |
DBG("%s : mask 0x%x\n", __FUNCTION__, mask); |
mask = mask & 0xff; |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK; |
i830->state.Ctx[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK | |
STENCIL_WRITE_MASK(mask)); |
} |
static void |
i830StencilOpSeparate(struct gl_context * ctx, GLenum face, GLenum fail, GLenum zfail, |
GLenum zpass) |
{ |
struct i830_context *i830 = i830_context(ctx); |
int fop, dfop, dpop; |
DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(fail), |
_mesa_lookup_enum_by_nr(zfail), |
_mesa_lookup_enum_by_nr(zpass)); |
fop = 0; |
dfop = 0; |
dpop = 0; |
switch (fail) { |
case GL_KEEP: |
fop = STENCILOP_KEEP; |
break; |
case GL_ZERO: |
fop = STENCILOP_ZERO; |
break; |
case GL_REPLACE: |
fop = STENCILOP_REPLACE; |
break; |
case GL_INCR: |
fop = STENCILOP_INCRSAT; |
break; |
case GL_DECR: |
fop = STENCILOP_DECRSAT; |
break; |
case GL_INCR_WRAP: |
fop = STENCILOP_INCR; |
break; |
case GL_DECR_WRAP: |
fop = STENCILOP_DECR; |
break; |
case GL_INVERT: |
fop = STENCILOP_INVERT; |
break; |
default: |
break; |
} |
switch (zfail) { |
case GL_KEEP: |
dfop = STENCILOP_KEEP; |
break; |
case GL_ZERO: |
dfop = STENCILOP_ZERO; |
break; |
case GL_REPLACE: |
dfop = STENCILOP_REPLACE; |
break; |
case GL_INCR: |
dfop = STENCILOP_INCRSAT; |
break; |
case GL_DECR: |
dfop = STENCILOP_DECRSAT; |
break; |
case GL_INCR_WRAP: |
dfop = STENCILOP_INCR; |
break; |
case GL_DECR_WRAP: |
dfop = STENCILOP_DECR; |
break; |
case GL_INVERT: |
dfop = STENCILOP_INVERT; |
break; |
default: |
break; |
} |
switch (zpass) { |
case GL_KEEP: |
dpop = STENCILOP_KEEP; |
break; |
case GL_ZERO: |
dpop = STENCILOP_ZERO; |
break; |
case GL_REPLACE: |
dpop = STENCILOP_REPLACE; |
break; |
case GL_INCR: |
dpop = STENCILOP_INCRSAT; |
break; |
case GL_DECR: |
dpop = STENCILOP_DECRSAT; |
break; |
case GL_INCR_WRAP: |
dpop = STENCILOP_INCR; |
break; |
case GL_DECR_WRAP: |
dpop = STENCILOP_DECR; |
break; |
case GL_INVERT: |
dpop = STENCILOP_INVERT; |
break; |
default: |
break; |
} |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK); |
i830->state.Ctx[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_PARMS | |
STENCIL_FAIL_OP(fop) | |
STENCIL_PASS_DEPTH_FAIL_OP |
(dfop) | |
STENCIL_PASS_DEPTH_PASS_OP |
(dpop)); |
} |
static void |
i830AlphaFunc(struct gl_context * ctx, GLenum func, GLfloat ref) |
{ |
struct i830_context *i830 = i830_context(ctx); |
int test = intel_translate_compare_func(func); |
GLubyte refByte; |
GLuint refInt; |
UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref); |
refInt = (GLuint) refByte; |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_STATE2] &= ~ALPHA_TEST_REF_MASK; |
i830->state.Ctx[I830_CTXREG_STATE2] |= (ENABLE_ALPHA_TEST_FUNC | |
ENABLE_ALPHA_REF_VALUE | |
ALPHA_TEST_FUNC(test) | |
ALPHA_REF_VALUE(refInt)); |
} |
/** |
* Makes sure that the proper enables are set for LogicOp, Independant Alpha |
* Blend, and Blending. It needs to be called from numerous places where we |
* could change the LogicOp or Independant Alpha Blend without subsequent |
* calls to glEnable. |
* |
* \todo |
* This function is substantially different from the old i830-specific driver. |
* I'm not sure which is correct. |
*/ |
static void |
i830EvalLogicOpBlendState(struct gl_context * ctx) |
{ |
struct i830_context *i830 = i830_context(ctx); |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
if (ctx->Color.ColorLogicOpEnabled) { |
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | |
ENABLE_LOGIC_OP_MASK); |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND | |
ENABLE_LOGIC_OP); |
} |
else if (ctx->Color.BlendEnabled) { |
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | |
ENABLE_LOGIC_OP_MASK); |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (ENABLE_COLOR_BLEND | |
DISABLE_LOGIC_OP); |
} |
else { |
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | |
ENABLE_LOGIC_OP_MASK); |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND | |
DISABLE_LOGIC_OP); |
} |
} |
static void |
i830BlendColor(struct gl_context * ctx, const GLfloat color[4]) |
{ |
struct i830_context *i830 = i830_context(ctx); |
GLubyte r, g, b, a; |
DBG("%s\n", __FUNCTION__); |
UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]); |
UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]); |
UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]); |
UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]); |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_BLENDCOLOR1] = |
(a << 24) | (r << 16) | (g << 8) | b; |
} |
/** |
* Sets both the blend equation (called "function" in i830 docs) and the |
* blend function (called "factor" in i830 docs). This is done in a single |
* function because some blend equations (i.e., \c GL_MIN and \c GL_MAX) |
* change the interpretation of the blend function. |
*/ |
static void |
i830_set_blend_state(struct gl_context * ctx) |
{ |
struct i830_context *i830 = i830_context(ctx); |
int funcA; |
int funcRGB; |
int eqnA; |
int eqnRGB; |
int iab; |
int s1; |
funcRGB = |
SRC_BLND_FACT(intel_translate_blend_factor(ctx->Color.Blend[0].SrcRGB)) |
| DST_BLND_FACT(intel_translate_blend_factor(ctx->Color.Blend[0].DstRGB)); |
switch (ctx->Color.Blend[0].EquationRGB) { |
case GL_FUNC_ADD: |
eqnRGB = BLENDFUNC_ADD; |
break; |
case GL_MIN: |
eqnRGB = BLENDFUNC_MIN; |
funcRGB = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); |
break; |
case GL_MAX: |
eqnRGB = BLENDFUNC_MAX; |
funcRGB = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); |
break; |
case GL_FUNC_SUBTRACT: |
eqnRGB = BLENDFUNC_SUB; |
break; |
case GL_FUNC_REVERSE_SUBTRACT: |
eqnRGB = BLENDFUNC_RVRSE_SUB; |
break; |
default: |
fprintf(stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n", |
__FUNCTION__, __LINE__, ctx->Color.Blend[0].EquationRGB); |
return; |
} |
funcA = SRC_ABLEND_FACT(intel_translate_blend_factor(ctx->Color.Blend[0].SrcA)) |
| DST_ABLEND_FACT(intel_translate_blend_factor(ctx->Color.Blend[0].DstA)); |
switch (ctx->Color.Blend[0].EquationA) { |
case GL_FUNC_ADD: |
eqnA = BLENDFUNC_ADD; |
break; |
case GL_MIN: |
eqnA = BLENDFUNC_MIN; |
funcA = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); |
break; |
case GL_MAX: |
eqnA = BLENDFUNC_MAX; |
funcA = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE); |
break; |
case GL_FUNC_SUBTRACT: |
eqnA = BLENDFUNC_SUB; |
break; |
case GL_FUNC_REVERSE_SUBTRACT: |
eqnA = BLENDFUNC_RVRSE_SUB; |
break; |
default: |
fprintf(stderr, "[%s:%u] Invalid alpha blend equation (0x%04x).\n", |
__FUNCTION__, __LINE__, ctx->Color.Blend[0].EquationA); |
return; |
} |
iab = eqnA | funcA |
| _3DSTATE_INDPT_ALPHA_BLEND_CMD |
| ENABLE_SRC_ABLEND_FACTOR | ENABLE_DST_ABLEND_FACTOR |
| ENABLE_ALPHA_BLENDFUNC; |
s1 = eqnRGB | funcRGB |
| _3DSTATE_MODES_1_CMD |
| ENABLE_SRC_BLND_FACTOR | ENABLE_DST_BLND_FACTOR |
| ENABLE_COLR_BLND_FUNC; |
if ((eqnA | funcA) != (eqnRGB | funcRGB)) |
iab |= ENABLE_INDPT_ALPHA_BLEND; |
else |
iab |= DISABLE_INDPT_ALPHA_BLEND; |
if (iab != i830->state.Ctx[I830_CTXREG_IALPHAB] || |
s1 != i830->state.Ctx[I830_CTXREG_STATE1]) { |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_IALPHAB] = iab; |
i830->state.Ctx[I830_CTXREG_STATE1] = s1; |
} |
/* This will catch a logicop blend equation. It will also ensure |
* independant alpha blend is really in the correct state (either enabled |
* or disabled) if blending is already enabled. |
*/ |
i830EvalLogicOpBlendState(ctx); |
if (0) { |
fprintf(stderr, |
"[%s:%u] STATE1: 0x%08x IALPHAB: 0x%08x blend is %sabled\n", |
__FUNCTION__, __LINE__, i830->state.Ctx[I830_CTXREG_STATE1], |
i830->state.Ctx[I830_CTXREG_IALPHAB], |
(ctx->Color.BlendEnabled) ? "en" : "dis"); |
} |
} |
static void |
i830BlendEquationSeparate(struct gl_context * ctx, GLenum modeRGB, GLenum modeA) |
{ |
DBG("%s -> %s, %s\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(modeRGB), |
_mesa_lookup_enum_by_nr(modeA)); |
(void) modeRGB; |
(void) modeA; |
i830_set_blend_state(ctx); |
} |
static void |
i830BlendFuncSeparate(struct gl_context * ctx, GLenum sfactorRGB, |
GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA) |
{ |
DBG("%s -> RGB(%s, %s) A(%s, %s)\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(sfactorRGB), |
_mesa_lookup_enum_by_nr(dfactorRGB), |
_mesa_lookup_enum_by_nr(sfactorA), |
_mesa_lookup_enum_by_nr(dfactorA)); |
(void) sfactorRGB; |
(void) dfactorRGB; |
(void) sfactorA; |
(void) dfactorA; |
i830_set_blend_state(ctx); |
} |
static void |
i830DepthFunc(struct gl_context * ctx, GLenum func) |
{ |
struct i830_context *i830 = i830_context(ctx); |
int test = intel_translate_compare_func(func); |
DBG("%s\n", __FUNCTION__); |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_STATE3] &= ~DEPTH_TEST_FUNC_MASK; |
i830->state.Ctx[I830_CTXREG_STATE3] |= (ENABLE_DEPTH_TEST_FUNC | |
DEPTH_TEST_FUNC(test)); |
} |
static void |
i830DepthMask(struct gl_context * ctx, GLboolean flag) |
{ |
struct i830_context *i830 = i830_context(ctx); |
DBG("%s flag (%d)\n", __FUNCTION__, flag); |
if (!ctx->DrawBuffer || !ctx->DrawBuffer->Visual.depthBits) |
flag = false; |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK; |
if (flag && ctx->Depth.Test) |
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_DEPTH_WRITE; |
else |
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE; |
} |
/** Called from ctx->Driver.Viewport() */ |
static void |
i830Viewport(struct gl_context * ctx, |
GLint x, GLint y, GLsizei width, GLsizei height) |
{ |
intelCalcViewport(ctx); |
} |
/** Called from ctx->Driver.DepthRange() */ |
static void |
i830DepthRange(struct gl_context * ctx, GLclampd nearval, GLclampd farval) |
{ |
intelCalcViewport(ctx); |
} |
/* ============================================================= |
* Polygon stipple |
* |
* The i830 supports a 4x4 stipple natively, GL wants 32x32. |
* Fortunately stipple is usually a repeating pattern. |
*/ |
static void |
i830PolygonStipple(struct gl_context * ctx, const GLubyte * mask) |
{ |
struct i830_context *i830 = i830_context(ctx); |
const GLubyte *m; |
GLubyte p[4]; |
int i, j, k; |
int active = (ctx->Polygon.StippleFlag && |
i830->intel.reduced_primitive == GL_TRIANGLES); |
GLuint newMask; |
if (active) { |
I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE); |
i830->state.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE; |
} |
/* Use the already unpacked stipple data from the context rather than the |
* uninterpreted mask passed in. |
*/ |
mask = (const GLubyte *)ctx->PolygonStipple; |
m = mask; |
p[0] = mask[12] & 0xf; |
p[0] |= p[0] << 4; |
p[1] = mask[8] & 0xf; |
p[1] |= p[1] << 4; |
p[2] = mask[4] & 0xf; |
p[2] |= p[2] << 4; |
p[3] = mask[0] & 0xf; |
p[3] |= p[3] << 4; |
for (k = 0; k < 8; k++) |
for (j = 3; j >= 0; j--) |
for (i = 0; i < 4; i++, m++) |
if (*m != p[j]) { |
i830->intel.hw_stipple = 0; |
return; |
} |
newMask = (((p[0] & 0xf) << 0) | |
((p[1] & 0xf) << 4) | |
((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12)); |
if (newMask == 0xffff || newMask == 0x0) { |
/* this is needed to make conform pass */ |
i830->intel.hw_stipple = 0; |
return; |
} |
i830->state.Stipple[I830_STPREG_ST1] &= ~0xffff; |
i830->state.Stipple[I830_STPREG_ST1] |= newMask; |
i830->intel.hw_stipple = 1; |
if (active) |
i830->state.Stipple[I830_STPREG_ST1] |= ST1_ENABLE; |
} |
/* ============================================================= |
* Hardware clipping |
*/ |
static void |
i830Scissor(struct gl_context * ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
{ |
struct i830_context *i830 = i830_context(ctx); |
int x1, y1, x2, y2; |
if (!ctx->DrawBuffer) |
return; |
DBG("%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h); |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
x1 = x; |
y1 = ctx->DrawBuffer->Height - (y + h); |
x2 = x + w - 1; |
y2 = y1 + h - 1; |
DBG("%s %d..%d,%d..%d (inverted)\n", __FUNCTION__, x1, x2, y1, y2); |
} |
else { |
/* FBO - not inverted |
*/ |
x1 = x; |
y1 = y; |
x2 = x + w - 1; |
y2 = y + h - 1; |
DBG("%s %d..%d,%d..%d (not inverted)\n", __FUNCTION__, x1, x2, y1, y2); |
} |
x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1); |
y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1); |
x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1); |
y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1); |
DBG("%s %d..%d,%d..%d (clamped)\n", __FUNCTION__, x1, x2, y1, y2); |
I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS); |
i830->state.Buffer[I830_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff); |
i830->state.Buffer[I830_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff); |
} |
static void |
i830LogicOp(struct gl_context * ctx, GLenum opcode) |
{ |
struct i830_context *i830 = i830_context(ctx); |
int tmp = intel_translate_logic_op(opcode); |
DBG("%s\n", __FUNCTION__); |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_STATE4] &= ~LOGICOP_MASK; |
i830->state.Ctx[I830_CTXREG_STATE4] |= LOGIC_OP_FUNC(tmp); |
} |
static void |
i830CullFaceFrontFace(struct gl_context * ctx, GLenum unused) |
{ |
struct i830_context *i830 = i830_context(ctx); |
GLuint mode; |
DBG("%s\n", __FUNCTION__); |
if (!ctx->Polygon.CullFlag) { |
mode = CULLMODE_NONE; |
} |
else if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) { |
mode = CULLMODE_CW; |
if (ctx->Polygon.CullFaceMode == GL_FRONT) |
mode ^= (CULLMODE_CW ^ CULLMODE_CCW); |
if (ctx->Polygon.FrontFace != GL_CCW) |
mode ^= (CULLMODE_CW ^ CULLMODE_CCW); |
} |
else { |
mode = CULLMODE_BOTH; |
} |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_STATE3] &= ~CULLMODE_MASK; |
i830->state.Ctx[I830_CTXREG_STATE3] |= ENABLE_CULL_MODE | mode; |
} |
static void |
i830LineWidth(struct gl_context * ctx, GLfloat widthf) |
{ |
struct i830_context *i830 = i830_context(ctx); |
int width; |
int state5; |
DBG("%s\n", __FUNCTION__); |
width = (int) (widthf * 2); |
width = CLAMP(width, 1, 15); |
state5 = i830->state.Ctx[I830_CTXREG_STATE5] & ~FIXED_LINE_WIDTH_MASK; |
state5 |= (ENABLE_FIXED_LINE_WIDTH | FIXED_LINE_WIDTH(width)); |
if (state5 != i830->state.Ctx[I830_CTXREG_STATE5]) { |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_STATE5] = state5; |
} |
} |
static void |
i830PointSize(struct gl_context * ctx, GLfloat size) |
{ |
struct i830_context *i830 = i830_context(ctx); |
GLint point_size = (int) size; |
DBG("%s\n", __FUNCTION__); |
point_size = CLAMP(point_size, 1, 256); |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_STATE5] &= ~FIXED_POINT_WIDTH_MASK; |
i830->state.Ctx[I830_CTXREG_STATE5] |= (ENABLE_FIXED_POINT_WIDTH | |
FIXED_POINT_WIDTH(point_size)); |
} |
/* ============================================================= |
* Color masks |
*/ |
static void |
i830ColorMask(struct gl_context * ctx, |
GLboolean r, GLboolean g, GLboolean b, GLboolean a) |
{ |
struct i830_context *i830 = i830_context(ctx); |
GLuint tmp = 0; |
DBG("%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a); |
tmp = ((i830->state.Ctx[I830_CTXREG_ENABLES_2] & ~WRITEMASK_MASK) | |
ENABLE_COLOR_MASK | |
ENABLE_COLOR_WRITE | |
((!r) << WRITEMASK_RED_SHIFT) | |
((!g) << WRITEMASK_GREEN_SHIFT) | |
((!b) << WRITEMASK_BLUE_SHIFT) | ((!a) << WRITEMASK_ALPHA_SHIFT)); |
if (tmp != i830->state.Ctx[I830_CTXREG_ENABLES_2]) { |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_ENABLES_2] = tmp; |
} |
} |
static void |
update_specular(struct gl_context * ctx) |
{ |
struct i830_context *i830 = i830_context(ctx); |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_SPEC_ADD_MASK; |
if (_mesa_need_secondary_color(ctx)) |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_SPEC_ADD; |
else |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_SPEC_ADD; |
} |
static void |
i830LightModelfv(struct gl_context * ctx, GLenum pname, const GLfloat * param) |
{ |
DBG("%s\n", __FUNCTION__); |
if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { |
update_specular(ctx); |
} |
} |
/* In Mesa 3.5 we can reliably do native flatshading. |
*/ |
static void |
i830ShadeModel(struct gl_context * ctx, GLenum mode) |
{ |
struct i830_context *i830 = i830_context(ctx); |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
#define SHADE_MODE_MASK ((1<<10)|(1<<8)|(1<<6)|(1<<4)) |
i830->state.Ctx[I830_CTXREG_STATE3] &= ~SHADE_MODE_MASK; |
if (mode == GL_FLAT) { |
i830->state.Ctx[I830_CTXREG_STATE3] |= |
(ALPHA_SHADE_MODE(SHADE_MODE_FLAT) | FOG_SHADE_MODE(SHADE_MODE_FLAT) |
| SPEC_SHADE_MODE(SHADE_MODE_FLAT) | |
COLOR_SHADE_MODE(SHADE_MODE_FLAT)); |
} |
else { |
i830->state.Ctx[I830_CTXREG_STATE3] |= |
(ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) | |
FOG_SHADE_MODE(SHADE_MODE_LINEAR) | |
SPEC_SHADE_MODE(SHADE_MODE_LINEAR) | |
COLOR_SHADE_MODE(SHADE_MODE_LINEAR)); |
} |
} |
/* ============================================================= |
* Fog |
*/ |
static void |
i830Fogfv(struct gl_context * ctx, GLenum pname, const GLfloat * param) |
{ |
struct i830_context *i830 = i830_context(ctx); |
DBG("%s\n", __FUNCTION__); |
if (pname == GL_FOG_COLOR) { |
GLuint color = (((GLubyte) (ctx->Fog.Color[0] * 255.0F) << 16) | |
((GLubyte) (ctx->Fog.Color[1] * 255.0F) << 8) | |
((GLubyte) (ctx->Fog.Color[2] * 255.0F) << 0)); |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_FOGCOLOR] = |
(_3DSTATE_FOG_COLOR_CMD | color); |
} |
} |
/* ============================================================= |
*/ |
static void |
i830Enable(struct gl_context * ctx, GLenum cap, GLboolean state) |
{ |
struct i830_context *i830 = i830_context(ctx); |
switch (cap) { |
case GL_LIGHTING: |
case GL_COLOR_SUM: |
update_specular(ctx); |
break; |
case GL_ALPHA_TEST: |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_ALPHA_TEST_MASK; |
if (state) |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_ALPHA_TEST; |
else |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_ALPHA_TEST; |
break; |
case GL_BLEND: |
i830EvalLogicOpBlendState(ctx); |
break; |
case GL_COLOR_LOGIC_OP: |
i830EvalLogicOpBlendState(ctx); |
/* Logicop doesn't seem to work at 16bpp: |
*/ |
if (i830->intel.ctx.Visual.rgbBits == 16) |
FALLBACK(&i830->intel, I830_FALLBACK_LOGICOP, state); |
break; |
case GL_DITHER: |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_ENABLES_2] &= ~ENABLE_DITHER; |
if (state) |
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_DITHER; |
else |
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= DISABLE_DITHER; |
break; |
case GL_DEPTH_TEST: |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK; |
if (!ctx->DrawBuffer || !ctx->DrawBuffer->Visual.depthBits) |
state = false; |
if (state) |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_DEPTH_TEST; |
else |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST; |
/* Also turn off depth writes when GL_DEPTH_TEST is disabled: |
*/ |
i830DepthMask(ctx, ctx->Depth.Mask); |
break; |
case GL_SCISSOR_TEST: |
I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS); |
if (state) |
i830->state.Buffer[I830_DESTREG_SENABLE] = |
(_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT); |
else |
i830->state.Buffer[I830_DESTREG_SENABLE] = |
(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); |
break; |
case GL_LINE_SMOOTH: |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_AA] &= ~AA_LINE_ENABLE; |
if (state) |
i830->state.Ctx[I830_CTXREG_AA] |= AA_LINE_ENABLE; |
else |
i830->state.Ctx[I830_CTXREG_AA] |= AA_LINE_DISABLE; |
break; |
case GL_FOG: |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_FOG_MASK; |
if (state) |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_FOG; |
else |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_FOG; |
break; |
case GL_CULL_FACE: |
i830CullFaceFrontFace(ctx, 0); |
break; |
case GL_TEXTURE_2D: |
break; |
case GL_STENCIL_TEST: |
{ |
bool hw_stencil = false; |
if (ctx->DrawBuffer) { |
struct intel_renderbuffer *irbStencil |
= intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); |
hw_stencil = (irbStencil && irbStencil->mt); |
} |
if (hw_stencil) { |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
if (state) { |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST; |
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE; |
} |
else { |
i830->state.Ctx[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST; |
i830->state.Ctx[I830_CTXREG_ENABLES_2] &= |
~ENABLE_STENCIL_WRITE; |
i830->state.Ctx[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST; |
i830->state.Ctx[I830_CTXREG_ENABLES_2] |= |
DISABLE_STENCIL_WRITE; |
} |
} |
else { |
FALLBACK(&i830->intel, I830_FALLBACK_STENCIL, state); |
} |
} |
break; |
case GL_POLYGON_STIPPLE: |
/* The stipple command worked on my 855GM box, but not my 845G. |
* I'll do more testing later to find out exactly which hardware |
* supports it. Disabled for now. |
*/ |
if (i830->intel.hw_stipple && |
i830->intel.reduced_primitive == GL_TRIANGLES) { |
I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE); |
i830->state.Stipple[I830_STPREG_ST1] &= ~ST1_ENABLE; |
if (state) |
i830->state.Stipple[I830_STPREG_ST1] |= ST1_ENABLE; |
} |
break; |
default: |
; |
} |
} |
static void |
i830_init_packets(struct i830_context *i830) |
{ |
/* Zero all state */ |
memset(&i830->state, 0, sizeof(i830->state)); |
/* Set default blend state */ |
i830->state.TexBlend[0][0] = (_3DSTATE_MAP_BLEND_OP_CMD(0) | |
TEXPIPE_COLOR | |
ENABLE_TEXOUTPUT_WRT_SEL | |
TEXOP_OUTPUT_CURRENT | |
DISABLE_TEX_CNTRL_STAGE | |
TEXOP_SCALE_1X | |
TEXOP_MODIFY_PARMS | |
TEXOP_LAST_STAGE | TEXBLENDOP_ARG1); |
i830->state.TexBlend[0][1] = (_3DSTATE_MAP_BLEND_OP_CMD(0) | |
TEXPIPE_ALPHA | |
ENABLE_TEXOUTPUT_WRT_SEL | |
TEXOP_OUTPUT_CURRENT | |
TEXOP_SCALE_1X | |
TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1); |
i830->state.TexBlend[0][2] = (_3DSTATE_MAP_BLEND_ARG_CMD(0) | |
TEXPIPE_COLOR | |
TEXBLEND_ARG1 | |
TEXBLENDARG_MODIFY_PARMS | |
TEXBLENDARG_DIFFUSE); |
i830->state.TexBlend[0][3] = (_3DSTATE_MAP_BLEND_ARG_CMD(0) | |
TEXPIPE_ALPHA | |
TEXBLEND_ARG1 | |
TEXBLENDARG_MODIFY_PARMS | |
TEXBLENDARG_DIFFUSE); |
i830->state.TexBlendWordsUsed[0] = 4; |
i830->state.Ctx[I830_CTXREG_VF] = 0; |
i830->state.Ctx[I830_CTXREG_VF2] = 0; |
i830->state.Ctx[I830_CTXREG_AA] = (_3DSTATE_AA_CMD | |
AA_LINE_ECAAR_WIDTH_ENABLE | |
AA_LINE_ECAAR_WIDTH_1_0 | |
AA_LINE_REGION_WIDTH_ENABLE | |
AA_LINE_REGION_WIDTH_1_0 | |
AA_LINE_DISABLE); |
i830->state.Ctx[I830_CTXREG_ENABLES_1] = (_3DSTATE_ENABLES_1_CMD | |
DISABLE_LOGIC_OP | |
DISABLE_STENCIL_TEST | |
DISABLE_DEPTH_BIAS | |
DISABLE_SPEC_ADD | |
DISABLE_FOG | |
DISABLE_ALPHA_TEST | |
DISABLE_COLOR_BLEND | |
DISABLE_DEPTH_TEST); |
#if 000 /* XXX all the stencil enable state is set in i830Enable(), right? */ |
if (i830->intel.hw_stencil) { |
i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD | |
ENABLE_STENCIL_WRITE | |
ENABLE_TEX_CACHE | |
ENABLE_DITHER | |
ENABLE_COLOR_MASK | |
/* set no color comps disabled */ |
ENABLE_COLOR_WRITE | |
ENABLE_DEPTH_WRITE); |
} |
else |
#endif |
{ |
i830->state.Ctx[I830_CTXREG_ENABLES_2] = (_3DSTATE_ENABLES_2_CMD | |
DISABLE_STENCIL_WRITE | |
ENABLE_TEX_CACHE | |
ENABLE_DITHER | |
ENABLE_COLOR_MASK | |
/* set no color comps disabled */ |
ENABLE_COLOR_WRITE | |
ENABLE_DEPTH_WRITE); |
} |
i830->state.Ctx[I830_CTXREG_STATE1] = (_3DSTATE_MODES_1_CMD | |
ENABLE_COLR_BLND_FUNC | |
BLENDFUNC_ADD | |
ENABLE_SRC_BLND_FACTOR | |
SRC_BLND_FACT(BLENDFACT_ONE) | |
ENABLE_DST_BLND_FACTOR | |
DST_BLND_FACT(BLENDFACT_ZERO)); |
i830->state.Ctx[I830_CTXREG_STATE2] = (_3DSTATE_MODES_2_CMD | |
ENABLE_GLOBAL_DEPTH_BIAS | |
GLOBAL_DEPTH_BIAS(0) | |
ENABLE_ALPHA_TEST_FUNC | |
ALPHA_TEST_FUNC(COMPAREFUNC_ALWAYS) |
| ALPHA_REF_VALUE(0)); |
i830->state.Ctx[I830_CTXREG_STATE3] = (_3DSTATE_MODES_3_CMD | |
ENABLE_DEPTH_TEST_FUNC | |
DEPTH_TEST_FUNC(COMPAREFUNC_LESS) | |
ENABLE_ALPHA_SHADE_MODE | |
ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) |
| ENABLE_FOG_SHADE_MODE | |
FOG_SHADE_MODE(SHADE_MODE_LINEAR) | |
ENABLE_SPEC_SHADE_MODE | |
SPEC_SHADE_MODE(SHADE_MODE_LINEAR) | |
ENABLE_COLOR_SHADE_MODE | |
COLOR_SHADE_MODE(SHADE_MODE_LINEAR) |
| ENABLE_CULL_MODE | CULLMODE_NONE); |
i830->state.Ctx[I830_CTXREG_STATE4] = (_3DSTATE_MODES_4_CMD | |
ENABLE_LOGIC_OP_FUNC | |
LOGIC_OP_FUNC(LOGICOP_COPY) | |
ENABLE_STENCIL_TEST_MASK | |
STENCIL_TEST_MASK(0xff) | |
ENABLE_STENCIL_WRITE_MASK | |
STENCIL_WRITE_MASK(0xff)); |
i830->state.Ctx[I830_CTXREG_STENCILTST] = (_3DSTATE_STENCIL_TEST_CMD | |
ENABLE_STENCIL_PARMS | |
STENCIL_FAIL_OP(STENCILOP_KEEP) |
| |
STENCIL_PASS_DEPTH_FAIL_OP |
(STENCILOP_KEEP) | |
STENCIL_PASS_DEPTH_PASS_OP |
(STENCILOP_KEEP) | |
ENABLE_STENCIL_TEST_FUNC | |
STENCIL_TEST_FUNC |
(COMPAREFUNC_ALWAYS) | |
ENABLE_STENCIL_REF_VALUE | |
STENCIL_REF_VALUE(0)); |
i830->state.Ctx[I830_CTXREG_STATE5] = (_3DSTATE_MODES_5_CMD | FLUSH_TEXTURE_CACHE | ENABLE_SPRITE_POINT_TEX | SPRITE_POINT_TEX_OFF | ENABLE_FIXED_LINE_WIDTH | FIXED_LINE_WIDTH(0x2) | /* 1.0 */ |
ENABLE_FIXED_POINT_WIDTH | |
FIXED_POINT_WIDTH(1)); |
i830->state.Ctx[I830_CTXREG_IALPHAB] = (_3DSTATE_INDPT_ALPHA_BLEND_CMD | |
DISABLE_INDPT_ALPHA_BLEND | |
ENABLE_ALPHA_BLENDFUNC | |
ABLENDFUNC_ADD); |
i830->state.Ctx[I830_CTXREG_FOGCOLOR] = (_3DSTATE_FOG_COLOR_CMD | |
FOG_COLOR_RED(0) | |
FOG_COLOR_GREEN(0) | |
FOG_COLOR_BLUE(0)); |
i830->state.Ctx[I830_CTXREG_BLENDCOLOR0] = _3DSTATE_CONST_BLEND_COLOR_CMD; |
i830->state.Ctx[I830_CTXREG_BLENDCOLOR1] = 0; |
i830->state.Ctx[I830_CTXREG_MCSB0] = _3DSTATE_MAP_COORD_SETBIND_CMD; |
i830->state.Ctx[I830_CTXREG_MCSB1] = (TEXBIND_SET3(TEXCOORDSRC_VTXSET_3) | |
TEXBIND_SET2(TEXCOORDSRC_VTXSET_2) | |
TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) | |
TEXBIND_SET0(TEXCOORDSRC_VTXSET_0)); |
i830->state.RasterRules[I830_RASTER_RULES] = (_3DSTATE_RASTER_RULES_CMD | |
ENABLE_POINT_RASTER_RULE | |
OGL_POINT_RASTER_RULE | |
ENABLE_LINE_STRIP_PROVOKE_VRTX | |
ENABLE_TRI_FAN_PROVOKE_VRTX | |
ENABLE_TRI_STRIP_PROVOKE_VRTX | |
LINE_STRIP_PROVOKE_VRTX(1) | |
TRI_FAN_PROVOKE_VRTX(2) | |
TRI_STRIP_PROVOKE_VRTX(2)); |
i830->state.Stipple[I830_STPREG_ST0] = _3DSTATE_STIPPLE; |
i830->state.Buffer[I830_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD; |
i830->state.Buffer[I830_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD | |
DISABLE_SCISSOR_RECT); |
i830->state.Buffer[I830_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD; |
i830->state.Buffer[I830_DESTREG_SR1] = 0; |
i830->state.Buffer[I830_DESTREG_SR2] = 0; |
} |
void |
i830_update_provoking_vertex(struct gl_context * ctx) |
{ |
struct i830_context *i830 = i830_context(ctx); |
I830_STATECHANGE(i830, I830_UPLOAD_RASTER_RULES); |
i830->state.RasterRules[I830_RASTER_RULES] &= ~(LINE_STRIP_PROVOKE_VRTX_MASK | |
TRI_FAN_PROVOKE_VRTX_MASK | |
TRI_STRIP_PROVOKE_VRTX_MASK); |
/* _NEW_LIGHT */ |
if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION) { |
i830->state.RasterRules[I830_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(1) | |
TRI_FAN_PROVOKE_VRTX(2) | |
TRI_STRIP_PROVOKE_VRTX(2)); |
} else { |
i830->state.RasterRules[I830_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(0) | |
TRI_FAN_PROVOKE_VRTX(1) | |
TRI_STRIP_PROVOKE_VRTX(0)); |
} |
} |
/* Fallback to swrast for select and feedback. |
*/ |
static void |
i830RenderMode(struct gl_context *ctx, GLenum mode) |
{ |
struct intel_context *intel = intel_context(ctx); |
FALLBACK(intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER)); |
} |
void |
i830InitStateFuncs(struct dd_function_table *functions) |
{ |
functions->AlphaFunc = i830AlphaFunc; |
functions->BlendColor = i830BlendColor; |
functions->BlendEquationSeparate = i830BlendEquationSeparate; |
functions->BlendFuncSeparate = i830BlendFuncSeparate; |
functions->ColorMask = i830ColorMask; |
functions->CullFace = i830CullFaceFrontFace; |
functions->DepthFunc = i830DepthFunc; |
functions->DepthMask = i830DepthMask; |
functions->Enable = i830Enable; |
functions->Fogfv = i830Fogfv; |
functions->FrontFace = i830CullFaceFrontFace; |
functions->LightModelfv = i830LightModelfv; |
functions->LineWidth = i830LineWidth; |
functions->LogicOpcode = i830LogicOp; |
functions->PointSize = i830PointSize; |
functions->PolygonStipple = i830PolygonStipple; |
functions->RenderMode = i830RenderMode; |
functions->Scissor = i830Scissor; |
functions->ShadeModel = i830ShadeModel; |
functions->StencilFuncSeparate = i830StencilFuncSeparate; |
functions->StencilMaskSeparate = i830StencilMaskSeparate; |
functions->StencilOpSeparate = i830StencilOpSeparate; |
functions->DepthRange = i830DepthRange; |
functions->Viewport = i830Viewport; |
} |
void |
i830InitState(struct i830_context *i830) |
{ |
struct gl_context *ctx = &i830->intel.ctx; |
i830_init_packets(i830); |
_mesa_init_driver_state(ctx); |
i830->state.emitted = 0; |
i830->state.active = (I830_UPLOAD_INVARIENT | |
I830_UPLOAD_RASTER_RULES | |
I830_UPLOAD_TEXBLEND(0) | |
I830_UPLOAD_STIPPLE | |
I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i830_texblend.c |
---|
0,0 → 1,459 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/simple_list.h" |
#include "main/enums.h" |
#include "main/mm.h" |
#include "intel_screen.h" |
#include "intel_tex.h" |
#include "i830_context.h" |
#include "i830_reg.h" |
/* ================================================================ |
* Texture combine functions |
*/ |
static GLuint |
pass_through(GLuint * state, GLuint blendUnit) |
{ |
state[0] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) | |
TEXPIPE_COLOR | |
ENABLE_TEXOUTPUT_WRT_SEL | |
TEXOP_OUTPUT_CURRENT | |
DISABLE_TEX_CNTRL_STAGE | |
TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1); |
state[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) | |
TEXPIPE_ALPHA | |
ENABLE_TEXOUTPUT_WRT_SEL | |
TEXOP_OUTPUT_CURRENT | |
TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1); |
state[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) | |
TEXPIPE_COLOR | |
TEXBLEND_ARG1 | |
TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_CURRENT); |
state[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) | |
TEXPIPE_ALPHA | |
TEXBLEND_ARG1 | |
TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_CURRENT); |
return 4; |
} |
static GLuint |
emit_factor(GLuint blendUnit, GLuint * state, GLuint count, |
const GLfloat * factor) |
{ |
GLubyte r, g, b, a; |
GLuint col; |
if (0) |
fprintf(stderr, "emit constant %d: %.2f %.2f %.2f %.2f\n", |
blendUnit, factor[0], factor[1], factor[2], factor[3]); |
UNCLAMPED_FLOAT_TO_UBYTE(r, factor[0]); |
UNCLAMPED_FLOAT_TO_UBYTE(g, factor[1]); |
UNCLAMPED_FLOAT_TO_UBYTE(b, factor[2]); |
UNCLAMPED_FLOAT_TO_UBYTE(a, factor[3]); |
col = ((a << 24) | (r << 16) | (g << 8) | b); |
state[count++] = _3DSTATE_COLOR_FACTOR_N_CMD(blendUnit); |
state[count++] = col; |
return count; |
} |
static INLINE GLuint |
GetTexelOp(GLint unit) |
{ |
switch (unit) { |
case 0: |
return TEXBLENDARG_TEXEL0; |
case 1: |
return TEXBLENDARG_TEXEL1; |
case 2: |
return TEXBLENDARG_TEXEL2; |
case 3: |
return TEXBLENDARG_TEXEL3; |
default: |
return TEXBLENDARG_TEXEL0; |
} |
} |
/** |
* Calculate the hardware instuctions to setup the current texture enviromnemt |
* settings. Since \c gl_texture_unit::_CurrentCombine is used, both |
* "classic" texture enviroments and GL_ARB_texture_env_combine type texture |
* environments are treated identically. |
* |
* \todo |
* This function should return \c bool. When \c false is returned, |
* it means that an environment is selected that the hardware cannot do. This |
* is the way the Radeon and R200 drivers work. |
* |
* \todo |
* Looking at i830_3d_regs.h, it seems the i830 can do part of |
* GL_ATI_texture_env_combine3. It can handle using \c GL_ONE and |
* \c GL_ZERO as combine inputs (which the code already supports). It can |
* also handle the \c GL_MODULATE_ADD_ATI mode. Is it worth investigating |
* partial support for the extension? |
*/ |
GLuint |
i830SetTexEnvCombine(struct i830_context * i830, |
const struct gl_tex_env_combine_state * combine, |
GLint blendUnit, |
GLuint texel_op, GLuint * state, const GLfloat * factor) |
{ |
const GLuint numColorArgs = combine->_NumArgsRGB; |
const GLuint numAlphaArgs = combine->_NumArgsA; |
GLuint blendop; |
GLuint ablendop; |
GLuint args_RGB[3]; |
GLuint args_A[3]; |
GLuint rgb_shift; |
GLuint alpha_shift; |
bool need_factor = 0; |
int i; |
unsigned used; |
static const GLuint tex_blend_rgb[3] = { |
TEXPIPE_COLOR | TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS, |
TEXPIPE_COLOR | TEXBLEND_ARG2 | TEXBLENDARG_MODIFY_PARMS, |
TEXPIPE_COLOR | TEXBLEND_ARG0 | TEXBLENDARG_MODIFY_PARMS, |
}; |
static const GLuint tex_blend_a[3] = { |
TEXPIPE_ALPHA | TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS, |
TEXPIPE_ALPHA | TEXBLEND_ARG2 | TEXBLENDARG_MODIFY_PARMS, |
TEXPIPE_ALPHA | TEXBLEND_ARG0 | TEXBLENDARG_MODIFY_PARMS, |
}; |
if (INTEL_DEBUG & DEBUG_TEXTURE) |
fprintf(stderr, "%s\n", __FUNCTION__); |
/* The EXT version of the DOT3 extension does not support the |
* scale factor, but the ARB version (and the version in OpenGL |
* 1.3) does. |
*/ |
switch (combine->ModeRGB) { |
case GL_DOT3_RGB_EXT: |
alpha_shift = combine->ScaleShiftA; |
rgb_shift = 0; |
break; |
case GL_DOT3_RGBA_EXT: |
alpha_shift = 0; |
rgb_shift = 0; |
break; |
default: |
rgb_shift = combine->ScaleShiftRGB; |
alpha_shift = combine->ScaleShiftA; |
break; |
} |
switch (combine->ModeRGB) { |
case GL_REPLACE: |
blendop = TEXBLENDOP_ARG1; |
break; |
case GL_MODULATE: |
blendop = TEXBLENDOP_MODULATE; |
break; |
case GL_ADD: |
blendop = TEXBLENDOP_ADD; |
break; |
case GL_ADD_SIGNED: |
blendop = TEXBLENDOP_ADDSIGNED; |
break; |
case GL_INTERPOLATE: |
blendop = TEXBLENDOP_BLEND; |
break; |
case GL_SUBTRACT: |
blendop = TEXBLENDOP_SUBTRACT; |
break; |
case GL_DOT3_RGB_EXT: |
case GL_DOT3_RGB: |
blendop = TEXBLENDOP_DOT3; |
break; |
case GL_DOT3_RGBA_EXT: |
case GL_DOT3_RGBA: |
blendop = TEXBLENDOP_DOT3; |
break; |
default: |
return pass_through(state, blendUnit); |
} |
blendop |= (rgb_shift << TEXOP_SCALE_SHIFT); |
/* Handle RGB args */ |
for (i = 0; i < 3; i++) { |
switch (combine->SourceRGB[i]) { |
case GL_TEXTURE: |
args_RGB[i] = texel_op; |
break; |
case GL_TEXTURE0: |
case GL_TEXTURE1: |
case GL_TEXTURE2: |
case GL_TEXTURE3: |
args_RGB[i] = GetTexelOp(combine->SourceRGB[i] - GL_TEXTURE0); |
break; |
case GL_CONSTANT: |
args_RGB[i] = TEXBLENDARG_FACTOR_N; |
need_factor = 1; |
break; |
case GL_PRIMARY_COLOR: |
args_RGB[i] = TEXBLENDARG_DIFFUSE; |
break; |
case GL_PREVIOUS: |
args_RGB[i] = TEXBLENDARG_CURRENT; |
break; |
default: |
return pass_through(state, blendUnit); |
} |
switch (combine->OperandRGB[i]) { |
case GL_SRC_COLOR: |
args_RGB[i] |= 0; |
break; |
case GL_ONE_MINUS_SRC_COLOR: |
args_RGB[i] |= TEXBLENDARG_INV_ARG; |
break; |
case GL_SRC_ALPHA: |
args_RGB[i] |= TEXBLENDARG_REPLICATE_ALPHA; |
break; |
case GL_ONE_MINUS_SRC_ALPHA: |
args_RGB[i] |= (TEXBLENDARG_REPLICATE_ALPHA | TEXBLENDARG_INV_ARG); |
break; |
default: |
return pass_through(state, blendUnit); |
} |
} |
/* Need to knobble the alpha calculations of TEXBLENDOP_DOT4 to |
* match the spec. Can't use DOT3 as it won't propogate values |
* into alpha as required: |
* |
* Note - the global factor is set up with alpha == .5, so |
* the alpha part of the DOT4 calculation should be zero. |
*/ |
if (combine->ModeRGB == GL_DOT3_RGBA_EXT || |
combine->ModeRGB == GL_DOT3_RGBA) { |
ablendop = TEXBLENDOP_DOT4; |
args_A[0] = TEXBLENDARG_FACTOR; /* the global factor */ |
args_A[1] = TEXBLENDARG_FACTOR; |
args_A[2] = TEXBLENDARG_FACTOR; |
} |
else { |
switch (combine->ModeA) { |
case GL_REPLACE: |
ablendop = TEXBLENDOP_ARG1; |
break; |
case GL_MODULATE: |
ablendop = TEXBLENDOP_MODULATE; |
break; |
case GL_ADD: |
ablendop = TEXBLENDOP_ADD; |
break; |
case GL_ADD_SIGNED: |
ablendop = TEXBLENDOP_ADDSIGNED; |
break; |
case GL_INTERPOLATE: |
ablendop = TEXBLENDOP_BLEND; |
break; |
case GL_SUBTRACT: |
ablendop = TEXBLENDOP_SUBTRACT; |
break; |
default: |
return pass_through(state, blendUnit); |
} |
ablendop |= (alpha_shift << TEXOP_SCALE_SHIFT); |
/* Handle A args */ |
for (i = 0; i < 3; i++) { |
switch (combine->SourceA[i]) { |
case GL_TEXTURE: |
args_A[i] = texel_op; |
break; |
case GL_TEXTURE0: |
case GL_TEXTURE1: |
case GL_TEXTURE2: |
case GL_TEXTURE3: |
args_A[i] = GetTexelOp(combine->SourceA[i] - GL_TEXTURE0); |
break; |
case GL_CONSTANT: |
args_A[i] = TEXBLENDARG_FACTOR_N; |
need_factor = 1; |
break; |
case GL_PRIMARY_COLOR: |
args_A[i] = TEXBLENDARG_DIFFUSE; |
break; |
case GL_PREVIOUS: |
args_A[i] = TEXBLENDARG_CURRENT; |
break; |
default: |
return pass_through(state, blendUnit); |
} |
switch (combine->OperandA[i]) { |
case GL_SRC_ALPHA: |
args_A[i] |= 0; |
break; |
case GL_ONE_MINUS_SRC_ALPHA: |
args_A[i] |= TEXBLENDARG_INV_ARG; |
break; |
default: |
return pass_through(state, blendUnit); |
} |
} |
} |
/* Native Arg1 == Arg0 in GL_EXT_texture_env_combine spec */ |
/* Native Arg2 == Arg1 in GL_EXT_texture_env_combine spec */ |
/* Native Arg0 == Arg2 in GL_EXT_texture_env_combine spec */ |
/* When we render we need to figure out which is the last really enabled |
* tex unit, and put last stage on it |
*/ |
/* Build color & alpha pipelines */ |
used = 0; |
state[used++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) | |
TEXPIPE_COLOR | |
ENABLE_TEXOUTPUT_WRT_SEL | |
TEXOP_OUTPUT_CURRENT | |
DISABLE_TEX_CNTRL_STAGE | TEXOP_MODIFY_PARMS | blendop); |
state[used++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit) | |
TEXPIPE_ALPHA | |
ENABLE_TEXOUTPUT_WRT_SEL | |
TEXOP_OUTPUT_CURRENT | TEXOP_MODIFY_PARMS | ablendop); |
for (i = 0; i < numColorArgs; i++) { |
state[used++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) | |
tex_blend_rgb[i] | args_RGB[i]); |
} |
for (i = 0; i < numAlphaArgs; i++) { |
state[used++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit) | |
tex_blend_a[i] | args_A[i]); |
} |
if (need_factor) |
return emit_factor(blendUnit, state, used, factor); |
else |
return used; |
} |
static void |
emit_texblend(struct i830_context *i830, GLuint unit, GLuint blendUnit, |
bool last_stage) |
{ |
struct gl_texture_unit *texUnit = &i830->intel.ctx.Texture.Unit[unit]; |
GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz; |
if (0) |
fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit); |
/* Update i830->state.TexBlend |
*/ |
tmp_sz = i830SetTexEnvCombine(i830, texUnit->_CurrentCombine, blendUnit, |
GetTexelOp(unit), tmp, texUnit->EnvColor); |
if (last_stage) |
tmp[0] |= TEXOP_LAST_STAGE; |
if (tmp_sz != i830->state.TexBlendWordsUsed[blendUnit] || |
memcmp(tmp, i830->state.TexBlend[blendUnit], |
tmp_sz * sizeof(GLuint))) { |
I830_STATECHANGE(i830, I830_UPLOAD_TEXBLEND(blendUnit)); |
memcpy(i830->state.TexBlend[blendUnit], tmp, tmp_sz * sizeof(GLuint)); |
i830->state.TexBlendWordsUsed[blendUnit] = tmp_sz; |
} |
I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(blendUnit), true); |
} |
static void |
emit_passthrough(struct i830_context *i830) |
{ |
GLuint tmp[I830_TEXBLEND_SIZE], tmp_sz; |
GLuint unit = 0; |
tmp_sz = pass_through(tmp, unit); |
tmp[0] |= TEXOP_LAST_STAGE; |
if (tmp_sz != i830->state.TexBlendWordsUsed[unit] || |
memcmp(tmp, i830->state.TexBlend[unit], tmp_sz * sizeof(GLuint))) { |
I830_STATECHANGE(i830, I830_UPLOAD_TEXBLEND(unit)); |
memcpy(i830->state.TexBlend[unit], tmp, tmp_sz * sizeof(GLuint)); |
i830->state.TexBlendWordsUsed[unit] = tmp_sz; |
} |
I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND(unit), true); |
} |
void |
i830EmitTextureBlend(struct i830_context *i830) |
{ |
struct gl_context *ctx = &i830->intel.ctx; |
GLuint unit, last_stage = 0, blendunit = 0; |
I830_ACTIVESTATE(i830, I830_UPLOAD_TEXBLEND_ALL, false); |
if (ctx->Texture._EnabledUnits) { |
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) |
if (ctx->Texture.Unit[unit]._ReallyEnabled) |
last_stage = unit; |
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) |
if (ctx->Texture.Unit[unit]._ReallyEnabled) |
emit_texblend(i830, unit, blendunit++, last_stage == unit); |
} |
else { |
emit_passthrough(i830); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i830_texstate.c |
---|
0,0 → 1,365 |
/************************************************************************** |
* |
* 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 "main/mtypes.h" |
#include "main/enums.h" |
#include "main/colormac.h" |
#include "main/macros.h" |
#include "main/samplerobj.h" |
#include "intel_mipmap_tree.h" |
#include "intel_tex.h" |
#include "i830_context.h" |
#include "i830_reg.h" |
#include "intel_chipset.h" |
static GLuint |
translate_texture_format(GLuint mesa_format) |
{ |
switch (mesa_format) { |
case MESA_FORMAT_L8: |
return MAPSURF_8BIT | MT_8BIT_L8; |
case MESA_FORMAT_I8: |
return MAPSURF_8BIT | MT_8BIT_I8; |
case MESA_FORMAT_A8: |
return MAPSURF_8BIT | MT_8BIT_I8; /* Kludge! */ |
case MESA_FORMAT_AL88: |
return MAPSURF_16BIT | MT_16BIT_AY88; |
case MESA_FORMAT_RGB565: |
return MAPSURF_16BIT | MT_16BIT_RGB565; |
case MESA_FORMAT_ARGB1555: |
return MAPSURF_16BIT | MT_16BIT_ARGB1555; |
case MESA_FORMAT_ARGB4444: |
return MAPSURF_16BIT | MT_16BIT_ARGB4444; |
case MESA_FORMAT_ARGB8888: |
return MAPSURF_32BIT | MT_32BIT_ARGB8888; |
case MESA_FORMAT_XRGB8888: |
return MAPSURF_32BIT | MT_32BIT_XRGB8888; |
case MESA_FORMAT_YCBCR_REV: |
return (MAPSURF_422 | MT_422_YCRCB_NORMAL); |
case MESA_FORMAT_YCBCR: |
return (MAPSURF_422 | MT_422_YCRCB_SWAPY); |
case MESA_FORMAT_RGB_FXT1: |
case MESA_FORMAT_RGBA_FXT1: |
return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); |
case MESA_FORMAT_RGBA_DXT1: |
case MESA_FORMAT_RGB_DXT1: |
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); |
case MESA_FORMAT_RGBA_DXT3: |
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); |
case MESA_FORMAT_RGBA_DXT5: |
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); |
default: |
fprintf(stderr, "%s: bad image format %s\n", __FUNCTION__, |
_mesa_get_format_name(mesa_format)); |
abort(); |
return 0; |
} |
} |
/* The i915 (and related graphics cores) do not support GL_CLAMP. The |
* Intel drivers for "other operating systems" implement GL_CLAMP as |
* GL_CLAMP_TO_EDGE, so the same is done here. |
*/ |
static GLuint |
translate_wrap_mode(GLenum wrap) |
{ |
switch (wrap) { |
case GL_REPEAT: |
return TEXCOORDMODE_WRAP; |
case GL_CLAMP: |
case GL_CLAMP_TO_EDGE: |
return TEXCOORDMODE_CLAMP; /* not really correct */ |
case GL_CLAMP_TO_BORDER: |
return TEXCOORDMODE_CLAMP_BORDER; |
case GL_MIRRORED_REPEAT: |
return TEXCOORDMODE_MIRROR; |
default: |
return TEXCOORDMODE_WRAP; |
} |
} |
/* Recalculate all state from scratch. Perhaps not the most |
* efficient, but this has gotten complex enough that we need |
* something which is understandable and reliable. |
*/ |
static bool |
i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) |
{ |
struct gl_context *ctx = &intel->ctx; |
struct i830_context *i830 = i830_context(ctx); |
struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit]; |
struct gl_texture_object *tObj = tUnit->_Current; |
struct intel_texture_object *intelObj = intel_texture_object(tObj); |
struct gl_texture_image *firstImage; |
struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); |
GLuint *state = i830->state.Tex[unit], format, pitch; |
GLint lodbias; |
GLubyte border[4]; |
GLuint dst_x, dst_y; |
memset(state, 0, sizeof(*state)); |
/*We need to refcount these. */ |
if (i830->state.tex_buffer[unit] != NULL) { |
drm_intel_bo_unreference(i830->state.tex_buffer[unit]); |
i830->state.tex_buffer[unit] = NULL; |
} |
if (!intel_finalize_mipmap_tree(intel, unit)) |
return false; |
/* Get first image here, since intelObj->firstLevel will get set in |
* the intel_finalize_mipmap_tree() call above. |
*/ |
firstImage = tObj->Image[0][tObj->BaseLevel]; |
intel_miptree_get_image_offset(intelObj->mt, tObj->BaseLevel, 0, |
&dst_x, &dst_y); |
drm_intel_bo_reference(intelObj->mt->region->bo); |
i830->state.tex_buffer[unit] = intelObj->mt->region->bo; |
pitch = intelObj->mt->region->pitch; |
/* XXX: This calculation is probably broken for tiled images with |
* a non-page-aligned offset. |
*/ |
i830->state.tex_offset[unit] = dst_x * intelObj->mt->cpp + dst_y * pitch; |
format = translate_texture_format(firstImage->TexFormat); |
state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 | |
(LOAD_TEXTURE_MAP0 << unit) | 4); |
state[I830_TEXREG_TM0S1] = |
(((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) | |
((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format); |
if (intelObj->mt->region->tiling != I915_TILING_NONE) { |
state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE; |
if (intelObj->mt->region->tiling == I915_TILING_Y) |
state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK; |
} |
state[I830_TEXREG_TM0S2] = |
((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK); |
{ |
if (tObj->Target == GL_TEXTURE_CUBE_MAP) |
state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) | |
CUBE_NEGX_ENABLE | |
CUBE_POSX_ENABLE | |
CUBE_NEGY_ENABLE | |
CUBE_POSY_ENABLE | |
CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE); |
else |
state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit)); |
} |
{ |
GLuint minFilt, mipFilt, magFilt; |
float maxlod; |
uint32_t minlod_fixed, maxlod_fixed; |
switch (sampler->MinFilter) { |
case GL_NEAREST: |
minFilt = FILTER_NEAREST; |
mipFilt = MIPFILTER_NONE; |
break; |
case GL_LINEAR: |
minFilt = FILTER_LINEAR; |
mipFilt = MIPFILTER_NONE; |
break; |
case GL_NEAREST_MIPMAP_NEAREST: |
minFilt = FILTER_NEAREST; |
mipFilt = MIPFILTER_NEAREST; |
break; |
case GL_LINEAR_MIPMAP_NEAREST: |
minFilt = FILTER_LINEAR; |
mipFilt = MIPFILTER_NEAREST; |
break; |
case GL_NEAREST_MIPMAP_LINEAR: |
minFilt = FILTER_NEAREST; |
mipFilt = MIPFILTER_LINEAR; |
break; |
case GL_LINEAR_MIPMAP_LINEAR: |
minFilt = FILTER_LINEAR; |
mipFilt = MIPFILTER_LINEAR; |
break; |
default: |
return false; |
} |
if (sampler->MaxAnisotropy > 1.0) { |
minFilt = FILTER_ANISOTROPIC; |
magFilt = FILTER_ANISOTROPIC; |
} |
else { |
switch (sampler->MagFilter) { |
case GL_NEAREST: |
magFilt = FILTER_NEAREST; |
break; |
case GL_LINEAR: |
magFilt = FILTER_LINEAR; |
break; |
default: |
return false; |
} |
} |
lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0); |
if (lodbias < -64) |
lodbias = -64; |
if (lodbias > 63) |
lodbias = 63; |
state[I830_TEXREG_TM0S3] = ((lodbias << TM0S3_LOD_BIAS_SHIFT) & |
TM0S3_LOD_BIAS_MASK); |
#if 0 |
/* YUV conversion: |
*/ |
if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR || |
firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV) |
state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION; |
#endif |
/* We get one field with fraction bits for the maximum |
* addressable (smallest resolution) LOD. Use it to cover both |
* MAX_LEVEL and MAX_LOD. |
*/ |
minlod_fixed = U_FIXED(CLAMP(sampler->MinLod, 0.0, 11), 4); |
maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel); |
if (intel->intelScreen->deviceID == PCI_CHIP_I855_GM || |
intel->intelScreen->deviceID == PCI_CHIP_I865_G) { |
maxlod_fixed = U_FIXED(CLAMP(maxlod, 0.0, 11.75), 2); |
maxlod_fixed = MAX2(maxlod_fixed, (minlod_fixed + 3) >> 2); |
state[I830_TEXREG_TM0S3] |= maxlod_fixed << TM0S3_MIN_MIP_SHIFT; |
state[I830_TEXREG_TM0S2] |= TM0S2_LOD_PRECLAMP; |
} else { |
maxlod_fixed = U_FIXED(CLAMP(maxlod, 0.0, 11), 0); |
maxlod_fixed = MAX2(maxlod_fixed, (minlod_fixed + 15) >> 4); |
state[I830_TEXREG_TM0S3] |= maxlod_fixed << TM0S3_MIN_MIP_SHIFT_830; |
} |
state[I830_TEXREG_TM0S3] |= minlod_fixed << TM0S3_MAX_MIP_SHIFT; |
state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) | |
(mipFilt << TM0S3_MIP_FILTER_SHIFT) | |
(magFilt << TM0S3_MAG_FILTER_SHIFT)); |
} |
{ |
GLenum ws = sampler->WrapS; |
GLenum wt = sampler->WrapT; |
/* 3D textures not available on i830 |
*/ |
if (tObj->Target == GL_TEXTURE_3D) |
return false; |
state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD | |
MAP_UNIT(unit) | |
ENABLE_TEXCOORD_PARAMS | |
ss3 | |
ENABLE_ADDR_V_CNTL | |
TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt)) |
| ENABLE_ADDR_U_CNTL | |
TEXCOORD_ADDR_U_MODE(translate_wrap_mode |
(ws))); |
} |
/* convert border color from float to ubyte */ |
CLAMPED_FLOAT_TO_UBYTE(border[0], sampler->BorderColor.f[0]); |
CLAMPED_FLOAT_TO_UBYTE(border[1], sampler->BorderColor.f[1]); |
CLAMPED_FLOAT_TO_UBYTE(border[2], sampler->BorderColor.f[2]); |
CLAMPED_FLOAT_TO_UBYTE(border[3], sampler->BorderColor.f[3]); |
state[I830_TEXREG_TM0S4] = PACK_COLOR_8888(border[3], |
border[0], |
border[1], |
border[2]); |
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), true); |
/* memcmp was already disabled, but definitely won't work as the |
* region might now change and that wouldn't be detected: |
*/ |
I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit)); |
return true; |
} |
void |
i830UpdateTextureState(struct intel_context *intel) |
{ |
struct i830_context *i830 = i830_context(&intel->ctx); |
bool ok = true; |
GLuint i; |
for (i = 0; i < I830_TEX_UNITS && ok; i++) { |
switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) { |
case TEXTURE_1D_BIT: |
case TEXTURE_2D_BIT: |
case TEXTURE_CUBE_BIT: |
ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_NORMAL); |
break; |
case TEXTURE_RECT_BIT: |
ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_IN_TEXELUNITS); |
break; |
case 0:{ |
struct i830_context *i830 = i830_context(&intel->ctx); |
if (i830->state.active & I830_UPLOAD_TEX(i)) |
I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), false); |
if (i830->state.tex_buffer[i] != NULL) { |
drm_intel_bo_unreference(i830->state.tex_buffer[i]); |
i830->state.tex_buffer[i] = NULL; |
} |
break; |
} |
case TEXTURE_3D_BIT: |
default: |
ok = false; |
break; |
} |
} |
FALLBACK(intel, I830_FALLBACK_TEXTURE, !ok); |
if (ok) |
i830EmitTextureBlend(i830); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i830_vtbl.c |
---|
0,0 → 1,898 |
/************************************************************************** |
* |
* 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 "i830_context.h" |
#include "i830_reg.h" |
#include "intel_batchbuffer.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_tris.h" |
#include "intel_fbo.h" |
#include "intel_buffers.h" |
#include "tnl/tnl.h" |
#include "tnl/t_context.h" |
#include "tnl/t_vertex.h" |
#include "swrast_setup/swrast_setup.h" |
#include "main/renderbuffer.h" |
#include "main/framebuffer.h" |
#include "main/fbobject.h" |
#define FILE_DEBUG_FLAG DEBUG_STATE |
static bool i830_check_vertex_size(struct intel_context *intel, |
GLuint expected); |
#define SZ_TO_HW(sz) ((sz-2)&0x3) |
#define EMIT_SZ(sz) (EMIT_1F + (sz) - 1) |
#define EMIT_ATTR( ATTR, STYLE, V0 ) \ |
do { \ |
intel->vertex_attrs[intel->vertex_attr_count].attrib = (ATTR); \ |
intel->vertex_attrs[intel->vertex_attr_count].format = (STYLE); \ |
intel->vertex_attr_count++; \ |
v0 |= V0; \ |
} while (0) |
#define EMIT_PAD( N ) \ |
do { \ |
intel->vertex_attrs[intel->vertex_attr_count].attrib = 0; \ |
intel->vertex_attrs[intel->vertex_attr_count].format = EMIT_PAD; \ |
intel->vertex_attrs[intel->vertex_attr_count].offset = (N); \ |
intel->vertex_attr_count++; \ |
} while (0) |
#define VRTX_TEX_SET_FMT(n, x) ((x)<<((n)*2)) |
#define TEXBIND_SET(n, x) ((x)<<((n)*4)) |
static void |
i830_render_prevalidate(struct intel_context *intel) |
{ |
} |
static void |
i830_render_start(struct intel_context *intel) |
{ |
struct gl_context *ctx = &intel->ctx; |
struct i830_context *i830 = i830_context(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLbitfield64 index_bitset = tnl->render_inputs_bitset; |
GLuint v0 = _3DSTATE_VFT0_CMD; |
GLuint v2 = _3DSTATE_VFT1_CMD; |
GLuint mcsb1 = 0; |
/* Important: |
*/ |
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; |
intel->vertex_attr_count = 0; |
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to |
* build up a hardware vertex. |
*/ |
if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) { |
EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VFT0_XYZW); |
intel->coloroffset = 4; |
} |
else { |
EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, VFT0_XYZ); |
intel->coloroffset = 3; |
} |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE)) { |
EMIT_ATTR(_TNL_ATTRIB_POINTSIZE, EMIT_1F, VFT0_POINT_WIDTH); |
} |
EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VFT0_DIFFUSE); |
intel->specoffset = 0; |
if (index_bitset & (BITFIELD64_BIT(_TNL_ATTRIB_COLOR1) | |
BITFIELD64_BIT(_TNL_ATTRIB_FOG))) { |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) { |
intel->specoffset = intel->coloroffset + 1; |
EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VFT0_SPEC); |
} |
else |
EMIT_PAD(3); |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) |
EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC); |
else |
EMIT_PAD(1); |
} |
if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) { |
int i, count = 0; |
for (i = 0; i < I830_TEX_UNITS; i++) { |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) { |
GLuint sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size; |
GLuint emit; |
GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] & |
~TEXCOORDTYPE_MASK); |
switch (sz) { |
case 1: |
case 2: |
emit = EMIT_2F; |
sz = 2; |
mcs |= TEXCOORDTYPE_CARTESIAN; |
break; |
case 3: |
emit = EMIT_3F; |
sz = 3; |
mcs |= TEXCOORDTYPE_VECTOR; |
break; |
case 4: |
emit = EMIT_3F_XYW; |
sz = 3; |
mcs |= TEXCOORDTYPE_HOMOGENEOUS; |
break; |
default: |
continue; |
}; |
EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, emit, 0); |
v2 |= VRTX_TEX_SET_FMT(count, SZ_TO_HW(sz)); |
mcsb1 |= (count + 8) << (i * 4); |
if (mcs != i830->state.Tex[i][I830_TEXREG_MCS]) { |
I830_STATECHANGE(i830, I830_UPLOAD_TEX(i)); |
i830->state.Tex[i][I830_TEXREG_MCS] = mcs; |
} |
count++; |
} |
} |
v0 |= VFT0_TEX_COUNT(count); |
} |
/* Only need to change the vertex emit code if there has been a |
* statechange to a new hardware vertex format: |
*/ |
if (v0 != i830->state.Ctx[I830_CTXREG_VF] || |
v2 != i830->state.Ctx[I830_CTXREG_VF2] || |
mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] || |
index_bitset != i830->last_index_bitset) { |
I830_STATECHANGE(i830, I830_UPLOAD_CTX); |
/* Must do this *after* statechange, so as not to affect |
* buffered vertices reliant on the old state: |
*/ |
intel->vertex_size = |
_tnl_install_attrs(ctx, |
intel->vertex_attrs, |
intel->vertex_attr_count, |
intel->ViewportMatrix.m, 0); |
intel->vertex_size >>= 2; |
i830->state.Ctx[I830_CTXREG_VF] = v0; |
i830->state.Ctx[I830_CTXREG_VF2] = v2; |
i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1; |
i830->last_index_bitset = index_bitset; |
assert(i830_check_vertex_size(intel, intel->vertex_size)); |
} |
} |
static void |
i830_reduced_primitive_state(struct intel_context *intel, GLenum rprim) |
{ |
struct i830_context *i830 = i830_context(&intel->ctx); |
GLuint st1 = i830->state.Stipple[I830_STPREG_ST1]; |
st1 &= ~ST1_ENABLE; |
switch (rprim) { |
case GL_TRIANGLES: |
if (intel->ctx.Polygon.StippleFlag && intel->hw_stipple) |
st1 |= ST1_ENABLE; |
break; |
case GL_LINES: |
case GL_POINTS: |
default: |
break; |
} |
i830->intel.reduced_primitive = rprim; |
if (st1 != i830->state.Stipple[I830_STPREG_ST1]) { |
INTEL_FIREVERTICES(intel); |
I830_STATECHANGE(i830, I830_UPLOAD_STIPPLE); |
i830->state.Stipple[I830_STPREG_ST1] = st1; |
} |
} |
/* Pull apart the vertex format registers and figure out how large a |
* vertex is supposed to be. |
*/ |
static bool |
i830_check_vertex_size(struct intel_context *intel, GLuint expected) |
{ |
struct i830_context *i830 = i830_context(&intel->ctx); |
int vft0 = i830->state.Ctx[I830_CTXREG_VF]; |
int vft1 = i830->state.Ctx[I830_CTXREG_VF2]; |
int nrtex = (vft0 & VFT0_TEX_COUNT_MASK) >> VFT0_TEX_COUNT_SHIFT; |
int i, sz = 0; |
switch (vft0 & VFT0_XYZW_MASK) { |
case VFT0_XY: |
sz = 2; |
break; |
case VFT0_XYZ: |
sz = 3; |
break; |
case VFT0_XYW: |
sz = 3; |
break; |
case VFT0_XYZW: |
sz = 4; |
break; |
default: |
fprintf(stderr, "no xyzw specified\n"); |
return 0; |
} |
if (vft0 & VFT0_SPEC) |
sz++; |
if (vft0 & VFT0_DIFFUSE) |
sz++; |
if (vft0 & VFT0_DEPTH_OFFSET) |
sz++; |
if (vft0 & VFT0_POINT_WIDTH) |
sz++; |
for (i = 0; i < nrtex; i++) { |
switch (vft1 & VFT1_TEX0_MASK) { |
case TEXCOORDFMT_2D: |
sz += 2; |
break; |
case TEXCOORDFMT_3D: |
sz += 3; |
break; |
case TEXCOORDFMT_4D: |
sz += 4; |
break; |
case TEXCOORDFMT_1D: |
sz += 1; |
break; |
} |
vft1 >>= VFT1_TEX1_SHIFT; |
} |
if (sz != expected) |
fprintf(stderr, "vertex size mismatch %d/%d\n", sz, expected); |
return sz == expected; |
} |
static void |
i830_emit_invarient_state(struct intel_context *intel) |
{ |
BATCH_LOCALS; |
BEGIN_BATCH(29); |
OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); |
OUT_BATCH(0); |
OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD); |
OUT_BATCH(0); |
OUT_BATCH(_3DSTATE_DFLT_Z_CMD); |
OUT_BATCH(0); |
OUT_BATCH(_3DSTATE_FOG_MODE_CMD); |
OUT_BATCH(FOGFUNC_ENABLE | |
FOG_LINEAR_CONST | FOGSRC_INDEX_Z | ENABLE_FOG_DENSITY); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | |
MAP_UNIT(0) | |
DISABLE_TEX_STREAM_BUMP | |
ENABLE_TEX_STREAM_COORD_SET | |
TEX_STREAM_COORD_SET(0) | |
ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(0)); |
OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | |
MAP_UNIT(1) | |
DISABLE_TEX_STREAM_BUMP | |
ENABLE_TEX_STREAM_COORD_SET | |
TEX_STREAM_COORD_SET(1) | |
ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(1)); |
OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | |
MAP_UNIT(2) | |
DISABLE_TEX_STREAM_BUMP | |
ENABLE_TEX_STREAM_COORD_SET | |
TEX_STREAM_COORD_SET(2) | |
ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(2)); |
OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | |
MAP_UNIT(3) | |
DISABLE_TEX_STREAM_BUMP | |
ENABLE_TEX_STREAM_COORD_SET | |
TEX_STREAM_COORD_SET(3) | |
ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(3)); |
OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM); |
OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(0)); |
OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM); |
OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(1)); |
OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM); |
OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(2)); |
OUT_BATCH(_3DSTATE_MAP_COORD_TRANSFORM); |
OUT_BATCH(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3)); |
OUT_BATCH(_3DSTATE_VERTEX_TRANSFORM); |
OUT_BATCH(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE); |
OUT_BATCH(_3DSTATE_W_STATE_CMD); |
OUT_BATCH(MAGIC_W_STATE_DWORD1); |
OUT_BATCH(0x3f800000 /* 1.0 in IEEE float */ ); |
OUT_BATCH(_3DSTATE_COLOR_FACTOR_CMD); |
OUT_BATCH(0x80808080); /* .5 required in alpha for GL_DOT3_RGBA_EXT */ |
ADVANCE_BATCH(); |
} |
#define emit( intel, state, size ) \ |
intel_batchbuffer_data(intel, state, size) |
static GLuint |
get_dirty(struct i830_hw_state *state) |
{ |
return state->active & ~state->emitted; |
} |
static GLuint |
get_state_size(struct i830_hw_state *state) |
{ |
GLuint dirty = get_dirty(state); |
GLuint sz = 0; |
GLuint i; |
if (dirty & I830_UPLOAD_INVARIENT) |
sz += 40 * sizeof(int); |
if (dirty & I830_UPLOAD_RASTER_RULES) |
sz += sizeof(state->RasterRules); |
if (dirty & I830_UPLOAD_CTX) |
sz += sizeof(state->Ctx); |
if (dirty & I830_UPLOAD_BUFFERS) |
sz += sizeof(state->Buffer); |
if (dirty & I830_UPLOAD_STIPPLE) |
sz += sizeof(state->Stipple); |
for (i = 0; i < I830_TEX_UNITS; i++) { |
if ((dirty & I830_UPLOAD_TEX(i))) |
sz += sizeof(state->Tex[i]); |
if (dirty & I830_UPLOAD_TEXBLEND(i)) |
sz += state->TexBlendWordsUsed[i] * 4; |
} |
return sz; |
} |
/* Push the state into the sarea and/or texture memory. |
*/ |
static void |
i830_emit_state(struct intel_context *intel) |
{ |
struct i830_context *i830 = i830_context(&intel->ctx); |
struct i830_hw_state *state = &i830->state; |
int i, count; |
GLuint dirty; |
drm_intel_bo *aper_array[3 + I830_TEX_UNITS]; |
int aper_count; |
GET_CURRENT_CONTEXT(ctx); |
BATCH_LOCALS; |
/* We don't hold the lock at this point, so want to make sure that |
* there won't be a buffer wrap between the state emits and the primitive |
* emit header. |
* |
* It might be better to talk about explicit places where |
* scheduling is allowed, rather than assume that it is whenever a |
* batchbuffer fills up. |
*/ |
intel_batchbuffer_require_space(intel, |
get_state_size(state) + |
INTEL_PRIM_EMIT_SIZE); |
count = 0; |
again: |
aper_count = 0; |
dirty = get_dirty(state); |
aper_array[aper_count++] = intel->batch.bo; |
if (dirty & I830_UPLOAD_BUFFERS) { |
aper_array[aper_count++] = state->draw_region->bo; |
if (state->depth_region) |
aper_array[aper_count++] = state->depth_region->bo; |
} |
for (i = 0; i < I830_TEX_UNITS; i++) |
if (dirty & I830_UPLOAD_TEX(i)) { |
if (state->tex_buffer[i]) { |
aper_array[aper_count++] = state->tex_buffer[i]; |
} |
} |
if (dri_bufmgr_check_aperture_space(aper_array, aper_count)) { |
if (count == 0) { |
count++; |
intel_batchbuffer_flush(intel); |
goto again; |
} else { |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "i830 emit state"); |
assert(0); |
} |
} |
/* Do this here as we may have flushed the batchbuffer above, |
* causing more state to be dirty! |
*/ |
dirty = get_dirty(state); |
state->emitted |= dirty; |
assert(get_dirty(state) == 0); |
if (dirty & I830_UPLOAD_INVARIENT) { |
DBG("I830_UPLOAD_INVARIENT:\n"); |
i830_emit_invarient_state(intel); |
} |
if (dirty & I830_UPLOAD_RASTER_RULES) { |
DBG("I830_UPLOAD_RASTER_RULES:\n"); |
emit(intel, state->RasterRules, sizeof(state->RasterRules)); |
} |
if (dirty & I830_UPLOAD_CTX) { |
DBG("I830_UPLOAD_CTX:\n"); |
emit(intel, state->Ctx, sizeof(state->Ctx)); |
} |
if (dirty & I830_UPLOAD_BUFFERS) { |
GLuint count = 15; |
DBG("I830_UPLOAD_BUFFERS:\n"); |
if (state->depth_region) |
count += 3; |
BEGIN_BATCH(count); |
OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR0]); |
OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR1]); |
OUT_RELOC(state->draw_region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); |
if (state->depth_region) { |
OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR0]); |
OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR1]); |
OUT_RELOC(state->depth_region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); |
} |
OUT_BATCH(state->Buffer[I830_DESTREG_DV0]); |
OUT_BATCH(state->Buffer[I830_DESTREG_DV1]); |
OUT_BATCH(state->Buffer[I830_DESTREG_SENABLE]); |
OUT_BATCH(state->Buffer[I830_DESTREG_SR0]); |
OUT_BATCH(state->Buffer[I830_DESTREG_SR1]); |
OUT_BATCH(state->Buffer[I830_DESTREG_SR2]); |
assert(state->Buffer[I830_DESTREG_DRAWRECT0] != MI_NOOP); |
OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT0]); |
OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT1]); |
OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT2]); |
OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT3]); |
OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT4]); |
OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT5]); |
ADVANCE_BATCH(); |
} |
if (dirty & I830_UPLOAD_STIPPLE) { |
DBG("I830_UPLOAD_STIPPLE:\n"); |
emit(intel, state->Stipple, sizeof(state->Stipple)); |
} |
for (i = 0; i < I830_TEX_UNITS; i++) { |
if ((dirty & I830_UPLOAD_TEX(i))) { |
DBG("I830_UPLOAD_TEX(%d):\n", i); |
BEGIN_BATCH(I830_TEX_SETUP_SIZE + 1); |
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0LI]); |
OUT_RELOC(state->tex_buffer[i], |
I915_GEM_DOMAIN_SAMPLER, 0, |
state->tex_offset[i]); |
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S1]); |
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S2]); |
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S3]); |
OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S4]); |
OUT_BATCH(state->Tex[i][I830_TEXREG_MCS]); |
OUT_BATCH(state->Tex[i][I830_TEXREG_CUBE]); |
ADVANCE_BATCH(); |
} |
if (dirty & I830_UPLOAD_TEXBLEND(i)) { |
DBG("I830_UPLOAD_TEXBLEND(%d): %d words\n", i, |
state->TexBlendWordsUsed[i]); |
emit(intel, state->TexBlend[i], state->TexBlendWordsUsed[i] * 4); |
} |
} |
assert(get_dirty(state) == 0); |
} |
static void |
i830_destroy_context(struct intel_context *intel) |
{ |
GLuint i; |
struct i830_context *i830 = i830_context(&intel->ctx); |
intel_region_release(&i830->state.draw_region); |
intel_region_release(&i830->state.depth_region); |
for (i = 0; i < I830_TEX_UNITS; i++) { |
if (i830->state.tex_buffer[i] != NULL) { |
drm_intel_bo_unreference(i830->state.tex_buffer[i]); |
i830->state.tex_buffer[i] = NULL; |
} |
} |
_tnl_free_vertices(&intel->ctx); |
} |
static uint32_t i830_render_target_format_for_mesa_format[MESA_FORMAT_COUNT] = |
{ |
[MESA_FORMAT_ARGB8888] = DV_PF_8888, |
[MESA_FORMAT_XRGB8888] = DV_PF_8888, |
[MESA_FORMAT_RGB565] = DV_PF_565, |
[MESA_FORMAT_ARGB1555] = DV_PF_1555, |
[MESA_FORMAT_ARGB4444] = DV_PF_4444, |
}; |
static bool |
i830_render_target_supported(struct intel_context *intel, |
struct gl_renderbuffer *rb) |
{ |
gl_format format = rb->Format; |
if (format == MESA_FORMAT_S8_Z24 || |
format == MESA_FORMAT_X8_Z24 || |
format == MESA_FORMAT_Z16) { |
return true; |
} |
return i830_render_target_format_for_mesa_format[format] != 0; |
} |
static void |
i830_set_draw_region(struct intel_context *intel, |
struct intel_region *color_regions[], |
struct intel_region *depth_region, |
GLuint num_regions) |
{ |
struct i830_context *i830 = i830_context(&intel->ctx); |
struct gl_context *ctx = &intel->ctx; |
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
struct gl_renderbuffer *drb; |
struct intel_renderbuffer *idrb = NULL; |
GLuint value; |
struct i830_hw_state *state = &i830->state; |
uint32_t draw_x, draw_y; |
if (state->draw_region != color_regions[0]) { |
intel_region_reference(&state->draw_region, color_regions[0]); |
} |
if (state->depth_region != depth_region) { |
intel_region_reference(&state->depth_region, depth_region); |
} |
/* |
* Set stride/cpp values |
*/ |
i915_set_buf_info_for_region(&state->Buffer[I830_DESTREG_CBUFADDR0], |
color_regions[0], BUF_3D_ID_COLOR_BACK); |
i915_set_buf_info_for_region(&state->Buffer[I830_DESTREG_DBUFADDR0], |
depth_region, BUF_3D_ID_DEPTH); |
/* |
* Compute/set I830_DESTREG_DV1 value |
*/ |
value = (DSTORG_HORT_BIAS(0x8) | /* .5 */ |
DSTORG_VERT_BIAS(0x8) | DEPTH_IS_Z); /* .5 */ |
if (irb != NULL) { |
value |= i830_render_target_format_for_mesa_format[intel_rb_format(irb)]; |
} |
if (depth_region && depth_region->cpp == 4) { |
value |= DEPTH_FRMT_24_FIXED_8_OTHER; |
} |
else { |
value |= DEPTH_FRMT_16_FIXED; |
} |
state->Buffer[I830_DESTREG_DV1] = value; |
drb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; |
if (!drb) |
drb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; |
if (drb) |
idrb = intel_renderbuffer(drb); |
/* We set up the drawing rectangle to be offset into the color |
* region's location in the miptree. If it doesn't match with |
* depth's offsets, we can't render to it. |
* |
* (Well, not actually true -- the hw grew a bit to let depth's |
* offset get forced to 0,0. We may want to use that if people are |
* hitting that case. Also, some configurations may be supportable |
* by tweaking the start offset of the buffers around, which we |
* can't do in general due to tiling) |
*/ |
FALLBACK(intel, I830_FALLBACK_DRAW_OFFSET, |
idrb && irb && (idrb->draw_x != irb->draw_x || |
idrb->draw_y != irb->draw_y)); |
if (irb) { |
draw_x = irb->draw_x; |
draw_y = irb->draw_y; |
} else if (idrb) { |
draw_x = idrb->draw_x; |
draw_y = idrb->draw_y; |
} else { |
draw_x = 0; |
draw_y = 0; |
} |
state->Buffer[I830_DESTREG_DRAWRECT0] = _3DSTATE_DRAWRECT_INFO; |
state->Buffer[I830_DESTREG_DRAWRECT1] = 0; |
state->Buffer[I830_DESTREG_DRAWRECT2] = (draw_y << 16) | draw_x; |
state->Buffer[I830_DESTREG_DRAWRECT3] = |
((ctx->DrawBuffer->Width + draw_x - 1) & 0xffff) | |
((ctx->DrawBuffer->Height + draw_y - 1) << 16); |
state->Buffer[I830_DESTREG_DRAWRECT4] = (draw_y << 16) | draw_x; |
state->Buffer[I830_DESTREG_DRAWRECT5] = MI_NOOP; |
I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS); |
} |
/** |
* Update the hardware state for drawing into a window or framebuffer object. |
* |
* Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other |
* places within the driver. |
* |
* Basically, this needs to be called any time the current framebuffer |
* changes, the renderbuffers change, or we need to draw into different |
* color buffers. |
*/ |
static void |
i830_update_draw_buffer(struct intel_context *intel) |
{ |
struct gl_context *ctx = &intel->ctx; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct intel_region *colorRegions[MAX_DRAW_BUFFERS], *depthRegion = NULL; |
struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL; |
if (!fb) { |
/* this can happen during the initial context initialization */ |
return; |
} |
irbDepth = intel_get_renderbuffer(fb, BUFFER_DEPTH); |
irbStencil = intel_get_renderbuffer(fb, BUFFER_STENCIL); |
/* Do this here, not core Mesa, since this function is called from |
* many places within the driver. |
*/ |
if (ctx->NewState & _NEW_BUFFERS) { |
/* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ |
_mesa_update_framebuffer(ctx); |
/* this updates the DrawBuffer's Width/Height if it's a FBO */ |
_mesa_update_draw_buffer_bounds(ctx); |
} |
if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { |
/* this may occur when we're called by glBindFrameBuffer() during |
* the process of someone setting up renderbuffers, etc. |
*/ |
/*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/ |
return; |
} |
/* How many color buffers are we drawing into? |
* |
* If there are zero buffers or the buffer is too big, don't configure any |
* regions for hardware drawing. We'll fallback to software below. Not |
* having regions set makes some of the software fallback paths faster. |
*/ |
if ((fb->Width > ctx->Const.MaxRenderbufferSize) |
|| (fb->Height > ctx->Const.MaxRenderbufferSize) |
|| (fb->_NumColorDrawBuffers == 0)) { |
/* writing to 0 */ |
colorRegions[0] = NULL; |
} |
else if (fb->_NumColorDrawBuffers > 1) { |
int i; |
struct intel_renderbuffer *irb; |
for (i = 0; i < fb->_NumColorDrawBuffers; i++) { |
irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]); |
colorRegions[i] = (irb && irb->mt) ? irb->mt->region : NULL; |
} |
} |
else { |
/* Get the intel_renderbuffer for the single colorbuffer we're drawing |
* into. |
*/ |
if (_mesa_is_winsys_fbo(fb)) { |
/* drawing to window system buffer */ |
if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) |
colorRegions[0] = intel_get_rb_region(fb, BUFFER_FRONT_LEFT); |
else |
colorRegions[0] = intel_get_rb_region(fb, BUFFER_BACK_LEFT); |
} |
else { |
/* drawing to user-created FBO */ |
struct intel_renderbuffer *irb; |
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); |
colorRegions[0] = (irb && irb->mt->region) ? irb->mt->region : NULL; |
} |
} |
if (!colorRegions[0]) { |
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, true); |
} |
else { |
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, false); |
} |
/* Check for depth fallback. */ |
if (irbDepth && irbDepth->mt) { |
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, false); |
depthRegion = irbDepth->mt->region; |
} else if (irbDepth && !irbDepth->mt) { |
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, true); |
depthRegion = NULL; |
} else { /* !irbDepth */ |
/* No fallback is needed because there is no depth buffer. */ |
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, false); |
depthRegion = NULL; |
} |
/* Check for stencil fallback. */ |
if (irbStencil && irbStencil->mt) { |
assert(intel_rb_format(irbStencil) == MESA_FORMAT_S8_Z24); |
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, false); |
} else if (irbStencil && !irbStencil->mt) { |
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, true); |
} else { /* !irbStencil */ |
/* No fallback is needed because there is no stencil buffer. */ |
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, false); |
} |
/* If we have a (packed) stencil buffer attached but no depth buffer, |
* we still need to set up the shared depth/stencil state so we can use it. |
*/ |
if (depthRegion == NULL && irbStencil && irbStencil->mt |
&& intel_rb_format(irbStencil) == MESA_FORMAT_S8_Z24) { |
depthRegion = irbStencil->mt->region; |
} |
/* |
* Update depth and stencil test state |
*/ |
ctx->Driver.Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test); |
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, |
(ctx->Stencil.Enabled && fb->Visual.stencilBits > 0)); |
intel->vtbl.set_draw_region(intel, colorRegions, depthRegion, |
fb->_NumColorDrawBuffers); |
intel->NewGLState |= _NEW_BUFFERS; |
/* update viewport since it depends on window size */ |
intelCalcViewport(ctx); |
/* Set state we know depends on drawable parameters: |
*/ |
ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, |
ctx->Scissor.Width, ctx->Scissor.Height); |
ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far); |
/* Update culling direction which changes depending on the |
* orientation of the buffer: |
*/ |
ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); |
} |
/* This isn't really handled at the moment. |
*/ |
static void |
i830_new_batch(struct intel_context *intel) |
{ |
struct i830_context *i830 = i830_context(&intel->ctx); |
i830->state.emitted = 0; |
} |
static void |
i830_assert_not_dirty( struct intel_context *intel ) |
{ |
struct i830_context *i830 = i830_context(&intel->ctx); |
assert(!get_dirty(&i830->state)); |
(void) i830; |
} |
static void |
i830_invalidate_state(struct intel_context *intel, GLuint new_state) |
{ |
struct gl_context *ctx = &intel->ctx; |
_swsetup_InvalidateState(ctx, new_state); |
_tnl_InvalidateState(ctx, new_state); |
_tnl_invalidate_vertex_state(ctx, new_state); |
if (new_state & _NEW_LIGHT) |
i830_update_provoking_vertex(&intel->ctx); |
} |
void |
i830InitVtbl(struct i830_context *i830) |
{ |
i830->intel.vtbl.check_vertex_size = i830_check_vertex_size; |
i830->intel.vtbl.destroy = i830_destroy_context; |
i830->intel.vtbl.emit_state = i830_emit_state; |
i830->intel.vtbl.new_batch = i830_new_batch; |
i830->intel.vtbl.reduced_primitive_state = i830_reduced_primitive_state; |
i830->intel.vtbl.set_draw_region = i830_set_draw_region; |
i830->intel.vtbl.update_draw_buffer = i830_update_draw_buffer; |
i830->intel.vtbl.update_texture_state = i830UpdateTextureState; |
i830->intel.vtbl.render_start = i830_render_start; |
i830->intel.vtbl.render_prevalidate = i830_render_prevalidate; |
i830->intel.vtbl.assert_not_dirty = i830_assert_not_dirty; |
i830->intel.vtbl.finish_batch = intel_finish_vb; |
i830->intel.vtbl.invalidate_state = i830_invalidate_state; |
i830->intel.vtbl.render_target_supported = i830_render_target_supported; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_context.c |
---|
0,0 → 1,285 |
/************************************************************************** |
* |
* 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 "i915_context.h" |
#include "main/api_exec.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "main/version.h" |
#include "main/vtxfmt.h" |
#include "intel_chipset.h" |
#include "intel_tris.h" |
#include "tnl/t_context.h" |
#include "tnl/t_pipeline.h" |
#include "tnl/t_vertex.h" |
#include "swrast/swrast.h" |
#include "swrast_setup/swrast_setup.h" |
#include "tnl/tnl.h" |
#include "../glsl/ralloc.h" |
#include "i915_reg.h" |
#include "i915_program.h" |
/*************************************** |
* Mesa's Driver Functions |
***************************************/ |
/* Override intel default. |
*/ |
static void |
i915InvalidateState(struct gl_context * ctx, GLuint new_state) |
{ |
_swrast_InvalidateState(ctx, new_state); |
_swsetup_InvalidateState(ctx, new_state); |
_vbo_InvalidateState(ctx, new_state); |
_tnl_InvalidateState(ctx, new_state); |
_tnl_invalidate_vertex_state(ctx, new_state); |
intel_context(ctx)->NewGLState |= new_state; |
/* Todo: gather state values under which tracked parameters become |
* invalidated, add callbacks for things like |
* ProgramLocalParameters, etc. |
*/ |
{ |
struct i915_fragment_program *p = |
(struct i915_fragment_program *) ctx->FragmentProgram._Current; |
if (p && p->nr_params) |
p->params_uptodate = 0; |
} |
if (new_state & (_NEW_STENCIL | _NEW_BUFFERS | _NEW_POLYGON)) |
i915_update_stencil(ctx); |
if (new_state & (_NEW_LIGHT)) |
i915_update_provoking_vertex(ctx); |
if (new_state & (_NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) |
i915_update_program(ctx); |
if (new_state & (_NEW_PROGRAM | _NEW_POINT)) |
i915_update_sprite_point_enable(ctx); |
} |
static void |
i915InitDriverFunctions(struct dd_function_table *functions) |
{ |
intelInitDriverFunctions(functions); |
i915InitStateFunctions(functions); |
i915InitFragProgFuncs(functions); |
functions->UpdateState = i915InvalidateState; |
} |
/* Note: this is shared with i830. */ |
void |
intel_init_texture_formats(struct gl_context *ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_screen *intel_screen = intel->intelScreen; |
ctx->TextureFormatSupported[MESA_FORMAT_ARGB8888] = true; |
if (intel_screen->deviceID != PCI_CHIP_I830_M && |
intel_screen->deviceID != PCI_CHIP_845_G) |
ctx->TextureFormatSupported[MESA_FORMAT_XRGB8888] = true; |
if (intel->gen == 3) |
ctx->TextureFormatSupported[MESA_FORMAT_SARGB8] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_ARGB4444] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_ARGB1555] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_RGB565] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_L8] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_A8] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_I8] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_AL88] = true; |
/* Depth and stencil */ |
ctx->TextureFormatSupported[MESA_FORMAT_S8_Z24] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_X8_Z24] = true; |
/* |
* This was disabled in initial FBO enabling to avoid combinations |
* of depth+stencil that wouldn't work together. We since decided |
* that it was OK, since it's up to the app to come up with the |
* combo that actually works, so this can probably be re-enabled. |
*/ |
/* |
ctx->TextureFormatSupported[MESA_FORMAT_Z16] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_Z24] = true; |
*/ |
/* ctx->Extensions.MESA_ycbcr_texture */ |
ctx->TextureFormatSupported[MESA_FORMAT_YCBCR] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_YCBCR_REV] = true; |
/* GL_3DFX_texture_compression_FXT1 */ |
ctx->TextureFormatSupported[MESA_FORMAT_RGB_FXT1] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_RGBA_FXT1] = true; |
/* GL_EXT_texture_compression_s3tc */ |
ctx->TextureFormatSupported[MESA_FORMAT_RGB_DXT1] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT1] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT3] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_RGBA_DXT5] = true; |
} |
extern const struct tnl_pipeline_stage *intel_pipeline[]; |
bool |
i915CreateContext(int api, |
const struct gl_config * mesaVis, |
__DRIcontext * driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
unsigned *error, |
void *sharedContextPrivate) |
{ |
struct dd_function_table functions; |
struct i915_context *i915 = rzalloc(NULL, struct i915_context); |
struct intel_context *intel = &i915->intel; |
struct gl_context *ctx = &intel->ctx; |
if (!i915) { |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
return false; |
} |
i915InitVtbl(i915); |
i915InitDriverFunctions(&functions); |
if (!intelInitContext(intel, api, major_version, minor_version, |
mesaVis, driContextPriv, |
sharedContextPrivate, &functions, |
error)) { |
ralloc_free(i915); |
return false; |
} |
intel_init_texture_formats(ctx); |
_math_matrix_ctr(&intel->ViewportMatrix); |
/* Initialize swrast, tnl driver tables: */ |
intelInitTriFuncs(ctx); |
/* Install the customized pipeline: */ |
_tnl_destroy_pipeline(ctx); |
_tnl_install_pipeline(ctx, intel_pipeline); |
if (intel->no_rast) |
FALLBACK(intel, INTEL_FALLBACK_USER, 1); |
ctx->Const.MaxTextureUnits = I915_TEX_UNITS; |
ctx->Const.FragmentProgram.MaxTextureImageUnits = I915_TEX_UNITS; |
ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS; |
ctx->Const.MaxVarying = I915_TEX_UNITS; |
ctx->Const.MaxCombinedTextureImageUnits = |
ctx->Const.VertexProgram.MaxTextureImageUnits + |
ctx->Const.FragmentProgram.MaxTextureImageUnits; |
/* Advertise the full hardware capabilities. The new memory |
* manager should cope much better with overload situations: |
*/ |
ctx->Const.MaxTextureLevels = 12; |
ctx->Const.Max3DTextureLevels = 9; |
ctx->Const.MaxCubeTextureLevels = 12; |
ctx->Const.MaxTextureRectSize = (1 << 11); |
ctx->Const.MaxTextureUnits = I915_TEX_UNITS; |
ctx->Const.MaxTextureMaxAnisotropy = 4.0; |
/* GL_ARB_fragment_program limits - don't think Mesa actually |
* validates programs against these, and in any case one ARB |
* instruction can translate to more than one HW instruction, so |
* we'll still have to check and fallback each time. |
*/ |
ctx->Const.FragmentProgram.MaxNativeTemps = I915_MAX_TEMPORARY; |
ctx->Const.FragmentProgram.MaxNativeAttribs = 11; /* 8 tex, 2 color, fog */ |
ctx->Const.FragmentProgram.MaxNativeParameters = I915_MAX_CONSTANT; |
ctx->Const.FragmentProgram.MaxNativeAluInstructions = I915_MAX_ALU_INSN; |
ctx->Const.FragmentProgram.MaxNativeTexInstructions = I915_MAX_TEX_INSN; |
ctx->Const.FragmentProgram.MaxNativeInstructions = (I915_MAX_ALU_INSN + |
I915_MAX_TEX_INSN); |
ctx->Const.FragmentProgram.MaxNativeTexIndirections = |
I915_MAX_TEX_INDIRECT; |
ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; /* I don't think we have one */ |
ctx->Const.FragmentProgram.MaxEnvParams = |
MIN2(ctx->Const.FragmentProgram.MaxNativeParameters, |
ctx->Const.FragmentProgram.MaxEnvParams); |
/* i915 stores all values in single-precision floats. Values aren't set |
* for other program targets because software is used for those targets. |
*/ |
ctx->Const.FragmentProgram.MediumFloat.RangeMin = 127; |
ctx->Const.FragmentProgram.MediumFloat.RangeMax = 127; |
ctx->Const.FragmentProgram.MediumFloat.Precision = 23; |
ctx->Const.FragmentProgram.LowFloat = ctx->Const.FragmentProgram.HighFloat = |
ctx->Const.FragmentProgram.MediumFloat; |
ctx->Const.FragmentProgram.MediumInt.RangeMin = 24; |
ctx->Const.FragmentProgram.MediumInt.RangeMax = 24; |
ctx->Const.FragmentProgram.MediumInt.Precision = 0; |
ctx->Const.FragmentProgram.LowInt = ctx->Const.FragmentProgram.HighInt = |
ctx->Const.FragmentProgram.MediumInt; |
ctx->FragmentProgram._MaintainTexEnvProgram = true; |
/* FINISHME: Are there other options that should be enabled for software |
* FINISHME: vertex shaders? |
*/ |
ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].EmitCondCodes = true; |
struct gl_shader_compiler_options *const fs_options = |
& ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT]; |
fs_options->MaxIfDepth = 0; |
fs_options->EmitNoNoise = true; |
fs_options->EmitNoPow = true; |
fs_options->EmitNoMainReturn = true; |
fs_options->EmitNoIndirectInput = true; |
fs_options->EmitNoIndirectOutput = true; |
fs_options->EmitNoIndirectUniform = true; |
fs_options->EmitNoIndirectTemp = true; |
ctx->Const.MaxDrawBuffers = 1; |
ctx->Const.QueryCounterBits.SamplesPassed = 0; |
_tnl_init_vertices(ctx, ctx->Const.MaxArrayLockSize + 12, |
36 * sizeof(GLfloat)); |
intel->verts = TNL_CONTEXT(ctx)->clipspace.vertex_buf; |
i915InitState(i915); |
/* Always enable pixel fog. Vertex fog using fog coord will conflict |
* with fog code appended onto fragment program. |
*/ |
_tnl_allow_vertex_fog(ctx, 0); |
_tnl_allow_pixel_fog(ctx, 1); |
_mesa_compute_version(ctx); |
_mesa_initialize_dispatch_tables(ctx); |
_mesa_initialize_vbo_vtxfmt(ctx); |
return true; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_context.h |
---|
0,0 → 1,376 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef I915CONTEXT_INC |
#define I915CONTEXT_INC |
#include "intel_context.h" |
#define I915_FALLBACK_TEXTURE 0x1000 |
#define I915_FALLBACK_COLORMASK 0x2000 |
#define I915_FALLBACK_STENCIL 0x4000 |
#define I915_FALLBACK_STIPPLE 0x8000 |
#define I915_FALLBACK_PROGRAM 0x10000 |
#define I915_FALLBACK_LOGICOP 0x20000 |
#define I915_FALLBACK_POLYGON_SMOOTH 0x40000 |
#define I915_FALLBACK_POINT_SMOOTH 0x80000 |
#define I915_FALLBACK_POINT_SPRITE_COORD_ORIGIN 0x100000 |
#define I915_FALLBACK_DRAW_OFFSET 0x200000 |
#define I915_FALLBACK_COORD_REPLACE 0x400000 |
#define I915_UPLOAD_CTX 0x1 |
#define I915_UPLOAD_BUFFERS 0x2 |
#define I915_UPLOAD_STIPPLE 0x4 |
#define I915_UPLOAD_PROGRAM 0x8 |
#define I915_UPLOAD_CONSTANTS 0x10 |
#define I915_UPLOAD_INVARIENT 0x40 |
#define I915_UPLOAD_DEFAULTS 0x80 |
#define I915_UPLOAD_RASTER_RULES 0x100 |
#define I915_UPLOAD_BLEND 0x200 |
#define I915_UPLOAD_TEX(i) (0x00010000<<(i)) |
#define I915_UPLOAD_TEX_ALL (0x00ff0000) |
#define I915_UPLOAD_TEX_0_SHIFT 16 |
/* State structure offsets - these will probably disappear. |
*/ |
#define I915_DESTREG_CBUFADDR0 0 |
#define I915_DESTREG_CBUFADDR1 1 |
#define I915_DESTREG_DBUFADDR0 3 |
#define I915_DESTREG_DBUFADDR1 4 |
#define I915_DESTREG_DV0 6 |
#define I915_DESTREG_DV1 7 |
#define I915_DESTREG_SENABLE 8 |
#define I915_DESTREG_SR0 9 |
#define I915_DESTREG_SR1 10 |
#define I915_DESTREG_SR2 11 |
#define I915_DESTREG_DRAWRECT0 12 |
#define I915_DESTREG_DRAWRECT1 13 |
#define I915_DESTREG_DRAWRECT2 14 |
#define I915_DESTREG_DRAWRECT3 15 |
#define I915_DESTREG_DRAWRECT4 16 |
#define I915_DESTREG_DRAWRECT5 17 |
#define I915_DEST_SETUP_SIZE 18 |
#define I915_CTXREG_STATE4 0 |
#define I915_CTXREG_LI 1 |
#define I915_CTXREG_LIS2 2 |
#define I915_CTXREG_LIS4 3 |
#define I915_CTXREG_LIS5 4 |
#define I915_CTXREG_LIS6 5 |
#define I915_CTXREG_BF_STENCIL_OPS 6 |
#define I915_CTXREG_BF_STENCIL_MASKS 7 |
#define I915_CTX_SETUP_SIZE 8 |
#define I915_BLENDREG_IAB 0 |
#define I915_BLENDREG_BLENDCOLOR0 1 |
#define I915_BLENDREG_BLENDCOLOR1 2 |
#define I915_BLEND_SETUP_SIZE 3 |
#define I915_STPREG_ST0 0 |
#define I915_STPREG_ST1 1 |
#define I915_STP_SETUP_SIZE 2 |
#define I915_TEXREG_MS3 1 |
#define I915_TEXREG_MS4 2 |
#define I915_TEXREG_SS2 3 |
#define I915_TEXREG_SS3 4 |
#define I915_TEXREG_SS4 5 |
#define I915_TEX_SETUP_SIZE 6 |
#define I915_DEFREG_C0 0 |
#define I915_DEFREG_C1 1 |
#define I915_DEFREG_S0 2 |
#define I915_DEFREG_S1 3 |
#define I915_DEFREG_Z0 4 |
#define I915_DEFREG_Z1 5 |
#define I915_DEF_SETUP_SIZE 6 |
enum { |
I915_RASTER_RULES, |
I915_RASTER_RULES_SETUP_SIZE, |
}; |
#define I915_MAX_CONSTANT 32 |
#define I915_CONSTANT_SIZE (2+(4*I915_MAX_CONSTANT)) |
#define I915_MAX_TEX_INDIRECT 4 |
#define I915_MAX_TEX_INSN 32 |
#define I915_MAX_ALU_INSN 64 |
#define I915_MAX_DECL_INSN 27 |
#define I915_MAX_TEMPORARY 16 |
#define I915_MAX_INSN (I915_MAX_DECL_INSN + \ |
I915_MAX_TEX_INSN + \ |
I915_MAX_ALU_INSN) |
/* Maximum size of the program packet, which matches the limits on |
* decl, tex, and ALU instructions. |
*/ |
#define I915_PROGRAM_SIZE (I915_MAX_INSN * 3 + 1) |
/* Hardware version of a parsed fragment program. "Derived" from the |
* mesa fragment_program struct. |
*/ |
struct i915_fragment_program |
{ |
struct gl_fragment_program FragProg; |
bool translated; |
bool params_uptodate; |
bool on_hardware; |
bool error; /* If program is malformed for any reason. */ |
/** Record of which phases R registers were last written in. */ |
GLuint register_phases[16]; |
GLuint indirections; |
GLuint nr_tex_indirect; |
GLuint nr_tex_insn; |
GLuint nr_alu_insn; |
GLuint nr_decl_insn; |
/* TODO: split between the stored representation of a program and |
* the state used to build that representation. |
*/ |
struct gl_context *ctx; |
/* declarations contains the packet header. */ |
GLuint declarations[I915_MAX_DECL_INSN * 3 + 1]; |
GLuint program[(I915_MAX_TEX_INSN + I915_MAX_ALU_INSN) * 3]; |
GLfloat constant[I915_MAX_CONSTANT][4]; |
GLuint constant_flags[I915_MAX_CONSTANT]; |
GLuint nr_constants; |
GLuint *csr; /* Cursor, points into program. |
*/ |
GLuint *decl; /* Cursor, points into declarations. |
*/ |
GLuint decl_s; /* flags for which s regs need to be decl'd */ |
GLuint decl_t; /* flags for which t regs need to be decl'd */ |
GLuint temp_flag; /* Tracks temporary regs which are in |
* use. |
*/ |
GLuint utemp_flag; /* Tracks TYPE_U temporary regs which are in |
* use. |
*/ |
/* Track which R registers are "live" for each instruction. |
* A register is live between the time it's written to and the last time |
* it's read. */ |
GLuint usedRegs[I915_MAX_INSN]; |
/* Helpers for i915_fragprog.c: |
*/ |
GLuint wpos_tex; |
bool depth_written; |
struct |
{ |
GLuint reg; /* Hardware constant idx */ |
const GLfloat *values; /* Pointer to tracked values */ |
} param[I915_MAX_CONSTANT]; |
GLuint nr_params; |
}; |
#define I915_TEX_UNITS 8 |
struct i915_hw_state |
{ |
GLuint Ctx[I915_CTX_SETUP_SIZE]; |
GLuint Blend[I915_BLEND_SETUP_SIZE]; |
GLuint Buffer[I915_DEST_SETUP_SIZE]; |
GLuint Stipple[I915_STP_SETUP_SIZE]; |
GLuint Defaults[I915_DEF_SETUP_SIZE]; |
GLuint RasterRules[I915_RASTER_RULES_SETUP_SIZE]; |
GLuint Tex[I915_TEX_UNITS][I915_TEX_SETUP_SIZE]; |
GLuint Constant[I915_CONSTANT_SIZE]; |
GLuint ConstantSize; |
GLuint Program[I915_PROGRAM_SIZE]; |
GLuint ProgramSize; |
/* Region pointers for relocation: |
*/ |
struct intel_region *draw_region; |
struct intel_region *depth_region; |
/* struct intel_region *tex_region[I915_TEX_UNITS]; */ |
/* Regions aren't actually that appropriate here as the memory may |
* be from a PBO or FBO. Will have to do this for draw and depth for |
* FBO's... |
*/ |
drm_intel_bo *tex_buffer[I915_TEX_UNITS]; |
GLuint tex_offset[I915_TEX_UNITS]; |
GLuint active; /* I915_UPLOAD_* */ |
GLuint emitted; /* I915_UPLOAD_* */ |
}; |
struct i915_context |
{ |
struct intel_context intel; |
GLuint last_ReallyEnabled; |
GLuint lodbias_ss2[MAX_TEXTURE_UNITS]; |
struct i915_fragment_program *current_program; |
drm_intel_bo *current_vb_bo; |
unsigned int current_vertex_size; |
struct i915_hw_state state; |
uint32_t last_draw_offset; |
GLuint last_sampler; |
}; |
#define I915_STATECHANGE(i915, flag) \ |
do { \ |
INTEL_FIREVERTICES( &(i915)->intel ); \ |
(i915)->state.emitted &= ~(flag); \ |
} while (0) |
#define I915_ACTIVESTATE(i915, flag, mode) \ |
do { \ |
INTEL_FIREVERTICES( &(i915)->intel ); \ |
if (mode) \ |
(i915)->state.active |= (flag); \ |
else \ |
(i915)->state.active &= ~(flag); \ |
} while (0) |
/*====================================================================== |
* i915_vtbl.c |
*/ |
extern void i915InitVtbl(struct i915_context *i915); |
extern void |
i915_state_draw_region(struct intel_context *intel, |
struct i915_hw_state *state, |
struct intel_region *color_region, |
struct intel_region *depth_region); |
#define SZ_TO_HW(sz) ((sz-2)&0x3) |
#define EMIT_SZ(sz) (EMIT_1F + (sz) - 1) |
#define EMIT_ATTR( ATTR, STYLE, S4, SZ ) \ |
do { \ |
intel->vertex_attrs[intel->vertex_attr_count].attrib = (ATTR); \ |
intel->vertex_attrs[intel->vertex_attr_count].format = (STYLE); \ |
s4 |= S4; \ |
intel->vertex_attr_count++; \ |
offset += (SZ); \ |
} while (0) |
#define EMIT_PAD( N ) \ |
do { \ |
intel->vertex_attrs[intel->vertex_attr_count].attrib = 0; \ |
intel->vertex_attrs[intel->vertex_attr_count].format = EMIT_PAD; \ |
intel->vertex_attrs[intel->vertex_attr_count].offset = (N); \ |
intel->vertex_attr_count++; \ |
offset += (N); \ |
} while (0) |
/*====================================================================== |
* i915_context.c |
*/ |
extern bool i915CreateContext(int api, |
const struct gl_config * mesaVis, |
__DRIcontext * driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
unsigned *error, |
void *sharedContextPrivate); |
/*====================================================================== |
* i915_debug.c |
*/ |
extern void i915_disassemble_program(const GLuint * program, GLuint sz); |
extern void i915_print_ureg(const char *msg, GLuint ureg); |
/*====================================================================== |
* i915_state.c |
*/ |
extern void i915InitStateFunctions(struct dd_function_table *functions); |
extern void i915InitState(struct i915_context *i915); |
extern void i915_update_stencil(struct gl_context * ctx); |
extern void i915_update_provoking_vertex(struct gl_context *ctx); |
extern void i915_update_sprite_point_enable(struct gl_context *ctx); |
/*====================================================================== |
* i915_tex.c |
*/ |
extern void i915UpdateTextureState(struct intel_context *intel); |
extern void i915InitTextureFuncs(struct dd_function_table *functions); |
/*====================================================================== |
* i915_fragprog.c |
*/ |
extern void i915ValidateFragmentProgram(struct i915_context *i915); |
extern void i915InitFragProgFuncs(struct dd_function_table *functions); |
/*====================================================================== |
* Inline conversion functions. These are better-typed than the |
* macros used previously: |
*/ |
static INLINE struct i915_context * |
i915_context(struct gl_context * ctx) |
{ |
return (struct i915_context *) ctx; |
} |
#define I915_CONTEXT(ctx) i915_context(ctx) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_debug.h |
---|
0,0 → 1,39 |
/************************************************************************** |
* |
* 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 I915_DEBUG_H |
#define I915_DEBUG_H |
struct i915_context; |
extern void i915_disassemble_program(const unsigned *program, unsigned sz); |
extern void i915_print_ureg(const char *msg, unsigned ureg); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_debug_fp.c |
---|
0,0 → 1,328 |
/************************************************************************** |
* |
* 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 <stdio.h> |
#include "i915_reg.h" |
#include "i915_debug.h" |
#include "main/imports.h" |
static const char *opcodes[0x20] = { |
"NOP", |
"ADD", |
"MOV", |
"MUL", |
"MAD", |
"DP2ADD", |
"DP3", |
"DP4", |
"FRC", |
"RCP", |
"RSQ", |
"EXP", |
"LOG", |
"CMP", |
"MIN", |
"MAX", |
"FLR", |
"MOD", |
"TRC", |
"SGE", |
"SLT", |
"TEXLD", |
"TEXLDP", |
"TEXLDB", |
"TEXKILL", |
"DCL", |
"0x1a", |
"0x1b", |
"0x1c", |
"0x1d", |
"0x1e", |
"0x1f", |
}; |
static const int args[0x20] = { |
0, /* 0 nop */ |
2, /* 1 add */ |
1, /* 2 mov */ |
2, /* 3 m ul */ |
3, /* 4 mad */ |
3, /* 5 dp2add */ |
2, /* 6 dp3 */ |
2, /* 7 dp4 */ |
1, /* 8 frc */ |
1, /* 9 rcp */ |
1, /* a rsq */ |
1, /* b exp */ |
1, /* c log */ |
3, /* d cmp */ |
2, /* e min */ |
2, /* f max */ |
1, /* 10 flr */ |
1, /* 11 mod */ |
1, /* 12 trc */ |
2, /* 13 sge */ |
2, /* 14 slt */ |
1, |
1, |
1, |
1, |
0, |
0, |
0, |
0, |
0, |
0, |
0, |
}; |
static const char *regname[0x8] = { |
"R", |
"T", |
"CONST", |
"S", |
"OC", |
"OD", |
"U", |
"UNKNOWN", |
}; |
static void |
print_reg_type_nr(GLuint type, GLuint nr) |
{ |
switch (type) { |
case REG_TYPE_T: |
switch (nr) { |
case T_DIFFUSE: |
printf("T_DIFFUSE"); |
return; |
case T_SPECULAR: |
printf("T_SPECULAR"); |
return; |
case T_FOG_W: |
printf("T_FOG_W"); |
return; |
default: |
printf("T_TEX%d", nr); |
return; |
} |
case REG_TYPE_OC: |
if (nr == 0) { |
printf("oC"); |
return; |
} |
break; |
case REG_TYPE_OD: |
if (nr == 0) { |
printf("oD"); |
return; |
} |
break; |
default: |
break; |
} |
printf("%s[%d]", regname[type], nr); |
} |
#define REG_SWIZZLE_MASK 0x7777 |
#define REG_NEGATE_MASK 0x8888 |
#define REG_SWIZZLE_XYZW ((SRC_X << A2_SRC2_CHANNEL_X_SHIFT) | \ |
(SRC_Y << A2_SRC2_CHANNEL_Y_SHIFT) | \ |
(SRC_Z << A2_SRC2_CHANNEL_Z_SHIFT) | \ |
(SRC_W << A2_SRC2_CHANNEL_W_SHIFT)) |
static void |
print_reg_neg_swizzle(GLuint reg) |
{ |
int i; |
if ((reg & REG_SWIZZLE_MASK) == REG_SWIZZLE_XYZW && |
(reg & REG_NEGATE_MASK) == 0) |
return; |
printf("."); |
for (i = 3; i >= 0; i--) { |
if (reg & (1 << ((i * 4) + 3))) |
printf("-"); |
switch ((reg >> (i * 4)) & 0x7) { |
case 0: |
printf("x"); |
break; |
case 1: |
printf("y"); |
break; |
case 2: |
printf("z"); |
break; |
case 3: |
printf("w"); |
break; |
case 4: |
printf("0"); |
break; |
case 5: |
printf("1"); |
break; |
default: |
printf("?"); |
break; |
} |
} |
} |
static void |
print_src_reg(GLuint dword) |
{ |
GLuint nr = (dword >> A2_SRC2_NR_SHIFT) & REG_NR_MASK; |
GLuint type = (dword >> A2_SRC2_TYPE_SHIFT) & REG_TYPE_MASK; |
print_reg_type_nr(type, nr); |
print_reg_neg_swizzle(dword); |
} |
static void |
print_dest_reg(GLuint dword) |
{ |
GLuint nr = (dword >> A0_DEST_NR_SHIFT) & REG_NR_MASK; |
GLuint type = (dword >> A0_DEST_TYPE_SHIFT) & REG_TYPE_MASK; |
print_reg_type_nr(type, nr); |
if ((dword & A0_DEST_CHANNEL_ALL) == A0_DEST_CHANNEL_ALL) |
return; |
printf("."); |
if (dword & A0_DEST_CHANNEL_X) |
printf("x"); |
if (dword & A0_DEST_CHANNEL_Y) |
printf("y"); |
if (dword & A0_DEST_CHANNEL_Z) |
printf("z"); |
if (dword & A0_DEST_CHANNEL_W) |
printf("w"); |
} |
#define GET_SRC0_REG(r0, r1) ((r0<<14)|(r1>>A1_SRC0_CHANNEL_W_SHIFT)) |
#define GET_SRC1_REG(r0, r1) ((r0<<8)|(r1>>A2_SRC1_CHANNEL_W_SHIFT)) |
#define GET_SRC2_REG(r) (r) |
static void |
print_arith_op(GLuint opcode, const GLuint * program) |
{ |
if (opcode != A0_NOP) { |
print_dest_reg(program[0]); |
if (program[0] & A0_DEST_SATURATE) |
printf(" = SATURATE "); |
else |
printf(" = "); |
} |
printf("%s ", opcodes[opcode]); |
print_src_reg(GET_SRC0_REG(program[0], program[1])); |
if (args[opcode] == 1) { |
printf("\n"); |
return; |
} |
printf(", "); |
print_src_reg(GET_SRC1_REG(program[1], program[2])); |
if (args[opcode] == 2) { |
printf("\n"); |
return; |
} |
printf(", "); |
print_src_reg(GET_SRC2_REG(program[2])); |
printf("\n"); |
return; |
} |
static void |
print_tex_op(GLuint opcode, const GLuint * program) |
{ |
print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); |
printf(" = "); |
printf("%s ", opcodes[opcode]); |
printf("S[%d],", program[0] & T0_SAMPLER_NR_MASK); |
print_reg_type_nr((program[1] >> T1_ADDRESS_REG_TYPE_SHIFT) & |
REG_TYPE_MASK, |
(program[1] >> T1_ADDRESS_REG_NR_SHIFT) & REG_NR_MASK); |
printf("\n"); |
} |
static void |
print_dcl_op(GLuint opcode, const GLuint * program) |
{ |
printf("%s ", opcodes[opcode]); |
print_dest_reg(program[0] | A0_DEST_CHANNEL_ALL); |
printf("\n"); |
} |
void |
i915_disassemble_program(const GLuint * program, GLuint sz) |
{ |
GLuint size = program[0] & 0x1ff; |
GLint i; |
printf("\t\tBEGIN\n"); |
assert(size + 2 == sz); |
program++; |
for (i = 1; i < sz; i += 3, program += 3) { |
GLuint opcode = program[0] & (0x1f << 24); |
printf("\t\t"); |
if ((GLint) opcode >= A0_NOP && opcode <= A0_SLT) |
print_arith_op(opcode >> 24, program); |
else if (opcode >= T0_TEXLD && opcode <= T0_TEXKILL) |
print_tex_op(opcode >> 24, program); |
else if (opcode == D0_DCL) |
print_dcl_op(opcode >> 24, program); |
else |
printf("Unknown opcode 0x%x\n", opcode); |
} |
printf("\t\tEND\n\n"); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_fragprog.c |
---|
0,0 → 1,1465 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "program/prog_instruction.h" |
#include "program/prog_parameter.h" |
#include "program/program.h" |
#include "program/programopt.h" |
#include "program/prog_print.h" |
#include "tnl/tnl.h" |
#include "tnl/t_context.h" |
#include "intel_batchbuffer.h" |
#include "i915_reg.h" |
#include "i915_context.h" |
#include "i915_program.h" |
static const GLfloat sin_quad_constants[2][4] = { |
{ |
2.0, |
-1.0, |
.5, |
.75 |
}, |
{ |
4.0, |
-4.0, |
1.0 / (2.0 * M_PI), |
.2225 |
} |
}; |
static const GLfloat sin_constants[4] = { 1.0, |
-1.0 / (3 * 2 * 1), |
1.0 / (5 * 4 * 3 * 2 * 1), |
-1.0 / (7 * 6 * 5 * 4 * 3 * 2 * 1) |
}; |
/* 1, -1/2!, 1/4!, -1/6! */ |
static const GLfloat cos_constants[4] = { 1.0, |
-1.0 / (2 * 1), |
1.0 / (4 * 3 * 2 * 1), |
-1.0 / (6 * 5 * 4 * 3 * 2 * 1) |
}; |
/** |
* Retrieve a ureg for the given source register. Will emit |
* constants, apply swizzling and negation as needed. |
*/ |
static GLuint |
src_vector(struct i915_fragment_program *p, |
const struct prog_src_register *source, |
const struct gl_fragment_program *program) |
{ |
GLuint src; |
switch (source->File) { |
/* Registers: |
*/ |
case PROGRAM_TEMPORARY: |
if (source->Index >= I915_MAX_TEMPORARY) { |
i915_program_error(p, "Exceeded max temporary reg: %d/%d", |
source->Index, I915_MAX_TEMPORARY); |
return 0; |
} |
src = UREG(REG_TYPE_R, source->Index); |
break; |
case PROGRAM_INPUT: |
switch (source->Index) { |
case VARYING_SLOT_POS: |
src = i915_emit_decl(p, REG_TYPE_T, p->wpos_tex, D0_CHANNEL_ALL); |
break; |
case VARYING_SLOT_COL0: |
src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL); |
break; |
case VARYING_SLOT_COL1: |
src = i915_emit_decl(p, REG_TYPE_T, T_SPECULAR, D0_CHANNEL_XYZ); |
src = swizzle(src, X, Y, Z, ONE); |
break; |
case VARYING_SLOT_FOGC: |
src = i915_emit_decl(p, REG_TYPE_T, T_FOG_W, D0_CHANNEL_W); |
src = swizzle(src, W, ZERO, ZERO, ONE); |
break; |
case VARYING_SLOT_TEX0: |
case VARYING_SLOT_TEX1: |
case VARYING_SLOT_TEX2: |
case VARYING_SLOT_TEX3: |
case VARYING_SLOT_TEX4: |
case VARYING_SLOT_TEX5: |
case VARYING_SLOT_TEX6: |
case VARYING_SLOT_TEX7: |
src = i915_emit_decl(p, REG_TYPE_T, |
T_TEX0 + (source->Index - VARYING_SLOT_TEX0), |
D0_CHANNEL_ALL); |
break; |
case VARYING_SLOT_VAR0: |
case VARYING_SLOT_VAR0 + 1: |
case VARYING_SLOT_VAR0 + 2: |
case VARYING_SLOT_VAR0 + 3: |
case VARYING_SLOT_VAR0 + 4: |
case VARYING_SLOT_VAR0 + 5: |
case VARYING_SLOT_VAR0 + 6: |
case VARYING_SLOT_VAR0 + 7: |
src = i915_emit_decl(p, REG_TYPE_T, |
T_TEX0 + (source->Index - VARYING_SLOT_VAR0), |
D0_CHANNEL_ALL); |
break; |
default: |
i915_program_error(p, "Bad source->Index: %d", source->Index); |
return 0; |
} |
break; |
case PROGRAM_OUTPUT: |
switch (source->Index) { |
case FRAG_RESULT_COLOR: |
src = UREG(REG_TYPE_OC, 0); |
break; |
case FRAG_RESULT_DEPTH: |
src = UREG(REG_TYPE_OD, 0); |
break; |
default: |
i915_program_error(p, "Bad source->Index: %d", source->Index); |
return 0; |
} |
break; |
/* Various paramters and env values. All emitted to |
* hardware as program constants. |
*/ |
case PROGRAM_LOCAL_PARAM: |
src = i915_emit_param4fv(p, program->Base.LocalParams[source->Index]); |
break; |
case PROGRAM_ENV_PARAM: |
src = |
i915_emit_param4fv(p, |
p->ctx->FragmentProgram.Parameters[source-> |
Index]); |
break; |
case PROGRAM_CONSTANT: |
case PROGRAM_STATE_VAR: |
case PROGRAM_UNIFORM: |
src = i915_emit_param4fv(p, |
&program->Base.Parameters->ParameterValues[source->Index][0].f); |
break; |
default: |
i915_program_error(p, "Bad source->File: %d", source->File); |
return 0; |
} |
src = swizzle(src, |
GET_SWZ(source->Swizzle, 0), |
GET_SWZ(source->Swizzle, 1), |
GET_SWZ(source->Swizzle, 2), GET_SWZ(source->Swizzle, 3)); |
if (source->Negate) |
src = negate(src, |
GET_BIT(source->Negate, 0), |
GET_BIT(source->Negate, 1), |
GET_BIT(source->Negate, 2), |
GET_BIT(source->Negate, 3)); |
return src; |
} |
static GLuint |
get_result_vector(struct i915_fragment_program *p, |
const struct prog_instruction *inst) |
{ |
switch (inst->DstReg.File) { |
case PROGRAM_OUTPUT: |
switch (inst->DstReg.Index) { |
case FRAG_RESULT_COLOR: |
case FRAG_RESULT_DATA0: |
return UREG(REG_TYPE_OC, 0); |
case FRAG_RESULT_DEPTH: |
p->depth_written = 1; |
return UREG(REG_TYPE_OD, 0); |
default: |
i915_program_error(p, "Bad inst->DstReg.Index: %d", |
inst->DstReg.Index); |
return 0; |
} |
case PROGRAM_TEMPORARY: |
return UREG(REG_TYPE_R, inst->DstReg.Index); |
default: |
i915_program_error(p, "Bad inst->DstReg.File: %d", inst->DstReg.File); |
return 0; |
} |
} |
static GLuint |
get_result_flags(const struct prog_instruction *inst) |
{ |
GLuint flags = 0; |
if (inst->SaturateMode == SATURATE_ZERO_ONE) |
flags |= A0_DEST_SATURATE; |
if (inst->DstReg.WriteMask & WRITEMASK_X) |
flags |= A0_DEST_CHANNEL_X; |
if (inst->DstReg.WriteMask & WRITEMASK_Y) |
flags |= A0_DEST_CHANNEL_Y; |
if (inst->DstReg.WriteMask & WRITEMASK_Z) |
flags |= A0_DEST_CHANNEL_Z; |
if (inst->DstReg.WriteMask & WRITEMASK_W) |
flags |= A0_DEST_CHANNEL_W; |
return flags; |
} |
static GLuint |
translate_tex_src_target(struct i915_fragment_program *p, GLubyte bit) |
{ |
switch (bit) { |
case TEXTURE_1D_INDEX: |
return D0_SAMPLE_TYPE_2D; |
case TEXTURE_2D_INDEX: |
return D0_SAMPLE_TYPE_2D; |
case TEXTURE_RECT_INDEX: |
return D0_SAMPLE_TYPE_2D; |
case TEXTURE_3D_INDEX: |
return D0_SAMPLE_TYPE_VOLUME; |
case TEXTURE_CUBE_INDEX: |
return D0_SAMPLE_TYPE_CUBE; |
default: |
i915_program_error(p, "TexSrcBit: %d", bit); |
return 0; |
} |
} |
#define EMIT_TEX( OP ) \ |
do { \ |
GLuint dim = translate_tex_src_target( p, inst->TexSrcTarget ); \ |
const struct gl_fragment_program *program = &p->FragProg; \ |
GLuint unit = program->Base.SamplerUnits[inst->TexSrcUnit]; \ |
GLuint sampler = i915_emit_decl(p, REG_TYPE_S, \ |
unit, dim); \ |
GLuint coord = src_vector( p, &inst->SrcReg[0], program); \ |
/* Texel lookup */ \ |
\ |
i915_emit_texld( p, get_live_regs(p, inst), \ |
get_result_vector( p, inst ), \ |
get_result_flags( inst ), \ |
sampler, \ |
coord, \ |
OP); \ |
} while (0) |
#define EMIT_ARITH( OP, N ) \ |
do { \ |
i915_emit_arith( p, \ |
OP, \ |
get_result_vector( p, inst ), \ |
get_result_flags( inst ), 0, \ |
(N<1)?0:src_vector( p, &inst->SrcReg[0], program), \ |
(N<2)?0:src_vector( p, &inst->SrcReg[1], program), \ |
(N<3)?0:src_vector( p, &inst->SrcReg[2], program)); \ |
} while (0) |
#define EMIT_1ARG_ARITH( OP ) EMIT_ARITH( OP, 1 ) |
#define EMIT_2ARG_ARITH( OP ) EMIT_ARITH( OP, 2 ) |
#define EMIT_3ARG_ARITH( OP ) EMIT_ARITH( OP, 3 ) |
/* |
* TODO: consider moving this into core |
*/ |
static bool calc_live_regs( struct i915_fragment_program *p ) |
{ |
const struct gl_fragment_program *program = &p->FragProg; |
GLuint regsUsed = ~((1 << I915_MAX_TEMPORARY) - 1); |
uint8_t live_components[I915_MAX_TEMPORARY] = { 0, }; |
GLint i; |
for (i = program->Base.NumInstructions - 1; i >= 0; i--) { |
struct prog_instruction *inst = &program->Base.Instructions[i]; |
int opArgs = _mesa_num_inst_src_regs(inst->Opcode); |
int a; |
/* Register is written to: unmark as live for this and preceeding ops */ |
if (inst->DstReg.File == PROGRAM_TEMPORARY) { |
if (inst->DstReg.Index >= I915_MAX_TEMPORARY) |
return false; |
live_components[inst->DstReg.Index] &= ~inst->DstReg.WriteMask; |
if (live_components[inst->DstReg.Index] == 0) |
regsUsed &= ~(1 << inst->DstReg.Index); |
} |
for (a = 0; a < opArgs; a++) { |
/* Register is read from: mark as live for this and preceeding ops */ |
if (inst->SrcReg[a].File == PROGRAM_TEMPORARY) { |
unsigned c; |
if (inst->SrcReg[a].Index >= I915_MAX_TEMPORARY) |
return false; |
regsUsed |= 1 << inst->SrcReg[a].Index; |
for (c = 0; c < 4; c++) { |
const unsigned field = GET_SWZ(inst->SrcReg[a].Swizzle, c); |
if (field <= SWIZZLE_W) |
live_components[inst->SrcReg[a].Index] |= (1U << field); |
} |
} |
} |
p->usedRegs[i] = regsUsed; |
} |
return true; |
} |
static GLuint get_live_regs( struct i915_fragment_program *p, |
const struct prog_instruction *inst ) |
{ |
const struct gl_fragment_program *program = &p->FragProg; |
GLuint nr = inst - program->Base.Instructions; |
return p->usedRegs[nr]; |
} |
/* Possible concerns: |
* |
* SIN, COS -- could use another taylor step? |
* LIT -- results seem a little different to sw mesa |
* LOG -- different to mesa on negative numbers, but this is conformant. |
* |
* Parse failures -- Mesa doesn't currently give a good indication |
* internally whether a particular program string parsed or not. This |
* can lead to confusion -- hopefully we cope with it ok now. |
* |
*/ |
static void |
upload_program(struct i915_fragment_program *p) |
{ |
const struct gl_fragment_program *program = &p->FragProg; |
const struct prog_instruction *inst = program->Base.Instructions; |
if (INTEL_DEBUG & DEBUG_WM) |
_mesa_print_program(&program->Base); |
/* Is this a parse-failed program? Ensure a valid program is |
* loaded, as the flagging of an error isn't sufficient to stop |
* this being uploaded to hardware. |
*/ |
if (inst[0].Opcode == OPCODE_END) { |
GLuint tmp = i915_get_utemp(p); |
i915_emit_arith(p, |
A0_MOV, |
UREG(REG_TYPE_OC, 0), |
A0_DEST_CHANNEL_ALL, 0, |
swizzle(tmp, ONE, ZERO, ONE, ONE), 0, 0); |
return; |
} |
if (program->Base.NumInstructions > I915_MAX_INSN) { |
i915_program_error(p, "Exceeded max instructions (%d out of %d)", |
program->Base.NumInstructions, I915_MAX_INSN); |
return; |
} |
/* Not always needed: |
*/ |
if (!calc_live_regs(p)) { |
i915_program_error(p, "Could not allocate registers"); |
return; |
} |
while (1) { |
GLuint src0, src1, src2, flags; |
GLuint tmp = 0, dst, consts0 = 0, consts1 = 0; |
switch (inst->Opcode) { |
case OPCODE_ABS: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
i915_emit_arith(p, |
A0_MAX, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
src0, negate(src0, 1, 1, 1, 1), 0); |
break; |
case OPCODE_ADD: |
EMIT_2ARG_ARITH(A0_ADD); |
break; |
case OPCODE_CMP: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
src1 = src_vector(p, &inst->SrcReg[1], program); |
src2 = src_vector(p, &inst->SrcReg[2], program); |
i915_emit_arith(p, A0_CMP, get_result_vector(p, inst), get_result_flags(inst), 0, src0, src2, src1); /* NOTE: order of src2, src1 */ |
break; |
case OPCODE_COS: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
tmp = i915_get_utemp(p); |
consts0 = i915_emit_const4fv(p, sin_quad_constants[0]); |
consts1 = i915_emit_const4fv(p, sin_quad_constants[1]); |
/* Reduce range from repeating about [-pi,pi] to [-1,1] */ |
i915_emit_arith(p, |
A0_MAD, |
tmp, A0_DEST_CHANNEL_X, 0, |
src0, |
swizzle(consts1, Z, ZERO, ZERO, ZERO), /* 1/(2pi) */ |
swizzle(consts0, W, ZERO, ZERO, ZERO)); /* .75 */ |
i915_emit_arith(p, A0_FRC, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0); |
i915_emit_arith(p, |
A0_MAD, |
tmp, A0_DEST_CHANNEL_X, 0, |
tmp, |
swizzle(consts0, X, ZERO, ZERO, ZERO), /* 2 */ |
swizzle(consts0, Y, ZERO, ZERO, ZERO)); /* -1 */ |
/* Compute COS with the same calculation used for SIN, but a |
* different source range has been mapped to [-1,1] this time. |
*/ |
/* tmp.y = abs(tmp.x); {x, abs(x), 0, 0} */ |
i915_emit_arith(p, |
A0_MAX, |
tmp, A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp, ZERO, X, ZERO, ZERO), |
negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0), |
0); |
/* tmp.y = tmp.y * tmp.x; {x, x * abs(x), 0, 0} */ |
i915_emit_arith(p, |
A0_MUL, |
tmp, A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp, ZERO, X, ZERO, ZERO), |
tmp, |
0); |
/* tmp.x = tmp.xy DP sin_quad_constants[2].xy */ |
i915_emit_arith(p, |
A0_DP3, |
tmp, A0_DEST_CHANNEL_X, 0, |
tmp, |
swizzle(consts1, X, Y, ZERO, ZERO), |
0); |
/* tmp.x now contains a first approximation (y). Now, weight it |
* against tmp.y**2 to get closer. |
*/ |
i915_emit_arith(p, |
A0_MAX, |
tmp, A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp, ZERO, X, ZERO, ZERO), |
negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0), |
0); |
/* tmp.y = tmp.x * tmp.y - tmp.x; {y, y * abs(y) - y, 0, 0} */ |
i915_emit_arith(p, |
A0_MAD, |
tmp, A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp, ZERO, X, ZERO, ZERO), |
swizzle(tmp, ZERO, Y, ZERO, ZERO), |
negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0)); |
/* result = .2225 * tmp.y + tmp.x =.2225(y * abs(y) - y) + y= */ |
i915_emit_arith(p, |
A0_MAD, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
swizzle(consts1, W, W, W, W), |
swizzle(tmp, Y, Y, Y, Y), |
swizzle(tmp, X, X, X, X)); |
break; |
case OPCODE_DP2: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
src1 = src_vector(p, &inst->SrcReg[1], program); |
i915_emit_arith(p, |
A0_DP3, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
swizzle(src0, X, Y, ZERO, ZERO), |
swizzle(src1, X, Y, ZERO, ZERO), |
0); |
break; |
case OPCODE_DP3: |
EMIT_2ARG_ARITH(A0_DP3); |
break; |
case OPCODE_DP4: |
EMIT_2ARG_ARITH(A0_DP4); |
break; |
case OPCODE_DPH: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
src1 = src_vector(p, &inst->SrcReg[1], program); |
i915_emit_arith(p, |
A0_DP4, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
swizzle(src0, X, Y, Z, ONE), src1, 0); |
break; |
case OPCODE_DST: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
src1 = src_vector(p, &inst->SrcReg[1], program); |
/* result[0] = 1 * 1; |
* result[1] = a[1] * b[1]; |
* result[2] = a[2] * 1; |
* result[3] = 1 * b[3]; |
*/ |
i915_emit_arith(p, |
A0_MUL, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
swizzle(src0, ONE, Y, Z, ONE), |
swizzle(src1, ONE, Y, ONE, W), 0); |
break; |
case OPCODE_EX2: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
i915_emit_arith(p, |
A0_EXP, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
swizzle(src0, X, X, X, X), 0, 0); |
break; |
case OPCODE_FLR: |
EMIT_1ARG_ARITH(A0_FLR); |
break; |
case OPCODE_TRUNC: |
EMIT_1ARG_ARITH(A0_TRC); |
break; |
case OPCODE_FRC: |
EMIT_1ARG_ARITH(A0_FRC); |
break; |
case OPCODE_KIL: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
tmp = i915_get_utemp(p); |
i915_emit_texld(p, get_live_regs(p, inst), |
tmp, A0_DEST_CHANNEL_ALL, /* use a dummy dest reg */ |
0, src0, T0_TEXKILL); |
break; |
case OPCODE_KIL_NV: |
if (inst->DstReg.CondMask == COND_TR) { |
tmp = i915_get_utemp(p); |
/* The KIL instruction discards the fragment if any component of |
* the source is < 0. Emit an immediate operand of {-1}.xywz. |
*/ |
i915_emit_texld(p, get_live_regs(p, inst), |
tmp, A0_DEST_CHANNEL_ALL, |
0, /* use a dummy dest reg */ |
negate(swizzle(tmp, ONE, ONE, ONE, ONE), |
1, 1, 1, 1), |
T0_TEXKILL); |
} else { |
p->error = 1; |
i915_program_error(p, "Unsupported KIL_NV condition code: %d", |
inst->DstReg.CondMask); |
} |
break; |
case OPCODE_LG2: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
i915_emit_arith(p, |
A0_LOG, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
swizzle(src0, X, X, X, X), 0, 0); |
break; |
case OPCODE_LIT: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
tmp = i915_get_utemp(p); |
/* tmp = max( a.xyzw, a.00zw ) |
* XXX: Clamp tmp.w to -128..128 |
* tmp.y = log(tmp.y) |
* tmp.y = tmp.w * tmp.y |
* tmp.y = exp(tmp.y) |
* result = cmp (a.11-x1, a.1x01, a.1xy1 ) |
*/ |
i915_emit_arith(p, A0_MAX, tmp, A0_DEST_CHANNEL_ALL, 0, |
src0, swizzle(src0, ZERO, ZERO, Z, W), 0); |
i915_emit_arith(p, A0_LOG, tmp, A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp, Y, Y, Y, Y), 0, 0); |
i915_emit_arith(p, A0_MUL, tmp, A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp, ZERO, Y, ZERO, ZERO), |
swizzle(tmp, ZERO, W, ZERO, ZERO), 0); |
i915_emit_arith(p, A0_EXP, tmp, A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp, Y, Y, Y, Y), 0, 0); |
i915_emit_arith(p, A0_CMP, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
negate(swizzle(tmp, ONE, ONE, X, ONE), 0, 0, 1, 0), |
swizzle(tmp, ONE, X, ZERO, ONE), |
swizzle(tmp, ONE, X, Y, ONE)); |
break; |
case OPCODE_LRP: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
src1 = src_vector(p, &inst->SrcReg[1], program); |
src2 = src_vector(p, &inst->SrcReg[2], program); |
flags = get_result_flags(inst); |
tmp = i915_get_utemp(p); |
/* b*a + c*(1-a) |
* |
* b*a + c - ca |
* |
* tmp = b*a + c, |
* result = (-c)*a + tmp |
*/ |
i915_emit_arith(p, A0_MAD, tmp, |
flags & A0_DEST_CHANNEL_ALL, 0, src1, src0, src2); |
i915_emit_arith(p, A0_MAD, |
get_result_vector(p, inst), |
flags, 0, negate(src2, 1, 1, 1, 1), src0, tmp); |
break; |
case OPCODE_MAD: |
EMIT_3ARG_ARITH(A0_MAD); |
break; |
case OPCODE_MAX: |
EMIT_2ARG_ARITH(A0_MAX); |
break; |
case OPCODE_MIN: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
src1 = src_vector(p, &inst->SrcReg[1], program); |
tmp = i915_get_utemp(p); |
flags = get_result_flags(inst); |
i915_emit_arith(p, |
A0_MAX, |
tmp, flags & A0_DEST_CHANNEL_ALL, 0, |
negate(src0, 1, 1, 1, 1), |
negate(src1, 1, 1, 1, 1), 0); |
i915_emit_arith(p, |
A0_MOV, |
get_result_vector(p, inst), |
flags, 0, negate(tmp, 1, 1, 1, 1), 0, 0); |
break; |
case OPCODE_MOV: |
EMIT_1ARG_ARITH(A0_MOV); |
break; |
case OPCODE_MUL: |
EMIT_2ARG_ARITH(A0_MUL); |
break; |
case OPCODE_POW: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
src1 = src_vector(p, &inst->SrcReg[1], program); |
tmp = i915_get_utemp(p); |
flags = get_result_flags(inst); |
/* XXX: masking on intermediate values, here and elsewhere. |
*/ |
i915_emit_arith(p, |
A0_LOG, |
tmp, A0_DEST_CHANNEL_X, 0, |
swizzle(src0, X, X, X, X), 0, 0); |
i915_emit_arith(p, A0_MUL, tmp, A0_DEST_CHANNEL_X, 0, tmp, src1, 0); |
i915_emit_arith(p, |
A0_EXP, |
get_result_vector(p, inst), |
flags, 0, swizzle(tmp, X, X, X, X), 0, 0); |
break; |
case OPCODE_RCP: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
i915_emit_arith(p, |
A0_RCP, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
swizzle(src0, X, X, X, X), 0, 0); |
break; |
case OPCODE_RSQ: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
i915_emit_arith(p, |
A0_RSQ, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
swizzle(src0, X, X, X, X), 0, 0); |
break; |
case OPCODE_SCS: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
tmp = i915_get_utemp(p); |
/* |
* t0.xy = MUL x.xx11, x.x1111 ; x^2, x, 1, 1 |
* t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, x |
* t1 = MUL t0.xyyw t0.yz11 ; x^7 x^5 x^3 x |
* scs.x = DP4 t1, sin_constants |
* t1 = MUL t0.xxz1 t0.z111 ; x^6 x^4 x^2 1 |
* scs.y = DP4 t1, cos_constants |
*/ |
i915_emit_arith(p, |
A0_MUL, |
tmp, A0_DEST_CHANNEL_XY, 0, |
swizzle(src0, X, X, ONE, ONE), |
swizzle(src0, X, ONE, ONE, ONE), 0); |
i915_emit_arith(p, |
A0_MUL, |
tmp, A0_DEST_CHANNEL_ALL, 0, |
swizzle(tmp, X, Y, X, Y), |
swizzle(tmp, X, X, ONE, ONE), 0); |
if (inst->DstReg.WriteMask & WRITEMASK_Y) { |
GLuint tmp1; |
if (inst->DstReg.WriteMask & WRITEMASK_X) |
tmp1 = i915_get_utemp(p); |
else |
tmp1 = tmp; |
i915_emit_arith(p, |
A0_MUL, |
tmp1, A0_DEST_CHANNEL_ALL, 0, |
swizzle(tmp, X, Y, Y, W), |
swizzle(tmp, X, Z, ONE, ONE), 0); |
i915_emit_arith(p, |
A0_DP4, |
get_result_vector(p, inst), |
A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp1, W, Z, Y, X), |
i915_emit_const4fv(p, sin_constants), 0); |
} |
if (inst->DstReg.WriteMask & WRITEMASK_X) { |
i915_emit_arith(p, |
A0_MUL, |
tmp, A0_DEST_CHANNEL_XYZ, 0, |
swizzle(tmp, X, X, Z, ONE), |
swizzle(tmp, Z, ONE, ONE, ONE), 0); |
i915_emit_arith(p, |
A0_DP4, |
get_result_vector(p, inst), |
A0_DEST_CHANNEL_X, 0, |
swizzle(tmp, ONE, Z, Y, X), |
i915_emit_const4fv(p, cos_constants), 0); |
} |
break; |
case OPCODE_SEQ: |
tmp = i915_get_utemp(p); |
flags = get_result_flags(inst); |
dst = get_result_vector(p, inst); |
/* tmp = src1 >= src2 */ |
i915_emit_arith(p, |
A0_SGE, |
tmp, |
flags, 0, |
src_vector(p, &inst->SrcReg[0], program), |
src_vector(p, &inst->SrcReg[1], program), |
0); |
/* dst = src1 <= src2 */ |
i915_emit_arith(p, |
A0_SGE, |
dst, |
flags, 0, |
negate(src_vector(p, &inst->SrcReg[0], program), |
1, 1, 1, 1), |
negate(src_vector(p, &inst->SrcReg[1], program), |
1, 1, 1, 1), |
0); |
/* dst = tmp && dst */ |
i915_emit_arith(p, |
A0_MUL, |
dst, |
flags, 0, |
dst, |
tmp, |
0); |
break; |
case OPCODE_SIN: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
tmp = i915_get_utemp(p); |
consts0 = i915_emit_const4fv(p, sin_quad_constants[0]); |
consts1 = i915_emit_const4fv(p, sin_quad_constants[1]); |
/* Reduce range from repeating about [-pi,pi] to [-1,1] */ |
i915_emit_arith(p, |
A0_MAD, |
tmp, A0_DEST_CHANNEL_X, 0, |
src0, |
swizzle(consts1, Z, ZERO, ZERO, ZERO), /* 1/(2pi) */ |
swizzle(consts0, Z, ZERO, ZERO, ZERO)); /* .5 */ |
i915_emit_arith(p, A0_FRC, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0); |
i915_emit_arith(p, |
A0_MAD, |
tmp, A0_DEST_CHANNEL_X, 0, |
tmp, |
swizzle(consts0, X, ZERO, ZERO, ZERO), /* 2 */ |
swizzle(consts0, Y, ZERO, ZERO, ZERO)); /* -1 */ |
/* Compute sin using a quadratic and quartic. It gives continuity |
* that repeating the Taylor series lacks every 2*pi, and has |
* reduced error. |
* |
* The idea was described at: |
* http://www.devmaster.net/forums/showthread.php?t=5784 |
*/ |
/* tmp.y = abs(tmp.x); {x, abs(x), 0, 0} */ |
i915_emit_arith(p, |
A0_MAX, |
tmp, A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp, ZERO, X, ZERO, ZERO), |
negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0), |
0); |
/* tmp.y = tmp.y * tmp.x; {x, x * abs(x), 0, 0} */ |
i915_emit_arith(p, |
A0_MUL, |
tmp, A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp, ZERO, X, ZERO, ZERO), |
tmp, |
0); |
/* tmp.x = tmp.xy DP sin_quad_constants[2].xy */ |
i915_emit_arith(p, |
A0_DP3, |
tmp, A0_DEST_CHANNEL_X, 0, |
tmp, |
swizzle(consts1, X, Y, ZERO, ZERO), |
0); |
/* tmp.x now contains a first approximation (y). Now, weight it |
* against tmp.y**2 to get closer. |
*/ |
i915_emit_arith(p, |
A0_MAX, |
tmp, A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp, ZERO, X, ZERO, ZERO), |
negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0), |
0); |
/* tmp.y = tmp.x * tmp.y - tmp.x; {y, y * abs(y) - y, 0, 0} */ |
i915_emit_arith(p, |
A0_MAD, |
tmp, A0_DEST_CHANNEL_Y, 0, |
swizzle(tmp, ZERO, X, ZERO, ZERO), |
swizzle(tmp, ZERO, Y, ZERO, ZERO), |
negate(swizzle(tmp, ZERO, X, ZERO, ZERO), 0, 1, 0, 0)); |
/* result = .2225 * tmp.y + tmp.x =.2225(y * abs(y) - y) + y= */ |
i915_emit_arith(p, |
A0_MAD, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
swizzle(consts1, W, W, W, W), |
swizzle(tmp, Y, Y, Y, Y), |
swizzle(tmp, X, X, X, X)); |
break; |
case OPCODE_SGE: |
EMIT_2ARG_ARITH(A0_SGE); |
break; |
case OPCODE_SGT: |
i915_emit_arith(p, |
A0_SLT, |
get_result_vector( p, inst ), |
get_result_flags( inst ), 0, |
negate(src_vector( p, &inst->SrcReg[0], program), |
1, 1, 1, 1), |
negate(src_vector( p, &inst->SrcReg[1], program), |
1, 1, 1, 1), |
0); |
break; |
case OPCODE_SLE: |
i915_emit_arith(p, |
A0_SGE, |
get_result_vector( p, inst ), |
get_result_flags( inst ), 0, |
negate(src_vector( p, &inst->SrcReg[0], program), |
1, 1, 1, 1), |
negate(src_vector( p, &inst->SrcReg[1], program), |
1, 1, 1, 1), |
0); |
break; |
case OPCODE_SLT: |
EMIT_2ARG_ARITH(A0_SLT); |
break; |
case OPCODE_SNE: |
tmp = i915_get_utemp(p); |
flags = get_result_flags(inst); |
dst = get_result_vector(p, inst); |
/* tmp = src1 < src2 */ |
i915_emit_arith(p, |
A0_SLT, |
tmp, |
flags, 0, |
src_vector(p, &inst->SrcReg[0], program), |
src_vector(p, &inst->SrcReg[1], program), |
0); |
/* dst = src1 > src2 */ |
i915_emit_arith(p, |
A0_SLT, |
dst, |
flags, 0, |
negate(src_vector(p, &inst->SrcReg[0], program), |
1, 1, 1, 1), |
negate(src_vector(p, &inst->SrcReg[1], program), |
1, 1, 1, 1), |
0); |
/* dst = tmp || dst */ |
i915_emit_arith(p, |
A0_ADD, |
dst, |
flags | A0_DEST_SATURATE, 0, |
dst, |
tmp, |
0); |
break; |
case OPCODE_SSG: |
dst = get_result_vector(p, inst); |
flags = get_result_flags(inst); |
src0 = src_vector(p, &inst->SrcReg[0], program); |
tmp = i915_get_utemp(p); |
/* tmp = (src < 0.0) */ |
i915_emit_arith(p, |
A0_SLT, |
tmp, |
flags, 0, |
src0, |
swizzle(src0, ZERO, ZERO, ZERO, ZERO), |
0); |
/* dst = (0.0 < src) */ |
i915_emit_arith(p, |
A0_SLT, |
dst, |
flags, 0, |
swizzle(src0, ZERO, ZERO, ZERO, ZERO), |
src0, |
0); |
/* dst = (src > 0.0) - (src < 0.0) */ |
i915_emit_arith(p, |
A0_ADD, |
dst, |
flags, 0, |
dst, |
negate(tmp, 1, 1, 1, 1), |
0); |
break; |
case OPCODE_SUB: |
src0 = src_vector(p, &inst->SrcReg[0], program); |
src1 = src_vector(p, &inst->SrcReg[1], program); |
i915_emit_arith(p, |
A0_ADD, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
src0, negate(src1, 1, 1, 1, 1), 0); |
break; |
case OPCODE_SWZ: |
EMIT_1ARG_ARITH(A0_MOV); /* extended swizzle handled natively */ |
break; |
case OPCODE_TEX: |
EMIT_TEX(T0_TEXLD); |
break; |
case OPCODE_TXB: |
EMIT_TEX(T0_TEXLDB); |
break; |
case OPCODE_TXP: |
EMIT_TEX(T0_TEXLDP); |
break; |
case OPCODE_XPD: |
/* Cross product: |
* result.x = src0.y * src1.z - src0.z * src1.y; |
* result.y = src0.z * src1.x - src0.x * src1.z; |
* result.z = src0.x * src1.y - src0.y * src1.x; |
* result.w = undef; |
*/ |
src0 = src_vector(p, &inst->SrcReg[0], program); |
src1 = src_vector(p, &inst->SrcReg[1], program); |
tmp = i915_get_utemp(p); |
i915_emit_arith(p, |
A0_MUL, |
tmp, A0_DEST_CHANNEL_ALL, 0, |
swizzle(src0, Z, X, Y, ONE), |
swizzle(src1, Y, Z, X, ONE), 0); |
i915_emit_arith(p, |
A0_MAD, |
get_result_vector(p, inst), |
get_result_flags(inst), 0, |
swizzle(src0, Y, Z, X, ONE), |
swizzle(src1, Z, X, Y, ONE), |
negate(tmp, 1, 1, 1, 0)); |
break; |
case OPCODE_END: |
return; |
case OPCODE_BGNLOOP: |
case OPCODE_BGNSUB: |
case OPCODE_BRK: |
case OPCODE_CAL: |
case OPCODE_CONT: |
case OPCODE_DDX: |
case OPCODE_DDY: |
case OPCODE_ELSE: |
case OPCODE_ENDIF: |
case OPCODE_ENDLOOP: |
case OPCODE_ENDSUB: |
case OPCODE_IF: |
case OPCODE_RET: |
p->error = 1; |
i915_program_error(p, "Unsupported opcode: %s", |
_mesa_opcode_string(inst->Opcode)); |
return; |
case OPCODE_EXP: |
case OPCODE_LOG: |
/* These opcodes are claimed as GLSL, NV_vp, and ARB_vp in |
* prog_instruction.h, but apparently GLSL doesn't ever emit them. |
* Instead, it translates to EX2 or LG2. |
*/ |
case OPCODE_TXD: |
case OPCODE_TXL: |
/* These opcodes are claimed by GLSL in prog_instruction.h, but |
* only NV_vp/fp appears to emit them. |
*/ |
default: |
i915_program_error(p, "bad opcode: %s", |
_mesa_opcode_string(inst->Opcode)); |
return; |
} |
inst++; |
i915_release_utemps(p); |
} |
} |
/* Rather than trying to intercept and jiggle depth writes during |
* emit, just move the value into its correct position at the end of |
* the program: |
*/ |
static void |
fixup_depth_write(struct i915_fragment_program *p) |
{ |
if (p->depth_written) { |
GLuint depth = UREG(REG_TYPE_OD, 0); |
i915_emit_arith(p, |
A0_MOV, |
depth, A0_DEST_CHANNEL_W, 0, |
swizzle(depth, X, Y, Z, Z), 0, 0); |
} |
} |
static void |
check_wpos(struct i915_fragment_program *p) |
{ |
GLbitfield64 inputs = p->FragProg.Base.InputsRead; |
GLint i; |
p->wpos_tex = -1; |
for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) { |
if (inputs & (VARYING_BIT_TEX(i) | VARYING_BIT_VAR(i))) |
continue; |
else if (inputs & VARYING_BIT_POS) { |
p->wpos_tex = i; |
inputs &= ~VARYING_BIT_POS; |
} |
} |
if (inputs & VARYING_BIT_POS) { |
i915_program_error(p, "No free texcoord for wpos value"); |
} |
} |
static void |
translate_program(struct i915_fragment_program *p) |
{ |
struct i915_context *i915 = I915_CONTEXT(p->ctx); |
if (INTEL_DEBUG & DEBUG_WM) { |
printf("fp:\n"); |
_mesa_print_program(&p->FragProg.Base); |
printf("\n"); |
} |
i915_init_program(i915, p); |
check_wpos(p); |
upload_program(p); |
fixup_depth_write(p); |
i915_fini_program(p); |
p->translated = 1; |
} |
static void |
track_params(struct i915_fragment_program *p) |
{ |
GLint i; |
if (p->nr_params) |
_mesa_load_state_parameters(p->ctx, p->FragProg.Base.Parameters); |
for (i = 0; i < p->nr_params; i++) { |
GLint reg = p->param[i].reg; |
COPY_4V(p->constant[reg], p->param[i].values); |
} |
p->params_uptodate = 1; |
p->on_hardware = 0; /* overkill */ |
} |
static void |
i915BindProgram(struct gl_context * ctx, GLenum target, struct gl_program *prog) |
{ |
if (target == GL_FRAGMENT_PROGRAM_ARB) { |
struct i915_context *i915 = I915_CONTEXT(ctx); |
struct i915_fragment_program *p = (struct i915_fragment_program *) prog; |
if (i915->current_program == p) |
return; |
if (i915->current_program) { |
i915->current_program->on_hardware = 0; |
i915->current_program->params_uptodate = 0; |
} |
i915->current_program = p; |
assert(p->on_hardware == 0); |
assert(p->params_uptodate == 0); |
} |
} |
static struct gl_program * |
i915NewProgram(struct gl_context * ctx, GLenum target, GLuint id) |
{ |
switch (target) { |
case GL_VERTEX_PROGRAM_ARB: |
return _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program), |
target, id); |
case GL_FRAGMENT_PROGRAM_ARB:{ |
struct i915_fragment_program *prog = |
CALLOC_STRUCT(i915_fragment_program); |
if (prog) { |
i915_init_program(I915_CONTEXT(ctx), prog); |
return _mesa_init_fragment_program(ctx, &prog->FragProg, |
target, id); |
} |
else |
return NULL; |
} |
default: |
/* Just fallback: |
*/ |
return _mesa_new_program(ctx, target, id); |
} |
} |
static void |
i915DeleteProgram(struct gl_context * ctx, struct gl_program *prog) |
{ |
if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) { |
struct i915_context *i915 = I915_CONTEXT(ctx); |
struct i915_fragment_program *p = (struct i915_fragment_program *) prog; |
if (i915->current_program == p) |
i915->current_program = 0; |
} |
_mesa_delete_program(ctx, prog); |
} |
static GLboolean |
i915IsProgramNative(struct gl_context * ctx, GLenum target, struct gl_program *prog) |
{ |
if (target == GL_FRAGMENT_PROGRAM_ARB) { |
struct i915_fragment_program *p = (struct i915_fragment_program *) prog; |
if (!p->translated) |
translate_program(p); |
return !p->error; |
} |
else |
return true; |
} |
static GLboolean |
i915ProgramStringNotify(struct gl_context * ctx, |
GLenum target, struct gl_program *prog) |
{ |
if (target == GL_FRAGMENT_PROGRAM_ARB) { |
struct i915_fragment_program *p = (struct i915_fragment_program *) prog; |
p->translated = 0; |
} |
(void) _tnl_program_string(ctx, target, prog); |
/* XXX check if program is legal, within limits */ |
return true; |
} |
static void |
i915SamplerUniformChange(struct gl_context *ctx, |
GLenum target, struct gl_program *prog) |
{ |
i915ProgramStringNotify(ctx, target, prog); |
} |
void |
i915_update_program(struct gl_context *ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct i915_context *i915 = i915_context(&intel->ctx); |
struct i915_fragment_program *fp = |
(struct i915_fragment_program *) ctx->FragmentProgram._Current; |
if (i915->current_program != fp) { |
if (i915->current_program) { |
i915->current_program->on_hardware = 0; |
i915->current_program->params_uptodate = 0; |
} |
i915->current_program = fp; |
} |
if (!fp->translated) |
translate_program(fp); |
FALLBACK(&i915->intel, I915_FALLBACK_PROGRAM, fp->error); |
} |
void |
i915ValidateFragmentProgram(struct i915_context *i915) |
{ |
struct gl_context *ctx = &i915->intel.ctx; |
struct intel_context *intel = intel_context(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
struct i915_fragment_program *p = |
(struct i915_fragment_program *) ctx->FragmentProgram._Current; |
const GLbitfield64 inputsRead = p->FragProg.Base.InputsRead; |
GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK; |
GLuint s2 = S2_TEXCOORD_NONE; |
int i, offset = 0; |
/* Important: |
*/ |
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; |
if (!p->translated) |
translate_program(p); |
intel->vertex_attr_count = 0; |
intel->wpos_offset = 0; |
intel->coloroffset = 0; |
intel->specoffset = 0; |
if (inputsRead & VARYING_BITS_TEX_ANY || p->wpos_tex != -1) { |
EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16); |
} |
else { |
EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, S4_VFMT_XYZ, 12); |
} |
/* Handle gl_PointSize builtin var here */ |
if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled) |
EMIT_ATTR(_TNL_ATTRIB_POINTSIZE, EMIT_1F, S4_VFMT_POINT_WIDTH, 4); |
if (inputsRead & VARYING_BIT_COL0) { |
intel->coloroffset = offset / 4; |
EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4); |
} |
if (inputsRead & VARYING_BIT_COL1) { |
intel->specoffset = offset / 4; |
EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_4UB_4F_BGRA, S4_VFMT_SPEC_FOG, 4); |
} |
if ((inputsRead & VARYING_BIT_FOGC)) { |
EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1F, S4_VFMT_FOG_PARAM, 4); |
} |
for (i = 0; i < p->ctx->Const.MaxTextureCoordUnits; i++) { |
if (inputsRead & VARYING_BIT_TEX(i)) { |
int sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size; |
s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); |
s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz)); |
EMIT_ATTR(_TNL_ATTRIB_TEX0 + i, EMIT_SZ(sz), 0, sz * 4); |
} |
else if (inputsRead & VARYING_BIT_VAR(i)) { |
int sz = VB->AttribPtr[_TNL_ATTRIB_GENERIC0 + i]->size; |
s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); |
s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(sz)); |
EMIT_ATTR(_TNL_ATTRIB_GENERIC0 + i, EMIT_SZ(sz), 0, sz * 4); |
} |
else if (i == p->wpos_tex) { |
int wpos_size = 4 * sizeof(float); |
/* If WPOS is required, duplicate the XYZ position data in an |
* unused texture coordinate: |
*/ |
s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK); |
s2 |= S2_TEXCOORD_FMT(i, SZ_TO_HW(wpos_size)); |
intel->wpos_offset = offset; |
EMIT_PAD(wpos_size); |
} |
} |
if (s2 != i915->state.Ctx[I915_CTXREG_LIS2] || |
s4 != i915->state.Ctx[I915_CTXREG_LIS4]) { |
int k; |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
/* Must do this *after* statechange, so as not to affect |
* buffered vertices reliant on the old state: |
*/ |
intel->vertex_size = _tnl_install_attrs(&intel->ctx, |
intel->vertex_attrs, |
intel->vertex_attr_count, |
intel->ViewportMatrix.m, 0); |
assert(intel->prim.current_offset == intel->prim.start_offset); |
intel->prim.start_offset = (intel->prim.current_offset + intel->vertex_size-1) / intel->vertex_size * intel->vertex_size; |
intel->prim.current_offset = intel->prim.start_offset; |
intel->vertex_size >>= 2; |
i915->state.Ctx[I915_CTXREG_LIS2] = s2; |
i915->state.Ctx[I915_CTXREG_LIS4] = s4; |
k = intel->vtbl.check_vertex_size(intel, intel->vertex_size); |
assert(k); |
} |
if (!p->params_uptodate) |
track_params(p); |
if (!p->on_hardware) |
i915_upload_program(i915, p); |
if (INTEL_DEBUG & DEBUG_WM) { |
printf("i915:\n"); |
i915_disassemble_program(i915->state.Program, i915->state.ProgramSize); |
} |
} |
void |
i915InitFragProgFuncs(struct dd_function_table *functions) |
{ |
functions->BindProgram = i915BindProgram; |
functions->NewProgram = i915NewProgram; |
functions->DeleteProgram = i915DeleteProgram; |
functions->IsProgramNative = i915IsProgramNative; |
functions->ProgramStringNotify = i915ProgramStringNotify; |
functions->SamplerUniformChange = i915SamplerUniformChange; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_program.c |
---|
0,0 → 1,588 |
/************************************************************************** |
* |
* 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 <strings.h> |
#include "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "tnl/t_context.h" |
#include "intel_batchbuffer.h" |
#include "i915_reg.h" |
#include "i915_context.h" |
#include "i915_program.h" |
#define A0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT) |
#define D0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT) |
#define T0_DEST( reg ) (((reg)&UREG_TYPE_NR_MASK)>>UREG_A0_DEST_SHIFT_LEFT) |
#define A0_SRC0( reg ) (((reg)&UREG_MASK)>>UREG_A0_SRC0_SHIFT_LEFT) |
#define A1_SRC0( reg ) (((reg)&UREG_MASK)<<UREG_A1_SRC0_SHIFT_RIGHT) |
#define A1_SRC1( reg ) (((reg)&UREG_MASK)>>UREG_A1_SRC1_SHIFT_LEFT) |
#define A2_SRC1( reg ) (((reg)&UREG_MASK)<<UREG_A2_SRC1_SHIFT_RIGHT) |
#define A2_SRC2( reg ) (((reg)&UREG_MASK)>>UREG_A2_SRC2_SHIFT_LEFT) |
/* These are special, and don't have swizzle/negate bits. |
*/ |
#define T0_SAMPLER( reg ) (GET_UREG_NR(reg)<<T0_SAMPLER_NR_SHIFT) |
#define T1_ADDRESS_REG( reg ) ((GET_UREG_NR(reg)<<T1_ADDRESS_REG_NR_SHIFT) | \ |
(GET_UREG_TYPE(reg)<<T1_ADDRESS_REG_TYPE_SHIFT)) |
/* Macros for translating UREG's into the various register fields used |
* by the I915 programmable unit. |
*/ |
#define UREG_A0_DEST_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_DEST_TYPE_SHIFT) |
#define UREG_A0_SRC0_SHIFT_LEFT (UREG_TYPE_SHIFT - A0_SRC0_TYPE_SHIFT) |
#define UREG_A1_SRC0_SHIFT_RIGHT (A1_SRC0_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT) |
#define UREG_A1_SRC1_SHIFT_LEFT (UREG_TYPE_SHIFT - A1_SRC1_TYPE_SHIFT) |
#define UREG_A2_SRC1_SHIFT_RIGHT (A2_SRC1_CHANNEL_W_SHIFT - UREG_CHANNEL_W_SHIFT) |
#define UREG_A2_SRC2_SHIFT_LEFT (UREG_TYPE_SHIFT - A2_SRC2_TYPE_SHIFT) |
#define UREG_MASK 0xffffff00 |
#define UREG_TYPE_NR_MASK ((REG_TYPE_MASK << UREG_TYPE_SHIFT) | \ |
(REG_NR_MASK << UREG_NR_SHIFT)) |
#define I915_CONSTFLAG_PARAM 0x1f |
GLuint |
i915_get_temp(struct i915_fragment_program *p) |
{ |
int bit = ffs(~p->temp_flag); |
if (!bit) { |
fprintf(stderr, "%s: out of temporaries\n", __FILE__); |
exit(1); |
} |
p->temp_flag |= 1 << (bit - 1); |
return UREG(REG_TYPE_R, (bit - 1)); |
} |
GLuint |
i915_get_utemp(struct i915_fragment_program * p) |
{ |
int bit = ffs(~p->utemp_flag); |
if (!bit) { |
fprintf(stderr, "%s: out of temporaries\n", __FILE__); |
exit(1); |
} |
p->utemp_flag |= 1 << (bit - 1); |
return UREG(REG_TYPE_U, (bit - 1)); |
} |
void |
i915_release_utemps(struct i915_fragment_program *p) |
{ |
p->utemp_flag = ~0x7; |
} |
GLuint |
i915_emit_decl(struct i915_fragment_program *p, |
GLuint type, GLuint nr, GLuint d0_flags) |
{ |
GLuint reg = UREG(type, nr); |
if (type == REG_TYPE_T) { |
if (p->decl_t & (1 << nr)) |
return reg; |
p->decl_t |= (1 << nr); |
} |
else if (type == REG_TYPE_S) { |
if (p->decl_s & (1 << nr)) |
return reg; |
p->decl_s |= (1 << nr); |
} |
else |
return reg; |
*(p->decl++) = (D0_DCL | D0_DEST(reg) | d0_flags); |
*(p->decl++) = D1_MBZ; |
*(p->decl++) = D2_MBZ; |
assert(p->decl <= p->declarations + ARRAY_SIZE(p->declarations)); |
p->nr_decl_insn++; |
return reg; |
} |
GLuint |
i915_emit_arith(struct i915_fragment_program * p, |
GLuint op, |
GLuint dest, |
GLuint mask, |
GLuint saturate, GLuint src0, GLuint src1, GLuint src2) |
{ |
GLuint c[3]; |
GLuint nr_const = 0; |
assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST); |
dest = UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)); |
assert(dest); |
if (GET_UREG_TYPE(src0) == REG_TYPE_CONST) |
c[nr_const++] = 0; |
if (GET_UREG_TYPE(src1) == REG_TYPE_CONST) |
c[nr_const++] = 1; |
if (GET_UREG_TYPE(src2) == REG_TYPE_CONST) |
c[nr_const++] = 2; |
/* Recursively call this function to MOV additional const values |
* into temporary registers. Use utemp registers for this - |
* currently shouldn't be possible to run out, but keep an eye on |
* this. |
*/ |
if (nr_const > 1) { |
GLuint s[3], first, i, old_utemp_flag; |
s[0] = src0; |
s[1] = src1; |
s[2] = src2; |
old_utemp_flag = p->utemp_flag; |
first = GET_UREG_NR(s[c[0]]); |
for (i = 1; i < nr_const; i++) { |
if (GET_UREG_NR(s[c[i]]) != first) { |
GLuint tmp = i915_get_utemp(p); |
i915_emit_arith(p, A0_MOV, tmp, A0_DEST_CHANNEL_ALL, 0, |
s[c[i]], 0, 0); |
s[c[i]] = tmp; |
} |
} |
src0 = s[0]; |
src1 = s[1]; |
src2 = s[2]; |
p->utemp_flag = old_utemp_flag; /* restore */ |
} |
if (p->csr >= p->program + ARRAY_SIZE(p->program)) { |
i915_program_error(p, "Program contains too many instructions"); |
return UREG_BAD; |
} |
*(p->csr++) = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0)); |
*(p->csr++) = (A1_SRC0(src0) | A1_SRC1(src1)); |
*(p->csr++) = (A2_SRC1(src1) | A2_SRC2(src2)); |
if (GET_UREG_TYPE(dest) == REG_TYPE_R) |
p->register_phases[GET_UREG_NR(dest)] = p->nr_tex_indirect; |
p->nr_alu_insn++; |
return dest; |
} |
static GLuint get_free_rreg (struct i915_fragment_program *p, |
GLuint live_regs) |
{ |
int bit = ffs(~live_regs); |
if (!bit) { |
i915_program_error(p, "Can't find free R reg"); |
return UREG_BAD; |
} |
return UREG(REG_TYPE_R, bit - 1); |
} |
GLuint i915_emit_texld( struct i915_fragment_program *p, |
GLuint live_regs, |
GLuint dest, |
GLuint destmask, |
GLuint sampler, |
GLuint coord, |
GLuint op ) |
{ |
if (coord != UREG(GET_UREG_TYPE(coord), GET_UREG_NR(coord))) { |
/* With the help of the "needed registers" table created earlier, pick |
* a register we can MOV the swizzled TC to (since TEX doesn't support |
* swizzled sources) */ |
GLuint swizCoord = get_free_rreg(p, live_regs); |
if (swizCoord == UREG_BAD) |
return 0; |
i915_emit_arith( p, A0_MOV, swizCoord, A0_DEST_CHANNEL_ALL, 0, coord, 0, 0 ); |
coord = swizCoord; |
} |
/* Don't worry about saturate as we only support texture formats |
* that are always in the 0..1 range. |
*/ |
if (destmask != A0_DEST_CHANNEL_ALL) { |
GLuint tmp = i915_get_utemp(p); |
i915_emit_texld( p, 0, tmp, A0_DEST_CHANNEL_ALL, sampler, coord, op ); |
i915_emit_arith( p, A0_MOV, dest, destmask, 0, tmp, 0, 0 ); |
return dest; |
} |
else { |
assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST); |
assert(dest == UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest))); |
/* Can't use unsaved temps for coords, as the phase boundary would result |
* in the contents becoming undefined. |
*/ |
assert(GET_UREG_TYPE(coord) != REG_TYPE_U); |
if ((GET_UREG_TYPE(coord) != REG_TYPE_R) && |
(GET_UREG_TYPE(coord) != REG_TYPE_OC) && |
(GET_UREG_TYPE(coord) != REG_TYPE_OD) && |
(GET_UREG_TYPE(coord) != REG_TYPE_T)) { |
GLuint tmpCoord = get_free_rreg(p, live_regs); |
if (tmpCoord == UREG_BAD) |
return 0; |
i915_emit_arith(p, A0_MOV, tmpCoord, A0_DEST_CHANNEL_ALL, 0, coord, 0, 0); |
coord = tmpCoord; |
} |
/* Output register being oC or oD defines a phase boundary */ |
if (GET_UREG_TYPE(dest) == REG_TYPE_OC || |
GET_UREG_TYPE(dest) == REG_TYPE_OD) |
p->nr_tex_indirect++; |
/* Reading from an r# register whose contents depend on output of the |
* current phase defines a phase boundary. |
*/ |
if (GET_UREG_TYPE(coord) == REG_TYPE_R && |
p->register_phases[GET_UREG_NR(coord)] == p->nr_tex_indirect) |
p->nr_tex_indirect++; |
if (p->csr >= p->program + ARRAY_SIZE(p->program)) { |
i915_program_error(p, "Program contains too many instructions"); |
return UREG_BAD; |
} |
*(p->csr++) = (op | |
T0_DEST( dest ) | |
T0_SAMPLER( sampler )); |
*(p->csr++) = T1_ADDRESS_REG( coord ); |
*(p->csr++) = T2_MBZ; |
if (GET_UREG_TYPE(dest) == REG_TYPE_R) |
p->register_phases[GET_UREG_NR(dest)] = p->nr_tex_indirect; |
p->nr_tex_insn++; |
return dest; |
} |
} |
GLuint |
i915_emit_const1f(struct i915_fragment_program * p, GLfloat c0) |
{ |
GLint reg, idx; |
if (c0 == 0.0) |
return swizzle(UREG(REG_TYPE_R, 0), ZERO, ZERO, ZERO, ZERO); |
if (c0 == 1.0) |
return swizzle(UREG(REG_TYPE_R, 0), ONE, ONE, ONE, ONE); |
for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { |
if (p->constant_flags[reg] == I915_CONSTFLAG_PARAM) |
continue; |
for (idx = 0; idx < 4; idx++) { |
if (!(p->constant_flags[reg] & (1 << idx)) || |
p->constant[reg][idx] == c0) { |
p->constant[reg][idx] = c0; |
p->constant_flags[reg] |= 1 << idx; |
if (reg + 1 > p->nr_constants) |
p->nr_constants = reg + 1; |
return swizzle(UREG(REG_TYPE_CONST, reg), idx, ZERO, ZERO, ONE); |
} |
} |
} |
fprintf(stderr, "%s: out of constants\n", __FUNCTION__); |
p->error = 1; |
return 0; |
} |
GLuint |
i915_emit_const2f(struct i915_fragment_program * p, GLfloat c0, GLfloat c1) |
{ |
GLint reg, idx; |
if (c0 == 0.0) |
return swizzle(i915_emit_const1f(p, c1), ZERO, X, Z, W); |
if (c0 == 1.0) |
return swizzle(i915_emit_const1f(p, c1), ONE, X, Z, W); |
if (c1 == 0.0) |
return swizzle(i915_emit_const1f(p, c0), X, ZERO, Z, W); |
if (c1 == 1.0) |
return swizzle(i915_emit_const1f(p, c0), X, ONE, Z, W); |
for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { |
if (p->constant_flags[reg] == 0xf || |
p->constant_flags[reg] == I915_CONSTFLAG_PARAM) |
continue; |
for (idx = 0; idx < 3; idx++) { |
if (!(p->constant_flags[reg] & (3 << idx))) { |
p->constant[reg][idx] = c0; |
p->constant[reg][idx + 1] = c1; |
p->constant_flags[reg] |= 3 << idx; |
if (reg + 1 > p->nr_constants) |
p->nr_constants = reg + 1; |
return swizzle(UREG(REG_TYPE_CONST, reg), idx, idx + 1, ZERO, |
ONE); |
} |
} |
} |
fprintf(stderr, "%s: out of constants\n", __FUNCTION__); |
p->error = 1; |
return 0; |
} |
GLuint |
i915_emit_const4f(struct i915_fragment_program * p, |
GLfloat c0, GLfloat c1, GLfloat c2, GLfloat c3) |
{ |
GLint reg; |
for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { |
if (p->constant_flags[reg] == 0xf && |
p->constant[reg][0] == c0 && |
p->constant[reg][1] == c1 && |
p->constant[reg][2] == c2 && p->constant[reg][3] == c3) { |
return UREG(REG_TYPE_CONST, reg); |
} |
else if (p->constant_flags[reg] == 0) { |
p->constant[reg][0] = c0; |
p->constant[reg][1] = c1; |
p->constant[reg][2] = c2; |
p->constant[reg][3] = c3; |
p->constant_flags[reg] = 0xf; |
if (reg + 1 > p->nr_constants) |
p->nr_constants = reg + 1; |
return UREG(REG_TYPE_CONST, reg); |
} |
} |
fprintf(stderr, "%s: out of constants\n", __FUNCTION__); |
p->error = 1; |
return 0; |
} |
GLuint |
i915_emit_const4fv(struct i915_fragment_program * p, const GLfloat * c) |
{ |
return i915_emit_const4f(p, c[0], c[1], c[2], c[3]); |
} |
GLuint |
i915_emit_param4fv(struct i915_fragment_program * p, const GLfloat * values) |
{ |
GLint reg, i; |
for (i = 0; i < p->nr_params; i++) { |
if (p->param[i].values == values) |
return UREG(REG_TYPE_CONST, p->param[i].reg); |
} |
for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { |
if (p->constant_flags[reg] == 0) { |
p->constant_flags[reg] = I915_CONSTFLAG_PARAM; |
i = p->nr_params++; |
p->param[i].values = values; |
p->param[i].reg = reg; |
p->params_uptodate = 0; |
if (reg + 1 > p->nr_constants) |
p->nr_constants = reg + 1; |
return UREG(REG_TYPE_CONST, reg); |
} |
} |
fprintf(stderr, "%s: out of constants\n", __FUNCTION__); |
p->error = 1; |
return 0; |
} |
/* Warning the user about program errors seems to be quite valuable, from |
* our bug reports. It unfortunately means piglit reporting errors |
* when we fall back to software due to an unsupportable program, though. |
*/ |
void |
i915_program_error(struct i915_fragment_program *p, const char *fmt, ...) |
{ |
if (unlikely((INTEL_DEBUG & (DEBUG_WM | DEBUG_PERF)) != 0)) { |
va_list args; |
fprintf(stderr, "i915_program_error: "); |
va_start(args, fmt); |
vfprintf(stderr, fmt, args); |
va_end(args); |
fprintf(stderr, "\n"); |
} |
p->error = 1; |
} |
void |
i915_init_program(struct i915_context *i915, struct i915_fragment_program *p) |
{ |
struct gl_context *ctx = &i915->intel.ctx; |
p->translated = 0; |
p->params_uptodate = 0; |
p->on_hardware = 0; |
p->error = 0; |
memset(&p->register_phases, 0, sizeof(p->register_phases)); |
p->nr_tex_indirect = 1; |
p->nr_tex_insn = 0; |
p->nr_alu_insn = 0; |
p->nr_decl_insn = 0; |
p->ctx = ctx; |
memset(p->constant_flags, 0, sizeof(p->constant_flags)); |
p->nr_constants = 0; |
p->csr = p->program; |
p->decl = p->declarations; |
p->decl_s = 0; |
p->decl_t = 0; |
p->temp_flag = 0xffff000; |
p->utemp_flag = ~0x7; |
p->wpos_tex = -1; |
p->depth_written = 0; |
p->nr_params = 0; |
*(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM; |
} |
void |
i915_fini_program(struct i915_fragment_program *p) |
{ |
GLuint program_size = p->csr - p->program; |
GLuint decl_size = p->decl - p->declarations; |
if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT) { |
i915_program_error(p, "Exceeded max nr indirect texture lookups " |
"(%d out of %d)", |
p->nr_tex_indirect, I915_MAX_TEX_INDIRECT); |
} |
if (p->nr_tex_insn > I915_MAX_TEX_INSN) { |
i915_program_error(p, "Exceeded max TEX instructions (%d out of %d)", |
p->nr_tex_insn, I915_MAX_TEX_INSN); |
} |
if (p->nr_alu_insn > I915_MAX_ALU_INSN) |
i915_program_error(p, "Exceeded max ALU instructions (%d out of %d)", |
p->nr_alu_insn, I915_MAX_ALU_INSN); |
if (p->nr_decl_insn > I915_MAX_DECL_INSN) { |
i915_program_error(p, "Exceeded max DECL instructions (%d out of %d)", |
p->nr_decl_insn, I915_MAX_DECL_INSN); |
} |
if (p->error) { |
p->FragProg.Base.NumNativeInstructions = 0; |
p->FragProg.Base.NumNativeAluInstructions = 0; |
p->FragProg.Base.NumNativeTexInstructions = 0; |
p->FragProg.Base.NumNativeTexIndirections = 0; |
} |
else { |
p->FragProg.Base.NumNativeInstructions = (p->nr_alu_insn + |
p->nr_tex_insn + |
p->nr_decl_insn); |
p->FragProg.Base.NumNativeAluInstructions = p->nr_alu_insn; |
p->FragProg.Base.NumNativeTexInstructions = p->nr_tex_insn; |
p->FragProg.Base.NumNativeTexIndirections = p->nr_tex_indirect; |
} |
p->declarations[0] |= program_size + decl_size - 2; |
} |
void |
i915_upload_program(struct i915_context *i915, |
struct i915_fragment_program *p) |
{ |
GLuint program_size = p->csr - p->program; |
GLuint decl_size = p->decl - p->declarations; |
if (p->error) |
return; |
/* Could just go straight to the batchbuffer from here: |
*/ |
if (i915->state.ProgramSize != (program_size + decl_size) || |
memcmp(i915->state.Program + decl_size, p->program, |
program_size * sizeof(int)) != 0) { |
I915_STATECHANGE(i915, I915_UPLOAD_PROGRAM); |
memcpy(i915->state.Program, p->declarations, decl_size * sizeof(int)); |
memcpy(i915->state.Program + decl_size, p->program, |
program_size * sizeof(int)); |
i915->state.ProgramSize = decl_size + program_size; |
} |
/* Always seemed to get a failure if I used memcmp() to |
* shortcircuit this state upload. Needs further investigation? |
*/ |
if (p->nr_constants) { |
GLuint nr = p->nr_constants; |
I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 1); |
I915_STATECHANGE(i915, I915_UPLOAD_CONSTANTS); |
i915->state.Constant[0] = _3DSTATE_PIXEL_SHADER_CONSTANTS | ((nr) * 4); |
i915->state.Constant[1] = (1 << (nr - 1)) | ((1 << (nr - 1)) - 1); |
memcpy(&i915->state.Constant[2], p->constant, 4 * sizeof(int) * (nr)); |
i915->state.ConstantSize = 2 + (nr) * 4; |
if (0) { |
GLuint i; |
for (i = 0; i < nr; i++) { |
fprintf(stderr, "const[%d]: %f %f %f %f\n", i, |
p->constant[i][0], |
p->constant[i][1], p->constant[i][2], p->constant[i][3]); |
} |
} |
} |
else { |
I915_ACTIVESTATE(i915, I915_UPLOAD_CONSTANTS, 0); |
} |
p->on_hardware = 1; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_program.h |
---|
0,0 → 1,160 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef I915_PROGRAM_H |
#define I915_PROGRAM_H |
#include "i915_context.h" |
#include "i915_reg.h" |
/* Having zero and one in here makes the definition of swizzle a lot |
* easier. |
*/ |
#define UREG_TYPE_SHIFT 29 |
#define UREG_NR_SHIFT 24 |
#define UREG_CHANNEL_X_NEGATE_SHIFT 23 |
#define UREG_CHANNEL_X_SHIFT 20 |
#define UREG_CHANNEL_Y_NEGATE_SHIFT 19 |
#define UREG_CHANNEL_Y_SHIFT 16 |
#define UREG_CHANNEL_Z_NEGATE_SHIFT 15 |
#define UREG_CHANNEL_Z_SHIFT 12 |
#define UREG_CHANNEL_W_NEGATE_SHIFT 11 |
#define UREG_CHANNEL_W_SHIFT 8 |
#define UREG_CHANNEL_ZERO_NEGATE_MBZ 5 |
#define UREG_CHANNEL_ZERO_SHIFT 4 |
#define UREG_CHANNEL_ONE_NEGATE_MBZ 1 |
#define UREG_CHANNEL_ONE_SHIFT 0 |
#define UREG_BAD 0xffffffff /* not a valid ureg */ |
#define X SRC_X |
#define Y SRC_Y |
#define Z SRC_Z |
#define W SRC_W |
#define ZERO SRC_ZERO |
#define ONE SRC_ONE |
/* Construct a ureg: |
*/ |
#define UREG( type, nr ) (((type)<< UREG_TYPE_SHIFT) | \ |
((nr) << UREG_NR_SHIFT) | \ |
(X << UREG_CHANNEL_X_SHIFT) | \ |
(Y << UREG_CHANNEL_Y_SHIFT) | \ |
(Z << UREG_CHANNEL_Z_SHIFT) | \ |
(W << UREG_CHANNEL_W_SHIFT) | \ |
(ZERO << UREG_CHANNEL_ZERO_SHIFT) | \ |
(ONE << UREG_CHANNEL_ONE_SHIFT)) |
#define GET_CHANNEL_SRC( reg, channel ) ((reg<<(channel*4)) & (0xf<<20)) |
#define CHANNEL_SRC( src, channel ) (src>>(channel*4)) |
#define GET_UREG_TYPE(reg) (((reg)>>UREG_TYPE_SHIFT)®_TYPE_MASK) |
#define GET_UREG_NR(reg) (((reg)>>UREG_NR_SHIFT)®_NR_MASK) |
#define UREG_XYZW_CHANNEL_MASK 0x00ffff00 |
/* One neat thing about the UREG representation: |
*/ |
static INLINE int |
swizzle(int reg, int x, int y, int z, int w) |
{ |
return ((reg & ~UREG_XYZW_CHANNEL_MASK) | |
CHANNEL_SRC(GET_CHANNEL_SRC(reg, x), 0) | |
CHANNEL_SRC(GET_CHANNEL_SRC(reg, y), 1) | |
CHANNEL_SRC(GET_CHANNEL_SRC(reg, z), 2) | |
CHANNEL_SRC(GET_CHANNEL_SRC(reg, w), 3)); |
} |
/* Another neat thing about the UREG representation: |
*/ |
static INLINE int |
negate(int reg, int x, int y, int z, int w) |
{ |
return reg ^ (((x & 1) << UREG_CHANNEL_X_NEGATE_SHIFT) | |
((y & 1) << UREG_CHANNEL_Y_NEGATE_SHIFT) | |
((z & 1) << UREG_CHANNEL_Z_NEGATE_SHIFT) | |
((w & 1) << UREG_CHANNEL_W_NEGATE_SHIFT)); |
} |
extern GLuint i915_get_temp(struct i915_fragment_program *p); |
extern GLuint i915_get_utemp(struct i915_fragment_program *p); |
extern void i915_release_utemps(struct i915_fragment_program *p); |
extern GLuint i915_emit_texld(struct i915_fragment_program *p, |
GLuint live_regs, |
GLuint dest, |
GLuint destmask, |
GLuint sampler, GLuint coord, GLuint op); |
extern GLuint i915_emit_arith(struct i915_fragment_program *p, |
GLuint op, |
GLuint dest, |
GLuint mask, |
GLuint saturate, |
GLuint src0, GLuint src1, GLuint src2); |
extern GLuint i915_emit_decl(struct i915_fragment_program *p, |
GLuint type, GLuint nr, GLuint d0_flags); |
extern GLuint i915_emit_const1f(struct i915_fragment_program *p, GLfloat c0); |
extern GLuint i915_emit_const2f(struct i915_fragment_program *p, |
GLfloat c0, GLfloat c1); |
extern GLuint i915_emit_const4fv(struct i915_fragment_program *p, |
const GLfloat * c); |
extern GLuint i915_emit_const4f(struct i915_fragment_program *p, |
GLfloat c0, GLfloat c1, |
GLfloat c2, GLfloat c3); |
extern GLuint i915_emit_param4fv(struct i915_fragment_program *p, |
const GLfloat * values); |
extern void i915_program_error(struct i915_fragment_program *p, |
const char *fmt, ...); |
extern void i915_init_program(struct i915_context *i915, |
struct i915_fragment_program *p); |
extern void i915_upload_program(struct i915_context *i915, |
struct i915_fragment_program *p); |
extern void i915_fini_program(struct i915_fragment_program *p); |
extern void i915_update_program(struct gl_context *ctx); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_reg.h |
---|
0,0 → 1,730 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef _I915_REG_H_ |
#define _I915_REG_H_ |
#include "intel_reg.h" |
#define I915_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value) |
#define PRIM3D_INLINE (CMD_3D | (0x1f<<24)) |
#define PRIM3D_TRILIST (0x0<<18) |
#define PRIM3D_TRISTRIP (0x1<<18) |
#define PRIM3D_TRISTRIP_RVRSE (0x2<<18) |
#define PRIM3D_TRIFAN (0x3<<18) |
#define PRIM3D_POLY (0x4<<18) |
#define PRIM3D_LINELIST (0x5<<18) |
#define PRIM3D_LINESTRIP (0x6<<18) |
#define PRIM3D_RECTLIST (0x7<<18) |
#define PRIM3D_POINTLIST (0x8<<18) |
#define PRIM3D_DIB (0x9<<18) |
#define PRIM3D_CLEAR_RECT (0xa<<18) |
#define PRIM3D_ZONE_INIT (0xd<<18) |
#define PRIM3D_MASK (0x1f<<18) |
/* p137 */ |
#define _3DSTATE_AA_CMD (CMD_3D | (0x06<<24)) |
#define AA_LINE_ECAAR_WIDTH_ENABLE (1<<16) |
#define AA_LINE_ECAAR_WIDTH_0_5 0 |
#define AA_LINE_ECAAR_WIDTH_1_0 (1<<14) |
#define AA_LINE_ECAAR_WIDTH_2_0 (2<<14) |
#define AA_LINE_ECAAR_WIDTH_4_0 (3<<14) |
#define AA_LINE_REGION_WIDTH_ENABLE (1<<8) |
#define AA_LINE_REGION_WIDTH_0_5 0 |
#define AA_LINE_REGION_WIDTH_1_0 (1<<6) |
#define AA_LINE_REGION_WIDTH_2_0 (2<<6) |
#define AA_LINE_REGION_WIDTH_4_0 (3<<6) |
/* 3DSTATE_BACKFACE_STENCIL_OPS, p138*/ |
#define _3DSTATE_BACKFACE_STENCIL_OPS (CMD_3D | (0x8<<24)) |
#define BFO_ENABLE_STENCIL_REF (1<<23) |
#define BFO_STENCIL_REF_SHIFT 15 |
#define BFO_STENCIL_REF_MASK (0xff<<15) |
#define BFO_ENABLE_STENCIL_FUNCS (1<<14) |
#define BFO_STENCIL_TEST_SHIFT 11 |
#define BFO_STENCIL_TEST_MASK (0x7<<11) |
#define BFO_STENCIL_FAIL_SHIFT 8 |
#define BFO_STENCIL_FAIL_MASK (0x7<<8) |
#define BFO_STENCIL_PASS_Z_FAIL_SHIFT 5 |
#define BFO_STENCIL_PASS_Z_FAIL_MASK (0x7<<5) |
#define BFO_STENCIL_PASS_Z_PASS_SHIFT 2 |
#define BFO_STENCIL_PASS_Z_PASS_MASK (0x7<<2) |
#define BFO_ENABLE_STENCIL_TWO_SIDE (1<<1) |
#define BFO_STENCIL_TWO_SIDE (1<<0) |
/* 3DSTATE_BACKFACE_STENCIL_MASKS, p140 */ |
#define _3DSTATE_BACKFACE_STENCIL_MASKS (CMD_3D | (0x9<<24)) |
#define BFM_ENABLE_STENCIL_TEST_MASK (1<<17) |
#define BFM_ENABLE_STENCIL_WRITE_MASK (1<<16) |
#define BFM_STENCIL_TEST_MASK_SHIFT 8 |
#define BFM_STENCIL_TEST_MASK_MASK (0xff<<8) |
#define BFM_STENCIL_TEST_MASK(x) (((x)&0xff) << 8) |
#define BFM_STENCIL_WRITE_MASK_SHIFT 0 |
#define BFM_STENCIL_WRITE_MASK_MASK (0xff<<0) |
#define BFM_STENCIL_WRITE_MASK(x) ((x)&0xff) |
/* 3DSTATE_BIN_CONTROL p141 */ |
/* 3DSTATE_CHROMA_KEY */ |
/* 3DSTATE_CLEAR_PARAMETERS, p150 */ |
/* |
* Sets the color, depth and stencil clear values used by the |
* CLEAR_RECT and ZONE_INIT primitive types, respectively. These |
* primitives set override most 3d state and only take a minimal x/y |
* vertex. The color/z/stencil information is supplied here and |
* therefore cannot vary per vertex. |
*/ |
#define _3DSTATE_CLEAR_PARAMETERS (CMD_3D | (0x1d<<24) | (0x9c<<16) | 5) |
/* Dword 1 */ |
#define CLEARPARAM_CLEAR_RECT (1 << 16) |
#define CLEARPARAM_ZONE_INIT (0 << 16) |
#define CLEARPARAM_WRITE_COLOR (1 << 2) |
#define CLEARPARAM_WRITE_DEPTH (1 << 1) |
#define CLEARPARAM_WRITE_STENCIL (1 << 0) |
/* 3DSTATE_CONSTANT_BLEND_COLOR, p153 */ |
#define _3DSTATE_CONST_BLEND_COLOR_CMD (CMD_3D | (0x1d<<24) | (0x88<<16)) |
/* 3DSTATE_COORD_SET_BINDINGS, p154 */ |
#define _3DSTATE_COORD_SET_BINDINGS (CMD_3D | (0x16<<24)) |
#define CSB_TCB(iunit, eunit) ((eunit)<<(iunit*3)) |
/* p156 */ |
#define _3DSTATE_DFLT_DIFFUSE_CMD (CMD_3D | (0x1d<<24) | (0x99<<16)) |
/* p157 */ |
#define _3DSTATE_DFLT_SPEC_CMD (CMD_3D | (0x1d<<24) | (0x9a<<16)) |
/* p158 */ |
#define _3DSTATE_DFLT_Z_CMD (CMD_3D | (0x1d<<24) | (0x98<<16)) |
/* 3DSTATE_DEPTH_OFFSET_SCALE, p159 */ |
#define _3DSTATE_DEPTH_OFFSET_SCALE (CMD_3D | (0x1d<<24) | (0x97<<16)) |
/* scale in dword 1 */ |
/* 3DSTATE_DEPTH_SUBRECT_DISABLE, p160 */ |
#define _3DSTATE_DEPTH_SUBRECT_DISABLE (CMD_3D | (0x1c<<24) | (0x11<<19) | 0x2) |
/* p161 */ |
#define _3DSTATE_DST_BUF_VARS_CMD (CMD_3D | (0x1d<<24) | (0x85<<16)) |
/* Dword 1 */ |
#define CLASSIC_EARLY_DEPTH (1<<31) |
#define TEX_DEFAULT_COLOR_OGL (0<<30) |
#define TEX_DEFAULT_COLOR_D3D (1<<30) |
#define ZR_EARLY_DEPTH (1<<29) |
#define LOD_PRECLAMP_OGL (1<<28) |
#define LOD_PRECLAMP_D3D (0<<28) |
#define DITHER_FULL_ALWAYS (0<<26) |
#define DITHER_FULL_ON_FB_BLEND (1<<26) |
#define DITHER_CLAMPED_ALWAYS (2<<26) |
#define LINEAR_GAMMA_BLEND_32BPP (1<<25) |
#define DEBUG_DISABLE_ENH_DITHER (1<<24) |
#define DSTORG_HORT_BIAS(x) ((x)<<20) |
#define DSTORG_VERT_BIAS(x) ((x)<<16) |
#define COLOR_4_2_2_CHNL_WRT_ALL 0 |
#define COLOR_4_2_2_CHNL_WRT_Y (1<<12) |
#define COLOR_4_2_2_CHNL_WRT_CR (2<<12) |
#define COLOR_4_2_2_CHNL_WRT_CB (3<<12) |
#define COLOR_4_2_2_CHNL_WRT_CRCB (4<<12) |
#define COLR_BUF_8BIT 0 |
#define COLR_BUF_RGB555 (1<<8) |
#define COLR_BUF_RGB565 (2<<8) |
#define COLR_BUF_ARGB8888 (3<<8) |
#define DEPTH_FRMT_16_FIXED 0 |
#define DEPTH_FRMT_16_FLOAT (1<<2) |
#define DEPTH_FRMT_24_FIXED_8_OTHER (2<<2) |
#define VERT_LINE_STRIDE_1 (1<<1) |
#define VERT_LINE_STRIDE_0 (0<<1) |
#define VERT_LINE_STRIDE_OFS_1 1 |
#define VERT_LINE_STRIDE_OFS_0 0 |
/* p166 */ |
#define _3DSTATE_DRAW_RECT_CMD (CMD_3D|(0x1d<<24)|(0x80<<16)|3) |
/* Dword 1 */ |
#define DRAW_RECT_DIS_DEPTH_OFS (1<<30) |
#define DRAW_DITHER_OFS_X(x) ((x)<<26) |
#define DRAW_DITHER_OFS_Y(x) ((x)<<24) |
/* Dword 2 */ |
#define DRAW_YMIN(x) ((x)<<16) |
#define DRAW_XMIN(x) (x) |
/* Dword 3 */ |
#define DRAW_YMAX(x) ((x)<<16) |
#define DRAW_XMAX(x) (x) |
/* Dword 4 */ |
#define DRAW_YORG(x) ((x)<<16) |
#define DRAW_XORG(x) (x) |
/* 3DSTATE_FILTER_COEFFICIENTS_4X4, p170 */ |
/* 3DSTATE_FILTER_COEFFICIENTS_6X5, p172 */ |
/* _3DSTATE_FOG_COLOR, p173 */ |
#define _3DSTATE_FOG_COLOR_CMD (CMD_3D|(0x15<<24)) |
#define FOG_COLOR_RED(x) ((x)<<16) |
#define FOG_COLOR_GREEN(x) ((x)<<8) |
#define FOG_COLOR_BLUE(x) (x) |
/* _3DSTATE_FOG_MODE, p174 */ |
#define _3DSTATE_FOG_MODE_CMD (CMD_3D|(0x1d<<24)|(0x89<<16)|2) |
/* Dword 1 */ |
#define FMC1_FOGFUNC_MODIFY_ENABLE (1<<31) |
#define FMC1_FOGFUNC_VERTEX (0<<28) |
#define FMC1_FOGFUNC_PIXEL_EXP (1<<28) |
#define FMC1_FOGFUNC_PIXEL_EXP2 (2<<28) |
#define FMC1_FOGFUNC_PIXEL_LINEAR (3<<28) |
#define FMC1_FOGFUNC_MASK (3<<28) |
#define FMC1_FOGINDEX_MODIFY_ENABLE (1<<27) |
#define FMC1_FOGINDEX_Z (0<<25) |
#define FMC1_FOGINDEX_W (1<<25) |
#define FMC1_C1_C2_MODIFY_ENABLE (1<<24) |
#define FMC1_DENSITY_MODIFY_ENABLE (1<<23) |
#define FMC1_C1_ONE (1<<13) |
#define FMC1_C1_MASK (0xffff<<4) |
/* Dword 2 */ |
#define FMC2_C2_ONE (1<<16) |
/* Dword 3 */ |
#define FMC3_D_ONE (1<<16) |
/* _3DSTATE_INDEPENDENT_ALPHA_BLEND, p177 */ |
#define _3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD (CMD_3D|(0x0b<<24)) |
#define IAB_MODIFY_ENABLE (1<<23) |
#define IAB_ENABLE (1<<22) |
#define IAB_MODIFY_FUNC (1<<21) |
#define IAB_FUNC_SHIFT 16 |
#define IAB_MODIFY_SRC_FACTOR (1<<11) |
#define IAB_SRC_FACTOR_SHIFT 6 |
#define IAB_SRC_FACTOR_MASK (BLENDFACT_MASK<<6) |
#define IAB_MODIFY_DST_FACTOR (1<<5) |
#define IAB_DST_FACTOR_SHIFT 0 |
#define IAB_DST_FACTOR_MASK (BLENDFACT_MASK<<0) |
#define BLENDFUNC_ADD 0x0 |
#define BLENDFUNC_SUBTRACT 0x1 |
#define BLENDFUNC_REVERSE_SUBTRACT 0x2 |
#define BLENDFUNC_MIN 0x3 |
#define BLENDFUNC_MAX 0x4 |
#define BLENDFUNC_MASK 0x7 |
/* 3DSTATE_LOAD_INDIRECT, p180 */ |
#define _3DSTATE_LOAD_INDIRECT (CMD_3D|(0x1d<<24)|(0x7<<16)) |
#define LI0_STATE_STATIC_INDIRECT (0x01<<8) |
#define LI0_STATE_DYNAMIC_INDIRECT (0x02<<8) |
#define LI0_STATE_SAMPLER (0x04<<8) |
#define LI0_STATE_MAP (0x08<<8) |
#define LI0_STATE_PROGRAM (0x10<<8) |
#define LI0_STATE_CONSTANTS (0x20<<8) |
#define SIS0_BUFFER_ADDRESS(x) ((x)&~0x3) |
#define SIS0_FORCE_LOAD (1<<1) |
#define SIS0_BUFFER_VALID (1<<0) |
#define SIS1_BUFFER_LENGTH(x) ((x)&0xff) |
#define DIS0_BUFFER_ADDRESS(x) ((x)&~0x3) |
#define DIS0_BUFFER_RESET (1<<1) |
#define DIS0_BUFFER_VALID (1<<0) |
#define SSB0_BUFFER_ADDRESS(x) ((x)&~0x3) |
#define SSB0_FORCE_LOAD (1<<1) |
#define SSB0_BUFFER_VALID (1<<0) |
#define SSB1_BUFFER_LENGTH(x) ((x)&0xff) |
#define MSB0_BUFFER_ADDRESS(x) ((x)&~0x3) |
#define MSB0_FORCE_LOAD (1<<1) |
#define MSB0_BUFFER_VALID (1<<0) |
#define MSB1_BUFFER_LENGTH(x) ((x)&0xff) |
#define PSP0_BUFFER_ADDRESS(x) ((x)&~0x3) |
#define PSP0_FORCE_LOAD (1<<1) |
#define PSP0_BUFFER_VALID (1<<0) |
#define PSP1_BUFFER_LENGTH(x) ((x)&0xff) |
#define PSC0_BUFFER_ADDRESS(x) ((x)&~0x3) |
#define PSC0_FORCE_LOAD (1<<1) |
#define PSC0_BUFFER_VALID (1<<0) |
#define PSC1_BUFFER_LENGTH(x) ((x)&0xff) |
/* _3DSTATE_RASTERIZATION_RULES */ |
#define _3DSTATE_RASTER_RULES_CMD (CMD_3D|(0x07<<24)) |
#define ENABLE_POINT_RASTER_RULE (1<<15) |
#define OGL_POINT_RASTER_RULE (1<<13) |
#define ENABLE_TEXKILL_3D_4D (1<<10) |
#define TEXKILL_3D (0<<9) |
#define TEXKILL_4D (1<<9) |
#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8) |
#define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5) |
#define LINE_STRIP_PROVOKE_VRTX_MASK (3 << 6) |
#define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6) |
#define TRI_FAN_PROVOKE_VRTX_MASK (3 << 3) |
#define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3) |
/* _3DSTATE_SCISSOR_ENABLE, p256 */ |
#define _3DSTATE_SCISSOR_ENABLE_CMD (CMD_3D|(0x1c<<24)|(0x10<<19)) |
#define ENABLE_SCISSOR_RECT ((1<<1) | 1) |
#define DISABLE_SCISSOR_RECT (1<<1) |
/* _3DSTATE_SCISSOR_RECTANGLE_0, p257 */ |
#define _3DSTATE_SCISSOR_RECT_0_CMD (CMD_3D|(0x1d<<24)|(0x81<<16)|1) |
/* Dword 1 */ |
#define SCISSOR_RECT_0_YMIN(x) ((x)<<16) |
#define SCISSOR_RECT_0_XMIN(x) (x) |
/* Dword 2 */ |
#define SCISSOR_RECT_0_YMAX(x) ((x)<<16) |
#define SCISSOR_RECT_0_XMAX(x) (x) |
/* Helper macros for blend factors |
*/ |
#define DST_BLND_FACT(f) ((f)<<S6_CBUF_DST_BLEND_FACT_SHIFT) |
#define SRC_BLND_FACT(f) ((f)<<S6_CBUF_SRC_BLEND_FACT_SHIFT) |
#define DST_ABLND_FACT(f) ((f)<<IAB_DST_FACTOR_SHIFT) |
#define SRC_ABLND_FACT(f) ((f)<<IAB_SRC_FACTOR_SHIFT) |
/* 3DSTATE_MAP_DEINTERLACER_PARAMETERS */ |
/* 3DSTATE_MAP_PALETTE_LOAD_32, p206 */ |
#define _3DSTATE_MAP_PALETTE_LOAD_32 (CMD_3D|(0x1d<<24)|(0x8f<<16)) |
/* subsequent dwords up to length (max 16) are ARGB8888 color values */ |
/* _3DSTATE_MODES_4, p218 */ |
#define _3DSTATE_MODES_4_CMD (CMD_3D|(0x0d<<24)) |
#define ENABLE_LOGIC_OP_FUNC (1<<23) |
#define LOGIC_OP_FUNC(x) ((x)<<18) |
#define LOGICOP_MASK (0xf<<18) |
#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00)) |
#define ENABLE_STENCIL_TEST_MASK (1<<17) |
#define STENCIL_TEST_MASK(x) (((x)&0xff)<<8) |
#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff)) |
#define ENABLE_STENCIL_WRITE_MASK (1<<16) |
#define STENCIL_WRITE_MASK(x) ((x)&0xff) |
/* _3DSTATE_MODES_5, p220 */ |
#define _3DSTATE_MODES_5_CMD (CMD_3D|(0x0c<<24)) |
#define PIPELINE_FLUSH_RENDER_CACHE (1<<18) |
#define PIPELINE_FLUSH_TEXTURE_CACHE (1<<16) |
/* p221 */ |
#define _3DSTATE_PIXEL_SHADER_CONSTANTS (CMD_3D|(0x1d<<24)|(0x6<<16)) |
#define PS1_REG(n) (1<<(n)) |
#define PS2_CONST_X(n) (n) |
#define PS3_CONST_Y(n) (n) |
#define PS4_CONST_Z(n) (n) |
#define PS5_CONST_W(n) (n) |
/* p222 */ |
/* Each instruction is 3 dwords long, though most don't require all |
* this space. Maximum of 123 instructions. Smaller maxes per insn |
* type. |
*/ |
#define _3DSTATE_PIXEL_SHADER_PROGRAM (CMD_3D|(0x1d<<24)|(0x5<<16)) |
#define REG_TYPE_R 0 /* temporary regs, no need to |
* dcl, must be written before |
* read -- Preserved between |
* phases. |
*/ |
#define REG_TYPE_T 1 /* Interpolated values, must be |
* dcl'ed before use. |
* |
* 0..7: texture coord, |
* 8: diffuse spec, |
* 9: specular color, |
* 10: fog parameter in w. |
*/ |
#define REG_TYPE_CONST 2 /* Restriction: only one const |
* can be referenced per |
* instruction, though it may be |
* selected for multiple inputs. |
* Constants not initialized |
* default to zero. |
*/ |
#define REG_TYPE_S 3 /* sampler */ |
#define REG_TYPE_OC 4 /* output color (rgba) */ |
#define REG_TYPE_OD 5 /* output depth (w), xyz are |
* temporaries. If not written, |
* interpolated depth is used? |
*/ |
#define REG_TYPE_U 6 /* unpreserved temporaries */ |
#define REG_TYPE_MASK 0x7 |
#define REG_NR_MASK 0xf |
/* REG_TYPE_T: |
*/ |
#define T_TEX0 0 |
#define T_TEX1 1 |
#define T_TEX2 2 |
#define T_TEX3 3 |
#define T_TEX4 4 |
#define T_TEX5 5 |
#define T_TEX6 6 |
#define T_TEX7 7 |
#define T_DIFFUSE 8 |
#define T_SPECULAR 9 |
#define T_FOG_W 10 /* interpolated fog is in W coord */ |
/* Arithmetic instructions */ |
/* .replicate_swizzle == selection and replication of a particular |
* scalar channel, ie., .xxxx, .yyyy, .zzzz or .wwww |
*/ |
#define A0_NOP (0x0<<24) /* no operation */ |
#define A0_ADD (0x1<<24) /* dst = src0 + src1 */ |
#define A0_MOV (0x2<<24) /* dst = src0 */ |
#define A0_MUL (0x3<<24) /* dst = src0 * src1 */ |
#define A0_MAD (0x4<<24) /* dst = src0 * src1 + src2 */ |
#define A0_DP2ADD (0x5<<24) /* dst.xyzw = src0.xy dot src1.xy + src2.replicate_swizzle */ |
#define A0_DP3 (0x6<<24) /* dst.xyzw = src0.xyz dot src1.xyz */ |
#define A0_DP4 (0x7<<24) /* dst.xyzw = src0.xyzw dot src1.xyzw */ |
#define A0_FRC (0x8<<24) /* dst = src0 - floor(src0) */ |
#define A0_RCP (0x9<<24) /* dst.xyzw = 1/(src0.replicate_swizzle) */ |
#define A0_RSQ (0xa<<24) /* dst.xyzw = 1/(sqrt(abs(src0.replicate_swizzle))) */ |
#define A0_EXP (0xb<<24) /* dst.xyzw = exp2(src0.replicate_swizzle) */ |
#define A0_LOG (0xc<<24) /* dst.xyzw = log2(abs(src0.replicate_swizzle)) */ |
#define A0_CMP (0xd<<24) /* dst = (src0 >= 0.0) ? src1 : src2 */ |
#define A0_MIN (0xe<<24) /* dst = (src0 < src1) ? src0 : src1 */ |
#define A0_MAX (0xf<<24) /* dst = (src0 >= src1) ? src0 : src1 */ |
#define A0_FLR (0x10<<24) /* dst = floor(src0) */ |
#define A0_MOD (0x11<<24) /* dst = src0 fmod 1.0 */ |
#define A0_TRC (0x12<<24) /* dst = int(src0) */ |
#define A0_SGE (0x13<<24) /* dst = src0 >= src1 ? 1.0 : 0.0 */ |
#define A0_SLT (0x14<<24) /* dst = src0 < src1 ? 1.0 : 0.0 */ |
#define A0_DEST_SATURATE (1<<22) |
#define A0_DEST_TYPE_SHIFT 19 |
/* Allow: R, OC, OD, U */ |
#define A0_DEST_NR_SHIFT 14 |
/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ |
#define A0_DEST_CHANNEL_X (1<<10) |
#define A0_DEST_CHANNEL_Y (2<<10) |
#define A0_DEST_CHANNEL_Z (4<<10) |
#define A0_DEST_CHANNEL_W (8<<10) |
#define A0_DEST_CHANNEL_ALL (0xf<<10) |
#define A0_DEST_CHANNEL_SHIFT 10 |
#define A0_SRC0_TYPE_SHIFT 7 |
#define A0_SRC0_NR_SHIFT 2 |
#define A0_DEST_CHANNEL_XY (A0_DEST_CHANNEL_X|A0_DEST_CHANNEL_Y) |
#define A0_DEST_CHANNEL_XYZ (A0_DEST_CHANNEL_XY|A0_DEST_CHANNEL_Z) |
#define SRC_X 0 |
#define SRC_Y 1 |
#define SRC_Z 2 |
#define SRC_W 3 |
#define SRC_ZERO 4 |
#define SRC_ONE 5 |
#define A1_SRC0_CHANNEL_X_NEGATE (1<<31) |
#define A1_SRC0_CHANNEL_X_SHIFT 28 |
#define A1_SRC0_CHANNEL_Y_NEGATE (1<<27) |
#define A1_SRC0_CHANNEL_Y_SHIFT 24 |
#define A1_SRC0_CHANNEL_Z_NEGATE (1<<23) |
#define A1_SRC0_CHANNEL_Z_SHIFT 20 |
#define A1_SRC0_CHANNEL_W_NEGATE (1<<19) |
#define A1_SRC0_CHANNEL_W_SHIFT 16 |
#define A1_SRC1_TYPE_SHIFT 13 |
#define A1_SRC1_NR_SHIFT 8 |
#define A1_SRC1_CHANNEL_X_NEGATE (1<<7) |
#define A1_SRC1_CHANNEL_X_SHIFT 4 |
#define A1_SRC1_CHANNEL_Y_NEGATE (1<<3) |
#define A1_SRC1_CHANNEL_Y_SHIFT 0 |
#define A2_SRC1_CHANNEL_Z_NEGATE (1<<31) |
#define A2_SRC1_CHANNEL_Z_SHIFT 28 |
#define A2_SRC1_CHANNEL_W_NEGATE (1<<27) |
#define A2_SRC1_CHANNEL_W_SHIFT 24 |
#define A2_SRC2_TYPE_SHIFT 21 |
#define A2_SRC2_NR_SHIFT 16 |
#define A2_SRC2_CHANNEL_X_NEGATE (1<<15) |
#define A2_SRC2_CHANNEL_X_SHIFT 12 |
#define A2_SRC2_CHANNEL_Y_NEGATE (1<<11) |
#define A2_SRC2_CHANNEL_Y_SHIFT 8 |
#define A2_SRC2_CHANNEL_Z_NEGATE (1<<7) |
#define A2_SRC2_CHANNEL_Z_SHIFT 4 |
#define A2_SRC2_CHANNEL_W_NEGATE (1<<3) |
#define A2_SRC2_CHANNEL_W_SHIFT 0 |
/* Texture instructions */ |
#define T0_TEXLD (0x15<<24) /* Sample texture using predeclared |
* sampler and address, and output |
* filtered texel data to destination |
* register */ |
#define T0_TEXLDP (0x16<<24) /* Same as texld but performs a |
* perspective divide of the texture |
* coordinate .xyz values by .w before |
* sampling. */ |
#define T0_TEXLDB (0x17<<24) /* Same as texld but biases the |
* computed LOD by w. Only S4.6 two's |
* comp is used. This implies that a |
* float to fixed conversion is |
* done. */ |
#define T0_TEXKILL (0x18<<24) /* Does not perform a sampling |
* operation. Simply kills the pixel |
* if any channel of the address |
* register is < 0.0. */ |
#define T0_DEST_TYPE_SHIFT 19 |
/* Allow: R, OC, OD, U */ |
/* Note: U (unpreserved) regs do not retain their values between |
* phases (cannot be used for feedback) |
* |
* Note: oC and OD registers can only be used as the destination of a |
* texture instruction once per phase (this is an implementation |
* restriction). |
*/ |
#define T0_DEST_NR_SHIFT 14 |
/* Allow R: 0..15, OC,OD: 0..0, U: 0..2 */ |
#define T0_SAMPLER_NR_SHIFT 0 /* This field ignored for TEXKILL */ |
#define T0_SAMPLER_NR_MASK (0xf<<0) |
#define T1_ADDRESS_REG_TYPE_SHIFT 24 /* Reg to use as texture coord */ |
/* Allow R, T, OC, OD -- R, OC, OD are 'dependent' reads, new program phase */ |
#define T1_ADDRESS_REG_NR_SHIFT 17 |
#define T2_MBZ 0 |
/* Declaration instructions */ |
#define D0_DCL (0x19<<24) /* Declare a t (interpolated attrib) |
* register or an s (sampler) |
* register. */ |
#define D0_SAMPLE_TYPE_SHIFT 22 |
#define D0_SAMPLE_TYPE_2D (0x0<<22) |
#define D0_SAMPLE_TYPE_CUBE (0x1<<22) |
#define D0_SAMPLE_TYPE_VOLUME (0x2<<22) |
#define D0_SAMPLE_TYPE_MASK (0x3<<22) |
#define D0_TYPE_SHIFT 19 |
/* Allow: T, S */ |
#define D0_NR_SHIFT 14 |
/* Allow T: 0..10, S: 0..15 */ |
#define D0_CHANNEL_X (1<<10) |
#define D0_CHANNEL_Y (2<<10) |
#define D0_CHANNEL_Z (4<<10) |
#define D0_CHANNEL_W (8<<10) |
#define D0_CHANNEL_ALL (0xf<<10) |
#define D0_CHANNEL_NONE (0<<10) |
#define D0_CHANNEL_XY (D0_CHANNEL_X|D0_CHANNEL_Y) |
#define D0_CHANNEL_XYZ (D0_CHANNEL_XY|D0_CHANNEL_Z) |
/* I915 Errata: Do not allow (xz), (xw), (xzw) combinations for diffuse |
* or specular declarations. |
* |
* For T dcls, only allow: (x), (xy), (xyz), (w), (xyzw) |
* |
* Must be zero for S (sampler) dcls |
*/ |
#define D1_MBZ 0 |
#define D2_MBZ 0 |
/* p207 */ |
#define _3DSTATE_MAP_STATE (CMD_3D|(0x1d<<24)|(0x0<<16)) |
#define MS1_MAPMASK_SHIFT 0 |
#define MS1_MAPMASK_MASK (0x8fff<<0) |
#define MS2_UNTRUSTED_SURFACE (1<<31) |
#define MS2_ADDRESS_MASK 0xfffffffc |
#define MS2_VERTICAL_LINE_STRIDE (1<<1) |
#define MS2_VERTICAL_OFFSET (1<<1) |
#define MS3_HEIGHT_SHIFT 21 |
#define MS3_WIDTH_SHIFT 10 |
#define MS3_PALETTE_SELECT (1<<9) |
#define MS3_MAPSURF_FORMAT_SHIFT 7 |
#define MS3_MAPSURF_FORMAT_MASK (0x7<<7) |
#define MAPSURF_8BIT (1<<7) |
#define MAPSURF_16BIT (2<<7) |
#define MAPSURF_32BIT (3<<7) |
#define MAPSURF_422 (5<<7) |
#define MAPSURF_COMPRESSED (6<<7) |
#define MAPSURF_4BIT_INDEXED (7<<7) |
#define MS3_MT_FORMAT_MASK (0x7 << 3) |
#define MS3_MT_FORMAT_SHIFT 3 |
#define MT_4BIT_IDX_ARGB8888 (7<<3) /* SURFACE_4BIT_INDEXED */ |
#define MT_8BIT_I8 (0<<3) /* SURFACE_8BIT */ |
#define MT_8BIT_L8 (1<<3) |
#define MT_8BIT_A8 (4<<3) |
#define MT_8BIT_MONO8 (5<<3) |
#define MT_16BIT_RGB565 (0<<3) /* SURFACE_16BIT */ |
#define MT_16BIT_ARGB1555 (1<<3) |
#define MT_16BIT_ARGB4444 (2<<3) |
#define MT_16BIT_AY88 (3<<3) |
#define MT_16BIT_88DVDU (5<<3) |
#define MT_16BIT_BUMP_655LDVDU (6<<3) |
#define MT_16BIT_I16 (7<<3) |
#define MT_16BIT_L16 (8<<3) |
#define MT_16BIT_A16 (9<<3) |
#define MT_32BIT_ARGB8888 (0<<3) /* SURFACE_32BIT */ |
#define MT_32BIT_ABGR8888 (1<<3) |
#define MT_32BIT_XRGB8888 (2<<3) |
#define MT_32BIT_XBGR8888 (3<<3) |
#define MT_32BIT_QWVU8888 (4<<3) |
#define MT_32BIT_AXVU8888 (5<<3) |
#define MT_32BIT_LXVU8888 (6<<3) |
#define MT_32BIT_XLVU8888 (7<<3) |
#define MT_32BIT_ARGB2101010 (8<<3) |
#define MT_32BIT_ABGR2101010 (9<<3) |
#define MT_32BIT_AWVU2101010 (0xA<<3) |
#define MT_32BIT_GR1616 (0xB<<3) |
#define MT_32BIT_VU1616 (0xC<<3) |
#define MT_32BIT_x8I24 (0xD<<3) |
#define MT_32BIT_x8L24 (0xE<<3) |
#define MT_32BIT_x8A24 (0xF<<3) |
#define MT_422_YCRCB_SWAPY (0<<3) /* SURFACE_422 */ |
#define MT_422_YCRCB_NORMAL (1<<3) |
#define MT_422_YCRCB_SWAPUV (2<<3) |
#define MT_422_YCRCB_SWAPUVY (3<<3) |
#define MT_COMPRESS_DXT1 (0<<3) /* SURFACE_COMPRESSED */ |
#define MT_COMPRESS_DXT2_3 (1<<3) |
#define MT_COMPRESS_DXT4_5 (2<<3) |
#define MT_COMPRESS_FXT1 (3<<3) |
#define MT_COMPRESS_DXT1_RGB (4<<3) |
#define MS3_USE_FENCE_REGS (1<<2) |
#define MS3_TILED_SURFACE (1<<1) |
#define MS3_TILE_WALK (1<<0) |
#define MS4_PITCH_SHIFT 21 |
#define MS4_CUBE_FACE_ENA_NEGX (1<<20) |
#define MS4_CUBE_FACE_ENA_POSX (1<<19) |
#define MS4_CUBE_FACE_ENA_NEGY (1<<18) |
#define MS4_CUBE_FACE_ENA_POSY (1<<17) |
#define MS4_CUBE_FACE_ENA_NEGZ (1<<16) |
#define MS4_CUBE_FACE_ENA_POSZ (1<<15) |
#define MS4_CUBE_FACE_ENA_MASK (0x3f<<15) |
#define MS4_MAX_LOD_SHIFT 9 |
#define MS4_MAX_LOD_MASK (0x3f<<9) |
#define MS4_MIP_LAYOUT_LEGACY (0<<8) |
#define MS4_MIP_LAYOUT_BELOW_LPT (0<<8) |
#define MS4_MIP_LAYOUT_RIGHT_LPT (1<<8) |
#define MS4_VOLUME_DEPTH_SHIFT 0 |
#define MS4_VOLUME_DEPTH_MASK (0xff<<0) |
/* p244 */ |
#define _3DSTATE_SAMPLER_STATE (CMD_3D|(0x1d<<24)|(0x1<<16)) |
#define SS1_MAPMASK_SHIFT 0 |
#define SS1_MAPMASK_MASK (0x8fff<<0) |
#define SS2_REVERSE_GAMMA_ENABLE (1<<31) |
#define SS2_PACKED_TO_PLANAR_ENABLE (1<<30) |
#define SS2_COLORSPACE_CONVERSION (1<<29) |
#define SS2_CHROMAKEY_SHIFT 27 |
#define SS2_BASE_MIP_LEVEL_SHIFT 22 |
#define SS2_BASE_MIP_LEVEL_MASK (0x1f<<22) |
#define SS2_MIP_FILTER_SHIFT 20 |
#define SS2_MIP_FILTER_MASK (0x3<<20) |
#define MIPFILTER_NONE 0 |
#define MIPFILTER_NEAREST 1 |
#define MIPFILTER_LINEAR 3 |
#define SS2_MAG_FILTER_SHIFT 17 |
#define SS2_MAG_FILTER_MASK (0x7<<17) |
#define FILTER_NEAREST 0 |
#define FILTER_LINEAR 1 |
#define FILTER_ANISOTROPIC 2 |
#define FILTER_4X4_1 3 |
#define FILTER_4X4_2 4 |
#define FILTER_4X4_FLAT 5 |
#define FILTER_6X5_MONO 6 /* XXX - check */ |
#define SS2_MIN_FILTER_SHIFT 14 |
#define SS2_MIN_FILTER_MASK (0x7<<14) |
#define SS2_LOD_BIAS_SHIFT 5 |
#define SS2_LOD_BIAS_ONE (0x10<<5) |
#define SS2_LOD_BIAS_MASK (0x1ff<<5) |
/* Shadow requires: |
* MT_X8{I,L,A}24 or MT_{I,L,A}16 texture format |
* FILTER_4X4_x MIN and MAG filters |
*/ |
#define SS2_SHADOW_ENABLE (1<<4) |
#define SS2_MAX_ANISO_MASK (1<<3) |
#define SS2_MAX_ANISO_2 (0<<3) |
#define SS2_MAX_ANISO_4 (1<<3) |
#define SS2_SHADOW_FUNC_SHIFT 0 |
#define SS2_SHADOW_FUNC_MASK (0x7<<0) |
/* SS2_SHADOW_FUNC values: see COMPAREFUNC_* */ |
#define SS3_MIN_LOD_SHIFT 24 |
#define SS3_MIN_LOD_ONE (0x10<<24) |
#define SS3_MIN_LOD_MASK (0xff<<24) |
#define SS3_KILL_PIXEL_ENABLE (1<<17) |
#define SS3_TCX_ADDR_MODE_SHIFT 12 |
#define SS3_TCX_ADDR_MODE_MASK (0x7<<12) |
#define TEXCOORDMODE_WRAP 0 |
#define TEXCOORDMODE_MIRROR 1 |
#define TEXCOORDMODE_CLAMP_EDGE 2 |
#define TEXCOORDMODE_CUBE 3 |
#define TEXCOORDMODE_CLAMP_BORDER 4 |
#define TEXCOORDMODE_MIRROR_ONCE 5 |
#define SS3_TCY_ADDR_MODE_SHIFT 9 |
#define SS3_TCY_ADDR_MODE_MASK (0x7<<9) |
#define SS3_TCZ_ADDR_MODE_SHIFT 6 |
#define SS3_TCZ_ADDR_MODE_MASK (0x7<<6) |
#define SS3_NORMALIZED_COORDS (1<<5) |
#define SS3_TEXTUREMAP_INDEX_SHIFT 1 |
#define SS3_TEXTUREMAP_INDEX_MASK (0xf<<1) |
#define SS3_DEINTERLACER_ENABLE (1<<0) |
#define SS4_BORDER_COLOR_MASK (~0) |
/* 3DSTATE_SPAN_STIPPLE, p258 |
*/ |
#define _3DSTATE_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) |
#define ST1_ENABLE (1<<16) |
#define ST1_MASK (0xffff) |
#define _3DSTATE_DEFAULT_Z ((0x3<<29)|(0x1d<<24)|(0x98<<16)) |
#define _3DSTATE_DEFAULT_DIFFUSE ((0x3<<29)|(0x1d<<24)|(0x99<<16)) |
#define _3DSTATE_DEFAULT_SPECULAR ((0x3<<29)|(0x1d<<24)|(0x9a<<16)) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_state.c |
---|
0,0 → 1,1106 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "main/fbobject.h" |
#include "main/dd.h" |
#include "main/state.h" |
#include "main/stencil.h" |
#include "tnl/tnl.h" |
#include "tnl/t_context.h" |
#include "drivers/common/driverfuncs.h" |
#include "intel_fbo.h" |
#include "intel_screen.h" |
#include "intel_batchbuffer.h" |
#include "intel_buffers.h" |
#include "i915_context.h" |
#include "i915_reg.h" |
#define FILE_DEBUG_FLAG DEBUG_STATE |
void |
i915_update_stencil(struct gl_context * ctx) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
GLuint front_ref, front_writemask, front_mask; |
GLenum front_func, front_fail, front_pass_z_fail, front_pass_z_pass; |
GLuint back_ref, back_writemask, back_mask; |
GLenum back_func, back_fail, back_pass_z_fail, back_pass_z_pass; |
GLuint dirty = 0; |
/* The 915 considers CW to be "front" for two-sided stencil, so choose |
* appropriately. |
*/ |
/* _NEW_POLYGON | _NEW_STENCIL */ |
if (ctx->Polygon.FrontFace == GL_CW) { |
front_ref = _mesa_get_stencil_ref(ctx, 0); |
front_mask = ctx->Stencil.ValueMask[0]; |
front_writemask = ctx->Stencil.WriteMask[0]; |
front_func = ctx->Stencil.Function[0]; |
front_fail = ctx->Stencil.FailFunc[0]; |
front_pass_z_fail = ctx->Stencil.ZFailFunc[0]; |
front_pass_z_pass = ctx->Stencil.ZPassFunc[0]; |
back_ref = _mesa_get_stencil_ref(ctx, ctx->Stencil._BackFace); |
back_mask = ctx->Stencil.ValueMask[ctx->Stencil._BackFace]; |
back_writemask = ctx->Stencil.WriteMask[ctx->Stencil._BackFace]; |
back_func = ctx->Stencil.Function[ctx->Stencil._BackFace]; |
back_fail = ctx->Stencil.FailFunc[ctx->Stencil._BackFace]; |
back_pass_z_fail = ctx->Stencil.ZFailFunc[ctx->Stencil._BackFace]; |
back_pass_z_pass = ctx->Stencil.ZPassFunc[ctx->Stencil._BackFace]; |
} else { |
front_ref = _mesa_get_stencil_ref(ctx, ctx->Stencil._BackFace); |
front_mask = ctx->Stencil.ValueMask[ctx->Stencil._BackFace]; |
front_writemask = ctx->Stencil.WriteMask[ctx->Stencil._BackFace]; |
front_func = ctx->Stencil.Function[ctx->Stencil._BackFace]; |
front_fail = ctx->Stencil.FailFunc[ctx->Stencil._BackFace]; |
front_pass_z_fail = ctx->Stencil.ZFailFunc[ctx->Stencil._BackFace]; |
front_pass_z_pass = ctx->Stencil.ZPassFunc[ctx->Stencil._BackFace]; |
back_ref = _mesa_get_stencil_ref(ctx, 0); |
back_mask = ctx->Stencil.ValueMask[0]; |
back_writemask = ctx->Stencil.WriteMask[0]; |
back_func = ctx->Stencil.Function[0]; |
back_fail = ctx->Stencil.FailFunc[0]; |
back_pass_z_fail = ctx->Stencil.ZFailFunc[0]; |
back_pass_z_pass = ctx->Stencil.ZPassFunc[0]; |
} |
#define set_ctx_bits(reg, mask, set) do{ \ |
GLuint dw = i915->state.Ctx[reg]; \ |
dw &= ~(mask); \ |
dw |= (set); \ |
dirty |= dw != i915->state.Ctx[reg]; \ |
i915->state.Ctx[reg] = dw; \ |
} while(0) |
/* Set front state. */ |
set_ctx_bits(I915_CTXREG_STATE4, |
MODE4_ENABLE_STENCIL_TEST_MASK | |
MODE4_ENABLE_STENCIL_WRITE_MASK, |
ENABLE_STENCIL_TEST_MASK | |
ENABLE_STENCIL_WRITE_MASK | |
STENCIL_TEST_MASK(front_mask) | |
STENCIL_WRITE_MASK(front_writemask)); |
set_ctx_bits(I915_CTXREG_LIS5, |
S5_STENCIL_REF_MASK | |
S5_STENCIL_TEST_FUNC_MASK | |
S5_STENCIL_FAIL_MASK | |
S5_STENCIL_PASS_Z_FAIL_MASK | |
S5_STENCIL_PASS_Z_PASS_MASK, |
(front_ref << S5_STENCIL_REF_SHIFT) | |
(intel_translate_compare_func(front_func) << S5_STENCIL_TEST_FUNC_SHIFT) | |
(intel_translate_stencil_op(front_fail) << S5_STENCIL_FAIL_SHIFT) | |
(intel_translate_stencil_op(front_pass_z_fail) << |
S5_STENCIL_PASS_Z_FAIL_SHIFT) | |
(intel_translate_stencil_op(front_pass_z_pass) << |
S5_STENCIL_PASS_Z_PASS_SHIFT)); |
/* Set back state if different from front. */ |
if (ctx->Stencil._TestTwoSide) { |
set_ctx_bits(I915_CTXREG_BF_STENCIL_OPS, |
BFO_STENCIL_REF_MASK | |
BFO_STENCIL_TEST_MASK | |
BFO_STENCIL_FAIL_MASK | |
BFO_STENCIL_PASS_Z_FAIL_MASK | |
BFO_STENCIL_PASS_Z_PASS_MASK, |
BFO_STENCIL_TWO_SIDE | |
(back_ref << BFO_STENCIL_REF_SHIFT) | |
(intel_translate_compare_func(back_func) << BFO_STENCIL_TEST_SHIFT) | |
(intel_translate_stencil_op(back_fail) << BFO_STENCIL_FAIL_SHIFT) | |
(intel_translate_stencil_op(back_pass_z_fail) << |
BFO_STENCIL_PASS_Z_FAIL_SHIFT) | |
(intel_translate_stencil_op(back_pass_z_pass) << |
BFO_STENCIL_PASS_Z_PASS_SHIFT)); |
set_ctx_bits(I915_CTXREG_BF_STENCIL_MASKS, |
BFM_STENCIL_TEST_MASK_MASK | |
BFM_STENCIL_WRITE_MASK_MASK, |
BFM_STENCIL_TEST_MASK(back_mask) | |
BFM_STENCIL_WRITE_MASK(back_writemask)); |
} else { |
set_ctx_bits(I915_CTXREG_BF_STENCIL_OPS, |
BFO_STENCIL_TWO_SIDE, 0); |
} |
#undef set_ctx_bits |
if (dirty) |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
} |
static void |
i915StencilFuncSeparate(struct gl_context * ctx, GLenum face, GLenum func, GLint ref, |
GLuint mask) |
{ |
} |
static void |
i915StencilMaskSeparate(struct gl_context * ctx, GLenum face, GLuint mask) |
{ |
} |
static void |
i915StencilOpSeparate(struct gl_context * ctx, GLenum face, GLenum fail, GLenum zfail, |
GLenum zpass) |
{ |
} |
static void |
i915AlphaFunc(struct gl_context * ctx, GLenum func, GLfloat ref) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
int test = intel_translate_compare_func(func); |
GLubyte refByte; |
GLuint dw; |
UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref); |
dw = i915->state.Ctx[I915_CTXREG_LIS6]; |
dw &= ~(S6_ALPHA_TEST_FUNC_MASK | S6_ALPHA_REF_MASK); |
dw |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) | |
(((GLuint) refByte) << S6_ALPHA_REF_SHIFT)); |
if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { |
i915->state.Ctx[I915_CTXREG_LIS6] = dw; |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
} |
} |
/* This function makes sure that the proper enables are |
* set for LogicOp, Independant Alpha Blend, and Blending. |
* It needs to be called from numerous places where we |
* could change the LogicOp or Independant Alpha Blend without subsequent |
* calls to glEnable. |
*/ |
static void |
i915EvalLogicOpBlendState(struct gl_context * ctx) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
GLuint dw0, dw1; |
dw0 = i915->state.Ctx[I915_CTXREG_LIS5]; |
dw1 = i915->state.Ctx[I915_CTXREG_LIS6]; |
if (ctx->Color.ColorLogicOpEnabled) { |
dw0 |= S5_LOGICOP_ENABLE; |
dw1 &= ~S6_CBUF_BLEND_ENABLE; |
} |
else { |
dw0 &= ~S5_LOGICOP_ENABLE; |
if (ctx->Color.BlendEnabled) { |
dw1 |= S6_CBUF_BLEND_ENABLE; |
} |
else { |
dw1 &= ~S6_CBUF_BLEND_ENABLE; |
} |
} |
if (dw0 != i915->state.Ctx[I915_CTXREG_LIS5] || |
dw1 != i915->state.Ctx[I915_CTXREG_LIS6]) { |
i915->state.Ctx[I915_CTXREG_LIS5] = dw0; |
i915->state.Ctx[I915_CTXREG_LIS6] = dw1; |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
} |
} |
static void |
i915BlendColor(struct gl_context * ctx, const GLfloat color[4]) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
GLubyte r, g, b, a; |
GLuint dw; |
DBG("%s\n", __FUNCTION__); |
UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]); |
UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]); |
UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]); |
UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]); |
dw = (a << 24) | (r << 16) | (g << 8) | b; |
if (dw != i915->state.Blend[I915_BLENDREG_BLENDCOLOR1]) { |
i915->state.Blend[I915_BLENDREG_BLENDCOLOR1] = dw; |
I915_STATECHANGE(i915, I915_UPLOAD_BLEND); |
} |
} |
#define DST_BLND_FACT(f) ((f)<<S6_CBUF_DST_BLEND_FACT_SHIFT) |
#define SRC_BLND_FACT(f) ((f)<<S6_CBUF_SRC_BLEND_FACT_SHIFT) |
#define DST_ABLND_FACT(f) ((f)<<IAB_DST_FACTOR_SHIFT) |
#define SRC_ABLND_FACT(f) ((f)<<IAB_SRC_FACTOR_SHIFT) |
static GLuint |
translate_blend_equation(GLenum mode) |
{ |
switch (mode) { |
case GL_FUNC_ADD: |
return BLENDFUNC_ADD; |
case GL_MIN: |
return BLENDFUNC_MIN; |
case GL_MAX: |
return BLENDFUNC_MAX; |
case GL_FUNC_SUBTRACT: |
return BLENDFUNC_SUBTRACT; |
case GL_FUNC_REVERSE_SUBTRACT: |
return BLENDFUNC_REVERSE_SUBTRACT; |
default: |
return 0; |
} |
} |
static void |
i915UpdateBlendState(struct gl_context * ctx) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
GLuint iab = (i915->state.Blend[I915_BLENDREG_IAB] & |
~(IAB_SRC_FACTOR_MASK | |
IAB_DST_FACTOR_MASK | |
(BLENDFUNC_MASK << IAB_FUNC_SHIFT) | IAB_ENABLE)); |
GLuint lis6 = (i915->state.Ctx[I915_CTXREG_LIS6] & |
~(S6_CBUF_SRC_BLEND_FACT_MASK | |
S6_CBUF_DST_BLEND_FACT_MASK | S6_CBUF_BLEND_FUNC_MASK)); |
GLuint eqRGB = ctx->Color.Blend[0].EquationRGB; |
GLuint eqA = ctx->Color.Blend[0].EquationA; |
GLuint srcRGB = ctx->Color.Blend[0].SrcRGB; |
GLuint dstRGB = ctx->Color.Blend[0].DstRGB; |
GLuint srcA = ctx->Color.Blend[0].SrcA; |
GLuint dstA = ctx->Color.Blend[0].DstA; |
if (eqRGB == GL_MIN || eqRGB == GL_MAX) { |
srcRGB = dstRGB = GL_ONE; |
} |
if (eqA == GL_MIN || eqA == GL_MAX) { |
srcA = dstA = GL_ONE; |
} |
lis6 |= SRC_BLND_FACT(intel_translate_blend_factor(srcRGB)); |
lis6 |= DST_BLND_FACT(intel_translate_blend_factor(dstRGB)); |
lis6 |= translate_blend_equation(eqRGB) << S6_CBUF_BLEND_FUNC_SHIFT; |
iab |= SRC_ABLND_FACT(intel_translate_blend_factor(srcA)); |
iab |= DST_ABLND_FACT(intel_translate_blend_factor(dstA)); |
iab |= translate_blend_equation(eqA) << IAB_FUNC_SHIFT; |
if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) |
iab |= IAB_ENABLE; |
if (iab != i915->state.Blend[I915_BLENDREG_IAB]) { |
i915->state.Blend[I915_BLENDREG_IAB] = iab; |
I915_STATECHANGE(i915, I915_UPLOAD_BLEND); |
} |
if (lis6 != i915->state.Ctx[I915_CTXREG_LIS6]) { |
i915->state.Ctx[I915_CTXREG_LIS6] = lis6; |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
} |
/* This will catch a logicop blend equation */ |
i915EvalLogicOpBlendState(ctx); |
} |
static void |
i915BlendFuncSeparate(struct gl_context * ctx, GLenum srcRGB, |
GLenum dstRGB, GLenum srcA, GLenum dstA) |
{ |
i915UpdateBlendState(ctx); |
} |
static void |
i915BlendEquationSeparate(struct gl_context * ctx, GLenum eqRGB, GLenum eqA) |
{ |
i915UpdateBlendState(ctx); |
} |
static void |
i915DepthFunc(struct gl_context * ctx, GLenum func) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
int test = intel_translate_compare_func(func); |
GLuint dw; |
DBG("%s\n", __FUNCTION__); |
dw = i915->state.Ctx[I915_CTXREG_LIS6]; |
dw &= ~S6_DEPTH_TEST_FUNC_MASK; |
dw |= test << S6_DEPTH_TEST_FUNC_SHIFT; |
if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
i915->state.Ctx[I915_CTXREG_LIS6] = dw; |
} |
} |
static void |
i915DepthMask(struct gl_context * ctx, GLboolean flag) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
GLuint dw; |
DBG("%s flag (%d)\n", __FUNCTION__, flag); |
if (!ctx->DrawBuffer || !ctx->DrawBuffer->Visual.depthBits) |
flag = false; |
dw = i915->state.Ctx[I915_CTXREG_LIS6]; |
if (flag && ctx->Depth.Test) |
dw |= S6_DEPTH_WRITE_ENABLE; |
else |
dw &= ~S6_DEPTH_WRITE_ENABLE; |
if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
i915->state.Ctx[I915_CTXREG_LIS6] = dw; |
} |
} |
/** |
* Update the viewport transformation matrix. Depends on: |
* - viewport pos/size |
* - depthrange |
* - window pos/size or FBO size |
*/ |
void |
intelCalcViewport(struct gl_context * ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
_math_matrix_viewport(&intel->ViewportMatrix, |
ctx->Viewport.X, |
ctx->DrawBuffer->Height - ctx->Viewport.Y, |
ctx->Viewport.Width, |
-ctx->Viewport.Height, |
ctx->Viewport.Near, |
ctx->Viewport.Far, |
1.0); |
} else { |
_math_matrix_viewport(&intel->ViewportMatrix, |
ctx->Viewport.X, |
ctx->Viewport.Y, |
ctx->Viewport.Width, |
ctx->Viewport.Height, |
ctx->Viewport.Near, |
ctx->Viewport.Far, |
1.0); |
} |
} |
/** Called from ctx->Driver.Viewport() */ |
static void |
i915Viewport(struct gl_context * ctx, |
GLint x, GLint y, GLsizei width, GLsizei height) |
{ |
intelCalcViewport(ctx); |
} |
/** Called from ctx->Driver.DepthRange() */ |
static void |
i915DepthRange(struct gl_context * ctx, GLclampd nearval, GLclampd farval) |
{ |
intelCalcViewport(ctx); |
} |
/* ============================================================= |
* Polygon stipple |
* |
* The i915 supports a 4x4 stipple natively, GL wants 32x32. |
* Fortunately stipple is usually a repeating pattern. |
*/ |
static void |
i915PolygonStipple(struct gl_context * ctx, const GLubyte * mask) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
const GLubyte *m; |
GLubyte p[4]; |
int i, j, k; |
int active = (ctx->Polygon.StippleFlag && |
i915->intel.reduced_primitive == GL_TRIANGLES); |
GLuint newMask; |
if (active) { |
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); |
i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE; |
} |
/* Use the already unpacked stipple data from the context rather than the |
* uninterpreted mask passed in. |
*/ |
mask = (const GLubyte *)ctx->PolygonStipple; |
m = mask; |
p[0] = mask[12] & 0xf; |
p[0] |= p[0] << 4; |
p[1] = mask[8] & 0xf; |
p[1] |= p[1] << 4; |
p[2] = mask[4] & 0xf; |
p[2] |= p[2] << 4; |
p[3] = mask[0] & 0xf; |
p[3] |= p[3] << 4; |
for (k = 0; k < 8; k++) |
for (j = 3; j >= 0; j--) |
for (i = 0; i < 4; i++, m++) |
if (*m != p[j]) { |
i915->intel.hw_stipple = 0; |
return; |
} |
newMask = (((p[0] & 0xf) << 0) | |
((p[1] & 0xf) << 4) | |
((p[2] & 0xf) << 8) | ((p[3] & 0xf) << 12)); |
if (newMask == 0xffff || newMask == 0x0) { |
/* this is needed to make conform pass */ |
i915->intel.hw_stipple = 0; |
return; |
} |
i915->state.Stipple[I915_STPREG_ST1] &= ~0xffff; |
i915->state.Stipple[I915_STPREG_ST1] |= newMask; |
i915->intel.hw_stipple = 1; |
if (active) |
i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE; |
} |
/* ============================================================= |
* Hardware clipping |
*/ |
static void |
i915Scissor(struct gl_context * ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
int x1, y1, x2, y2; |
if (!ctx->DrawBuffer) |
return; |
DBG("%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h); |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
x1 = x; |
y1 = ctx->DrawBuffer->Height - (y + h); |
x2 = x + w - 1; |
y2 = y1 + h - 1; |
DBG("%s %d..%d,%d..%d (inverted)\n", __FUNCTION__, x1, x2, y1, y2); |
} |
else { |
/* FBO - not inverted |
*/ |
x1 = x; |
y1 = y; |
x2 = x + w - 1; |
y2 = y + h - 1; |
DBG("%s %d..%d,%d..%d (not inverted)\n", __FUNCTION__, x1, x2, y1, y2); |
} |
x1 = CLAMP(x1, 0, ctx->DrawBuffer->Width - 1); |
y1 = CLAMP(y1, 0, ctx->DrawBuffer->Height - 1); |
x2 = CLAMP(x2, 0, ctx->DrawBuffer->Width - 1); |
y2 = CLAMP(y2, 0, ctx->DrawBuffer->Height - 1); |
DBG("%s %d..%d,%d..%d (clamped)\n", __FUNCTION__, x1, x2, y1, y2); |
I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); |
i915->state.Buffer[I915_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff); |
i915->state.Buffer[I915_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff); |
} |
static void |
i915LogicOp(struct gl_context * ctx, GLenum opcode) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
int tmp = intel_translate_logic_op(opcode); |
DBG("%s\n", __FUNCTION__); |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
i915->state.Ctx[I915_CTXREG_STATE4] &= ~LOGICOP_MASK; |
i915->state.Ctx[I915_CTXREG_STATE4] |= LOGIC_OP_FUNC(tmp); |
} |
static void |
i915CullFaceFrontFace(struct gl_context * ctx, GLenum unused) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
GLuint mode, dw; |
DBG("%s %d\n", __FUNCTION__, |
ctx->DrawBuffer ? ctx->DrawBuffer->Name : 0); |
if (!ctx->Polygon.CullFlag) { |
mode = S4_CULLMODE_NONE; |
} |
else if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) { |
mode = S4_CULLMODE_CW; |
if (ctx->DrawBuffer && _mesa_is_user_fbo(ctx->DrawBuffer)) |
mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); |
if (ctx->Polygon.CullFaceMode == GL_FRONT) |
mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); |
if (ctx->Polygon.FrontFace != GL_CCW) |
mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW); |
} |
else { |
mode = S4_CULLMODE_BOTH; |
} |
dw = i915->state.Ctx[I915_CTXREG_LIS4]; |
dw &= ~S4_CULLMODE_MASK; |
dw |= mode; |
if (dw != i915->state.Ctx[I915_CTXREG_LIS4]) { |
i915->state.Ctx[I915_CTXREG_LIS4] = dw; |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
} |
} |
static void |
i915LineWidth(struct gl_context * ctx, GLfloat widthf) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK; |
int width; |
DBG("%s\n", __FUNCTION__); |
width = (int) (widthf * 2); |
width = CLAMP(width, 1, 0xf); |
lis4 |= width << S4_LINE_WIDTH_SHIFT; |
if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) { |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
i915->state.Ctx[I915_CTXREG_LIS4] = lis4; |
} |
} |
static void |
i915PointSize(struct gl_context * ctx, GLfloat size) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK; |
GLint point_size = (int) round(size); |
DBG("%s\n", __FUNCTION__); |
point_size = CLAMP(point_size, 1, 255); |
lis4 |= point_size << S4_POINT_WIDTH_SHIFT; |
if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) { |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
i915->state.Ctx[I915_CTXREG_LIS4] = lis4; |
} |
} |
static void |
i915PointParameterfv(struct gl_context * ctx, GLenum pname, const GLfloat *params) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
switch (pname) { |
case GL_POINT_SPRITE_COORD_ORIGIN: |
/* This could be supported, but it would require modifying the fragment |
* program to invert the y component of the texture coordinate by |
* inserting a 'SUB tc.y, {1.0}.xxxx, tc' instruction. |
*/ |
FALLBACK(&i915->intel, I915_FALLBACK_POINT_SPRITE_COORD_ORIGIN, |
(params[0] != GL_UPPER_LEFT)); |
break; |
} |
} |
void |
i915_update_sprite_point_enable(struct gl_context *ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
/* _NEW_PROGRAM */ |
struct i915_fragment_program *p = |
(struct i915_fragment_program *) ctx->FragmentProgram._Current; |
const GLbitfield64 inputsRead = p->FragProg.Base.InputsRead; |
struct i915_context *i915 = i915_context(ctx); |
GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK; |
int i; |
GLuint coord_replace_bits = 0x0; |
GLuint tex_coord_unit_bits = 0x0; |
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { |
/* _NEW_POINT */ |
if (ctx->Point.CoordReplace[i] && ctx->Point.PointSprite) |
coord_replace_bits |= (1 << i); |
if (inputsRead & VARYING_BIT_TEX(i)) |
tex_coord_unit_bits |= (1 << i); |
} |
/* |
* Here we can't enable the SPRITE_POINT_ENABLE bit when the mis-match |
* of tex_coord_unit_bits and coord_replace_bits, or this will make all |
* the other non-point-sprite coords(like varying inputs, as we now use |
* tex coord to implement varying inputs) be replaced to value (0, 0)-(1, 1). |
* |
* Thus, do fallback when needed. |
*/ |
FALLBACK(intel, I915_FALLBACK_COORD_REPLACE, |
coord_replace_bits && coord_replace_bits != tex_coord_unit_bits); |
s4 &= ~S4_SPRITE_POINT_ENABLE; |
s4 |= (coord_replace_bits && coord_replace_bits == tex_coord_unit_bits) ? |
S4_SPRITE_POINT_ENABLE : 0; |
if (s4 != i915->state.Ctx[I915_CTXREG_LIS4]) { |
i915->state.Ctx[I915_CTXREG_LIS4] = s4; |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
} |
} |
/* ============================================================= |
* Color masks |
*/ |
static void |
i915ColorMask(struct gl_context * ctx, |
GLboolean r, GLboolean g, GLboolean b, GLboolean a) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
GLuint tmp = i915->state.Ctx[I915_CTXREG_LIS5] & ~S5_WRITEDISABLE_MASK; |
DBG("%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, |
a); |
if (!r) |
tmp |= S5_WRITEDISABLE_RED; |
if (!g) |
tmp |= S5_WRITEDISABLE_GREEN; |
if (!b) |
tmp |= S5_WRITEDISABLE_BLUE; |
if (!a) |
tmp |= S5_WRITEDISABLE_ALPHA; |
if (tmp != i915->state.Ctx[I915_CTXREG_LIS5]) { |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
i915->state.Ctx[I915_CTXREG_LIS5] = tmp; |
} |
} |
static void |
update_specular(struct gl_context * ctx) |
{ |
/* A hack to trigger the rebuild of the fragment program. |
*/ |
intel_context(ctx)->NewGLState |= _NEW_TEXTURE; |
} |
static void |
i915LightModelfv(struct gl_context * ctx, GLenum pname, const GLfloat * param) |
{ |
DBG("%s\n", __FUNCTION__); |
if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { |
update_specular(ctx); |
} |
} |
static void |
i915ShadeModel(struct gl_context * ctx, GLenum mode) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
if (mode == GL_SMOOTH) { |
i915->state.Ctx[I915_CTXREG_LIS4] &= ~(S4_FLATSHADE_ALPHA | |
S4_FLATSHADE_COLOR | |
S4_FLATSHADE_SPECULAR); |
} |
else { |
i915->state.Ctx[I915_CTXREG_LIS4] |= (S4_FLATSHADE_ALPHA | |
S4_FLATSHADE_COLOR | |
S4_FLATSHADE_SPECULAR); |
} |
} |
/* ============================================================= |
* Fog |
* |
* This empty function remains because _mesa_init_driver_state calls |
* dd_function_table::Fogfv unconditionally. We have to have some function |
* there so that it doesn't try to call a NULL pointer. |
*/ |
static void |
i915Fogfv(struct gl_context * ctx, GLenum pname, const GLfloat * param) |
{ |
(void) ctx; |
(void) pname; |
(void) param; |
} |
/* ============================================================= |
*/ |
static void |
i915Enable(struct gl_context * ctx, GLenum cap, GLboolean state) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
GLuint dw; |
switch (cap) { |
case GL_TEXTURE_2D: |
break; |
case GL_LIGHTING: |
case GL_COLOR_SUM: |
update_specular(ctx); |
break; |
case GL_ALPHA_TEST: |
dw = i915->state.Ctx[I915_CTXREG_LIS6]; |
if (state) |
dw |= S6_ALPHA_TEST_ENABLE; |
else |
dw &= ~S6_ALPHA_TEST_ENABLE; |
if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { |
i915->state.Ctx[I915_CTXREG_LIS6] = dw; |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
} |
break; |
case GL_BLEND: |
i915EvalLogicOpBlendState(ctx); |
break; |
case GL_COLOR_LOGIC_OP: |
i915EvalLogicOpBlendState(ctx); |
/* Logicop doesn't seem to work at 16bpp: |
*/ |
if (ctx->Visual.rgbBits == 16) |
FALLBACK(&i915->intel, I915_FALLBACK_LOGICOP, state); |
break; |
case GL_FRAGMENT_PROGRAM_ARB: |
break; |
case GL_DITHER: |
dw = i915->state.Ctx[I915_CTXREG_LIS5]; |
if (state) |
dw |= S5_COLOR_DITHER_ENABLE; |
else |
dw &= ~S5_COLOR_DITHER_ENABLE; |
if (dw != i915->state.Ctx[I915_CTXREG_LIS5]) { |
i915->state.Ctx[I915_CTXREG_LIS5] = dw; |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
} |
break; |
case GL_DEPTH_TEST: |
dw = i915->state.Ctx[I915_CTXREG_LIS6]; |
if (!ctx->DrawBuffer || !ctx->DrawBuffer->Visual.depthBits) |
state = false; |
if (state) |
dw |= S6_DEPTH_TEST_ENABLE; |
else |
dw &= ~S6_DEPTH_TEST_ENABLE; |
if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { |
i915->state.Ctx[I915_CTXREG_LIS6] = dw; |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
} |
i915DepthMask(ctx, ctx->Depth.Mask); |
break; |
case GL_SCISSOR_TEST: |
I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); |
if (state) |
i915->state.Buffer[I915_DESTREG_SENABLE] = |
(_3DSTATE_SCISSOR_ENABLE_CMD | ENABLE_SCISSOR_RECT); |
else |
i915->state.Buffer[I915_DESTREG_SENABLE] = |
(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); |
break; |
case GL_LINE_SMOOTH: |
dw = i915->state.Ctx[I915_CTXREG_LIS4]; |
if (state) |
dw |= S4_LINE_ANTIALIAS_ENABLE; |
else |
dw &= ~S4_LINE_ANTIALIAS_ENABLE; |
if (dw != i915->state.Ctx[I915_CTXREG_LIS4]) { |
i915->state.Ctx[I915_CTXREG_LIS4] = dw; |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
} |
break; |
case GL_CULL_FACE: |
i915CullFaceFrontFace(ctx, 0); |
break; |
case GL_STENCIL_TEST: |
if (!ctx->DrawBuffer || !ctx->DrawBuffer->Visual.stencilBits) |
state = false; |
dw = i915->state.Ctx[I915_CTXREG_LIS5]; |
if (state) |
dw |= (S5_STENCIL_TEST_ENABLE | S5_STENCIL_WRITE_ENABLE); |
else |
dw &= ~(S5_STENCIL_TEST_ENABLE | S5_STENCIL_WRITE_ENABLE); |
if (dw != i915->state.Ctx[I915_CTXREG_LIS5]) { |
i915->state.Ctx[I915_CTXREG_LIS5] = dw; |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
} |
break; |
case GL_POLYGON_STIPPLE: |
/* The stipple command worked on my 855GM box, but not my 845G. |
* I'll do more testing later to find out exactly which hardware |
* supports it. Disabled for now. |
*/ |
if (i915->intel.hw_stipple && |
i915->intel.reduced_primitive == GL_TRIANGLES) { |
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); |
if (state) |
i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE; |
else |
i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE; |
} |
break; |
case GL_POLYGON_SMOOTH: |
break; |
case GL_POINT_SPRITE: |
/* Handle it at i915_update_sprite_point_enable () */ |
break; |
case GL_POINT_SMOOTH: |
break; |
default: |
; |
} |
} |
static void |
i915_init_packets(struct i915_context *i915) |
{ |
/* Zero all state */ |
memset(&i915->state, 0, sizeof(i915->state)); |
{ |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
I915_STATECHANGE(i915, I915_UPLOAD_BLEND); |
/* Probably don't want to upload all this stuff every time one |
* piece changes. |
*/ |
i915->state.Ctx[I915_CTXREG_LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 | |
I1_LOAD_S(2) | |
I1_LOAD_S(4) | |
I1_LOAD_S(5) | I1_LOAD_S(6) | (3)); |
i915->state.Ctx[I915_CTXREG_LIS2] = 0; |
i915->state.Ctx[I915_CTXREG_LIS4] = 0; |
i915->state.Ctx[I915_CTXREG_LIS5] = 0; |
if (i915->intel.ctx.Visual.rgbBits == 16) |
i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE; |
i915->state.Ctx[I915_CTXREG_LIS6] = (S6_COLOR_WRITE_ENABLE | |
(2 << S6_TRISTRIP_PV_SHIFT)); |
i915->state.Ctx[I915_CTXREG_STATE4] = (_3DSTATE_MODES_4_CMD | |
ENABLE_LOGIC_OP_FUNC | |
LOGIC_OP_FUNC(LOGICOP_COPY) | |
ENABLE_STENCIL_TEST_MASK | |
STENCIL_TEST_MASK(0xff) | |
ENABLE_STENCIL_WRITE_MASK | |
STENCIL_WRITE_MASK(0xff)); |
i915->state.Blend[I915_BLENDREG_IAB] = |
(_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD | IAB_MODIFY_ENABLE | |
IAB_MODIFY_FUNC | IAB_MODIFY_SRC_FACTOR | IAB_MODIFY_DST_FACTOR); |
i915->state.Blend[I915_BLENDREG_BLENDCOLOR0] = |
_3DSTATE_CONST_BLEND_COLOR_CMD; |
i915->state.Blend[I915_BLENDREG_BLENDCOLOR1] = 0; |
i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] = |
_3DSTATE_BACKFACE_STENCIL_MASKS | |
BFM_ENABLE_STENCIL_TEST_MASK | |
BFM_ENABLE_STENCIL_WRITE_MASK | |
(0xff << BFM_STENCIL_WRITE_MASK_SHIFT) | |
(0xff << BFM_STENCIL_TEST_MASK_SHIFT); |
i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] = |
_3DSTATE_BACKFACE_STENCIL_OPS | |
BFO_ENABLE_STENCIL_REF | |
BFO_ENABLE_STENCIL_FUNCS | |
BFO_ENABLE_STENCIL_TWO_SIDE; |
} |
{ |
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); |
i915->state.Stipple[I915_STPREG_ST0] = _3DSTATE_STIPPLE; |
} |
{ |
i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD; |
/* scissor */ |
i915->state.Buffer[I915_DESTREG_SENABLE] = |
(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); |
i915->state.Buffer[I915_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD; |
i915->state.Buffer[I915_DESTREG_SR1] = 0; |
i915->state.Buffer[I915_DESTREG_SR2] = 0; |
} |
i915->state.RasterRules[I915_RASTER_RULES] = _3DSTATE_RASTER_RULES_CMD | |
ENABLE_POINT_RASTER_RULE | |
OGL_POINT_RASTER_RULE | |
ENABLE_LINE_STRIP_PROVOKE_VRTX | |
ENABLE_TRI_FAN_PROVOKE_VRTX | |
LINE_STRIP_PROVOKE_VRTX(1) | |
TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D; |
#if 0 |
{ |
I915_STATECHANGE(i915, I915_UPLOAD_DEFAULTS); |
i915->state.Default[I915_DEFREG_C0] = _3DSTATE_DEFAULT_DIFFUSE; |
i915->state.Default[I915_DEFREG_C1] = 0; |
i915->state.Default[I915_DEFREG_S0] = _3DSTATE_DEFAULT_SPECULAR; |
i915->state.Default[I915_DEFREG_S1] = 0; |
i915->state.Default[I915_DEFREG_Z0] = _3DSTATE_DEFAULT_Z; |
i915->state.Default[I915_DEFREG_Z1] = 0; |
} |
#endif |
/* These will be emitted every at the head of every buffer, unless |
* we get hardware contexts working. |
*/ |
i915->state.active = (I915_UPLOAD_PROGRAM | |
I915_UPLOAD_STIPPLE | |
I915_UPLOAD_CTX | |
I915_UPLOAD_BLEND | |
I915_UPLOAD_BUFFERS | |
I915_UPLOAD_INVARIENT | |
I915_UPLOAD_RASTER_RULES); |
} |
void |
i915_update_provoking_vertex(struct gl_context * ctx) |
{ |
struct i915_context *i915 = I915_CONTEXT(ctx); |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_TRISTRIP_PV_MASK); |
I915_STATECHANGE(i915, I915_UPLOAD_RASTER_RULES); |
i915->state.RasterRules[I915_RASTER_RULES] &= ~(LINE_STRIP_PROVOKE_VRTX_MASK | |
TRI_FAN_PROVOKE_VRTX_MASK); |
/* _NEW_LIGHT */ |
if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION) { |
i915->state.RasterRules[I915_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(1) | |
TRI_FAN_PROVOKE_VRTX(2)); |
i915->state.Ctx[I915_CTXREG_LIS6] |= (2 << S6_TRISTRIP_PV_SHIFT); |
} else { |
i915->state.RasterRules[I915_RASTER_RULES] |= (LINE_STRIP_PROVOKE_VRTX(0) | |
TRI_FAN_PROVOKE_VRTX(1)); |
i915->state.Ctx[I915_CTXREG_LIS6] |= (0 << S6_TRISTRIP_PV_SHIFT); |
} |
} |
/* Fallback to swrast for select and feedback. |
*/ |
static void |
i915RenderMode(struct gl_context *ctx, GLenum mode) |
{ |
struct intel_context *intel = intel_context(ctx); |
FALLBACK(intel, INTEL_FALLBACK_RENDERMODE, (mode != GL_RENDER)); |
} |
void |
i915InitStateFunctions(struct dd_function_table *functions) |
{ |
functions->AlphaFunc = i915AlphaFunc; |
functions->BlendColor = i915BlendColor; |
functions->BlendEquationSeparate = i915BlendEquationSeparate; |
functions->BlendFuncSeparate = i915BlendFuncSeparate; |
functions->ColorMask = i915ColorMask; |
functions->CullFace = i915CullFaceFrontFace; |
functions->DepthFunc = i915DepthFunc; |
functions->DepthMask = i915DepthMask; |
functions->Enable = i915Enable; |
functions->Fogfv = i915Fogfv; |
functions->FrontFace = i915CullFaceFrontFace; |
functions->LightModelfv = i915LightModelfv; |
functions->LineWidth = i915LineWidth; |
functions->LogicOpcode = i915LogicOp; |
functions->PointSize = i915PointSize; |
functions->PointParameterfv = i915PointParameterfv; |
functions->PolygonStipple = i915PolygonStipple; |
functions->RenderMode = i915RenderMode; |
functions->Scissor = i915Scissor; |
functions->ShadeModel = i915ShadeModel; |
functions->StencilFuncSeparate = i915StencilFuncSeparate; |
functions->StencilMaskSeparate = i915StencilMaskSeparate; |
functions->StencilOpSeparate = i915StencilOpSeparate; |
functions->DepthRange = i915DepthRange; |
functions->Viewport = i915Viewport; |
} |
void |
i915InitState(struct i915_context *i915) |
{ |
struct gl_context *ctx = &i915->intel.ctx; |
i915_init_packets(i915); |
_mesa_init_driver_state(ctx); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_tex_layout.c |
---|
0,0 → 1,481 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
/** @file i915_tex_layout.c |
* Code to layout images in a mipmap tree for i830M-GM915 and G945 and beyond. |
*/ |
#include "intel_mipmap_tree.h" |
#include "intel_tex_layout.h" |
#include "main/macros.h" |
#include "intel_context.h" |
#define FILE_DEBUG_FLAG DEBUG_TEXTURE |
static GLint initial_offsets[6][2] = { |
[FACE_POS_X] = {0, 0}, |
[FACE_POS_Y] = {1, 0}, |
[FACE_POS_Z] = {1, 1}, |
[FACE_NEG_X] = {0, 2}, |
[FACE_NEG_Y] = {1, 2}, |
[FACE_NEG_Z] = {1, 3}, |
}; |
static GLint step_offsets[6][2] = { |
[FACE_POS_X] = {0, 2}, |
[FACE_POS_Y] = {-1, 2}, |
[FACE_POS_Z] = {-1, 1}, |
[FACE_NEG_X] = {0, 2}, |
[FACE_NEG_Y] = {-1, 2}, |
[FACE_NEG_Z] = {-1, 1}, |
}; |
static GLint bottom_offsets[6] = { |
[FACE_POS_X] = 16 + 0 * 8, |
[FACE_POS_Y] = 16 + 1 * 8, |
[FACE_POS_Z] = 16 + 2 * 8, |
[FACE_NEG_X] = 16 + 3 * 8, |
[FACE_NEG_Y] = 16 + 4 * 8, |
[FACE_NEG_Z] = 16 + 5 * 8, |
}; |
/** |
* Cube texture map layout for i830M-GM915 and |
* non-compressed cube texture map on GM945. |
* |
* Hardware layout looks like: |
* |
* +-------+-------+ |
* | | | |
* | | | |
* | | | |
* | +x | +y | |
* | | | |
* | | | |
* | | | |
* | | | |
* +---+---+-------+ |
* | | | | |
* | +x| +y| | |
* | | | | |
* | | | | |
* +-+-+---+ +z | |
* | | | | | |
* +-+-+ +z| | |
* | | | | |
* +-+-+---+-------+ |
* | | | |
* | | | |
* | | | |
* | -x | -y | |
* | | | |
* | | | |
* | | | |
* | | | |
* +---+---+-------+ |
* | | | | |
* | -x| -y| | |
* | | | | |
* | | | | |
* +-+-+---+ -z | |
* | | | | | |
* +-+-+ -z| | |
* | | | | |
* +-+---+-------+ |
* |
*/ |
static void |
i915_miptree_layout_cube(struct intel_mipmap_tree * mt) |
{ |
const GLuint dim = mt->physical_width0; |
GLuint face; |
GLuint lvlWidth = mt->physical_width0, lvlHeight = mt->physical_height0; |
GLint level; |
assert(lvlWidth == lvlHeight); /* cubemap images are square */ |
/* double pitch for cube layouts */ |
mt->total_width = dim * 2; |
mt->total_height = dim * 4; |
for (level = mt->first_level; level <= mt->last_level; level++) { |
intel_miptree_set_level_info(mt, level, |
0, 0, |
lvlWidth, lvlHeight, |
6); |
lvlWidth /= 2; |
lvlHeight /= 2; |
} |
for (face = 0; face < 6; face++) { |
GLuint x = initial_offsets[face][0] * dim; |
GLuint y = initial_offsets[face][1] * dim; |
GLuint d = dim; |
for (level = mt->first_level; level <= mt->last_level; level++) { |
intel_miptree_set_image_offset(mt, level, face, x, y); |
if (d == 0) |
printf("cube mipmap %d/%d (%d..%d) is 0x0\n", |
face, level, mt->first_level, mt->last_level); |
d >>= 1; |
x += step_offsets[face][0] * d; |
y += step_offsets[face][1] * d; |
} |
} |
} |
static void |
i915_miptree_layout_3d(struct intel_mipmap_tree * mt) |
{ |
GLuint width = mt->physical_width0; |
GLuint height = mt->physical_height0; |
GLuint depth = mt->physical_depth0; |
GLuint stack_height = 0; |
GLint level; |
/* Calculate the size of a single slice. */ |
mt->total_width = mt->physical_width0; |
/* XXX: hardware expects/requires 9 levels at minimum. */ |
for (level = mt->first_level; level <= MAX2(8, mt->last_level); level++) { |
intel_miptree_set_level_info(mt, level, 0, mt->total_height, |
width, height, depth); |
stack_height += MAX2(2, height); |
width = minify(width, 1); |
height = minify(height, 1); |
depth = minify(depth, 1); |
} |
/* Fixup depth image_offsets: */ |
depth = mt->physical_depth0; |
for (level = mt->first_level; level <= mt->last_level; level++) { |
GLuint i; |
for (i = 0; i < depth; i++) { |
intel_miptree_set_image_offset(mt, level, i, |
0, i * stack_height); |
} |
depth = minify(depth, 1); |
} |
/* Multiply slice size by texture depth for total size. It's |
* remarkable how wasteful of memory the i915 texture layouts |
* are. They are largely fixed in the i945. |
*/ |
mt->total_height = stack_height * mt->physical_depth0; |
} |
static void |
i915_miptree_layout_2d(struct intel_mipmap_tree * mt) |
{ |
GLuint width = mt->physical_width0; |
GLuint height = mt->physical_height0; |
GLuint img_height; |
GLint level; |
mt->total_width = mt->physical_width0; |
mt->total_height = 0; |
for (level = mt->first_level; level <= mt->last_level; level++) { |
intel_miptree_set_level_info(mt, level, |
0, mt->total_height, |
width, height, 1); |
if (mt->compressed) |
img_height = ALIGN(height, 4) / 4; |
else |
img_height = ALIGN(height, 2); |
mt->total_height += img_height; |
width = minify(width, 1); |
height = minify(height, 1); |
} |
} |
void |
i915_miptree_layout(struct intel_mipmap_tree * mt) |
{ |
switch (mt->target) { |
case GL_TEXTURE_CUBE_MAP: |
i915_miptree_layout_cube(mt); |
break; |
case GL_TEXTURE_3D: |
i915_miptree_layout_3d(mt); |
break; |
case GL_TEXTURE_1D: |
case GL_TEXTURE_2D: |
case GL_TEXTURE_RECTANGLE_ARB: |
i915_miptree_layout_2d(mt); |
break; |
default: |
_mesa_problem(NULL, "Unexpected tex target in i915_miptree_layout()"); |
break; |
} |
DBG("%s: %dx%dx%d\n", __FUNCTION__, |
mt->total_width, mt->total_height, mt->cpp); |
} |
/** |
* Compressed cube texture map layout for GM945 and later. |
* |
* The hardware layout looks like the 830-915 layout, except for the small |
* sizes. A zoomed in view of the layout for 945 is: |
* |
* +-------+-------+ |
* | 8x8 | 8x8 | |
* | | | |
* | | | |
* | +x | +y | |
* | | | |
* | | | |
* | | | |
* | | | |
* +---+---+-------+ |
* |4x4| | 8x8 | |
* | +x| | | |
* | | | | |
* | | | | |
* +---+ | +z | |
* |4x4| | | |
* | +y| | | |
* | | | | |
* +---+ +-------+ |
* |
* ... |
* |
* +-------+-------+ |
* | 8x8 | 8x8 | |
* | | | |
* | | | |
* | -x | -y | |
* | | | |
* | | | |
* | | | |
* | | | |
* +---+---+-------+ |
* |4x4| | 8x8 | |
* | -x| | | |
* | | | | |
* | | | | |
* +---+ | -z | |
* |4x4| | | |
* | -y| | | |
* | | | | |
* +---+ +---+---+---+---+---+---+---+---+---+ |
* |4x4| |4x4| |2x2| |2x2| |2x2| |2x2| |
* | +z| | -z| | +x| | +y| | +z| | -x| ... |
* | | | | | | | | | | | | |
* +---+ +---+ +---+ +---+ +---+ +---+ |
* |
* The bottom row continues with the remaining 2x2 then the 1x1 mip contents |
* in order, with each of them aligned to a 8x8 block boundary. Thus, for |
* 32x32 cube maps and smaller, the bottom row layout is going to dictate the |
* pitch of the tree. For a tree with 4x4 images, the pitch is at least |
* 14 * 8 = 112 texels, for 2x2 it is at least 12 * 8 texels, and for 1x1 |
* it is 6 * 8 texels. |
*/ |
static void |
i945_miptree_layout_cube(struct intel_mipmap_tree * mt) |
{ |
const GLuint dim = mt->physical_width0; |
GLuint face; |
GLuint lvlWidth = mt->physical_width0, lvlHeight = mt->physical_height0; |
GLint level; |
assert(lvlWidth == lvlHeight); /* cubemap images are square */ |
/* Depending on the size of the largest images, pitch can be |
* determined either by the old-style packing of cubemap faces, |
* or the final row of 4x4, 2x2 and 1x1 faces below this. |
*/ |
if (dim > 32) |
mt->total_width = dim * 2; |
else |
mt->total_width = 14 * 8; |
if (dim >= 4) |
mt->total_height = dim * 4 + 4; |
else |
mt->total_height = 4; |
/* Set all the levels to effectively occupy the whole rectangular region. */ |
for (level = mt->first_level; level <= mt->last_level; level++) { |
intel_miptree_set_level_info(mt, level, |
0, 0, |
lvlWidth, lvlHeight, 6); |
lvlWidth /= 2; |
lvlHeight /= 2; |
} |
for (face = 0; face < 6; face++) { |
GLuint x = initial_offsets[face][0] * dim; |
GLuint y = initial_offsets[face][1] * dim; |
GLuint d = dim; |
if (dim == 4 && face >= 4) { |
y = mt->total_height - 4; |
x = (face - 4) * 8; |
} else if (dim < 4 && (face > 0 || mt->first_level > 0)) { |
y = mt->total_height - 4; |
x = face * 8; |
} |
for (level = mt->first_level; level <= mt->last_level; level++) { |
intel_miptree_set_image_offset(mt, level, face, x, y); |
d >>= 1; |
switch (d) { |
case 4: |
switch (face) { |
case FACE_POS_X: |
case FACE_NEG_X: |
x += step_offsets[face][0] * d; |
y += step_offsets[face][1] * d; |
break; |
case FACE_POS_Y: |
case FACE_NEG_Y: |
y += 12; |
x -= 8; |
break; |
case FACE_POS_Z: |
case FACE_NEG_Z: |
y = mt->total_height - 4; |
x = (face - 4) * 8; |
break; |
} |
break; |
case 2: |
y = mt->total_height - 4; |
x = bottom_offsets[face]; |
break; |
case 1: |
x += 48; |
break; |
default: |
x += step_offsets[face][0] * d; |
y += step_offsets[face][1] * d; |
break; |
} |
} |
} |
} |
static void |
i945_miptree_layout_3d(struct intel_mipmap_tree * mt) |
{ |
GLuint width = mt->physical_width0; |
GLuint height = mt->physical_height0; |
GLuint depth = mt->physical_depth0; |
GLuint pack_x_pitch, pack_x_nr; |
GLuint pack_y_pitch; |
GLuint level; |
mt->total_width = mt->physical_width0; |
mt->total_height = 0; |
pack_y_pitch = MAX2(mt->physical_height0, 2); |
pack_x_pitch = mt->total_width; |
pack_x_nr = 1; |
for (level = mt->first_level; level <= mt->last_level; level++) { |
GLint x = 0; |
GLint y = 0; |
GLint q, j; |
intel_miptree_set_level_info(mt, level, |
0, mt->total_height, |
width, height, depth); |
for (q = 0; q < depth;) { |
for (j = 0; j < pack_x_nr && q < depth; j++, q++) { |
intel_miptree_set_image_offset(mt, level, q, x, y); |
x += pack_x_pitch; |
} |
x = 0; |
y += pack_y_pitch; |
} |
mt->total_height += y; |
if (pack_x_pitch > 4) { |
pack_x_pitch >>= 1; |
pack_x_nr <<= 1; |
assert(pack_x_pitch * pack_x_nr <= mt->total_width); |
} |
if (pack_y_pitch > 2) { |
pack_y_pitch >>= 1; |
} |
width = minify(width, 1); |
height = minify(height, 1); |
depth = minify(depth, 1); |
} |
} |
void |
i945_miptree_layout(struct intel_mipmap_tree * mt) |
{ |
switch (mt->target) { |
case GL_TEXTURE_CUBE_MAP: |
if (mt->compressed) |
i945_miptree_layout_cube(mt); |
else |
i915_miptree_layout_cube(mt); |
break; |
case GL_TEXTURE_3D: |
i945_miptree_layout_3d(mt); |
break; |
case GL_TEXTURE_1D: |
case GL_TEXTURE_2D: |
case GL_TEXTURE_RECTANGLE_ARB: |
i945_miptree_layout_2d(mt); |
break; |
default: |
_mesa_problem(NULL, "Unexpected tex target in i945_miptree_layout()"); |
break; |
} |
DBG("%s: %dx%dx%d\n", __FUNCTION__, |
mt->total_width, mt->total_height, mt->cpp); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_texstate.c |
---|
0,0 → 1,449 |
/************************************************************************** |
* |
* 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 "main/mtypes.h" |
#include "main/enums.h" |
#include "main/macros.h" |
#include "main/colormac.h" |
#include "main/samplerobj.h" |
#include "intel_mipmap_tree.h" |
#include "intel_tex.h" |
#include "i915_context.h" |
#include "i915_reg.h" |
static GLuint |
translate_texture_format(gl_format mesa_format, GLenum DepthMode) |
{ |
switch (mesa_format) { |
case MESA_FORMAT_L8: |
return MAPSURF_8BIT | MT_8BIT_L8; |
case MESA_FORMAT_I8: |
return MAPSURF_8BIT | MT_8BIT_I8; |
case MESA_FORMAT_A8: |
return MAPSURF_8BIT | MT_8BIT_A8; |
case MESA_FORMAT_AL88: |
return MAPSURF_16BIT | MT_16BIT_AY88; |
case MESA_FORMAT_RGB565: |
return MAPSURF_16BIT | MT_16BIT_RGB565; |
case MESA_FORMAT_ARGB1555: |
return MAPSURF_16BIT | MT_16BIT_ARGB1555; |
case MESA_FORMAT_ARGB4444: |
return MAPSURF_16BIT | MT_16BIT_ARGB4444; |
case MESA_FORMAT_SARGB8: |
case MESA_FORMAT_ARGB8888: |
return MAPSURF_32BIT | MT_32BIT_ARGB8888; |
case MESA_FORMAT_XRGB8888: |
return MAPSURF_32BIT | MT_32BIT_XRGB8888; |
case MESA_FORMAT_RGBA8888_REV: |
return MAPSURF_32BIT | MT_32BIT_ABGR8888; |
case MESA_FORMAT_YCBCR_REV: |
return (MAPSURF_422 | MT_422_YCRCB_NORMAL); |
case MESA_FORMAT_YCBCR: |
return (MAPSURF_422 | MT_422_YCRCB_SWAPY); |
case MESA_FORMAT_RGB_FXT1: |
case MESA_FORMAT_RGBA_FXT1: |
return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); |
case MESA_FORMAT_Z16: |
if (DepthMode == GL_ALPHA) |
return (MAPSURF_16BIT | MT_16BIT_A16); |
else if (DepthMode == GL_INTENSITY) |
return (MAPSURF_16BIT | MT_16BIT_I16); |
else |
return (MAPSURF_16BIT | MT_16BIT_L16); |
case MESA_FORMAT_RGBA_DXT1: |
case MESA_FORMAT_RGB_DXT1: |
case MESA_FORMAT_SRGB_DXT1: |
case MESA_FORMAT_SRGBA_DXT1: |
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); |
case MESA_FORMAT_RGBA_DXT3: |
case MESA_FORMAT_SRGBA_DXT3: |
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); |
case MESA_FORMAT_RGBA_DXT5: |
case MESA_FORMAT_SRGBA_DXT5: |
return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); |
case MESA_FORMAT_S8_Z24: |
case MESA_FORMAT_X8_Z24: |
if (DepthMode == GL_ALPHA) |
return (MAPSURF_32BIT | MT_32BIT_x8A24); |
else if (DepthMode == GL_INTENSITY) |
return (MAPSURF_32BIT | MT_32BIT_x8I24); |
else |
return (MAPSURF_32BIT | MT_32BIT_x8L24); |
default: |
fprintf(stderr, "%s: bad image format %s\n", __FUNCTION__, |
_mesa_get_format_name(mesa_format)); |
abort(); |
return 0; |
} |
} |
/* The i915 (and related graphics cores) do not support GL_CLAMP. The |
* Intel drivers for "other operating systems" implement GL_CLAMP as |
* GL_CLAMP_TO_EDGE, so the same is done here. |
*/ |
static GLuint |
translate_wrap_mode(GLenum wrap) |
{ |
switch (wrap) { |
case GL_REPEAT: |
return TEXCOORDMODE_WRAP; |
case GL_CLAMP: |
return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */ |
case GL_CLAMP_TO_EDGE: |
return TEXCOORDMODE_CLAMP_EDGE; |
case GL_CLAMP_TO_BORDER: |
return TEXCOORDMODE_CLAMP_BORDER; |
case GL_MIRRORED_REPEAT: |
return TEXCOORDMODE_MIRROR; |
default: |
return TEXCOORDMODE_WRAP; |
} |
} |
/* Recalculate all state from scratch. Perhaps not the most |
* efficient, but this has gotten complex enough that we need |
* something which is understandable and reliable. |
*/ |
static bool |
i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3) |
{ |
struct gl_context *ctx = &intel->ctx; |
struct i915_context *i915 = i915_context(ctx); |
struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit]; |
struct gl_texture_object *tObj = tUnit->_Current; |
struct intel_texture_object *intelObj = intel_texture_object(tObj); |
struct gl_texture_image *firstImage; |
struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); |
GLuint *state = i915->state.Tex[unit], format; |
GLint lodbias, aniso = 0; |
GLubyte border[4]; |
GLfloat maxlod; |
memset(state, 0, sizeof(*state)); |
/*We need to refcount these. */ |
if (i915->state.tex_buffer[unit] != NULL) { |
drm_intel_bo_unreference(i915->state.tex_buffer[unit]); |
i915->state.tex_buffer[unit] = NULL; |
} |
if (!intel_finalize_mipmap_tree(intel, unit)) |
return false; |
/* Get first image here, since intelObj->firstLevel will get set in |
* the intel_finalize_mipmap_tree() call above. |
*/ |
firstImage = tObj->Image[0][tObj->BaseLevel]; |
drm_intel_bo_reference(intelObj->mt->region->bo); |
i915->state.tex_buffer[unit] = intelObj->mt->region->bo; |
i915->state.tex_offset[unit] = intelObj->mt->offset; |
format = translate_texture_format(firstImage->TexFormat, |
tObj->DepthMode); |
state[I915_TEXREG_MS3] = |
(((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) | |
((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format); |
if (intelObj->mt->region->tiling != I915_TILING_NONE) { |
state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE; |
if (intelObj->mt->region->tiling == I915_TILING_Y) |
state[I915_TEXREG_MS3] |= MS3_TILE_WALK; |
} |
/* We get one field with fraction bits for the maximum addressable |
* (lowest resolution) LOD. Use it to cover both MAX_LEVEL and |
* MAX_LOD. |
*/ |
maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel); |
state[I915_TEXREG_MS4] = |
((((intelObj->mt->region->pitch / 4) - 1) << MS4_PITCH_SHIFT) | |
MS4_CUBE_FACE_ENA_MASK | |
(U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) | |
((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); |
{ |
GLuint minFilt, mipFilt, magFilt; |
switch (sampler->MinFilter) { |
case GL_NEAREST: |
minFilt = FILTER_NEAREST; |
mipFilt = MIPFILTER_NONE; |
break; |
case GL_LINEAR: |
minFilt = FILTER_LINEAR; |
mipFilt = MIPFILTER_NONE; |
break; |
case GL_NEAREST_MIPMAP_NEAREST: |
minFilt = FILTER_NEAREST; |
mipFilt = MIPFILTER_NEAREST; |
break; |
case GL_LINEAR_MIPMAP_NEAREST: |
minFilt = FILTER_LINEAR; |
mipFilt = MIPFILTER_NEAREST; |
break; |
case GL_NEAREST_MIPMAP_LINEAR: |
minFilt = FILTER_NEAREST; |
mipFilt = MIPFILTER_LINEAR; |
break; |
case GL_LINEAR_MIPMAP_LINEAR: |
minFilt = FILTER_LINEAR; |
mipFilt = MIPFILTER_LINEAR; |
break; |
default: |
return false; |
} |
if (sampler->MaxAnisotropy > 1.0) { |
minFilt = FILTER_ANISOTROPIC; |
magFilt = FILTER_ANISOTROPIC; |
if (sampler->MaxAnisotropy > 2.0) |
aniso = SS2_MAX_ANISO_4; |
else |
aniso = SS2_MAX_ANISO_2; |
} |
else { |
switch (sampler->MagFilter) { |
case GL_NEAREST: |
magFilt = FILTER_NEAREST; |
break; |
case GL_LINEAR: |
magFilt = FILTER_LINEAR; |
break; |
default: |
return false; |
} |
} |
lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0); |
if (lodbias < -256) |
lodbias = -256; |
if (lodbias > 255) |
lodbias = 255; |
state[I915_TEXREG_SS2] = ((lodbias << SS2_LOD_BIAS_SHIFT) & |
SS2_LOD_BIAS_MASK); |
/* YUV conversion: |
*/ |
if (firstImage->TexFormat == MESA_FORMAT_YCBCR || |
firstImage->TexFormat == MESA_FORMAT_YCBCR_REV) |
state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION; |
/* Shadow: |
*/ |
if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && |
tObj->Target != GL_TEXTURE_3D) { |
if (tObj->Target == GL_TEXTURE_1D) |
return false; |
state[I915_TEXREG_SS2] |= |
(SS2_SHADOW_ENABLE | |
intel_translate_shadow_compare_func(sampler->CompareFunc)); |
minFilt = FILTER_4X4_FLAT; |
magFilt = FILTER_4X4_FLAT; |
} |
state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | |
(mipFilt << SS2_MIP_FILTER_SHIFT) | |
(magFilt << SS2_MAG_FILTER_SHIFT) | |
aniso); |
} |
{ |
GLenum ws = sampler->WrapS; |
GLenum wt = sampler->WrapT; |
GLenum wr = sampler->WrapR; |
float minlod; |
/* We program 1D textures as 2D textures, so the 2D texcoord could |
* result in sampling border values if we don't set the T wrap to |
* repeat. |
*/ |
if (tObj->Target == GL_TEXTURE_1D) |
wt = GL_REPEAT; |
/* 3D textures don't seem to respect the border color. |
* Fallback if there's ever a danger that they might refer to |
* it. |
* |
* Effectively this means fallback on 3D clamp or |
* clamp_to_border. |
*/ |
if (tObj->Target == GL_TEXTURE_3D && |
(sampler->MinFilter != GL_NEAREST || |
sampler->MagFilter != GL_NEAREST) && |
(ws == GL_CLAMP || |
wt == GL_CLAMP || |
wr == GL_CLAMP || |
ws == GL_CLAMP_TO_BORDER || |
wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER)) |
return false; |
/* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not |
* used) when using cube map texture coordinates |
*/ |
if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB && |
(((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) || |
((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE)))) |
return false; |
/* |
* According to 3DSTATE_MAP_STATE at page of 104 in Bspec |
* Vol3d 3D Instructions: |
* [DevGDG and DevAlv]: Must be a power of 2 for cube maps. |
* [DevLPT, DevCST and DevBLB]: If not a power of 2, cube maps |
* must have all faces enabled. |
* |
* But, as I tested on pineview(DevBLB derived), the rendering is |
* bad(you will find the color isn't samplered right in some |
* fragments). After checking, it seems that the texture layout is |
* wrong: making the width and height align of 4(although this |
* doesn't make much sense) will fix this issue and also broke some |
* others. Well, Bspec mentioned nothing about the layout alignment |
* and layout for NPOT cube map. I guess the Bspec just assume it's |
* a POT cube map. |
* |
* Thus, I guess we need do this for other platforms as well. |
*/ |
if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB && |
!is_power_of_two(firstImage->Height)) |
return false; |
state[I915_TEXREG_SS3] = ss3; /* SS3_NORMALIZED_COORDS */ |
state[I915_TEXREG_SS3] |= |
((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) | |
(translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) | |
(translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT)); |
minlod = MIN2(sampler->MinLod, tObj->_MaxLevel - tObj->BaseLevel); |
state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT); |
state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(minlod, 0.0, 11.0), 4) << |
SS3_MIN_LOD_SHIFT); |
} |
if (sampler->sRGBDecode == GL_DECODE_EXT && |
(_mesa_get_srgb_format_linear(firstImage->TexFormat) != |
firstImage->TexFormat)) { |
state[I915_TEXREG_SS2] |= SS2_REVERSE_GAMMA_ENABLE; |
} |
/* convert border color from float to ubyte */ |
CLAMPED_FLOAT_TO_UBYTE(border[0], sampler->BorderColor.f[0]); |
CLAMPED_FLOAT_TO_UBYTE(border[1], sampler->BorderColor.f[1]); |
CLAMPED_FLOAT_TO_UBYTE(border[2], sampler->BorderColor.f[2]); |
CLAMPED_FLOAT_TO_UBYTE(border[3], sampler->BorderColor.f[3]); |
if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) { |
/* GL specs that border color for depth textures is taken from the |
* R channel, while the hardware uses A. Spam R into all the channels |
* for safety. |
*/ |
state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[0], |
border[0], |
border[0], |
border[0]); |
} else { |
state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[3], |
border[0], |
border[1], |
border[2]); |
} |
I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), true); |
/* memcmp was already disabled, but definitely won't work as the |
* region might now change and that wouldn't be detected: |
*/ |
I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); |
#if 0 |
DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]); |
DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]); |
DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]); |
DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]); |
DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]); |
DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]); |
#endif |
return true; |
} |
void |
i915UpdateTextureState(struct intel_context *intel) |
{ |
bool ok = true; |
GLuint i; |
for (i = 0; i < I915_TEX_UNITS && ok; i++) { |
switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) { |
case TEXTURE_1D_BIT: |
case TEXTURE_2D_BIT: |
case TEXTURE_CUBE_BIT: |
case TEXTURE_3D_BIT: |
ok = i915_update_tex_unit(intel, i, SS3_NORMALIZED_COORDS); |
break; |
case TEXTURE_RECT_BIT: |
ok = i915_update_tex_unit(intel, i, 0); |
break; |
case 0:{ |
struct i915_context *i915 = i915_context(&intel->ctx); |
if (i915->state.active & I915_UPLOAD_TEX(i)) |
I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), false); |
if (i915->state.tex_buffer[i] != NULL) { |
drm_intel_bo_unreference(i915->state.tex_buffer[i]); |
i915->state.tex_buffer[i] = NULL; |
} |
break; |
} |
default: |
ok = false; |
break; |
} |
} |
FALLBACK(intel, I915_FALLBACK_TEXTURE, !ok); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/i915_vtbl.c |
---|
0,0 → 1,877 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/mtypes.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "main/colormac.h" |
#include "main/renderbuffer.h" |
#include "main/framebuffer.h" |
#include "tnl/tnl.h" |
#include "tnl/t_context.h" |
#include "tnl/t_vertex.h" |
#include "swrast_setup/swrast_setup.h" |
#include "intel_batchbuffer.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_tris.h" |
#include "intel_fbo.h" |
#include "intel_buffers.h" |
#include "i915_reg.h" |
#include "i915_context.h" |
static void |
i915_render_prevalidate(struct intel_context *intel) |
{ |
struct i915_context *i915 = i915_context(&intel->ctx); |
i915ValidateFragmentProgram(i915); |
} |
static void |
i915_render_start(struct intel_context *intel) |
{ |
intel_prepare_render(intel); |
} |
static void |
i915_reduced_primitive_state(struct intel_context *intel, GLenum rprim) |
{ |
struct i915_context *i915 = i915_context(&intel->ctx); |
GLuint st1 = i915->state.Stipple[I915_STPREG_ST1]; |
st1 &= ~ST1_ENABLE; |
switch (rprim) { |
case GL_QUADS: /* from RASTERIZE(GL_QUADS) in t_dd_tritemp.h */ |
case GL_TRIANGLES: |
if (intel->ctx.Polygon.StippleFlag && intel->hw_stipple) |
st1 |= ST1_ENABLE; |
break; |
case GL_LINES: |
case GL_POINTS: |
default: |
break; |
} |
i915->intel.reduced_primitive = rprim; |
if (st1 != i915->state.Stipple[I915_STPREG_ST1]) { |
INTEL_FIREVERTICES(intel); |
I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE); |
i915->state.Stipple[I915_STPREG_ST1] = st1; |
} |
} |
/* Pull apart the vertex format registers and figure out how large a |
* vertex is supposed to be. |
*/ |
static bool |
i915_check_vertex_size(struct intel_context *intel, GLuint expected) |
{ |
struct i915_context *i915 = i915_context(&intel->ctx); |
int lis2 = i915->state.Ctx[I915_CTXREG_LIS2]; |
int lis4 = i915->state.Ctx[I915_CTXREG_LIS4]; |
int i, sz = 0; |
switch (lis4 & S4_VFMT_XYZW_MASK) { |
case S4_VFMT_XY: |
sz = 2; |
break; |
case S4_VFMT_XYZ: |
sz = 3; |
break; |
case S4_VFMT_XYW: |
sz = 3; |
break; |
case S4_VFMT_XYZW: |
sz = 4; |
break; |
default: |
fprintf(stderr, "no xyzw specified\n"); |
return 0; |
} |
if (lis4 & S4_VFMT_SPEC_FOG) |
sz++; |
if (lis4 & S4_VFMT_COLOR) |
sz++; |
if (lis4 & S4_VFMT_DEPTH_OFFSET) |
sz++; |
if (lis4 & S4_VFMT_POINT_WIDTH) |
sz++; |
if (lis4 & S4_VFMT_FOG_PARAM) |
sz++; |
for (i = 0; i < 8; i++) { |
switch (lis2 & S2_TEXCOORD_FMT0_MASK) { |
case TEXCOORDFMT_2D: |
sz += 2; |
break; |
case TEXCOORDFMT_3D: |
sz += 3; |
break; |
case TEXCOORDFMT_4D: |
sz += 4; |
break; |
case TEXCOORDFMT_1D: |
sz += 1; |
break; |
case TEXCOORDFMT_2D_16: |
sz += 1; |
break; |
case TEXCOORDFMT_4D_16: |
sz += 2; |
break; |
case TEXCOORDFMT_NOT_PRESENT: |
break; |
default: |
fprintf(stderr, "bad texcoord fmt %d\n", i); |
return false; |
} |
lis2 >>= S2_TEXCOORD_FMT1_SHIFT; |
} |
if (sz != expected) |
fprintf(stderr, "vertex size mismatch %d/%d\n", sz, expected); |
return sz == expected; |
} |
static void |
i915_emit_invarient_state(struct intel_context *intel) |
{ |
BATCH_LOCALS; |
BEGIN_BATCH(17); |
OUT_BATCH(_3DSTATE_AA_CMD | |
AA_LINE_ECAAR_WIDTH_ENABLE | |
AA_LINE_ECAAR_WIDTH_1_0 | |
AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0); |
OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); |
OUT_BATCH(0); |
OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD); |
OUT_BATCH(0); |
OUT_BATCH(_3DSTATE_DFLT_Z_CMD); |
OUT_BATCH(0); |
/* Don't support texture crossbar yet */ |
OUT_BATCH(_3DSTATE_COORD_SET_BINDINGS | |
CSB_TCB(0, 0) | |
CSB_TCB(1, 1) | |
CSB_TCB(2, 2) | |
CSB_TCB(3, 3) | |
CSB_TCB(4, 4) | CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7)); |
/* Need to initialize this to zero. |
*/ |
OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | (0)); |
OUT_BATCH(0); |
/* XXX: Use this */ |
OUT_BATCH(_3DSTATE_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); |
OUT_BATCH(_3DSTATE_SCISSOR_RECT_0_CMD); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE); |
OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0); /* disable indirect state */ |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
#define emit(intel, state, size ) \ |
intel_batchbuffer_data(intel, state, size) |
static GLuint |
get_dirty(struct i915_hw_state *state) |
{ |
GLuint dirty; |
/* Workaround the multitex hang - if one texture unit state is |
* modified, emit all texture units. |
*/ |
dirty = state->active & ~state->emitted; |
if (dirty & I915_UPLOAD_TEX_ALL) |
state->emitted &= ~I915_UPLOAD_TEX_ALL; |
dirty = state->active & ~state->emitted; |
return dirty; |
} |
static GLuint |
get_state_size(struct i915_hw_state *state) |
{ |
GLuint dirty = get_dirty(state); |
GLuint i; |
GLuint sz = 0; |
if (dirty & I915_UPLOAD_INVARIENT) |
sz += 30 * 4; |
if (dirty & I915_UPLOAD_RASTER_RULES) |
sz += sizeof(state->RasterRules); |
if (dirty & I915_UPLOAD_CTX) |
sz += sizeof(state->Ctx); |
if (dirty & I915_UPLOAD_BLEND) |
sz += sizeof(state->Blend); |
if (dirty & I915_UPLOAD_BUFFERS) |
sz += sizeof(state->Buffer); |
if (dirty & I915_UPLOAD_STIPPLE) |
sz += sizeof(state->Stipple); |
if (dirty & I915_UPLOAD_TEX_ALL) { |
int nr = 0; |
for (i = 0; i < I915_TEX_UNITS; i++) |
if (dirty & I915_UPLOAD_TEX(i)) |
nr++; |
sz += (2 + nr * 3) * sizeof(GLuint) * 2; |
} |
if (dirty & I915_UPLOAD_CONSTANTS) |
sz += state->ConstantSize * sizeof(GLuint); |
if (dirty & I915_UPLOAD_PROGRAM) |
sz += state->ProgramSize * sizeof(GLuint); |
return sz; |
} |
/* Push the state into the sarea and/or texture memory. |
*/ |
static void |
i915_emit_state(struct intel_context *intel) |
{ |
struct i915_context *i915 = i915_context(&intel->ctx); |
struct i915_hw_state *state = &i915->state; |
int i, count, aper_count; |
GLuint dirty; |
drm_intel_bo *aper_array[3 + I915_TEX_UNITS]; |
GET_CURRENT_CONTEXT(ctx); |
BATCH_LOCALS; |
/* We don't hold the lock at this point, so want to make sure that |
* there won't be a buffer wrap between the state emits and the primitive |
* emit header. |
* |
* It might be better to talk about explicit places where |
* scheduling is allowed, rather than assume that it is whenever a |
* batchbuffer fills up. |
*/ |
intel_batchbuffer_require_space(intel, |
get_state_size(state) + |
INTEL_PRIM_EMIT_SIZE); |
count = 0; |
again: |
if (intel->batch.bo == NULL) { |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "i915 emit state"); |
assert(0); |
} |
aper_count = 0; |
dirty = get_dirty(state); |
aper_array[aper_count++] = intel->batch.bo; |
if (dirty & I915_UPLOAD_BUFFERS) { |
if (state->draw_region) |
aper_array[aper_count++] = state->draw_region->bo; |
if (state->depth_region) |
aper_array[aper_count++] = state->depth_region->bo; |
} |
if (dirty & I915_UPLOAD_TEX_ALL) { |
for (i = 0; i < I915_TEX_UNITS; i++) { |
if (dirty & I915_UPLOAD_TEX(i)) { |
if (state->tex_buffer[i]) { |
aper_array[aper_count++] = state->tex_buffer[i]; |
} |
} |
} |
} |
if (dri_bufmgr_check_aperture_space(aper_array, aper_count)) { |
if (count == 0) { |
count++; |
intel_batchbuffer_flush(intel); |
goto again; |
} else { |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "i915 emit state"); |
assert(0); |
} |
} |
/* work out list of buffers to emit */ |
/* Do this here as we may have flushed the batchbuffer above, |
* causing more state to be dirty! |
*/ |
dirty = get_dirty(state); |
state->emitted |= dirty; |
assert(get_dirty(state) == 0); |
if (INTEL_DEBUG & DEBUG_STATE) |
fprintf(stderr, "%s dirty: %x\n", __FUNCTION__, dirty); |
if (dirty & I915_UPLOAD_INVARIENT) { |
if (INTEL_DEBUG & DEBUG_STATE) |
fprintf(stderr, "I915_UPLOAD_INVARIENT:\n"); |
i915_emit_invarient_state(intel); |
} |
if (dirty & I915_UPLOAD_RASTER_RULES) { |
if (INTEL_DEBUG & DEBUG_STATE) |
fprintf(stderr, "I915_UPLOAD_RASTER_RULES:\n"); |
emit(intel, state->RasterRules, sizeof(state->RasterRules)); |
} |
if (dirty & I915_UPLOAD_CTX) { |
if (INTEL_DEBUG & DEBUG_STATE) |
fprintf(stderr, "I915_UPLOAD_CTX:\n"); |
emit(intel, state->Ctx, sizeof(state->Ctx)); |
} |
if (dirty & I915_UPLOAD_BLEND) { |
if (INTEL_DEBUG & DEBUG_STATE) |
fprintf(stderr, "I915_UPLOAD_BLEND:\n"); |
emit(intel, state->Blend, sizeof(state->Blend)); |
} |
if (dirty & I915_UPLOAD_BUFFERS) { |
GLuint count; |
if (INTEL_DEBUG & DEBUG_STATE) |
fprintf(stderr, "I915_UPLOAD_BUFFERS:\n"); |
count = 17; |
if (state->Buffer[I915_DESTREG_DRAWRECT0] != MI_NOOP) |
count++; |
BEGIN_BATCH(count); |
OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]); |
OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]); |
if (state->draw_region) { |
OUT_RELOC(state->draw_region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); |
} else { |
OUT_BATCH(0); |
} |
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]); |
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]); |
if (state->depth_region) { |
OUT_RELOC(state->depth_region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); |
} else { |
OUT_BATCH(0); |
} |
OUT_BATCH(state->Buffer[I915_DESTREG_DV0]); |
OUT_BATCH(state->Buffer[I915_DESTREG_DV1]); |
OUT_BATCH(state->Buffer[I915_DESTREG_SENABLE]); |
OUT_BATCH(state->Buffer[I915_DESTREG_SR0]); |
OUT_BATCH(state->Buffer[I915_DESTREG_SR1]); |
OUT_BATCH(state->Buffer[I915_DESTREG_SR2]); |
if (state->Buffer[I915_DESTREG_DRAWRECT0] != MI_NOOP) |
OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT0]); |
OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT1]); |
OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT2]); |
OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT3]); |
OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT4]); |
OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT5]); |
ADVANCE_BATCH(); |
} |
if (dirty & I915_UPLOAD_STIPPLE) { |
if (INTEL_DEBUG & DEBUG_STATE) |
fprintf(stderr, "I915_UPLOAD_STIPPLE:\n"); |
emit(intel, state->Stipple, sizeof(state->Stipple)); |
} |
/* Combine all the dirty texture state into a single command to |
* avoid lockups on I915 hardware. |
*/ |
if (dirty & I915_UPLOAD_TEX_ALL) { |
int nr = 0; |
GLuint unwind; |
for (i = 0; i < I915_TEX_UNITS; i++) |
if (dirty & I915_UPLOAD_TEX(i)) |
nr++; |
BEGIN_BATCH(2 + nr * 3); |
OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr)); |
OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); |
for (i = 0; i < I915_TEX_UNITS; i++) |
if (dirty & I915_UPLOAD_TEX(i)) { |
OUT_RELOC(state->tex_buffer[i], |
I915_GEM_DOMAIN_SAMPLER, 0, |
state->tex_offset[i]); |
OUT_BATCH(state->Tex[i][I915_TEXREG_MS3]); |
OUT_BATCH(state->Tex[i][I915_TEXREG_MS4]); |
} |
ADVANCE_BATCH(); |
unwind = intel->batch.used; |
BEGIN_BATCH(2 + nr * 3); |
OUT_BATCH(_3DSTATE_SAMPLER_STATE | (3 * nr)); |
OUT_BATCH((dirty & I915_UPLOAD_TEX_ALL) >> I915_UPLOAD_TEX_0_SHIFT); |
for (i = 0; i < I915_TEX_UNITS; i++) |
if (dirty & I915_UPLOAD_TEX(i)) { |
OUT_BATCH(state->Tex[i][I915_TEXREG_SS2]); |
OUT_BATCH(state->Tex[i][I915_TEXREG_SS3]); |
OUT_BATCH(state->Tex[i][I915_TEXREG_SS4]); |
} |
ADVANCE_BATCH(); |
if (i915->last_sampler && |
memcmp(intel->batch.map + i915->last_sampler, |
intel->batch.map + unwind, |
(2 + nr*3)*sizeof(int)) == 0) |
intel->batch.used = unwind; |
else |
i915->last_sampler = unwind; |
} |
if (dirty & I915_UPLOAD_CONSTANTS) { |
if (INTEL_DEBUG & DEBUG_STATE) |
fprintf(stderr, "I915_UPLOAD_CONSTANTS:\n"); |
emit(intel, state->Constant, state->ConstantSize * sizeof(GLuint)); |
} |
if (dirty & I915_UPLOAD_PROGRAM) { |
if (state->ProgramSize) { |
if (INTEL_DEBUG & DEBUG_STATE) |
fprintf(stderr, "I915_UPLOAD_PROGRAM:\n"); |
assert((state->Program[0] & 0x1ff) + 2 == state->ProgramSize); |
emit(intel, state->Program, state->ProgramSize * sizeof(GLuint)); |
if (INTEL_DEBUG & DEBUG_STATE) |
i915_disassemble_program(state->Program, state->ProgramSize); |
} |
} |
assert(get_dirty(state) == 0); |
} |
static void |
i915_destroy_context(struct intel_context *intel) |
{ |
GLuint i; |
struct i915_context *i915 = i915_context(&intel->ctx); |
intel_region_release(&i915->state.draw_region); |
intel_region_release(&i915->state.depth_region); |
for (i = 0; i < I915_TEX_UNITS; i++) { |
if (i915->state.tex_buffer[i] != NULL) { |
drm_intel_bo_unreference(i915->state.tex_buffer[i]); |
i915->state.tex_buffer[i] = NULL; |
} |
} |
_tnl_free_vertices(&intel->ctx); |
} |
void |
i915_set_buf_info_for_region(uint32_t *state, struct intel_region *region, |
uint32_t buffer_id) |
{ |
state[0] = _3DSTATE_BUF_INFO_CMD; |
state[1] = buffer_id; |
if (region != NULL) { |
state[1] |= BUF_3D_PITCH(region->pitch); |
if (region->tiling != I915_TILING_NONE) { |
state[1] |= BUF_3D_TILED_SURFACE; |
if (region->tiling == I915_TILING_Y) |
state[1] |= BUF_3D_TILE_WALK_Y; |
} |
} else { |
/* Fill in a default pitch, since 0 is invalid. We'll be |
* setting the buffer offset to 0 and not referencing the |
* buffer, so the pitch could really be any valid value. |
*/ |
state[1] |= BUF_3D_PITCH(4096); |
} |
} |
static uint32_t i915_render_target_format_for_mesa_format[MESA_FORMAT_COUNT] = |
{ |
[MESA_FORMAT_ARGB8888] = DV_PF_8888, |
[MESA_FORMAT_XRGB8888] = DV_PF_8888, |
[MESA_FORMAT_RGB565] = DV_PF_565 | DITHER_FULL_ALWAYS, |
[MESA_FORMAT_ARGB1555] = DV_PF_1555 | DITHER_FULL_ALWAYS, |
[MESA_FORMAT_ARGB4444] = DV_PF_4444 | DITHER_FULL_ALWAYS, |
}; |
static bool |
i915_render_target_supported(struct intel_context *intel, |
struct gl_renderbuffer *rb) |
{ |
gl_format format = rb->Format; |
if (format == MESA_FORMAT_S8_Z24 || |
format == MESA_FORMAT_X8_Z24 || |
format == MESA_FORMAT_Z16) { |
return true; |
} |
return i915_render_target_format_for_mesa_format[format] != 0; |
} |
static void |
i915_set_draw_region(struct intel_context *intel, |
struct intel_region *color_regions[], |
struct intel_region *depth_region, |
GLuint num_regions) |
{ |
struct i915_context *i915 = i915_context(&intel->ctx); |
struct gl_context *ctx = &intel->ctx; |
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
struct gl_renderbuffer *drb; |
struct intel_renderbuffer *idrb = NULL; |
GLuint value; |
struct i915_hw_state *state = &i915->state; |
uint32_t draw_x, draw_y, draw_offset; |
if (state->draw_region != color_regions[0]) { |
intel_region_reference(&state->draw_region, color_regions[0]); |
} |
if (state->depth_region != depth_region) { |
intel_region_reference(&state->depth_region, depth_region); |
} |
/* |
* Set stride/cpp values |
*/ |
i915_set_buf_info_for_region(&state->Buffer[I915_DESTREG_CBUFADDR0], |
color_regions[0], BUF_3D_ID_COLOR_BACK); |
i915_set_buf_info_for_region(&state->Buffer[I915_DESTREG_DBUFADDR0], |
depth_region, BUF_3D_ID_DEPTH); |
/* |
* Compute/set I915_DESTREG_DV1 value |
*/ |
value = (DSTORG_HORT_BIAS(0x8) | /* .5 */ |
DSTORG_VERT_BIAS(0x8) | /* .5 */ |
LOD_PRECLAMP_OGL | TEX_DEFAULT_COLOR_OGL); |
if (irb != NULL) { |
value |= i915_render_target_format_for_mesa_format[intel_rb_format(irb)]; |
} else { |
value |= DV_PF_8888; |
} |
/* This isn't quite safe, thus being hidden behind an option. When changing |
* the value of this bit, the pipeline needs to be MI_FLUSHed. And it |
* can only be set when a depth buffer is already defined. |
*/ |
if (intel->is_945 && intel->use_early_z && |
depth_region->tiling != I915_TILING_NONE) |
value |= CLASSIC_EARLY_DEPTH; |
if (depth_region && depth_region->cpp == 4) { |
value |= DEPTH_FRMT_24_FIXED_8_OTHER; |
} |
else { |
value |= DEPTH_FRMT_16_FIXED; |
} |
state->Buffer[I915_DESTREG_DV1] = value; |
drb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; |
if (!drb) |
drb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; |
if (drb) |
idrb = intel_renderbuffer(drb); |
/* We set up the drawing rectangle to be offset into the color |
* region's location in the miptree. If it doesn't match with |
* depth's offsets, we can't render to it. |
* |
* (Well, not actually true -- the hw grew a bit to let depth's |
* offset get forced to 0,0. We may want to use that if people are |
* hitting that case. Also, some configurations may be supportable |
* by tweaking the start offset of the buffers around, which we |
* can't do in general due to tiling) |
*/ |
FALLBACK(intel, I915_FALLBACK_DRAW_OFFSET, |
idrb && irb && (idrb->draw_x != irb->draw_x || |
idrb->draw_y != irb->draw_y)); |
if (irb) { |
draw_x = irb->draw_x; |
draw_y = irb->draw_y; |
} else if (idrb) { |
draw_x = idrb->draw_x; |
draw_y = idrb->draw_y; |
} else { |
draw_x = 0; |
draw_y = 0; |
} |
draw_offset = (draw_y << 16) | draw_x; |
FALLBACK(intel, I915_FALLBACK_DRAW_OFFSET, |
(ctx->DrawBuffer->Width + draw_x > 2048) || |
(ctx->DrawBuffer->Height + draw_y > 2048)); |
/* When changing drawing rectangle offset, an MI_FLUSH is first required. */ |
if (draw_offset != i915->last_draw_offset) { |
state->Buffer[I915_DESTREG_DRAWRECT0] = MI_FLUSH | INHIBIT_FLUSH_RENDER_CACHE; |
i915->last_draw_offset = draw_offset; |
} else |
state->Buffer[I915_DESTREG_DRAWRECT0] = MI_NOOP; |
state->Buffer[I915_DESTREG_DRAWRECT1] = _3DSTATE_DRAWRECT_INFO; |
state->Buffer[I915_DESTREG_DRAWRECT2] = 0; |
state->Buffer[I915_DESTREG_DRAWRECT3] = draw_offset; |
state->Buffer[I915_DESTREG_DRAWRECT4] = |
((ctx->DrawBuffer->Width + draw_x - 1) & 0xffff) | |
((ctx->DrawBuffer->Height + draw_y - 1) << 16); |
state->Buffer[I915_DESTREG_DRAWRECT5] = draw_offset; |
I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS); |
} |
static void |
i915_update_color_write_enable(struct i915_context *i915, bool enable) |
{ |
uint32_t dw = i915->state.Ctx[I915_CTXREG_LIS6]; |
if (enable) |
dw |= S6_COLOR_WRITE_ENABLE; |
else |
dw &= ~S6_COLOR_WRITE_ENABLE; |
if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) { |
I915_STATECHANGE(i915, I915_UPLOAD_CTX); |
i915->state.Ctx[I915_CTXREG_LIS6] = dw; |
} |
} |
/** |
* Update the hardware state for drawing into a window or framebuffer object. |
* |
* Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other |
* places within the driver. |
* |
* Basically, this needs to be called any time the current framebuffer |
* changes, the renderbuffers change, or we need to draw into different |
* color buffers. |
*/ |
static void |
i915_update_draw_buffer(struct intel_context *intel) |
{ |
struct i915_context *i915 = (struct i915_context *)intel; |
struct gl_context *ctx = &intel->ctx; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct intel_region *colorRegion = NULL, *depthRegion = NULL; |
struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL; |
if (!fb) { |
/* this can happen during the initial context initialization */ |
return; |
} |
irbDepth = intel_get_renderbuffer(fb, BUFFER_DEPTH); |
irbStencil = intel_get_renderbuffer(fb, BUFFER_STENCIL); |
/* Do this here, not core Mesa, since this function is called from |
* many places within the driver. |
*/ |
if (ctx->NewState & _NEW_BUFFERS) { |
/* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ |
_mesa_update_framebuffer(ctx); |
/* this updates the DrawBuffer's Width/Height if it's a FBO */ |
_mesa_update_draw_buffer_bounds(ctx); |
} |
if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { |
/* this may occur when we're called by glBindFrameBuffer() during |
* the process of someone setting up renderbuffers, etc. |
*/ |
/*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/ |
return; |
} |
/* How many color buffers are we drawing into? |
* |
* If there is more than one drawbuffer (GL_FRONT_AND_BACK), or the |
* drawbuffers are too big, we have to fallback to software. |
*/ |
if ((fb->Width > ctx->Const.MaxRenderbufferSize) |
|| (fb->Height > ctx->Const.MaxRenderbufferSize)) { |
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, true); |
} else if (fb->_NumColorDrawBuffers > 1) { |
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, true); |
} else { |
struct intel_renderbuffer *irb; |
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); |
colorRegion = (irb && irb->mt) ? irb->mt->region : NULL; |
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, false); |
} |
/* Check for depth fallback. */ |
if (irbDepth && irbDepth->mt) { |
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, false); |
depthRegion = irbDepth->mt->region; |
} else if (irbDepth && !irbDepth->mt) { |
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, true); |
depthRegion = NULL; |
} else { /* !irbDepth */ |
/* No fallback is needed because there is no depth buffer. */ |
FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, false); |
depthRegion = NULL; |
} |
/* Check for stencil fallback. */ |
if (irbStencil && irbStencil->mt) { |
assert(intel_rb_format(irbStencil) == MESA_FORMAT_S8_Z24); |
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, false); |
} else if (irbStencil && !irbStencil->mt) { |
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, true); |
} else { /* !irbStencil */ |
/* No fallback is needed because there is no stencil buffer. */ |
FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, false); |
} |
/* If we have a (packed) stencil buffer attached but no depth buffer, |
* we still need to set up the shared depth/stencil state so we can use it. |
*/ |
if (depthRegion == NULL && irbStencil && irbStencil->mt |
&& intel_rb_format(irbStencil) == MESA_FORMAT_S8_Z24) { |
depthRegion = irbStencil->mt->region; |
} |
/* |
* Update depth and stencil test state |
*/ |
ctx->Driver.Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test); |
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); |
i915_update_color_write_enable(i915, colorRegion != NULL); |
intel->vtbl.set_draw_region(intel, &colorRegion, depthRegion, |
fb->_NumColorDrawBuffers); |
intel->NewGLState |= _NEW_BUFFERS; |
/* update viewport since it depends on window size */ |
intelCalcViewport(ctx); |
/* Set state we know depends on drawable parameters: |
*/ |
ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, |
ctx->Scissor.Width, ctx->Scissor.Height); |
ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far); |
/* Update culling direction which changes depending on the |
* orientation of the buffer: |
*/ |
ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); |
} |
static void |
i915_new_batch(struct intel_context *intel) |
{ |
struct i915_context *i915 = i915_context(&intel->ctx); |
/* Mark all state as needing to be emitted when starting a new batchbuffer. |
* Using hardware contexts would be an alternative, but they have some |
* difficulties associated with them (physical address requirements). |
*/ |
i915->state.emitted = 0; |
i915->last_draw_offset = 0; |
i915->last_sampler = 0; |
i915->current_vb_bo = NULL; |
i915->current_vertex_size = 0; |
} |
static void |
i915_assert_not_dirty( struct intel_context *intel ) |
{ |
struct i915_context *i915 = i915_context(&intel->ctx); |
GLuint dirty = get_dirty(&i915->state); |
assert(!dirty); |
(void) dirty; |
} |
static void |
i915_invalidate_state(struct intel_context *intel, GLuint new_state) |
{ |
struct gl_context *ctx = &intel->ctx; |
_swsetup_InvalidateState(ctx, new_state); |
_tnl_InvalidateState(ctx, new_state); |
_tnl_invalidate_vertex_state(ctx, new_state); |
} |
void |
i915InitVtbl(struct i915_context *i915) |
{ |
i915->intel.vtbl.check_vertex_size = i915_check_vertex_size; |
i915->intel.vtbl.destroy = i915_destroy_context; |
i915->intel.vtbl.emit_state = i915_emit_state; |
i915->intel.vtbl.new_batch = i915_new_batch; |
i915->intel.vtbl.reduced_primitive_state = i915_reduced_primitive_state; |
i915->intel.vtbl.render_start = i915_render_start; |
i915->intel.vtbl.render_prevalidate = i915_render_prevalidate; |
i915->intel.vtbl.set_draw_region = i915_set_draw_region; |
i915->intel.vtbl.update_draw_buffer = i915_update_draw_buffer; |
i915->intel.vtbl.update_texture_state = i915UpdateTextureState; |
i915->intel.vtbl.assert_not_dirty = i915_assert_not_dirty; |
i915->intel.vtbl.finish_batch = intel_finish_vb; |
i915->intel.vtbl.invalidate_state = i915_invalidate_state; |
i915->intel.vtbl.render_target_supported = i915_render_target_supported; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_batchbuffer.c |
---|
0,0 → 1,265 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#include "intel_context.h" |
#include "intel_batchbuffer.h" |
#include "intel_buffer_objects.h" |
#include "intel_reg.h" |
#include "intel_bufmgr.h" |
#include "intel_buffers.h" |
static void |
intel_batchbuffer_reset(struct intel_context *intel); |
void |
intel_batchbuffer_init(struct intel_context *intel) |
{ |
intel_batchbuffer_reset(intel); |
intel->batch.cpu_map = malloc(intel->maxBatchSize); |
intel->batch.map = intel->batch.cpu_map; |
} |
static void |
intel_batchbuffer_reset(struct intel_context *intel) |
{ |
if (intel->batch.last_bo != NULL) { |
drm_intel_bo_unreference(intel->batch.last_bo); |
intel->batch.last_bo = NULL; |
} |
intel->batch.last_bo = intel->batch.bo; |
intel->batch.bo = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer", |
intel->maxBatchSize, 4096); |
intel->batch.reserved_space = BATCH_RESERVED; |
intel->batch.used = 0; |
} |
void |
intel_batchbuffer_free(struct intel_context *intel) |
{ |
free(intel->batch.cpu_map); |
drm_intel_bo_unreference(intel->batch.last_bo); |
drm_intel_bo_unreference(intel->batch.bo); |
} |
static void |
do_batch_dump(struct intel_context *intel) |
{ |
struct drm_intel_decode *decode; |
struct intel_batchbuffer *batch = &intel->batch; |
int ret; |
decode = drm_intel_decode_context_alloc(intel->intelScreen->deviceID); |
if (!decode) |
return; |
ret = drm_intel_bo_map(batch->bo, false); |
if (ret == 0) { |
drm_intel_decode_set_batch_pointer(decode, |
batch->bo->virtual, |
batch->bo->offset, |
batch->used); |
} else { |
fprintf(stderr, |
"WARNING: failed to map batchbuffer (%s), " |
"dumping uploaded data instead.\n", strerror(ret)); |
drm_intel_decode_set_batch_pointer(decode, |
batch->map, |
batch->bo->offset, |
batch->used); |
} |
drm_intel_decode(decode); |
drm_intel_decode_context_free(decode); |
if (ret == 0) { |
drm_intel_bo_unmap(batch->bo); |
if (intel->vtbl.debug_batch != NULL) |
intel->vtbl.debug_batch(intel); |
} |
} |
/* TODO: Push this whole function into bufmgr. |
*/ |
static int |
do_flush_locked(struct intel_context *intel) |
{ |
struct intel_batchbuffer *batch = &intel->batch; |
int ret = 0; |
ret = drm_intel_bo_subdata(batch->bo, 0, 4*batch->used, batch->map); |
if (!intel->intelScreen->no_hw) { |
if (ret == 0) { |
if (unlikely(INTEL_DEBUG & DEBUG_AUB) && intel->vtbl.annotate_aub) |
intel->vtbl.annotate_aub(intel); |
ret = drm_intel_bo_mrb_exec(batch->bo, 4 * batch->used, NULL, 0, 0, |
I915_EXEC_RENDER); |
} |
} |
if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) |
do_batch_dump(intel); |
if (ret != 0) { |
fprintf(stderr, "intel_do_flush_locked failed: %s\n", strerror(-ret)); |
exit(1); |
} |
intel->vtbl.new_batch(intel); |
return ret; |
} |
int |
_intel_batchbuffer_flush(struct intel_context *intel, |
const char *file, int line) |
{ |
int ret; |
if (intel->batch.used == 0) |
return 0; |
if (intel->first_post_swapbuffers_batch == NULL) { |
intel->first_post_swapbuffers_batch = intel->batch.bo; |
drm_intel_bo_reference(intel->first_post_swapbuffers_batch); |
} |
if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) |
fprintf(stderr, "%s:%d: Batchbuffer flush with %db used\n", file, line, |
4*intel->batch.used); |
intel->batch.reserved_space = 0; |
if (intel->vtbl.finish_batch) |
intel->vtbl.finish_batch(intel); |
/* Mark the end of the buffer. */ |
intel_batchbuffer_emit_dword(intel, MI_BATCH_BUFFER_END); |
if (intel->batch.used & 1) { |
/* Round batchbuffer usage to 2 DWORDs. */ |
intel_batchbuffer_emit_dword(intel, MI_NOOP); |
} |
intel_upload_finish(intel); |
/* Check that we didn't just wrap our batchbuffer at a bad time. */ |
assert(!intel->no_batch_wrap); |
ret = do_flush_locked(intel); |
if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) { |
fprintf(stderr, "waiting for idle\n"); |
drm_intel_bo_wait_rendering(intel->batch.bo); |
} |
/* Reset the buffer: |
*/ |
intel_batchbuffer_reset(intel); |
return ret; |
} |
/* This is the only way buffers get added to the validate list. |
*/ |
bool |
intel_batchbuffer_emit_reloc(struct intel_context *intel, |
drm_intel_bo *buffer, |
uint32_t read_domains, uint32_t write_domain, |
uint32_t delta) |
{ |
int ret; |
ret = drm_intel_bo_emit_reloc(intel->batch.bo, 4*intel->batch.used, |
buffer, delta, |
read_domains, write_domain); |
assert(ret == 0); |
(void)ret; |
/* |
* Using the old buffer offset, write in what the right data would be, in case |
* the buffer doesn't move and we can short-circuit the relocation processing |
* in the kernel |
*/ |
intel_batchbuffer_emit_dword(intel, buffer->offset + delta); |
return true; |
} |
bool |
intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel, |
drm_intel_bo *buffer, |
uint32_t read_domains, |
uint32_t write_domain, |
uint32_t delta) |
{ |
int ret; |
ret = drm_intel_bo_emit_reloc_fence(intel->batch.bo, 4*intel->batch.used, |
buffer, delta, |
read_domains, write_domain); |
assert(ret == 0); |
(void)ret; |
/* |
* Using the old buffer offset, write in what the right data would |
* be, in case the buffer doesn't move and we can short-circuit the |
* relocation processing in the kernel |
*/ |
intel_batchbuffer_emit_dword(intel, buffer->offset + delta); |
return true; |
} |
void |
intel_batchbuffer_data(struct intel_context *intel, |
const void *data, GLuint bytes) |
{ |
assert((bytes & 3) == 0); |
intel_batchbuffer_require_space(intel, bytes); |
__memcpy(intel->batch.map + intel->batch.used, data, bytes); |
intel->batch.used += bytes >> 2; |
} |
/* Emit a pipelined flush to either flush render and texture cache for |
* reading from a FBO-drawn texture, or flush so that frontbuffer |
* render appears on the screen in DRI1. |
* |
* This is also used for the always_flush_cache driconf debug option. |
*/ |
void |
intel_batchbuffer_emit_mi_flush(struct intel_context *intel) |
{ |
BEGIN_BATCH(1); |
OUT_BATCH(MI_FLUSH); |
ADVANCE_BATCH(); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_batchbuffer.h |
---|
0,0 → 1,157 |
#ifndef INTEL_BATCHBUFFER_H |
#define INTEL_BATCHBUFFER_H |
#include "main/mtypes.h" |
#include "intel_context.h" |
#include "intel_bufmgr.h" |
#include "intel_reg.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
/** |
* Number of bytes to reserve for commands necessary to complete a batch. |
* |
* This includes: |
* - MI_BATCHBUFFER_END (4 bytes) |
* - Optional MI_NOOP for ensuring the batch length is qword aligned (4 bytes) |
* - Any state emitted by vtbl->finish_batch(): |
* - Gen4-5 record ending occlusion query values (4 * 4 = 16 bytes) |
*/ |
#define BATCH_RESERVED 24 |
struct intel_batchbuffer; |
void intel_batchbuffer_init(struct intel_context *intel); |
void intel_batchbuffer_free(struct intel_context *intel); |
int _intel_batchbuffer_flush(struct intel_context *intel, |
const char *file, int line); |
#define intel_batchbuffer_flush(intel) \ |
_intel_batchbuffer_flush(intel, __FILE__, __LINE__) |
/* Unlike bmBufferData, this currently requires the buffer be mapped. |
* Consider it a convenience function wrapping multple |
* intel_buffer_dword() calls. |
*/ |
void intel_batchbuffer_data(struct intel_context *intel, |
const void *data, GLuint bytes); |
bool intel_batchbuffer_emit_reloc(struct intel_context *intel, |
drm_intel_bo *buffer, |
uint32_t read_domains, |
uint32_t write_domain, |
uint32_t offset); |
bool intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel, |
drm_intel_bo *buffer, |
uint32_t read_domains, |
uint32_t write_domain, |
uint32_t offset); |
void intel_batchbuffer_emit_mi_flush(struct intel_context *intel); |
static INLINE uint32_t float_as_int(float f) |
{ |
union { |
float f; |
uint32_t d; |
} fi; |
fi.f = f; |
return fi.d; |
} |
/* Inline functions - might actually be better off with these |
* non-inlined. Certainly better off switching all command packets to |
* be passed as structs rather than dwords, but that's a little bit of |
* work... |
*/ |
static INLINE unsigned |
intel_batchbuffer_space(struct intel_context *intel) |
{ |
return (intel->batch.bo->size - intel->batch.reserved_space) |
- intel->batch.used*4; |
} |
static INLINE void |
intel_batchbuffer_emit_dword(struct intel_context *intel, GLuint dword) |
{ |
#ifdef DEBUG |
assert(intel_batchbuffer_space(intel) >= 4); |
#endif |
intel->batch.map[intel->batch.used++] = dword; |
} |
static INLINE void |
intel_batchbuffer_emit_float(struct intel_context *intel, float f) |
{ |
intel_batchbuffer_emit_dword(intel, float_as_int(f)); |
} |
static INLINE void |
intel_batchbuffer_require_space(struct intel_context *intel, |
GLuint sz) |
{ |
#ifdef DEBUG |
assert(sz < intel->maxBatchSize - BATCH_RESERVED); |
#endif |
if (intel_batchbuffer_space(intel) < sz) |
intel_batchbuffer_flush(intel); |
} |
static INLINE void |
intel_batchbuffer_begin(struct intel_context *intel, int n) |
{ |
intel_batchbuffer_require_space(intel, n * 4); |
intel->batch.emit = intel->batch.used; |
#ifdef DEBUG |
intel->batch.total = n; |
#endif |
} |
static INLINE void |
intel_batchbuffer_advance(struct intel_context *intel) |
{ |
#ifdef DEBUG |
struct intel_batchbuffer *batch = &intel->batch; |
unsigned int _n = batch->used - batch->emit; |
assert(batch->total != 0); |
if (_n != batch->total) { |
fprintf(stderr, "ADVANCE_BATCH: %d of %d dwords emitted\n", |
_n, batch->total); |
abort(); |
} |
batch->total = 0; |
#endif |
} |
/* Here are the crusty old macros, to be removed: |
*/ |
#define BATCH_LOCALS |
#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel, n) |
#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel, d) |
#define OUT_BATCH_F(f) intel_batchbuffer_emit_float(intel,f) |
#define OUT_RELOC(buf, read_domains, write_domain, delta) do { \ |
intel_batchbuffer_emit_reloc(intel, buf, \ |
read_domains, write_domain, delta); \ |
} while (0) |
#define OUT_RELOC_FENCED(buf, read_domains, write_domain, delta) do { \ |
intel_batchbuffer_emit_reloc_fenced(intel, buf, \ |
read_domains, write_domain, delta); \ |
} while (0) |
#define ADVANCE_BATCH() intel_batchbuffer_advance(intel); |
#define CACHED_BATCH() intel_batchbuffer_cached_advance(intel); |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_blit.c |
---|
0,0 → 1,690 |
/************************************************************************** |
* |
* 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 "main/mtypes.h" |
#include "main/context.h" |
#include "main/enums.h" |
#include "main/colormac.h" |
#include "main/fbobject.h" |
#include "intel_blit.h" |
#include "intel_buffers.h" |
#include "intel_context.h" |
#include "intel_fbo.h" |
#include "intel_reg.h" |
#include "intel_regions.h" |
#include "intel_batchbuffer.h" |
#include "intel_mipmap_tree.h" |
#define FILE_DEBUG_FLAG DEBUG_BLIT |
static void |
intel_miptree_set_alpha_to_one(struct intel_context *intel, |
struct intel_mipmap_tree *mt, |
int x, int y, int width, int height); |
static GLuint translate_raster_op(GLenum logicop) |
{ |
switch(logicop) { |
case GL_CLEAR: return 0x00; |
case GL_AND: return 0x88; |
case GL_AND_REVERSE: return 0x44; |
case GL_COPY: return 0xCC; |
case GL_AND_INVERTED: return 0x22; |
case GL_NOOP: return 0xAA; |
case GL_XOR: return 0x66; |
case GL_OR: return 0xEE; |
case GL_NOR: return 0x11; |
case GL_EQUIV: return 0x99; |
case GL_INVERT: return 0x55; |
case GL_OR_REVERSE: return 0xDD; |
case GL_COPY_INVERTED: return 0x33; |
case GL_OR_INVERTED: return 0xBB; |
case GL_NAND: return 0x77; |
case GL_SET: return 0xFF; |
default: return 0; |
} |
} |
static uint32_t |
br13_for_cpp(int cpp) |
{ |
switch (cpp) { |
case 4: |
return BR13_8888; |
break; |
case 2: |
return BR13_565; |
break; |
case 1: |
return BR13_8; |
break; |
default: |
assert(0); |
return 0; |
} |
} |
/** |
* Implements a rectangular block transfer (blit) of pixels between two |
* miptrees. |
* |
* Our blitter can operate on 1, 2, or 4-byte-per-pixel data, with generous, |
* but limited, pitches and sizes allowed. |
* |
* The src/dst coordinates are relative to the given level/slice of the |
* miptree. |
* |
* If @src_flip or @dst_flip is set, then the rectangle within that miptree |
* will be inverted (including scanline order) when copying. This is common |
* in GL when copying between window system and user-created |
* renderbuffers/textures. |
*/ |
bool |
intel_miptree_blit(struct intel_context *intel, |
struct intel_mipmap_tree *src_mt, |
int src_level, int src_slice, |
uint32_t src_x, uint32_t src_y, bool src_flip, |
struct intel_mipmap_tree *dst_mt, |
int dst_level, int dst_slice, |
uint32_t dst_x, uint32_t dst_y, bool dst_flip, |
uint32_t width, uint32_t height, |
GLenum logicop) |
{ |
/* No sRGB decode or encode is done by the hardware blitter, which is |
* consistent with what we want in the callers (glCopyTexSubImage(), |
* glBlitFramebuffer(), texture validation, etc.). |
*/ |
gl_format src_format = _mesa_get_srgb_format_linear(src_mt->format); |
gl_format dst_format = _mesa_get_srgb_format_linear(dst_mt->format); |
/* The blitter doesn't support doing any format conversions. We do also |
* support blitting ARGB8888 to XRGB8888 (trivial, the values dropped into |
* the X channel don't matter), and XRGB8888 to ARGB8888 by setting the A |
* channel to 1.0 at the end. |
*/ |
if (src_format != dst_format && |
((src_format != MESA_FORMAT_ARGB8888 && |
src_format != MESA_FORMAT_XRGB8888) || |
(dst_format != MESA_FORMAT_ARGB8888 && |
dst_format != MESA_FORMAT_XRGB8888))) { |
perf_debug("%s: Can't use hardware blitter from %s to %s, " |
"falling back.\n", __FUNCTION__, |
_mesa_get_format_name(src_format), |
_mesa_get_format_name(dst_format)); |
return false; |
} |
/* According to the Ivy Bridge PRM, Vol1 Part4, section 1.2.1.2 (Graphics |
* Data Size Limitations): |
* |
* The BLT engine is capable of transferring very large quantities of |
* graphics data. Any graphics data read from and written to the |
* destination is permitted to represent a number of pixels that |
* occupies up to 65,536 scan lines and up to 32,768 bytes per scan line |
* at the destination. The maximum number of pixels that may be |
* represented per scan line’s worth of graphics data depends on the |
* color depth. |
* |
* Furthermore, intelEmitCopyBlit (which is called below) uses a signed |
* 16-bit integer to represent buffer pitch, so it can only handle buffer |
* pitches < 32k. |
* |
* As a result of these two limitations, we can only use the blitter to do |
* this copy when the region's pitch is less than 32k. |
*/ |
if (src_mt->region->pitch > 32768 || |
dst_mt->region->pitch > 32768) { |
perf_debug("Falling back due to >32k pitch\n"); |
return false; |
} |
if (src_flip) |
src_y = src_mt->level[src_level].height - src_y - height; |
if (dst_flip) |
dst_y = dst_mt->level[dst_level].height - dst_y - height; |
int src_pitch = src_mt->region->pitch; |
if (src_flip != dst_flip) |
src_pitch = -src_pitch; |
uint32_t src_image_x, src_image_y; |
intel_miptree_get_image_offset(src_mt, src_level, src_slice, |
&src_image_x, &src_image_y); |
src_x += src_image_x; |
src_y += src_image_y; |
uint32_t dst_image_x, dst_image_y; |
intel_miptree_get_image_offset(dst_mt, dst_level, dst_slice, |
&dst_image_x, &dst_image_y); |
dst_x += dst_image_x; |
dst_y += dst_image_y; |
if (!intelEmitCopyBlit(intel, |
src_mt->cpp, |
src_pitch, |
src_mt->region->bo, src_mt->offset, |
src_mt->region->tiling, |
dst_mt->region->pitch, |
dst_mt->region->bo, dst_mt->offset, |
dst_mt->region->tiling, |
src_x, src_y, |
dst_x, dst_y, |
width, height, |
logicop)) { |
return false; |
} |
if (src_mt->format == MESA_FORMAT_XRGB8888 && |
dst_mt->format == MESA_FORMAT_ARGB8888) { |
intel_miptree_set_alpha_to_one(intel, dst_mt, |
dst_x, dst_y, |
width, height); |
} |
return true; |
} |
/* Copy BitBlt |
*/ |
bool |
intelEmitCopyBlit(struct intel_context *intel, |
GLuint cpp, |
GLshort src_pitch, |
drm_intel_bo *src_buffer, |
GLuint src_offset, |
uint32_t src_tiling, |
GLshort dst_pitch, |
drm_intel_bo *dst_buffer, |
GLuint dst_offset, |
uint32_t dst_tiling, |
GLshort src_x, GLshort src_y, |
GLshort dst_x, GLshort dst_y, |
GLshort w, GLshort h, |
GLenum logic_op) |
{ |
GLuint CMD, BR13, pass = 0; |
int dst_y2 = dst_y + h; |
int dst_x2 = dst_x + w; |
drm_intel_bo *aper_array[3]; |
bool dst_y_tiled = dst_tiling == I915_TILING_Y; |
bool src_y_tiled = src_tiling == I915_TILING_Y; |
BATCH_LOCALS; |
if (dst_tiling != I915_TILING_NONE) { |
if (dst_offset & 4095) |
return false; |
} |
if (src_tiling != I915_TILING_NONE) { |
if (src_offset & 4095) |
return false; |
} |
if (dst_y_tiled || src_y_tiled) |
return false; |
/* do space check before going any further */ |
do { |
aper_array[0] = intel->batch.bo; |
aper_array[1] = dst_buffer; |
aper_array[2] = src_buffer; |
if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) { |
intel_batchbuffer_flush(intel); |
pass++; |
} else |
break; |
} while (pass < 2); |
if (pass >= 2) |
return false; |
intel_batchbuffer_require_space(intel, 8 * 4); |
DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", |
__FUNCTION__, |
src_buffer, src_pitch, src_offset, src_x, src_y, |
dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h); |
/* Blit pitch must be dword-aligned. Otherwise, the hardware appears to drop |
* the low bits. |
*/ |
if (src_pitch % 4 != 0 || dst_pitch % 4 != 0) |
return false; |
/* For big formats (such as floating point), do the copy using 16 or 32bpp |
* and multiply the coordinates. |
*/ |
if (cpp > 4) { |
if (cpp % 4 == 2) { |
dst_x *= cpp / 2; |
dst_x2 *= cpp / 2; |
src_x *= cpp / 2; |
cpp = 2; |
} else { |
assert(cpp % 4 == 0); |
dst_x *= cpp / 4; |
dst_x2 *= cpp / 4; |
src_x *= cpp / 4; |
cpp = 4; |
} |
} |
BR13 = br13_for_cpp(cpp) | translate_raster_op(logic_op) << 16; |
switch (cpp) { |
case 1: |
case 2: |
CMD = XY_SRC_COPY_BLT_CMD; |
break; |
case 4: |
CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; |
break; |
default: |
return false; |
} |
if (dst_y2 <= dst_y || dst_x2 <= dst_x) { |
return true; |
} |
assert(dst_x < dst_x2); |
assert(dst_y < dst_y2); |
BEGIN_BATCH(8); |
OUT_BATCH(CMD | (8 - 2)); |
OUT_BATCH(BR13 | (uint16_t)dst_pitch); |
OUT_BATCH((dst_y << 16) | dst_x); |
OUT_BATCH((dst_y2 << 16) | dst_x2); |
OUT_RELOC_FENCED(dst_buffer, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
dst_offset); |
OUT_BATCH((src_y << 16) | src_x); |
OUT_BATCH((uint16_t)src_pitch); |
OUT_RELOC_FENCED(src_buffer, |
I915_GEM_DOMAIN_RENDER, 0, |
src_offset); |
ADVANCE_BATCH(); |
intel_batchbuffer_emit_mi_flush(intel); |
return true; |
} |
/** |
* Use blitting to clear the renderbuffers named by 'flags'. |
* Note: we can't use the ctx->DrawBuffer->_ColorDrawBufferIndexes field |
* since that might include software renderbuffers or renderbuffers |
* which we're clearing with triangles. |
* \param mask bitmask of BUFFER_BIT_* values indicating buffers to clear |
*/ |
GLbitfield |
intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
GLuint clear_depth_value, clear_depth_mask; |
GLint cx, cy, cw, ch; |
GLbitfield fail_mask = 0; |
BATCH_LOCALS; |
/* Note: we don't use this function on Gen7+ hardware, so we can safely |
* ignore fast color clear issues. |
*/ |
assert(intel->gen < 7); |
/* |
* Compute values for clearing the buffers. |
*/ |
clear_depth_value = 0; |
clear_depth_mask = 0; |
if (mask & BUFFER_BIT_DEPTH) { |
clear_depth_value = (GLuint) (fb->_DepthMax * ctx->Depth.Clear); |
clear_depth_mask = XY_BLT_WRITE_RGB; |
} |
if (mask & BUFFER_BIT_STENCIL) { |
clear_depth_value |= (ctx->Stencil.Clear & 0xff) << 24; |
clear_depth_mask |= XY_BLT_WRITE_ALPHA; |
} |
cx = fb->_Xmin; |
if (_mesa_is_winsys_fbo(fb)) |
cy = ctx->DrawBuffer->Height - fb->_Ymax; |
else |
cy = fb->_Ymin; |
cw = fb->_Xmax - fb->_Xmin; |
ch = fb->_Ymax - fb->_Ymin; |
if (cw == 0 || ch == 0) |
return 0; |
/* Loop over all renderbuffers */ |
mask &= (1 << BUFFER_COUNT) - 1; |
while (mask) { |
GLuint buf = ffs(mask) - 1; |
bool is_depth_stencil = buf == BUFFER_DEPTH || buf == BUFFER_STENCIL; |
struct intel_renderbuffer *irb; |
int x1, y1, x2, y2; |
uint32_t clear_val; |
uint32_t BR13, CMD; |
struct intel_region *region; |
int pitch, cpp; |
drm_intel_bo *aper_array[2]; |
mask &= ~(1 << buf); |
irb = intel_get_renderbuffer(fb, buf); |
if (irb && irb->mt) { |
region = irb->mt->region; |
assert(region); |
assert(region->bo); |
} else { |
fail_mask |= 1 << buf; |
continue; |
} |
/* OK, clear this renderbuffer */ |
x1 = cx + irb->draw_x; |
y1 = cy + irb->draw_y; |
x2 = cx + cw + irb->draw_x; |
y2 = cy + ch + irb->draw_y; |
pitch = region->pitch; |
cpp = region->cpp; |
DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n", |
__FUNCTION__, |
region->bo, pitch, |
x1, y1, x2 - x1, y2 - y1); |
BR13 = 0xf0 << 16; |
CMD = XY_COLOR_BLT_CMD; |
/* Setup the blit command */ |
if (cpp == 4) { |
if (is_depth_stencil) { |
CMD |= clear_depth_mask; |
} else { |
/* clearing RGBA */ |
CMD |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; |
} |
} |
assert(region->tiling != I915_TILING_Y); |
BR13 |= pitch; |
if (is_depth_stencil) { |
clear_val = clear_depth_value; |
} else { |
uint8_t clear[4]; |
GLfloat *color = ctx->Color.ClearColor.f; |
_mesa_unclamped_float_rgba_to_ubyte(clear, color); |
switch (intel_rb_format(irb)) { |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_XRGB8888: |
clear_val = PACK_COLOR_8888(clear[3], clear[0], |
clear[1], clear[2]); |
break; |
case MESA_FORMAT_RGB565: |
clear_val = PACK_COLOR_565(clear[0], clear[1], clear[2]); |
break; |
case MESA_FORMAT_ARGB4444: |
clear_val = PACK_COLOR_4444(clear[3], clear[0], |
clear[1], clear[2]); |
break; |
case MESA_FORMAT_ARGB1555: |
clear_val = PACK_COLOR_1555(clear[3], clear[0], |
clear[1], clear[2]); |
break; |
case MESA_FORMAT_A8: |
clear_val = PACK_COLOR_8888(clear[3], clear[3], |
clear[3], clear[3]); |
break; |
default: |
fail_mask |= 1 << buf; |
continue; |
} |
} |
BR13 |= br13_for_cpp(cpp); |
assert(x1 < x2); |
assert(y1 < y2); |
/* do space check before going any further */ |
aper_array[0] = intel->batch.bo; |
aper_array[1] = region->bo; |
if (drm_intel_bufmgr_check_aperture_space(aper_array, |
ARRAY_SIZE(aper_array)) != 0) { |
intel_batchbuffer_flush(intel); |
} |
BEGIN_BATCH(6); |
OUT_BATCH(CMD | (6 - 2)); |
OUT_BATCH(BR13); |
OUT_BATCH((y1 << 16) | x1); |
OUT_BATCH((y2 << 16) | x2); |
OUT_RELOC_FENCED(region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
0); |
OUT_BATCH(clear_val); |
ADVANCE_BATCH(); |
if (intel->always_flush_cache) |
intel_batchbuffer_emit_mi_flush(intel); |
if (buf == BUFFER_DEPTH || buf == BUFFER_STENCIL) |
mask &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); |
} |
return fail_mask; |
} |
bool |
intelEmitImmediateColorExpandBlit(struct intel_context *intel, |
GLuint cpp, |
GLubyte *src_bits, GLuint src_size, |
GLuint fg_color, |
GLshort dst_pitch, |
drm_intel_bo *dst_buffer, |
GLuint dst_offset, |
uint32_t dst_tiling, |
GLshort x, GLshort y, |
GLshort w, GLshort h, |
GLenum logic_op) |
{ |
int dwords = ALIGN(src_size, 8) / 4; |
uint32_t opcode, br13, blit_cmd; |
if (dst_tiling != I915_TILING_NONE) { |
if (dst_offset & 4095) |
return false; |
if (dst_tiling == I915_TILING_Y) |
return false; |
} |
assert( logic_op - GL_CLEAR >= 0 ); |
assert( logic_op - GL_CLEAR < 0x10 ); |
assert(dst_pitch > 0); |
if (w < 0 || h < 0) |
return true; |
DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n", |
__FUNCTION__, |
dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords); |
intel_batchbuffer_require_space(intel, |
(8 * 4) + |
(3 * 4) + |
dwords * 4); |
opcode = XY_SETUP_BLT_CMD; |
if (cpp == 4) |
opcode |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; |
br13 = dst_pitch | (translate_raster_op(logic_op) << 16) | (1 << 29); |
br13 |= br13_for_cpp(cpp); |
blit_cmd = XY_TEXT_IMMEDIATE_BLIT_CMD | XY_TEXT_BYTE_PACKED; /* packing? */ |
if (dst_tiling != I915_TILING_NONE) |
blit_cmd |= XY_DST_TILED; |
BEGIN_BATCH(8 + 3); |
OUT_BATCH(opcode | (8 - 2)); |
OUT_BATCH(br13); |
OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */ |
OUT_BATCH((100 << 16) | 100); /* clip x2, y2 */ |
OUT_RELOC_FENCED(dst_buffer, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
dst_offset); |
OUT_BATCH(0); /* bg */ |
OUT_BATCH(fg_color); /* fg */ |
OUT_BATCH(0); /* pattern base addr */ |
OUT_BATCH(blit_cmd | ((3 - 2) + dwords)); |
OUT_BATCH((y << 16) | x); |
OUT_BATCH(((y + h) << 16) | (x + w)); |
ADVANCE_BATCH(); |
intel_batchbuffer_data(intel, src_bits, dwords * 4); |
intel_batchbuffer_emit_mi_flush(intel); |
return true; |
} |
/* We don't have a memmove-type blit like some other hardware, so we'll do a |
* rectangular blit covering a large space, then emit 1-scanline blit at the |
* end to cover the last if we need. |
*/ |
void |
intel_emit_linear_blit(struct intel_context *intel, |
drm_intel_bo *dst_bo, |
unsigned int dst_offset, |
drm_intel_bo *src_bo, |
unsigned int src_offset, |
unsigned int size) |
{ |
struct gl_context *ctx = &intel->ctx; |
GLuint pitch, height; |
bool ok; |
/* The pitch given to the GPU must be DWORD aligned, and |
* we want width to match pitch. Max width is (1 << 15 - 1), |
* rounding that down to the nearest DWORD is 1 << 15 - 4 |
*/ |
pitch = ROUND_DOWN_TO(MIN2(size, (1 << 15) - 1), 4); |
height = (pitch == 0) ? 1 : size / pitch; |
ok = intelEmitCopyBlit(intel, 1, |
pitch, src_bo, src_offset, I915_TILING_NONE, |
pitch, dst_bo, dst_offset, I915_TILING_NONE, |
0, 0, /* src x/y */ |
0, 0, /* dst x/y */ |
pitch, height, /* w, h */ |
GL_COPY); |
if (!ok) |
_mesa_problem(ctx, "Failed to linear blit %dx%d\n", pitch, height); |
src_offset += pitch * height; |
dst_offset += pitch * height; |
size -= pitch * height; |
assert (size < (1 << 15)); |
pitch = ALIGN(size, 4); |
if (size != 0) { |
ok = intelEmitCopyBlit(intel, 1, |
pitch, src_bo, src_offset, I915_TILING_NONE, |
pitch, dst_bo, dst_offset, I915_TILING_NONE, |
0, 0, /* src x/y */ |
0, 0, /* dst x/y */ |
size, 1, /* w, h */ |
GL_COPY); |
if (!ok) |
_mesa_problem(ctx, "Failed to linear blit %dx%d\n", size, 1); |
} |
} |
/** |
* Used to initialize the alpha value of an ARGB8888 miptree after copying |
* into it from an XRGB8888 source. |
* |
* This is very common with glCopyTexImage2D(). Note that the coordinates are |
* relative to the start of the miptree, not relative to a slice within the |
* miptree. |
*/ |
static void |
intel_miptree_set_alpha_to_one(struct intel_context *intel, |
struct intel_mipmap_tree *mt, |
int x, int y, int width, int height) |
{ |
struct intel_region *region = mt->region; |
uint32_t BR13, CMD; |
int pitch, cpp; |
drm_intel_bo *aper_array[2]; |
BATCH_LOCALS; |
pitch = region->pitch; |
cpp = region->cpp; |
DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n", |
__FUNCTION__, region->bo, pitch, x, y, width, height); |
BR13 = br13_for_cpp(cpp) | 0xf0 << 16; |
CMD = XY_COLOR_BLT_CMD; |
CMD |= XY_BLT_WRITE_ALPHA; |
BR13 |= pitch; |
/* do space check before going any further */ |
aper_array[0] = intel->batch.bo; |
aper_array[1] = region->bo; |
if (drm_intel_bufmgr_check_aperture_space(aper_array, |
ARRAY_SIZE(aper_array)) != 0) { |
intel_batchbuffer_flush(intel); |
} |
BEGIN_BATCH(6); |
OUT_BATCH(CMD | (6 - 2)); |
OUT_BATCH(BR13); |
OUT_BATCH((y << 16) | x); |
OUT_BATCH(((y + height) << 16) | (x + width)); |
OUT_RELOC_FENCED(region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
0); |
OUT_BATCH(0xffffffff); /* white, but only alpha gets written */ |
ADVANCE_BATCH(); |
intel_batchbuffer_emit_mi_flush(intel); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_blit.h |
---|
0,0 → 1,83 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_BLIT_H |
#define INTEL_BLIT_H |
#include "intel_context.h" |
extern void intelCopyBuffer(const __DRIdrawable * dpriv, |
const drm_clip_rect_t * rect); |
extern GLbitfield intelClearWithBlit(struct gl_context * ctx, GLbitfield mask); |
bool |
intelEmitCopyBlit(struct intel_context *intel, |
GLuint cpp, |
GLshort src_pitch, |
drm_intel_bo *src_buffer, |
GLuint src_offset, |
uint32_t src_tiling, |
GLshort dst_pitch, |
drm_intel_bo *dst_buffer, |
GLuint dst_offset, |
uint32_t dst_tiling, |
GLshort srcx, GLshort srcy, |
GLshort dstx, GLshort dsty, |
GLshort w, GLshort h, |
GLenum logicop ); |
bool intel_miptree_blit(struct intel_context *intel, |
struct intel_mipmap_tree *src_mt, |
int src_level, int src_slice, |
uint32_t src_x, uint32_t src_y, bool src_flip, |
struct intel_mipmap_tree *dst_mt, |
int dst_level, int dst_slice, |
uint32_t dst_x, uint32_t dst_y, bool dst_flip, |
uint32_t width, uint32_t height, |
GLenum logicop); |
bool |
intelEmitImmediateColorExpandBlit(struct intel_context *intel, |
GLuint cpp, |
GLubyte *src_bits, GLuint src_size, |
GLuint fg_color, |
GLshort dst_pitch, |
drm_intel_bo *dst_buffer, |
GLuint dst_offset, |
uint32_t dst_tiling, |
GLshort x, GLshort y, |
GLshort w, GLshort h, |
GLenum logic_op); |
void intel_emit_linear_blit(struct intel_context *intel, |
drm_intel_bo *dst_bo, |
unsigned int dst_offset, |
drm_intel_bo *src_bo, |
unsigned int src_offset, |
unsigned int size); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_buffer_objects.c |
---|
0,0 → 1,777 |
/************************************************************************** |
* |
* 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 "main/imports.h" |
#include "main/mtypes.h" |
#include "main/macros.h" |
#include "main/bufferobj.h" |
#include "intel_blit.h" |
#include "intel_buffer_objects.h" |
#include "intel_batchbuffer.h" |
#include "intel_context.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
static GLboolean |
intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj); |
/** Allocates a new drm_intel_bo to store the data for the buffer object. */ |
static void |
intel_bufferobj_alloc_buffer(struct intel_context *intel, |
struct intel_buffer_object *intel_obj) |
{ |
intel_obj->buffer = drm_intel_bo_alloc(intel->bufmgr, "bufferobj", |
intel_obj->Base.Size, 64); |
} |
static void |
release_buffer(struct intel_buffer_object *intel_obj) |
{ |
drm_intel_bo_unreference(intel_obj->buffer); |
intel_obj->buffer = NULL; |
intel_obj->offset = 0; |
intel_obj->source = 0; |
} |
/** |
* There is some duplication between mesa's bufferobjects and our |
* bufmgr buffers. Both have an integer handle and a hashtable to |
* lookup an opaque structure. It would be nice if the handles and |
* internal structure where somehow shared. |
*/ |
static struct gl_buffer_object * |
intel_bufferobj_alloc(struct gl_context * ctx, GLuint name, GLenum target) |
{ |
struct intel_buffer_object *obj = CALLOC_STRUCT(intel_buffer_object); |
_mesa_initialize_buffer_object(ctx, &obj->Base, name, target); |
obj->buffer = NULL; |
return &obj->Base; |
} |
/** |
* Deallocate/free a vertex/pixel buffer object. |
* Called via glDeleteBuffersARB(). |
*/ |
static void |
intel_bufferobj_free(struct gl_context * ctx, struct gl_buffer_object *obj) |
{ |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
assert(intel_obj); |
/* Buffer objects are automatically unmapped when deleting according |
* to the spec, but Mesa doesn't do UnmapBuffer for us at context destroy |
* (though it does if you call glDeleteBuffers) |
*/ |
if (obj->Pointer) |
intel_bufferobj_unmap(ctx, obj); |
free(intel_obj->sys_buffer); |
drm_intel_bo_unreference(intel_obj->buffer); |
free(intel_obj); |
} |
/** |
* Allocate space for and store data in a buffer object. Any data that was |
* previously stored in the buffer object is lost. If data is NULL, |
* memory will be allocated, but no copy will occur. |
* Called via ctx->Driver.BufferData(). |
* \return true for success, false if out of memory |
*/ |
static GLboolean |
intel_bufferobj_data(struct gl_context * ctx, |
GLenum target, |
GLsizeiptrARB size, |
const GLvoid * data, |
GLenum usage, struct gl_buffer_object *obj) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
intel_obj->Base.Size = size; |
intel_obj->Base.Usage = usage; |
assert(!obj->Pointer); /* Mesa should have unmapped it */ |
if (intel_obj->buffer != NULL) |
release_buffer(intel_obj); |
free(intel_obj->sys_buffer); |
intel_obj->sys_buffer = NULL; |
if (size != 0) { |
/* Stick VBOs in system memory, as we're always doing swtnl with their |
* contents anyway. |
*/ |
if (target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER) { |
intel_obj->sys_buffer = malloc(size); |
if (intel_obj->sys_buffer != NULL) { |
if (data != NULL) |
memcpy(intel_obj->sys_buffer, data, size); |
return true; |
} |
} |
intel_bufferobj_alloc_buffer(intel, intel_obj); |
if (!intel_obj->buffer) |
return false; |
if (data != NULL) |
drm_intel_bo_subdata(intel_obj->buffer, 0, size, data); |
} |
return true; |
} |
/** |
* Replace data in a subrange of buffer object. If the data range |
* specified by size + offset extends beyond the end of the buffer or |
* if data is NULL, no copy is performed. |
* Called via glBufferSubDataARB(). |
*/ |
static void |
intel_bufferobj_subdata(struct gl_context * ctx, |
GLintptrARB offset, |
GLsizeiptrARB size, |
const GLvoid * data, struct gl_buffer_object *obj) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
bool busy; |
if (size == 0) |
return; |
assert(intel_obj); |
/* If we have a single copy in system memory, update that */ |
if (intel_obj->sys_buffer) { |
if (intel_obj->source) |
release_buffer(intel_obj); |
if (intel_obj->buffer == NULL) { |
memcpy((char *)intel_obj->sys_buffer + offset, data, size); |
return; |
} |
free(intel_obj->sys_buffer); |
intel_obj->sys_buffer = NULL; |
} |
/* Otherwise we need to update the copy in video memory. */ |
busy = |
drm_intel_bo_busy(intel_obj->buffer) || |
drm_intel_bo_references(intel->batch.bo, intel_obj->buffer); |
if (busy) { |
if (size == intel_obj->Base.Size) { |
/* Replace the current busy bo with fresh data. */ |
drm_intel_bo_unreference(intel_obj->buffer); |
intel_bufferobj_alloc_buffer(intel, intel_obj); |
drm_intel_bo_subdata(intel_obj->buffer, 0, size, data); |
} else { |
perf_debug("Using a blit copy to avoid stalling on %ldb " |
"glBufferSubData() to a busy buffer object.\n", |
(long)size); |
drm_intel_bo *temp_bo = |
drm_intel_bo_alloc(intel->bufmgr, "subdata temp", size, 64); |
drm_intel_bo_subdata(temp_bo, 0, size, data); |
intel_emit_linear_blit(intel, |
intel_obj->buffer, offset, |
temp_bo, 0, |
size); |
drm_intel_bo_unreference(temp_bo); |
} |
} else { |
drm_intel_bo_subdata(intel_obj->buffer, offset, size, data); |
} |
} |
/** |
* Called via glGetBufferSubDataARB(). |
*/ |
static void |
intel_bufferobj_get_subdata(struct gl_context * ctx, |
GLintptrARB offset, |
GLsizeiptrARB size, |
GLvoid * data, struct gl_buffer_object *obj) |
{ |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
struct intel_context *intel = intel_context(ctx); |
assert(intel_obj); |
if (intel_obj->sys_buffer) |
memcpy(data, (char *)intel_obj->sys_buffer + offset, size); |
else { |
if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) { |
intel_batchbuffer_flush(intel); |
} |
drm_intel_bo_get_subdata(intel_obj->buffer, offset, size, data); |
} |
} |
/** |
* Called via glMapBufferRange and glMapBuffer |
* |
* The goal of this extension is to allow apps to accumulate their rendering |
* at the same time as they accumulate their buffer object. Without it, |
* you'd end up blocking on execution of rendering every time you mapped |
* the buffer to put new data in. |
* |
* We support it in 3 ways: If unsynchronized, then don't bother |
* flushing the batchbuffer before mapping the buffer, which can save blocking |
* in many cases. If we would still block, and they allow the whole buffer |
* to be invalidated, then just allocate a new buffer to replace the old one. |
* If not, and we'd block, and they allow the subrange of the buffer to be |
* invalidated, then we can make a new little BO, let them write into that, |
* and blit it into the real BO at unmap time. |
*/ |
static void * |
intel_bufferobj_map_range(struct gl_context * ctx, |
GLintptr offset, GLsizeiptr length, |
GLbitfield access, struct gl_buffer_object *obj) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
assert(intel_obj); |
/* _mesa_MapBufferRange (GL entrypoint) sets these, but the vbo module also |
* internally uses our functions directly. |
*/ |
obj->Offset = offset; |
obj->Length = length; |
obj->AccessFlags = access; |
if (intel_obj->sys_buffer) { |
const bool read_only = |
(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == GL_MAP_READ_BIT; |
if (!read_only && intel_obj->source) |
release_buffer(intel_obj); |
if (!intel_obj->buffer || intel_obj->source) { |
obj->Pointer = intel_obj->sys_buffer + offset; |
return obj->Pointer; |
} |
free(intel_obj->sys_buffer); |
intel_obj->sys_buffer = NULL; |
} |
if (intel_obj->buffer == NULL) { |
obj->Pointer = NULL; |
return NULL; |
} |
/* If the access is synchronized (like a normal buffer mapping), then get |
* things flushed out so the later mapping syncs appropriately through GEM. |
* If the user doesn't care about existing buffer contents and mapping would |
* cause us to block, then throw out the old buffer. |
* |
* If they set INVALIDATE_BUFFER, we can pitch the current contents to |
* achieve the required synchronization. |
*/ |
if (!(access & GL_MAP_UNSYNCHRONIZED_BIT)) { |
if (drm_intel_bo_references(intel->batch.bo, intel_obj->buffer)) { |
if (access & GL_MAP_INVALIDATE_BUFFER_BIT) { |
drm_intel_bo_unreference(intel_obj->buffer); |
intel_bufferobj_alloc_buffer(intel, intel_obj); |
} else { |
perf_debug("Stalling on the GPU for mapping a busy buffer " |
"object\n"); |
intel_flush(ctx); |
} |
} else if (drm_intel_bo_busy(intel_obj->buffer) && |
(access & GL_MAP_INVALIDATE_BUFFER_BIT)) { |
drm_intel_bo_unreference(intel_obj->buffer); |
intel_bufferobj_alloc_buffer(intel, intel_obj); |
} |
} |
/* If the user is mapping a range of an active buffer object but |
* doesn't require the current contents of that range, make a new |
* BO, and we'll copy what they put in there out at unmap or |
* FlushRange time. |
*/ |
if ((access & GL_MAP_INVALIDATE_RANGE_BIT) && |
drm_intel_bo_busy(intel_obj->buffer)) { |
if (access & GL_MAP_FLUSH_EXPLICIT_BIT) { |
intel_obj->range_map_buffer = malloc(length); |
obj->Pointer = intel_obj->range_map_buffer; |
} else { |
intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr, |
"range map", |
length, 64); |
if (!(access & GL_MAP_READ_BIT)) { |
drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo); |
} else { |
drm_intel_bo_map(intel_obj->range_map_bo, |
(access & GL_MAP_WRITE_BIT) != 0); |
} |
obj->Pointer = intel_obj->range_map_bo->virtual; |
} |
return obj->Pointer; |
} |
if (access & GL_MAP_UNSYNCHRONIZED_BIT) |
drm_intel_gem_bo_map_unsynchronized(intel_obj->buffer); |
else if (!(access & GL_MAP_READ_BIT)) { |
drm_intel_gem_bo_map_gtt(intel_obj->buffer); |
} else { |
drm_intel_bo_map(intel_obj->buffer, (access & GL_MAP_WRITE_BIT) != 0); |
} |
obj->Pointer = intel_obj->buffer->virtual + offset; |
return obj->Pointer; |
} |
/* Ideally we'd use a BO to avoid taking up cache space for the temporary |
* data, but FlushMappedBufferRange may be followed by further writes to |
* the pointer, so we would have to re-map after emitting our blit, which |
* would defeat the point. |
*/ |
static void |
intel_bufferobj_flush_mapped_range(struct gl_context *ctx, |
GLintptr offset, GLsizeiptr length, |
struct gl_buffer_object *obj) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
drm_intel_bo *temp_bo; |
/* Unless we're in the range map using a temporary system buffer, |
* there's no work to do. |
*/ |
if (intel_obj->range_map_buffer == NULL) |
return; |
if (length == 0) |
return; |
temp_bo = drm_intel_bo_alloc(intel->bufmgr, "range map flush", length, 64); |
drm_intel_bo_subdata(temp_bo, 0, length, intel_obj->range_map_buffer); |
intel_emit_linear_blit(intel, |
intel_obj->buffer, obj->Offset + offset, |
temp_bo, 0, |
length); |
drm_intel_bo_unreference(temp_bo); |
} |
/** |
* Called via glUnmapBuffer(). |
*/ |
static GLboolean |
intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
assert(intel_obj); |
assert(obj->Pointer); |
if (intel_obj->sys_buffer != NULL) { |
/* always keep the mapping around. */ |
} else if (intel_obj->range_map_buffer != NULL) { |
/* Since we've emitted some blits to buffers that will (likely) be used |
* in rendering operations in other cache domains in this batch, emit a |
* flush. Once again, we wish for a domain tracker in libdrm to cover |
* usage inside of a batchbuffer. |
*/ |
intel_batchbuffer_emit_mi_flush(intel); |
free(intel_obj->range_map_buffer); |
intel_obj->range_map_buffer = NULL; |
} else if (intel_obj->range_map_bo != NULL) { |
drm_intel_bo_unmap(intel_obj->range_map_bo); |
intel_emit_linear_blit(intel, |
intel_obj->buffer, obj->Offset, |
intel_obj->range_map_bo, 0, |
obj->Length); |
/* Since we've emitted some blits to buffers that will (likely) be used |
* in rendering operations in other cache domains in this batch, emit a |
* flush. Once again, we wish for a domain tracker in libdrm to cover |
* usage inside of a batchbuffer. |
*/ |
intel_batchbuffer_emit_mi_flush(intel); |
drm_intel_bo_unreference(intel_obj->range_map_bo); |
intel_obj->range_map_bo = NULL; |
} else if (intel_obj->buffer != NULL) { |
drm_intel_bo_unmap(intel_obj->buffer); |
} |
obj->Pointer = NULL; |
obj->Offset = 0; |
obj->Length = 0; |
return true; |
} |
drm_intel_bo * |
intel_bufferobj_buffer(struct intel_context *intel, |
struct intel_buffer_object *intel_obj, |
GLuint flag) |
{ |
if (intel_obj->source) |
release_buffer(intel_obj); |
if (intel_obj->buffer == NULL) { |
intel_bufferobj_alloc_buffer(intel, intel_obj); |
drm_intel_bo_subdata(intel_obj->buffer, |
0, intel_obj->Base.Size, |
intel_obj->sys_buffer); |
free(intel_obj->sys_buffer); |
intel_obj->sys_buffer = NULL; |
intel_obj->offset = 0; |
} |
return intel_obj->buffer; |
} |
#define INTEL_UPLOAD_SIZE (64*1024) |
void |
intel_upload_finish(struct intel_context *intel) |
{ |
if (!intel->upload.bo) |
return; |
if (intel->upload.buffer_len) { |
drm_intel_bo_subdata(intel->upload.bo, |
intel->upload.buffer_offset, |
intel->upload.buffer_len, |
intel->upload.buffer); |
intel->upload.buffer_len = 0; |
} |
drm_intel_bo_unreference(intel->upload.bo); |
intel->upload.bo = NULL; |
} |
static void wrap_buffers(struct intel_context *intel, GLuint size) |
{ |
intel_upload_finish(intel); |
if (size < INTEL_UPLOAD_SIZE) |
size = INTEL_UPLOAD_SIZE; |
intel->upload.bo = drm_intel_bo_alloc(intel->bufmgr, "upload", size, 0); |
intel->upload.offset = 0; |
} |
void intel_upload_data(struct intel_context *intel, |
const void *ptr, GLuint size, GLuint align, |
drm_intel_bo **return_bo, |
GLuint *return_offset) |
{ |
GLuint base, delta; |
base = (intel->upload.offset + align - 1) / align * align; |
if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) { |
wrap_buffers(intel, size); |
base = 0; |
} |
drm_intel_bo_reference(intel->upload.bo); |
*return_bo = intel->upload.bo; |
*return_offset = base; |
delta = base - intel->upload.offset; |
if (intel->upload.buffer_len && |
intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer)) |
{ |
drm_intel_bo_subdata(intel->upload.bo, |
intel->upload.buffer_offset, |
intel->upload.buffer_len, |
intel->upload.buffer); |
intel->upload.buffer_len = 0; |
} |
if (size < sizeof(intel->upload.buffer)) |
{ |
if (intel->upload.buffer_len == 0) |
intel->upload.buffer_offset = base; |
else |
intel->upload.buffer_len += delta; |
memcpy(intel->upload.buffer + intel->upload.buffer_len, ptr, size); |
intel->upload.buffer_len += size; |
} |
else |
{ |
drm_intel_bo_subdata(intel->upload.bo, base, size, ptr); |
} |
intel->upload.offset = base + size; |
} |
drm_intel_bo * |
intel_bufferobj_source(struct intel_context *intel, |
struct intel_buffer_object *intel_obj, |
GLuint align, GLuint *offset) |
{ |
if (intel_obj->buffer == NULL) { |
intel_upload_data(intel, |
intel_obj->sys_buffer, intel_obj->Base.Size, align, |
&intel_obj->buffer, &intel_obj->offset); |
intel_obj->source = 1; |
} |
*offset = intel_obj->offset; |
return intel_obj->buffer; |
} |
static void |
intel_bufferobj_copy_subdata(struct gl_context *ctx, |
struct gl_buffer_object *src, |
struct gl_buffer_object *dst, |
GLintptr read_offset, GLintptr write_offset, |
GLsizeiptr size) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_buffer_object *intel_src = intel_buffer_object(src); |
struct intel_buffer_object *intel_dst = intel_buffer_object(dst); |
drm_intel_bo *src_bo, *dst_bo; |
GLuint src_offset; |
if (size == 0) |
return; |
/* If we're in system memory, just map and memcpy. */ |
if (intel_src->sys_buffer || intel_dst->sys_buffer) { |
/* The same buffer may be used, but note that regions copied may |
* not overlap. |
*/ |
if (src == dst) { |
char *ptr = intel_bufferobj_map_range(ctx, 0, dst->Size, |
GL_MAP_READ_BIT | |
GL_MAP_WRITE_BIT, |
dst); |
memmove(ptr + write_offset, ptr + read_offset, size); |
intel_bufferobj_unmap(ctx, dst); |
} else { |
const char *src_ptr; |
char *dst_ptr; |
src_ptr = intel_bufferobj_map_range(ctx, 0, src->Size, |
GL_MAP_READ_BIT, src); |
dst_ptr = intel_bufferobj_map_range(ctx, 0, dst->Size, |
GL_MAP_WRITE_BIT, dst); |
memcpy(dst_ptr + write_offset, src_ptr + read_offset, size); |
intel_bufferobj_unmap(ctx, src); |
intel_bufferobj_unmap(ctx, dst); |
} |
return; |
} |
/* Otherwise, we have real BOs, so blit them. */ |
dst_bo = intel_bufferobj_buffer(intel, intel_dst, INTEL_WRITE_PART); |
src_bo = intel_bufferobj_source(intel, intel_src, 64, &src_offset); |
intel_emit_linear_blit(intel, |
dst_bo, write_offset, |
src_bo, read_offset + src_offset, size); |
/* Since we've emitted some blits to buffers that will (likely) be used |
* in rendering operations in other cache domains in this batch, emit a |
* flush. Once again, we wish for a domain tracker in libdrm to cover |
* usage inside of a batchbuffer. |
*/ |
intel_batchbuffer_emit_mi_flush(intel); |
} |
static GLenum |
intel_buffer_purgeable(drm_intel_bo *buffer) |
{ |
int retained = 0; |
if (buffer != NULL) |
retained = drm_intel_bo_madvise (buffer, I915_MADV_DONTNEED); |
return retained ? GL_VOLATILE_APPLE : GL_RELEASED_APPLE; |
} |
static GLenum |
intel_buffer_object_purgeable(struct gl_context * ctx, |
struct gl_buffer_object *obj, |
GLenum option) |
{ |
struct intel_buffer_object *intel_obj = intel_buffer_object (obj); |
if (intel_obj->buffer != NULL) |
return intel_buffer_purgeable(intel_obj->buffer); |
if (option == GL_RELEASED_APPLE) { |
free(intel_obj->sys_buffer); |
intel_obj->sys_buffer = NULL; |
return GL_RELEASED_APPLE; |
} else { |
/* XXX Create the buffer and madvise(MADV_DONTNEED)? */ |
struct intel_context *intel = intel_context(ctx); |
drm_intel_bo *bo = intel_bufferobj_buffer(intel, intel_obj, INTEL_READ); |
return intel_buffer_purgeable(bo); |
} |
} |
static GLenum |
intel_texture_object_purgeable(struct gl_context * ctx, |
struct gl_texture_object *obj, |
GLenum option) |
{ |
struct intel_texture_object *intel; |
(void) ctx; |
(void) option; |
intel = intel_texture_object(obj); |
if (intel->mt == NULL || intel->mt->region == NULL) |
return GL_RELEASED_APPLE; |
return intel_buffer_purgeable(intel->mt->region->bo); |
} |
static GLenum |
intel_render_object_purgeable(struct gl_context * ctx, |
struct gl_renderbuffer *obj, |
GLenum option) |
{ |
struct intel_renderbuffer *intel; |
(void) ctx; |
(void) option; |
intel = intel_renderbuffer(obj); |
if (intel->mt == NULL) |
return GL_RELEASED_APPLE; |
return intel_buffer_purgeable(intel->mt->region->bo); |
} |
static GLenum |
intel_buffer_unpurgeable(drm_intel_bo *buffer) |
{ |
int retained; |
retained = 0; |
if (buffer != NULL) |
retained = drm_intel_bo_madvise (buffer, I915_MADV_WILLNEED); |
return retained ? GL_RETAINED_APPLE : GL_UNDEFINED_APPLE; |
} |
static GLenum |
intel_buffer_object_unpurgeable(struct gl_context * ctx, |
struct gl_buffer_object *obj, |
GLenum option) |
{ |
(void) ctx; |
(void) option; |
return intel_buffer_unpurgeable(intel_buffer_object (obj)->buffer); |
} |
static GLenum |
intel_texture_object_unpurgeable(struct gl_context * ctx, |
struct gl_texture_object *obj, |
GLenum option) |
{ |
struct intel_texture_object *intel; |
(void) ctx; |
(void) option; |
intel = intel_texture_object(obj); |
if (intel->mt == NULL || intel->mt->region == NULL) |
return GL_UNDEFINED_APPLE; |
return intel_buffer_unpurgeable(intel->mt->region->bo); |
} |
static GLenum |
intel_render_object_unpurgeable(struct gl_context * ctx, |
struct gl_renderbuffer *obj, |
GLenum option) |
{ |
struct intel_renderbuffer *intel; |
(void) ctx; |
(void) option; |
intel = intel_renderbuffer(obj); |
if (intel->mt == NULL) |
return GL_UNDEFINED_APPLE; |
return intel_buffer_unpurgeable(intel->mt->region->bo); |
} |
void |
intelInitBufferObjectFuncs(struct dd_function_table *functions) |
{ |
functions->NewBufferObject = intel_bufferobj_alloc; |
functions->DeleteBuffer = intel_bufferobj_free; |
functions->BufferData = intel_bufferobj_data; |
functions->BufferSubData = intel_bufferobj_subdata; |
functions->GetBufferSubData = intel_bufferobj_get_subdata; |
functions->MapBufferRange = intel_bufferobj_map_range; |
functions->FlushMappedBufferRange = intel_bufferobj_flush_mapped_range; |
functions->UnmapBuffer = intel_bufferobj_unmap; |
functions->CopyBufferSubData = intel_bufferobj_copy_subdata; |
functions->BufferObjectPurgeable = intel_buffer_object_purgeable; |
functions->TextureObjectPurgeable = intel_texture_object_purgeable; |
functions->RenderObjectPurgeable = intel_render_object_purgeable; |
functions->BufferObjectUnpurgeable = intel_buffer_object_unpurgeable; |
functions->TextureObjectUnpurgeable = intel_texture_object_unpurgeable; |
functions->RenderObjectUnpurgeable = intel_render_object_unpurgeable; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_buffer_objects.h |
---|
0,0 → 1,85 |
/************************************************************************** |
* |
* Copyright 2005 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 INTEL_BUFFEROBJ_H |
#define INTEL_BUFFEROBJ_H |
#include "main/mtypes.h" |
struct intel_context; |
struct gl_buffer_object; |
/** |
* Intel vertex/pixel buffer object, derived from Mesa's gl_buffer_object. |
*/ |
struct intel_buffer_object |
{ |
struct gl_buffer_object Base; |
drm_intel_bo *buffer; /* the low-level buffer manager's buffer handle */ |
GLuint offset; /* any offset into that buffer */ |
/** System memory buffer data, if not using a BO to store the data. */ |
void *sys_buffer; |
drm_intel_bo *range_map_bo; |
void *range_map_buffer; |
unsigned int range_map_offset; |
GLsizei range_map_size; |
bool source; |
}; |
/* Get the bm buffer associated with a GL bufferobject: |
*/ |
drm_intel_bo *intel_bufferobj_buffer(struct intel_context *intel, |
struct intel_buffer_object *obj, |
GLuint flag); |
drm_intel_bo *intel_bufferobj_source(struct intel_context *intel, |
struct intel_buffer_object *obj, |
GLuint align, |
GLuint *offset); |
void intel_upload_data(struct intel_context *intel, |
const void *ptr, GLuint size, GLuint align, |
drm_intel_bo **return_bo, |
GLuint *return_offset); |
void intel_upload_finish(struct intel_context *intel); |
/* Hook the bufferobject implementation into mesa: |
*/ |
void intelInitBufferObjectFuncs(struct dd_function_table *functions); |
static inline struct intel_buffer_object * |
intel_buffer_object(struct gl_buffer_object *obj) |
{ |
return (struct intel_buffer_object *) obj; |
} |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_buffers.c |
---|
0,0 → 1,104 |
/************************************************************************** |
* |
* 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 "intel_context.h" |
#include "intel_buffers.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "main/fbobject.h" |
#include "main/framebuffer.h" |
#include "main/renderbuffer.h" |
/** |
* Check if we're about to draw into the front color buffer. |
* If so, set the intel->front_buffer_dirty field to true. |
*/ |
void |
intel_check_front_buffer_rendering(struct intel_context *intel) |
{ |
const struct gl_framebuffer *fb = intel->ctx.DrawBuffer; |
if (_mesa_is_winsys_fbo(fb)) { |
/* drawing to window system buffer */ |
if (fb->_NumColorDrawBuffers > 0) { |
if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { |
intel->front_buffer_dirty = true; |
} |
} |
} |
} |
static void |
intelDrawBuffer(struct gl_context * ctx, GLenum mode) |
{ |
if (ctx->DrawBuffer && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
struct intel_context *const intel = intel_context(ctx); |
const bool was_front_buffer_rendering = |
intel->is_front_buffer_rendering; |
intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) |
|| (mode == GL_FRONT) || (mode == GL_FRONT_AND_BACK); |
/* If we weren't front-buffer rendering before but we are now, |
* invalidate our DRI drawable so we'll ask for new buffers |
* (including the fake front) before we start rendering again. |
*/ |
if (!was_front_buffer_rendering && intel->is_front_buffer_rendering) |
dri2InvalidateDrawable(intel->driContext->driDrawablePriv); |
} |
intel_draw_buffer(ctx); |
} |
static void |
intelReadBuffer(struct gl_context * ctx, GLenum mode) |
{ |
if (ctx->DrawBuffer && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
struct intel_context *const intel = intel_context(ctx); |
const bool was_front_buffer_reading = |
intel->is_front_buffer_reading; |
intel->is_front_buffer_reading = (mode == GL_FRONT_LEFT) |
|| (mode == GL_FRONT); |
/* If we weren't front-buffer reading before but we are now, |
* invalidate our DRI drawable so we'll ask for new buffers |
* (including the fake front) before we start reading again. |
*/ |
if (!was_front_buffer_reading && intel->is_front_buffer_reading) |
dri2InvalidateDrawable(intel->driContext->driReadablePriv); |
} |
} |
void |
intelInitBufferFuncs(struct dd_function_table *functions) |
{ |
functions->DrawBuffer = intelDrawBuffer; |
functions->ReadBuffer = intelReadBuffer; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_buffers.h |
---|
0,0 → 1,52 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_BUFFERS_H |
#define INTEL_BUFFERS_H |
#include "dri_util.h" |
#include "drm.h" |
#include "intel_context.h" |
struct intel_context; |
struct intel_framebuffer; |
extern void intel_check_front_buffer_rendering(struct intel_context *intel); |
static inline void |
intel_draw_buffer(struct gl_context * ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
intel->vtbl.update_draw_buffer(intel); |
} |
extern void intelInitBufferFuncs(struct dd_function_table *functions); |
void intelCalcViewport(struct gl_context * ctx); |
#endif /* INTEL_BUFFERS_H */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_chipset.h |
---|
0,0 → 1,86 |
/* |
* Copyright © 2007 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#define PCI_CHIP_I810 0x7121 |
#define PCI_CHIP_I810_DC100 0x7123 |
#define PCI_CHIP_I810_E 0x7125 |
#define PCI_CHIP_I815 0x1132 |
#define PCI_CHIP_I830_M 0x3577 |
#define PCI_CHIP_845_G 0x2562 |
#define PCI_CHIP_I855_GM 0x3582 |
#define PCI_CHIP_I865_G 0x2572 |
#define PCI_CHIP_I915_G 0x2582 |
#define PCI_CHIP_E7221_G 0x258A |
#define PCI_CHIP_I915_GM 0x2592 |
#define PCI_CHIP_I945_G 0x2772 |
#define PCI_CHIP_I945_GM 0x27A2 |
#define PCI_CHIP_I945_GME 0x27AE |
#define PCI_CHIP_Q35_G 0x29B2 |
#define PCI_CHIP_G33_G 0x29C2 |
#define PCI_CHIP_Q33_G 0x29D2 |
#define PCI_CHIP_IGD_GM 0xA011 |
#define PCI_CHIP_IGD_G 0xA001 |
#define IS_IGDGM(devid) (devid == PCI_CHIP_IGD_GM) |
#define IS_IGDG(devid) (devid == PCI_CHIP_IGD_G) |
#define IS_IGD(devid) (IS_IGDG(devid) || IS_IGDGM(devid)) |
#define IS_MOBILE(devid) (devid == PCI_CHIP_I855_GM || \ |
devid == PCI_CHIP_I915_GM || \ |
devid == PCI_CHIP_I945_GM || \ |
devid == PCI_CHIP_I945_GME || \ |
devid == PCI_CHIP_I965_GM || \ |
devid == PCI_CHIP_I965_GME || \ |
devid == PCI_CHIP_GM45_GM || \ |
IS_IGD(devid) || \ |
devid == PCI_CHIP_ILM_G) |
#define IS_915(devid) (devid == PCI_CHIP_I915_G || \ |
devid == PCI_CHIP_E7221_G || \ |
devid == PCI_CHIP_I915_GM) |
#define IS_945(devid) (devid == PCI_CHIP_I945_G || \ |
devid == PCI_CHIP_I945_GM || \ |
devid == PCI_CHIP_I945_GME || \ |
devid == PCI_CHIP_G33_G || \ |
devid == PCI_CHIP_Q33_G || \ |
devid == PCI_CHIP_Q35_G || IS_IGD(devid)) |
#define IS_9XX(devid) (IS_915(devid) || \ |
IS_945(devid)) |
#define IS_GEN3(devid) (IS_915(devid) || \ |
IS_945(devid)) |
#define IS_GEN2(devid) (devid == PCI_CHIP_I830_M || \ |
devid == PCI_CHIP_845_G || \ |
devid == PCI_CHIP_I855_GM || \ |
devid == PCI_CHIP_I865_G) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_clear.c |
---|
0,0 → 1,194 |
/************************************************************************** |
* |
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. |
* Copyright 2009 Intel Corporation. |
* 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 "main/glheader.h" |
#include "main/mtypes.h" |
#include "main/condrender.h" |
#include "swrast/swrast.h" |
#include "drivers/common/meta.h" |
#include "intel_context.h" |
#include "intel_blit.h" |
#include "intel_clear.h" |
#include "intel_fbo.h" |
#include "intel_regions.h" |
#define FILE_DEBUG_FLAG DEBUG_BLIT |
static const char *buffer_names[] = { |
[BUFFER_FRONT_LEFT] = "front", |
[BUFFER_BACK_LEFT] = "back", |
[BUFFER_FRONT_RIGHT] = "front right", |
[BUFFER_BACK_RIGHT] = "back right", |
[BUFFER_DEPTH] = "depth", |
[BUFFER_STENCIL] = "stencil", |
[BUFFER_ACCUM] = "accum", |
[BUFFER_AUX0] = "aux0", |
[BUFFER_COLOR0] = "color0", |
[BUFFER_COLOR1] = "color1", |
[BUFFER_COLOR2] = "color2", |
[BUFFER_COLOR3] = "color3", |
[BUFFER_COLOR4] = "color4", |
[BUFFER_COLOR5] = "color5", |
[BUFFER_COLOR6] = "color6", |
[BUFFER_COLOR7] = "color7", |
}; |
static void |
debug_mask(const char *name, GLbitfield mask) |
{ |
GLuint i; |
if (unlikely(INTEL_DEBUG & DEBUG_BLIT)) { |
DBG("%s clear:", name); |
for (i = 0; i < BUFFER_COUNT; i++) { |
if (mask & (1 << i)) |
DBG(" %s", buffer_names[i]); |
} |
DBG("\n"); |
} |
} |
/** |
* Called by ctx->Driver.Clear. |
*/ |
static void |
intelClear(struct gl_context *ctx, GLbitfield mask) |
{ |
struct intel_context *intel = intel_context(ctx); |
const GLuint colorMask = *((GLuint *) & ctx->Color.ColorMask[0]); |
GLbitfield tri_mask = 0; |
GLbitfield blit_mask = 0; |
GLbitfield swrast_mask = 0; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct intel_renderbuffer *irb; |
int i; |
if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT)) { |
intel->front_buffer_dirty = true; |
} |
if (0) |
fprintf(stderr, "%s\n", __FUNCTION__); |
/* Get SW clears out of the way: Anything without an intel_renderbuffer */ |
for (i = 0; i < BUFFER_COUNT; i++) { |
if (!(mask & (1 << i))) |
continue; |
irb = intel_get_renderbuffer(fb, i); |
if (unlikely(!irb)) { |
swrast_mask |= (1 << i); |
mask &= ~(1 << i); |
} |
} |
if (unlikely(swrast_mask)) { |
debug_mask("swrast", swrast_mask); |
_swrast_Clear(ctx, swrast_mask); |
} |
/* HW color buffers (front, back, aux, generic FBO, etc) */ |
if (colorMask == ~0) { |
/* clear all R,G,B,A */ |
blit_mask |= (mask & BUFFER_BITS_COLOR); |
} |
else { |
/* glColorMask in effect */ |
tri_mask |= (mask & BUFFER_BITS_COLOR); |
} |
/* Make sure we have up to date buffers before we start looking at |
* the tiling bits to determine how to clear. */ |
intel_prepare_render(intel); |
/* HW stencil */ |
if (mask & BUFFER_BIT_STENCIL) { |
const struct intel_region *stencilRegion |
= intel_get_rb_region(fb, BUFFER_STENCIL); |
if (stencilRegion) { |
/* have hw stencil */ |
if (stencilRegion->tiling == I915_TILING_Y || |
(ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { |
/* We have to use the 3D engine if we're clearing a partial mask |
* of the stencil buffer, or if we're on a 965 which has a tiled |
* depth/stencil buffer in a layout we can't blit to. |
*/ |
tri_mask |= BUFFER_BIT_STENCIL; |
} |
else { |
/* clearing all stencil bits, use blitting */ |
blit_mask |= BUFFER_BIT_STENCIL; |
} |
} |
} |
/* HW depth */ |
if (mask & BUFFER_BIT_DEPTH) { |
const struct intel_region *irb = intel_get_rb_region(fb, BUFFER_DEPTH); |
/* clear depth with whatever method is used for stencil (see above) */ |
if (irb->tiling == I915_TILING_Y || tri_mask & BUFFER_BIT_STENCIL) |
tri_mask |= BUFFER_BIT_DEPTH; |
else |
blit_mask |= BUFFER_BIT_DEPTH; |
} |
/* If we're doing a tri pass for depth/stencil, include a likely color |
* buffer with it. |
*/ |
if (mask & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) { |
int color_bit = ffs(mask & BUFFER_BITS_COLOR); |
if (color_bit != 0) { |
tri_mask |= blit_mask & (1 << (color_bit - 1)); |
blit_mask &= ~(1 << (color_bit - 1)); |
} |
} |
/* Anything left, just use tris */ |
tri_mask |= mask & ~blit_mask; |
if (blit_mask) { |
debug_mask("blit", blit_mask); |
tri_mask |= intelClearWithBlit(ctx, blit_mask); |
} |
if (tri_mask) { |
debug_mask("tri", tri_mask); |
if (ctx->API == API_OPENGLES) |
_mesa_meta_Clear(&intel->ctx, tri_mask); |
else |
_mesa_meta_glsl_Clear(&intel->ctx, tri_mask); |
} |
} |
void |
intelInitClearFuncs(struct dd_function_table *functions) |
{ |
functions->Clear = intelClear; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_clear.h |
---|
0,0 → 1,38 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_CLEAR_H |
#define INTEL_CLEAR_H |
struct dd_function_table; |
extern void |
intelInitClearFuncs(struct dd_function_table *functions); |
#endif /* INTEL_CLEAR_H */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_context.c |
---|
0,0 → 1,833 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/context.h" |
#include "main/extensions.h" |
#include "main/fbobject.h" |
#include "main/framebuffer.h" |
#include "main/imports.h" |
#include "main/points.h" |
#include "main/renderbuffer.h" |
#include "swrast/swrast.h" |
#include "swrast_setup/swrast_setup.h" |
#include "tnl/tnl.h" |
#include "drivers/common/driverfuncs.h" |
#include "drivers/common/meta.h" |
#include "intel_chipset.h" |
#include "intel_buffers.h" |
#include "intel_tex.h" |
#include "intel_batchbuffer.h" |
#include "intel_clear.h" |
#include "intel_extensions.h" |
#include "intel_pixel.h" |
#include "intel_regions.h" |
#include "intel_buffer_objects.h" |
#include "intel_fbo.h" |
#include "intel_bufmgr.h" |
#include "intel_screen.h" |
#include "intel_mipmap_tree.h" |
#include "utils.h" |
#include "../glsl/ralloc.h" |
#ifndef INTEL_DEBUG |
int INTEL_DEBUG = (0); |
#endif |
static const GLubyte * |
intelGetString(struct gl_context * ctx, GLenum name) |
{ |
const struct intel_context *const intel = intel_context(ctx); |
const char *chipset; |
static char buffer[128]; |
switch (name) { |
case GL_VENDOR: |
return (GLubyte *) "Intel Open Source Technology Center"; |
break; |
case GL_RENDERER: |
switch (intel->intelScreen->deviceID) { |
#undef CHIPSET |
#define CHIPSET(id, symbol, str) case id: chipset = str; break; |
#include "pci_ids/i915_pci_ids.h" |
default: |
chipset = "Unknown Intel Chipset"; |
break; |
} |
(void) driGetRendererString(buffer, chipset, 0); |
return (GLubyte *) buffer; |
default: |
return NULL; |
} |
} |
static void |
intel_flush_front(struct gl_context *ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
__DRIcontext *driContext = intel->driContext; |
__DRIdrawable *driDrawable = driContext->driDrawablePriv; |
__DRIscreen *const screen = intel->intelScreen->driScrnPriv; |
if (intel->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
if (screen->dri2.loader->flushFrontBuffer != NULL && |
driDrawable && |
driDrawable->loaderPrivate) { |
screen->dri2.loader->flushFrontBuffer(driDrawable, |
driDrawable->loaderPrivate); |
/* We set the dirty bit in intel_prepare_render() if we're |
* front buffer rendering once we get there. |
*/ |
intel->front_buffer_dirty = false; |
} |
} |
} |
static unsigned |
intel_bits_per_pixel(const struct intel_renderbuffer *rb) |
{ |
return _mesa_get_format_bytes(intel_rb_format(rb)) * 8; |
} |
static void |
intel_query_dri2_buffers(struct intel_context *intel, |
__DRIdrawable *drawable, |
__DRIbuffer **buffers, |
int *count); |
static void |
intel_process_dri2_buffer(struct intel_context *intel, |
__DRIdrawable *drawable, |
__DRIbuffer *buffer, |
struct intel_renderbuffer *rb, |
const char *buffer_name); |
void |
intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) |
{ |
struct gl_framebuffer *fb = drawable->driverPrivate; |
struct intel_renderbuffer *rb; |
struct intel_context *intel = context->driverPrivate; |
__DRIbuffer *buffers = NULL; |
int i, count; |
const char *region_name; |
/* Set this up front, so that in case our buffers get invalidated |
* while we're getting new buffers, we don't clobber the stamp and |
* thus ignore the invalidate. */ |
drawable->lastStamp = drawable->dri2.stamp; |
if (unlikely(INTEL_DEBUG & DEBUG_DRI)) |
fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); |
intel_query_dri2_buffers(intel, drawable, &buffers, &count); |
if (buffers == NULL) |
return; |
for (i = 0; i < count; i++) { |
switch (buffers[i].attachment) { |
case __DRI_BUFFER_FRONT_LEFT: |
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
region_name = "dri2 front buffer"; |
break; |
case __DRI_BUFFER_FAKE_FRONT_LEFT: |
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
region_name = "dri2 fake front buffer"; |
break; |
case __DRI_BUFFER_BACK_LEFT: |
rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); |
region_name = "dri2 back buffer"; |
break; |
case __DRI_BUFFER_DEPTH: |
case __DRI_BUFFER_HIZ: |
case __DRI_BUFFER_DEPTH_STENCIL: |
case __DRI_BUFFER_STENCIL: |
case __DRI_BUFFER_ACCUM: |
default: |
fprintf(stderr, |
"unhandled buffer attach event, attachment type %d\n", |
buffers[i].attachment); |
return; |
} |
intel_process_dri2_buffer(intel, drawable, &buffers[i], rb, region_name); |
} |
driUpdateFramebufferSize(&intel->ctx, drawable); |
} |
/** |
* intel_prepare_render should be called anywhere that curent read/drawbuffer |
* state is required. |
*/ |
void |
intel_prepare_render(struct intel_context *intel) |
{ |
__DRIcontext *driContext = intel->driContext; |
__DRIdrawable *drawable; |
drawable = driContext->driDrawablePriv; |
if (drawable && drawable->dri2.stamp != driContext->dri2.draw_stamp) { |
if (drawable->lastStamp != drawable->dri2.stamp) |
intel_update_renderbuffers(driContext, drawable); |
intel_draw_buffer(&intel->ctx); |
driContext->dri2.draw_stamp = drawable->dri2.stamp; |
} |
drawable = driContext->driReadablePriv; |
if (drawable && drawable->dri2.stamp != driContext->dri2.read_stamp) { |
if (drawable->lastStamp != drawable->dri2.stamp) |
intel_update_renderbuffers(driContext, drawable); |
driContext->dri2.read_stamp = drawable->dri2.stamp; |
} |
/* If we're currently rendering to the front buffer, the rendering |
* that will happen next will probably dirty the front buffer. So |
* mark it as dirty here. |
*/ |
if (intel->is_front_buffer_rendering) |
intel->front_buffer_dirty = true; |
/* Wait for the swapbuffers before the one we just emitted, so we |
* don't get too many swaps outstanding for apps that are GPU-heavy |
* but not CPU-heavy. |
* |
* We're using intelDRI2Flush (called from the loader before |
* swapbuffer) and glFlush (for front buffer rendering) as the |
* indicator that a frame is done and then throttle when we get |
* here as we prepare to render the next frame. At this point for |
* round trips for swap/copy and getting new buffers are done and |
* we'll spend less time waiting on the GPU. |
* |
* Unfortunately, we don't have a handle to the batch containing |
* the swap, and getting our hands on that doesn't seem worth it, |
* so we just us the first batch we emitted after the last swap. |
*/ |
if (intel->need_throttle && intel->first_post_swapbuffers_batch) { |
if (!intel->disable_throttling) |
drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch); |
drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); |
intel->first_post_swapbuffers_batch = NULL; |
intel->need_throttle = false; |
} |
} |
static void |
intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
{ |
struct intel_context *intel = intel_context(ctx); |
__DRIcontext *driContext = intel->driContext; |
if (intel->saved_viewport) |
intel->saved_viewport(ctx, x, y, w, h); |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
dri2InvalidateDrawable(driContext->driDrawablePriv); |
dri2InvalidateDrawable(driContext->driReadablePriv); |
} |
} |
static const struct dri_debug_control debug_control[] = { |
{ "tex", DEBUG_TEXTURE}, |
{ "state", DEBUG_STATE}, |
{ "blit", DEBUG_BLIT}, |
{ "mip", DEBUG_MIPTREE}, |
{ "fall", DEBUG_PERF}, |
{ "perf", DEBUG_PERF}, |
{ "bat", DEBUG_BATCH}, |
{ "pix", DEBUG_PIXEL}, |
{ "buf", DEBUG_BUFMGR}, |
{ "reg", DEBUG_REGION}, |
{ "fbo", DEBUG_FBO}, |
{ "fs", DEBUG_WM }, |
{ "sync", DEBUG_SYNC}, |
{ "dri", DEBUG_DRI }, |
{ "stats", DEBUG_STATS }, |
{ "wm", DEBUG_WM }, |
{ "aub", DEBUG_AUB }, |
{ NULL, 0 } |
}; |
static void |
intelInvalidateState(struct gl_context * ctx, GLuint new_state) |
{ |
struct intel_context *intel = intel_context(ctx); |
if (ctx->swrast_context) |
_swrast_InvalidateState(ctx, new_state); |
_vbo_InvalidateState(ctx, new_state); |
intel->NewGLState |= new_state; |
if (intel->vtbl.invalidate_state) |
intel->vtbl.invalidate_state( intel, new_state ); |
} |
void |
intel_flush_rendering_to_batch(struct gl_context *ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
if (intel->Fallback) |
_swrast_flush(ctx); |
INTEL_FIREVERTICES(intel); |
} |
void |
_intel_flush(struct gl_context *ctx, const char *file, int line) |
{ |
struct intel_context *intel = intel_context(ctx); |
intel_flush_rendering_to_batch(ctx); |
if (intel->batch.used) |
_intel_batchbuffer_flush(intel, file, line); |
} |
static void |
intel_glFlush(struct gl_context *ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
intel_flush(ctx); |
intel_flush_front(ctx); |
if (intel->is_front_buffer_rendering) |
intel->need_throttle = true; |
} |
void |
intelFinish(struct gl_context * ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
intel_flush(ctx); |
intel_flush_front(ctx); |
if (intel->batch.last_bo) |
drm_intel_bo_wait_rendering(intel->batch.last_bo); |
} |
void |
intelInitDriverFunctions(struct dd_function_table *functions) |
{ |
_mesa_init_driver_functions(functions); |
functions->Flush = intel_glFlush; |
functions->Finish = intelFinish; |
functions->GetString = intelGetString; |
functions->UpdateState = intelInvalidateState; |
intelInitTextureFuncs(functions); |
intelInitTextureImageFuncs(functions); |
intelInitTextureSubImageFuncs(functions); |
intelInitTextureCopyImageFuncs(functions); |
intelInitClearFuncs(functions); |
intelInitBufferFuncs(functions); |
intelInitPixelFuncs(functions); |
intelInitBufferObjectFuncs(functions); |
intel_init_syncobj_functions(functions); |
} |
static bool |
validate_context_version(struct intel_screen *screen, |
int mesa_api, |
unsigned major_version, |
unsigned minor_version, |
unsigned *dri_ctx_error) |
{ |
unsigned req_version = 10 * major_version + minor_version; |
unsigned max_version = 0; |
switch (mesa_api) { |
case API_OPENGL_COMPAT: |
max_version = screen->max_gl_compat_version; |
break; |
case API_OPENGL_CORE: |
max_version = screen->max_gl_core_version; |
break; |
case API_OPENGLES: |
max_version = screen->max_gl_es1_version; |
break; |
case API_OPENGLES2: |
max_version = screen->max_gl_es2_version; |
break; |
default: |
max_version = 0; |
break; |
} |
if (max_version == 0) { |
*dri_ctx_error = __DRI_CTX_ERROR_BAD_API; |
return false; |
} else if (req_version > max_version) { |
*dri_ctx_error = __DRI_CTX_ERROR_BAD_VERSION; |
return false; |
} |
return true; |
} |
bool |
intelInitContext(struct intel_context *intel, |
int api, |
unsigned major_version, |
unsigned minor_version, |
const struct gl_config * mesaVis, |
__DRIcontext * driContextPriv, |
void *sharedContextPrivate, |
struct dd_function_table *functions, |
unsigned *dri_ctx_error) |
{ |
struct gl_context *ctx = &intel->ctx; |
struct gl_context *shareCtx = (struct gl_context *) sharedContextPrivate; |
__DRIscreen *sPriv = driContextPriv->driScreenPriv; |
struct intel_screen *intelScreen = sPriv->driverPrivate; |
int bo_reuse_mode; |
struct gl_config visual; |
/* we can't do anything without a connection to the device */ |
if (intelScreen->bufmgr == NULL) { |
*dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY; |
return false; |
} |
if (!validate_context_version(intelScreen, |
api, major_version, minor_version, |
dri_ctx_error)) |
return false; |
/* Can't rely on invalidate events, fall back to glViewport hack */ |
if (!driContextPriv->driScreenPriv->dri2.useInvalidate) { |
intel->saved_viewport = functions->Viewport; |
functions->Viewport = intel_viewport; |
} |
if (mesaVis == NULL) { |
memset(&visual, 0, sizeof visual); |
mesaVis = &visual; |
} |
intel->intelScreen = intelScreen; |
if (!_mesa_initialize_context(&intel->ctx, api, mesaVis, shareCtx, |
functions)) { |
*dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY; |
printf("%s: failed to init mesa context\n", __FUNCTION__); |
return false; |
} |
driContextPriv->driverPrivate = intel; |
intel->driContext = driContextPriv; |
intel->driFd = sPriv->fd; |
intel->gen = intelScreen->gen; |
const int devID = intelScreen->deviceID; |
intel->is_945 = IS_945(devID); |
intel->has_swizzling = intel->intelScreen->hw_has_swizzling; |
memset(&ctx->TextureFormatSupported, |
0, sizeof(ctx->TextureFormatSupported)); |
driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache, |
sPriv->myNum, "i915"); |
intel->maxBatchSize = 4096; |
/* Estimate the size of the mappable aperture into the GTT. There's an |
* ioctl to get the whole GTT size, but not one to get the mappable subset. |
* It turns out it's basically always 256MB, though some ancient hardware |
* was smaller. |
*/ |
uint32_t gtt_size = 256 * 1024 * 1024; |
if (intel->gen == 2) |
gtt_size = 128 * 1024 * 1024; |
/* We don't want to map two objects such that a memcpy between them would |
* just fault one mapping in and then the other over and over forever. So |
* we would need to divide the GTT size by 2. Additionally, some GTT is |
* taken up by things like the framebuffer and the ringbuffer and such, so |
* be more conservative. |
*/ |
intel->max_gtt_map_object_size = gtt_size / 4; |
intel->bufmgr = intelScreen->bufmgr; |
bo_reuse_mode = driQueryOptioni(&intel->optionCache, "bo_reuse"); |
switch (bo_reuse_mode) { |
case DRI_CONF_BO_REUSE_DISABLED: |
break; |
case DRI_CONF_BO_REUSE_ALL: |
intel_bufmgr_gem_enable_reuse(intel->bufmgr); |
break; |
} |
ctx->Const.MinLineWidth = 1.0; |
ctx->Const.MinLineWidthAA = 1.0; |
ctx->Const.MaxLineWidth = 5.0; |
ctx->Const.MaxLineWidthAA = 5.0; |
ctx->Const.LineWidthGranularity = 0.5; |
ctx->Const.MinPointSize = 1.0; |
ctx->Const.MinPointSizeAA = 1.0; |
ctx->Const.MaxPointSize = 255.0; |
ctx->Const.MaxPointSizeAA = 3.0; |
ctx->Const.PointSizeGranularity = 1.0; |
ctx->Const.StripTextureBorder = GL_TRUE; |
/* reinitialize the context point state. |
* It depend on constants in __struct gl_contextRec::Const |
*/ |
_mesa_init_point(ctx); |
ctx->Const.MaxRenderbufferSize = 2048; |
_swrast_CreateContext(ctx); |
_vbo_CreateContext(ctx); |
if (ctx->swrast_context) { |
_tnl_CreateContext(ctx); |
_swsetup_CreateContext(ctx); |
/* Configure swrast to match hardware characteristics: */ |
_swrast_allow_pixel_fog(ctx, false); |
_swrast_allow_vertex_fog(ctx, true); |
} |
_mesa_meta_init(ctx); |
intel->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24; |
intel->hw_stipple = 1; |
intel->RenderIndex = ~0; |
intelInitExtensions(ctx); |
INTEL_DEBUG = driParseDebugString(getenv("INTEL_DEBUG"), debug_control); |
if (INTEL_DEBUG & DEBUG_BUFMGR) |
dri_bufmgr_set_debug(intel->bufmgr, true); |
if (INTEL_DEBUG & DEBUG_PERF) |
intel->perf_debug = true; |
if (INTEL_DEBUG & DEBUG_AUB) |
drm_intel_bufmgr_gem_set_aub_dump(intel->bufmgr, true); |
intel_batchbuffer_init(intel); |
intel_fbo_init(intel); |
intel->use_early_z = driQueryOptionb(&intel->optionCache, "early_z"); |
intel->prim.primitive = ~0; |
/* Force all software fallbacks */ |
if (driQueryOptionb(&intel->optionCache, "no_rast")) { |
fprintf(stderr, "disabling 3D rasterization\n"); |
intel->no_rast = 1; |
} |
if (driQueryOptionb(&intel->optionCache, "always_flush_batch")) { |
fprintf(stderr, "flushing batchbuffer before/after each draw call\n"); |
intel->always_flush_batch = 1; |
} |
if (driQueryOptionb(&intel->optionCache, "always_flush_cache")) { |
fprintf(stderr, "flushing GPU caches before/after each draw call\n"); |
intel->always_flush_cache = 1; |
} |
if (driQueryOptionb(&intel->optionCache, "disable_throttling")) { |
fprintf(stderr, "disabling flush throttling\n"); |
intel->disable_throttling = 1; |
} |
return true; |
} |
void |
intelDestroyContext(__DRIcontext * driContextPriv) |
{ |
struct intel_context *intel = |
(struct intel_context *) driContextPriv->driverPrivate; |
struct gl_context *ctx = &intel->ctx; |
assert(intel); /* should never be null */ |
if (intel) { |
INTEL_FIREVERTICES(intel); |
/* Dump a final BMP in case the application doesn't call SwapBuffers */ |
if (INTEL_DEBUG & DEBUG_AUB) { |
intel_batchbuffer_flush(intel); |
aub_dump_bmp(&intel->ctx); |
} |
_mesa_meta_free(&intel->ctx); |
intel->vtbl.destroy(intel); |
if (ctx->swrast_context) { |
_swsetup_DestroyContext(&intel->ctx); |
_tnl_DestroyContext(&intel->ctx); |
} |
_vbo_DestroyContext(&intel->ctx); |
if (ctx->swrast_context) |
_swrast_DestroyContext(&intel->ctx); |
intel->Fallback = 0x0; /* don't call _swrast_Flush later */ |
intel_batchbuffer_free(intel); |
free(intel->prim.vb); |
intel->prim.vb = NULL; |
drm_intel_bo_unreference(intel->prim.vb_bo); |
intel->prim.vb_bo = NULL; |
drm_intel_bo_unreference(intel->first_post_swapbuffers_batch); |
intel->first_post_swapbuffers_batch = NULL; |
driDestroyOptionCache(&intel->optionCache); |
/* free the Mesa context */ |
_mesa_free_context_data(&intel->ctx); |
_math_matrix_dtr(&intel->ViewportMatrix); |
ralloc_free(intel); |
driContextPriv->driverPrivate = NULL; |
} |
} |
GLboolean |
intelUnbindContext(__DRIcontext * driContextPriv) |
{ |
/* Unset current context and dispath table */ |
_mesa_make_current(NULL, NULL, NULL); |
return true; |
} |
GLboolean |
intelMakeCurrent(__DRIcontext * driContextPriv, |
__DRIdrawable * driDrawPriv, |
__DRIdrawable * driReadPriv) |
{ |
struct intel_context *intel; |
GET_CURRENT_CONTEXT(curCtx); |
if (driContextPriv) |
intel = (struct intel_context *) driContextPriv->driverPrivate; |
else |
intel = NULL; |
/* According to the glXMakeCurrent() man page: "Pending commands to |
* the previous context, if any, are flushed before it is released." |
* But only flush if we're actually changing contexts. |
*/ |
if (intel_context(curCtx) && intel_context(curCtx) != intel) { |
_mesa_flush(curCtx); |
} |
if (driContextPriv) { |
struct gl_context *ctx = &intel->ctx; |
struct gl_framebuffer *fb, *readFb; |
if (driDrawPriv == NULL && driReadPriv == NULL) { |
fb = _mesa_get_incomplete_framebuffer(); |
readFb = _mesa_get_incomplete_framebuffer(); |
} else { |
fb = driDrawPriv->driverPrivate; |
readFb = driReadPriv->driverPrivate; |
driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; |
driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; |
} |
intel_prepare_render(intel); |
_mesa_make_current(ctx, fb, readFb); |
/* We do this in intel_prepare_render() too, but intel->ctx.DrawBuffer |
* is NULL at that point. We can't call _mesa_makecurrent() |
* first, since we need the buffer size for the initial |
* viewport. So just call intel_draw_buffer() again here. */ |
intel_draw_buffer(ctx); |
} |
else { |
_mesa_make_current(NULL, NULL, NULL); |
} |
return true; |
} |
/** |
* \brief Query DRI2 to obtain a DRIdrawable's buffers. |
* |
* To determine which DRI buffers to request, examine the renderbuffers |
* attached to the drawable's framebuffer. Then request the buffers with |
* DRI2GetBuffers() or DRI2GetBuffersWithFormat(). |
* |
* This is called from intel_update_renderbuffers(). |
* |
* \param drawable Drawable whose buffers are queried. |
* \param buffers [out] List of buffers returned by DRI2 query. |
* \param buffer_count [out] Number of buffers returned. |
* |
* \see intel_update_renderbuffers() |
* \see DRI2GetBuffers() |
* \see DRI2GetBuffersWithFormat() |
*/ |
static void |
intel_query_dri2_buffers(struct intel_context *intel, |
__DRIdrawable *drawable, |
__DRIbuffer **buffers, |
int *buffer_count) |
{ |
__DRIscreen *screen = intel->intelScreen->driScrnPriv; |
struct gl_framebuffer *fb = drawable->driverPrivate; |
int i = 0; |
unsigned attachments[8]; |
struct intel_renderbuffer *front_rb; |
struct intel_renderbuffer *back_rb; |
front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); |
memset(attachments, 0, sizeof(attachments)); |
if ((intel->is_front_buffer_rendering || |
intel->is_front_buffer_reading || |
!back_rb) && front_rb) { |
/* If a fake front buffer is in use, then querying for |
* __DRI_BUFFER_FRONT_LEFT will cause the server to copy the image from |
* the real front buffer to the fake front buffer. So before doing the |
* query, we need to make sure all the pending drawing has landed in the |
* real front buffer. |
*/ |
intel_flush(&intel->ctx); |
intel_flush_front(&intel->ctx); |
attachments[i++] = __DRI_BUFFER_FRONT_LEFT; |
attachments[i++] = intel_bits_per_pixel(front_rb); |
} else if (front_rb && intel->front_buffer_dirty) { |
/* We have pending front buffer rendering, but we aren't querying for a |
* front buffer. If the front buffer we have is a fake front buffer, |
* the X server is going to throw it away when it processes the query. |
* So before doing the query, make sure all the pending drawing has |
* landed in the real front buffer. |
*/ |
intel_flush(&intel->ctx); |
intel_flush_front(&intel->ctx); |
} |
if (back_rb) { |
attachments[i++] = __DRI_BUFFER_BACK_LEFT; |
attachments[i++] = intel_bits_per_pixel(back_rb); |
} |
assert(i <= ARRAY_SIZE(attachments)); |
*buffers = screen->dri2.loader->getBuffersWithFormat(drawable, |
&drawable->w, |
&drawable->h, |
attachments, i / 2, |
buffer_count, |
drawable->loaderPrivate); |
} |
/** |
* \brief Assign a DRI buffer's DRM region to a renderbuffer. |
* |
* This is called from intel_update_renderbuffers(). |
* |
* \par Note: |
* DRI buffers whose attachment point is DRI2BufferStencil or |
* DRI2BufferDepthStencil are handled as special cases. |
* |
* \param buffer_name is a human readable name, such as "dri2 front buffer", |
* that is passed to intel_region_alloc_for_handle(). |
* |
* \see intel_update_renderbuffers() |
* \see intel_region_alloc_for_handle() |
*/ |
static void |
intel_process_dri2_buffer(struct intel_context *intel, |
__DRIdrawable *drawable, |
__DRIbuffer *buffer, |
struct intel_renderbuffer *rb, |
const char *buffer_name) |
{ |
struct intel_region *region = NULL; |
if (!rb) |
return; |
/* We try to avoid closing and reopening the same BO name, because the first |
* use of a mapping of the buffer involves a bunch of page faulting which is |
* moderately expensive. |
*/ |
if (rb->mt && |
rb->mt->region && |
rb->mt->region->name == buffer->name) |
return; |
if (unlikely(INTEL_DEBUG & DEBUG_DRI)) { |
fprintf(stderr, |
"attaching buffer %d, at %d, cpp %d, pitch %d\n", |
buffer->name, buffer->attachment, |
buffer->cpp, buffer->pitch); |
} |
intel_miptree_release(&rb->mt); |
region = intel_region_alloc_for_handle(intel->intelScreen, |
buffer->cpp, |
drawable->w, |
drawable->h, |
buffer->pitch, |
buffer->name, |
buffer_name); |
if (!region) |
return; |
rb->mt = intel_miptree_create_for_dri2_buffer(intel, |
buffer->attachment, |
intel_rb_format(rb), |
region); |
intel_region_release(®ion); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_context.h |
---|
0,0 → 1,540 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTELCONTEXT_INC |
#define INTELCONTEXT_INC |
#include <stdbool.h> |
#include <string.h> |
#include "main/mtypes.h" |
#include "main/mm.h" |
#ifdef __cplusplus |
extern "C" { |
/* Evil hack for using libdrm in a c++ compiler. */ |
#define virtual virt |
#endif |
#include "drm.h" |
#include "intel_bufmgr.h" |
#include "intel_screen.h" |
#include "intel_tex_obj.h" |
#include "i915_drm.h" |
#ifdef __cplusplus |
#undef virtual |
#endif |
#include "tnl/t_vertex.h" |
#define TAG(x) intel##x |
#include "tnl_dd/t_dd_vertex.h" |
#undef TAG |
#define DV_PF_555 (1<<8) |
#define DV_PF_565 (2<<8) |
#define DV_PF_8888 (3<<8) |
#define DV_PF_4444 (8<<8) |
#define DV_PF_1555 (9<<8) |
struct intel_region; |
struct intel_context; |
typedef void (*intel_tri_func) (struct intel_context *, intelVertex *, |
intelVertex *, intelVertex *); |
typedef void (*intel_line_func) (struct intel_context *, intelVertex *, |
intelVertex *); |
typedef void (*intel_point_func) (struct intel_context *, intelVertex *); |
/** |
* Bits for intel->Fallback field |
*/ |
/*@{*/ |
#define INTEL_FALLBACK_DRAW_BUFFER 0x1 |
#define INTEL_FALLBACK_READ_BUFFER 0x2 |
#define INTEL_FALLBACK_DEPTH_BUFFER 0x4 |
#define INTEL_FALLBACK_STENCIL_BUFFER 0x8 |
#define INTEL_FALLBACK_USER 0x10 |
#define INTEL_FALLBACK_RENDERMODE 0x20 |
#define INTEL_FALLBACK_TEXTURE 0x40 |
#define INTEL_FALLBACK_DRIVER 0x1000 /**< first for drivers */ |
/*@}*/ |
extern void intelFallback(struct intel_context *intel, GLbitfield bit, |
bool mode); |
#define FALLBACK( intel, bit, mode ) intelFallback( intel, bit, mode ) |
#define INTEL_WRITE_PART 0x1 |
#define INTEL_WRITE_FULL 0x2 |
#define INTEL_READ 0x4 |
#ifndef likely |
#ifdef __GNUC__ |
#define likely(expr) (__builtin_expect(expr, 1)) |
#define unlikely(expr) (__builtin_expect(expr, 0)) |
#else |
#define likely(expr) (expr) |
#define unlikely(expr) (expr) |
#endif |
#endif |
struct intel_sync_object { |
struct gl_sync_object Base; |
/** Batch associated with this sync object */ |
drm_intel_bo *bo; |
}; |
struct intel_batchbuffer { |
/** Current batchbuffer being queued up. */ |
drm_intel_bo *bo; |
/** Last BO submitted to the hardware. Used for glFinish(). */ |
drm_intel_bo *last_bo; |
uint16_t emit, total; |
uint16_t used, reserved_space; |
uint32_t *map; |
uint32_t *cpu_map; |
#define BATCH_SZ (8192*sizeof(uint32_t)) |
}; |
/** |
* intel_context is derived from Mesa's context class: struct gl_context. |
*/ |
struct intel_context |
{ |
struct gl_context ctx; /**< base class, must be first field */ |
struct |
{ |
void (*destroy) (struct intel_context * intel); |
void (*emit_state) (struct intel_context * intel); |
void (*finish_batch) (struct intel_context * intel); |
void (*new_batch) (struct intel_context * intel); |
void (*emit_invarient_state) (struct intel_context * intel); |
void (*update_texture_state) (struct intel_context * intel); |
void (*render_start) (struct intel_context * intel); |
void (*render_prevalidate) (struct intel_context * intel); |
void (*set_draw_region) (struct intel_context * intel, |
struct intel_region * draw_regions[], |
struct intel_region * depth_region, |
GLuint num_regions); |
void (*update_draw_buffer)(struct intel_context *intel); |
void (*reduced_primitive_state) (struct intel_context * intel, |
GLenum rprim); |
bool (*check_vertex_size) (struct intel_context * intel, |
GLuint expected); |
void (*invalidate_state) (struct intel_context *intel, |
GLuint new_state); |
void (*assert_not_dirty) (struct intel_context *intel); |
void (*debug_batch)(struct intel_context *intel); |
void (*annotate_aub)(struct intel_context *intel); |
bool (*render_target_supported)(struct intel_context *intel, |
struct gl_renderbuffer *rb); |
} vtbl; |
GLbitfield Fallback; /**< mask of INTEL_FALLBACK_x bits */ |
GLuint NewGLState; |
dri_bufmgr *bufmgr; |
unsigned int maxBatchSize; |
/** |
* Generation number of the hardware: 2 is 8xx, 3 is 9xx pre-965, 4 is 965. |
*/ |
int gen; |
bool is_945; |
bool has_swizzling; |
struct intel_batchbuffer batch; |
drm_intel_bo *first_post_swapbuffers_batch; |
bool need_throttle; |
bool no_batch_wrap; |
bool tnl_pipeline_running; /**< Set while i915's _tnl_run_pipeline. */ |
/** |
* Set if we're either a debug context or the INTEL_DEBUG=perf environment |
* variable is set, this is the flag indicating to do expensive work that |
* might lead to a perf_debug() call. |
*/ |
bool perf_debug; |
struct |
{ |
GLuint id; |
uint32_t start_ptr; /**< for i8xx */ |
uint32_t primitive; /**< Current hardware primitive type */ |
void (*flush) (struct intel_context *); |
drm_intel_bo *vb_bo; |
uint8_t *vb; |
unsigned int start_offset; /**< Byte offset of primitive sequence */ |
unsigned int current_offset; /**< Byte offset of next vertex */ |
unsigned int count; /**< Number of vertices in current primitive */ |
} prim; |
struct { |
drm_intel_bo *bo; |
GLuint offset; |
uint32_t buffer_len; |
uint32_t buffer_offset; |
char buffer[4096]; |
} upload; |
uint32_t max_gtt_map_object_size; |
/* Offsets of fields within the current vertex: |
*/ |
GLuint coloroffset; |
GLuint specoffset; |
GLuint wpos_offset; |
struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX]; |
GLuint vertex_attr_count; |
GLfloat polygon_offset_scale; /* dependent on depth_scale, bpp */ |
bool hw_stencil; |
bool hw_stipple; |
bool no_rast; |
bool always_flush_batch; |
bool always_flush_cache; |
bool disable_throttling; |
/* State for intelvb.c and inteltris.c. |
*/ |
GLuint RenderIndex; |
GLmatrix ViewportMatrix; |
GLenum render_primitive; |
GLenum reduced_primitive; /*< Only gen < 6 */ |
GLuint vertex_size; |
GLubyte *verts; /* points to tnl->clipspace.vertex_buf */ |
/* Fallback rasterization functions |
*/ |
intel_point_func draw_point; |
intel_line_func draw_line; |
intel_tri_func draw_tri; |
/** |
* Set if rendering has occured to the drawable's front buffer. |
* |
* This is used in the DRI2 case to detect that glFlush should also copy |
* the contents of the fake front buffer to the real front buffer. |
*/ |
bool front_buffer_dirty; |
/** |
* Track whether front-buffer rendering is currently enabled |
* |
* A separate flag is used to track this in order to support MRT more |
* easily. |
*/ |
bool is_front_buffer_rendering; |
/** |
* Track whether front-buffer is the current read target. |
* |
* This is closely associated with is_front_buffer_rendering, but may |
* be set separately. The DRI2 fake front buffer must be referenced |
* either way. |
*/ |
bool is_front_buffer_reading; |
bool use_early_z; |
int driFd; |
__DRIcontext *driContext; |
struct intel_screen *intelScreen; |
void (*saved_viewport)(struct gl_context * ctx, |
GLint x, GLint y, GLsizei width, GLsizei height); |
/** |
* Configuration cache |
*/ |
driOptionCache optionCache; |
}; |
extern char *__progname; |
#define SUBPIXEL_X 0.125 |
#define SUBPIXEL_Y 0.125 |
/** |
* Align a value down to an alignment value |
* |
* If \c value is not already aligned to the requested alignment value, it |
* will be rounded down. |
* |
* \param value Value to be rounded |
* \param alignment Alignment value to be used. This must be a power of two. |
* |
* \sa ALIGN() |
*/ |
#define ROUND_DOWN_TO(value, alignment) ((value) & ~(alignment - 1)) |
static INLINE uint32_t |
U_FIXED(float value, uint32_t frac_bits) |
{ |
value *= (1 << frac_bits); |
return value < 0 ? 0 : value; |
} |
static INLINE uint32_t |
S_FIXED(float value, uint32_t frac_bits) |
{ |
return value * (1 << frac_bits); |
} |
#define INTEL_FIREVERTICES(intel) \ |
do { \ |
if ((intel)->prim.flush) \ |
(intel)->prim.flush(intel); \ |
} while (0) |
/* ================================================================ |
* From linux kernel i386 header files, copes with odd sizes better |
* than COPY_DWORDS would: |
* XXX Put this in src/mesa/main/imports.h ??? |
*/ |
#if defined(i386) || defined(__i386__) |
static INLINE void * __memcpy(void * to, const void * from, size_t n) |
{ |
int d0, d1, d2; |
__asm__ __volatile__( |
"rep ; movsl\n\t" |
"testb $2,%b4\n\t" |
"je 1f\n\t" |
"movsw\n" |
"1:\ttestb $1,%b4\n\t" |
"je 2f\n\t" |
"movsb\n" |
"2:" |
: "=&c" (d0), "=&D" (d1), "=&S" (d2) |
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) |
: "memory"); |
return (to); |
} |
#else |
#define __memcpy(a,b,c) memcpy(a,b,c) |
#endif |
/* ================================================================ |
* Debugging: |
*/ |
extern int INTEL_DEBUG; |
#define DEBUG_TEXTURE 0x1 |
#define DEBUG_STATE 0x2 |
#define DEBUG_BLIT 0x8 |
#define DEBUG_MIPTREE 0x10 |
#define DEBUG_PERF 0x20 |
#define DEBUG_BATCH 0x80 |
#define DEBUG_PIXEL 0x100 |
#define DEBUG_BUFMGR 0x200 |
#define DEBUG_REGION 0x400 |
#define DEBUG_FBO 0x800 |
#define DEBUG_SYNC 0x2000 |
#define DEBUG_DRI 0x10000 |
#define DEBUG_STATS 0x100000 |
#define DEBUG_WM 0x400000 |
#define DEBUG_AUB 0x4000000 |
#ifdef HAVE_ANDROID_PLATFORM |
#define LOG_TAG "INTEL-MESA" |
#include <cutils/log.h> |
#ifndef ALOGW |
#define ALOGW LOGW |
#endif |
#define dbg_printf(...) ALOGW(__VA_ARGS__) |
#else |
#define dbg_printf(...) printf(__VA_ARGS__) |
#endif /* HAVE_ANDROID_PLATFORM */ |
#define DBG(...) do { \ |
if (unlikely(INTEL_DEBUG & FILE_DEBUG_FLAG)) \ |
dbg_printf(__VA_ARGS__); \ |
} while(0) |
#define perf_debug(...) do { \ |
static GLuint msg_id = 0; \ |
if (unlikely(INTEL_DEBUG & DEBUG_PERF)) \ |
dbg_printf(__VA_ARGS__); \ |
if (intel->perf_debug) \ |
_mesa_gl_debug(&intel->ctx, &msg_id, \ |
MESA_DEBUG_TYPE_PERFORMANCE, \ |
MESA_DEBUG_SEVERITY_MEDIUM, \ |
__VA_ARGS__); \ |
} while(0) |
#define WARN_ONCE(cond, fmt...) do { \ |
if (unlikely(cond)) { \ |
static bool _warned = false; \ |
static GLuint msg_id = 0; \ |
if (!_warned) { \ |
fprintf(stderr, "WARNING: "); \ |
fprintf(stderr, fmt); \ |
_warned = true; \ |
\ |
_mesa_gl_debug(ctx, &msg_id, \ |
MESA_DEBUG_TYPE_OTHER, \ |
MESA_DEBUG_SEVERITY_HIGH, fmt); \ |
} \ |
} \ |
} while (0) |
/* ================================================================ |
* intel_context.c: |
*/ |
extern bool intelInitContext(struct intel_context *intel, |
int api, |
unsigned major_version, |
unsigned minor_version, |
const struct gl_config * mesaVis, |
__DRIcontext * driContextPriv, |
void *sharedContextPrivate, |
struct dd_function_table *functions, |
unsigned *dri_ctx_error); |
extern void intelFinish(struct gl_context * ctx); |
extern void intel_flush_rendering_to_batch(struct gl_context *ctx); |
extern void _intel_flush(struct gl_context * ctx, const char *file, int line); |
#define intel_flush(ctx) _intel_flush(ctx, __FILE__, __LINE__) |
extern void intelInitDriverFunctions(struct dd_function_table *functions); |
void intel_init_syncobj_functions(struct dd_function_table *functions); |
/* ================================================================ |
* intel_state.c: |
*/ |
#define COMPAREFUNC_ALWAYS 0 |
#define COMPAREFUNC_NEVER 0x1 |
#define COMPAREFUNC_LESS 0x2 |
#define COMPAREFUNC_EQUAL 0x3 |
#define COMPAREFUNC_LEQUAL 0x4 |
#define COMPAREFUNC_GREATER 0x5 |
#define COMPAREFUNC_NOTEQUAL 0x6 |
#define COMPAREFUNC_GEQUAL 0x7 |
#define STENCILOP_KEEP 0 |
#define STENCILOP_ZERO 0x1 |
#define STENCILOP_REPLACE 0x2 |
#define STENCILOP_INCRSAT 0x3 |
#define STENCILOP_DECRSAT 0x4 |
#define STENCILOP_INCR 0x5 |
#define STENCILOP_DECR 0x6 |
#define STENCILOP_INVERT 0x7 |
#define LOGICOP_CLEAR 0 |
#define LOGICOP_NOR 0x1 |
#define LOGICOP_AND_INV 0x2 |
#define LOGICOP_COPY_INV 0x3 |
#define LOGICOP_AND_RVRSE 0x4 |
#define LOGICOP_INV 0x5 |
#define LOGICOP_XOR 0x6 |
#define LOGICOP_NAND 0x7 |
#define LOGICOP_AND 0x8 |
#define LOGICOP_EQUIV 0x9 |
#define LOGICOP_NOOP 0xa |
#define LOGICOP_OR_INV 0xb |
#define LOGICOP_COPY 0xc |
#define LOGICOP_OR_RVRSE 0xd |
#define LOGICOP_OR 0xe |
#define LOGICOP_SET 0xf |
#define BLENDFACT_ZERO 0x01 |
#define BLENDFACT_ONE 0x02 |
#define BLENDFACT_SRC_COLR 0x03 |
#define BLENDFACT_INV_SRC_COLR 0x04 |
#define BLENDFACT_SRC_ALPHA 0x05 |
#define BLENDFACT_INV_SRC_ALPHA 0x06 |
#define BLENDFACT_DST_ALPHA 0x07 |
#define BLENDFACT_INV_DST_ALPHA 0x08 |
#define BLENDFACT_DST_COLR 0x09 |
#define BLENDFACT_INV_DST_COLR 0x0a |
#define BLENDFACT_SRC_ALPHA_SATURATE 0x0b |
#define BLENDFACT_CONST_COLOR 0x0c |
#define BLENDFACT_INV_CONST_COLOR 0x0d |
#define BLENDFACT_CONST_ALPHA 0x0e |
#define BLENDFACT_INV_CONST_ALPHA 0x0f |
#define BLENDFACT_MASK 0x0f |
enum { |
DRI_CONF_BO_REUSE_DISABLED, |
DRI_CONF_BO_REUSE_ALL |
}; |
extern int intel_translate_shadow_compare_func(GLenum func); |
extern int intel_translate_compare_func(GLenum func); |
extern int intel_translate_stencil_op(GLenum op); |
extern int intel_translate_blend_factor(GLenum factor); |
extern int intel_translate_logic_op(GLenum opcode); |
void intel_update_renderbuffers(__DRIcontext *context, |
__DRIdrawable *drawable); |
void intel_prepare_render(struct intel_context *intel); |
void i915_set_buf_info_for_region(uint32_t *state, struct intel_region *region, |
uint32_t buffer_id); |
void intel_init_texture_formats(struct gl_context *ctx); |
/*====================================================================== |
* Inline conversion functions. |
* These are better-typed than the macros used previously: |
*/ |
static INLINE struct intel_context * |
intel_context(struct gl_context * ctx) |
{ |
return (struct intel_context *) ctx; |
} |
static INLINE bool |
is_power_of_two(uint32_t value) |
{ |
return (value & (value - 1)) == 0; |
} |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_extensions.c |
---|
0,0 → 1,107 |
/************************************************************************** |
* |
* 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 "main/version.h" |
#include "intel_chipset.h" |
#include "intel_context.h" |
#include "intel_extensions.h" |
#include "intel_reg.h" |
#include "utils.h" |
/** |
* Initializes potential list of extensions if ctx == NULL, or actually enables |
* extensions for a context. |
*/ |
void |
intelInitExtensions(struct gl_context *ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
assert(intel->gen == 2 || intel->gen == 3); |
ctx->Extensions.ARB_draw_elements_base_vertex = true; |
ctx->Extensions.ARB_explicit_attrib_location = true; |
ctx->Extensions.ARB_framebuffer_object = true; |
ctx->Extensions.ARB_half_float_pixel = true; |
ctx->Extensions.ARB_internalformat_query = true; |
ctx->Extensions.ARB_map_buffer_range = true; |
ctx->Extensions.ARB_point_sprite = true; |
ctx->Extensions.ARB_sync = true; |
ctx->Extensions.ARB_texture_border_clamp = true; |
ctx->Extensions.ARB_texture_cube_map = true; |
ctx->Extensions.ARB_texture_env_combine = true; |
ctx->Extensions.ARB_texture_env_crossbar = true; |
ctx->Extensions.ARB_texture_env_dot3 = true; |
ctx->Extensions.ARB_vertex_program = true; |
ctx->Extensions.ARB_vertex_shader = true; |
ctx->Extensions.EXT_blend_color = true; |
ctx->Extensions.EXT_blend_equation_separate = true; |
ctx->Extensions.EXT_blend_func_separate = true; |
ctx->Extensions.EXT_blend_minmax = true; |
ctx->Extensions.EXT_framebuffer_blit = true; |
ctx->Extensions.EXT_gpu_program_parameters = true; |
ctx->Extensions.EXT_packed_depth_stencil = true; |
ctx->Extensions.EXT_pixel_buffer_object = true; |
ctx->Extensions.EXT_point_parameters = true; |
ctx->Extensions.EXT_provoking_vertex = true; |
ctx->Extensions.EXT_separate_shader_objects = true; |
ctx->Extensions.EXT_texture_env_dot3 = true; |
ctx->Extensions.EXT_texture_filter_anisotropic = true; |
ctx->Extensions.APPLE_object_purgeable = true; |
ctx->Extensions.MESA_pack_invert = true; |
ctx->Extensions.MESA_ycbcr_texture = true; |
ctx->Extensions.NV_texture_rectangle = true; |
ctx->Extensions.TDFX_texture_compression_FXT1 = true; |
ctx->Extensions.OES_EGL_image = true; |
ctx->Extensions.OES_draw_texture = true; |
ctx->Const.GLSLVersion = 120; |
_mesa_override_glsl_version(ctx); |
if (intel->gen >= 3) { |
ctx->Extensions.ARB_ES2_compatibility = true; |
ctx->Extensions.ARB_depth_texture = true; |
ctx->Extensions.ARB_fragment_program = true; |
ctx->Extensions.ARB_shadow = true; |
ctx->Extensions.ARB_texture_non_power_of_two = true; |
ctx->Extensions.EXT_texture_sRGB = true; |
ctx->Extensions.EXT_texture_sRGB_decode = true; |
ctx->Extensions.EXT_stencil_two_side = true; |
ctx->Extensions.ATI_separate_stencil = true; |
ctx->Extensions.ATI_texture_env_combine3 = true; |
ctx->Extensions.NV_texture_env_combine4 = true; |
ctx->Extensions.ARB_fragment_shader = true; |
ctx->Extensions.ARB_occlusion_query = true; |
} |
if (intel->ctx.Mesa_DXTn |
|| driQueryOptionb(&intel->optionCache, "force_s3tc_enable")) |
ctx->Extensions.EXT_texture_compression_s3tc = true; |
ctx->Extensions.ANGLE_texture_compression_dxt = true; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_extensions.h |
---|
0,0 → 1,42 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_EXTENSIONS_H |
#define INTEL_EXTENSIONS_H |
extern void |
intelInitExtensions(struct gl_context *ctx); |
extern void |
intelInitExtensionsES1(struct gl_context *ctx); |
extern void |
intelInitExtensionsES2(struct gl_context *ctx); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_fbo.c |
---|
0,0 → 1,757 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#include "main/enums.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/fbobject.h" |
#include "main/framebuffer.h" |
#include "main/renderbuffer.h" |
#include "main/context.h" |
#include "main/teximage.h" |
#include "main/image.h" |
#include "swrast/swrast.h" |
#include "drivers/common/meta.h" |
#include "intel_context.h" |
#include "intel_batchbuffer.h" |
#include "intel_buffers.h" |
#include "intel_blit.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_tex.h" |
#define FILE_DEBUG_FLAG DEBUG_FBO |
static struct gl_renderbuffer * |
intel_new_renderbuffer(struct gl_context * ctx, GLuint name); |
struct intel_region* |
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) |
{ |
struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex); |
if (irb && irb->mt) |
return irb->mt->region; |
else |
return NULL; |
} |
/** |
* Create a new framebuffer object. |
*/ |
static struct gl_framebuffer * |
intel_new_framebuffer(struct gl_context * ctx, GLuint name) |
{ |
/* Only drawable state in intel_framebuffer at this time, just use Mesa's |
* class |
*/ |
return _mesa_new_framebuffer(ctx, name); |
} |
/** Called by gl_renderbuffer::Delete() */ |
static void |
intel_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) |
{ |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
ASSERT(irb); |
intel_miptree_release(&irb->mt); |
_mesa_delete_renderbuffer(ctx, rb); |
} |
/** |
* \see dd_function_table::MapRenderbuffer |
*/ |
static void |
intel_map_renderbuffer(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **out_map, |
GLint *out_stride) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
void *map; |
int stride; |
if (srb->Buffer) { |
/* this is a malloc'd renderbuffer (accum buffer), not an irb */ |
GLint bpp = _mesa_get_format_bytes(rb->Format); |
GLint rowStride = srb->RowStride; |
*out_map = (GLubyte *) srb->Buffer + y * rowStride + x * bpp; |
*out_stride = rowStride; |
return; |
} |
intel_prepare_render(intel); |
/* For a window-system renderbuffer, we need to flip the mapping we receive |
* upside-down. So we need to ask for a rectangle on flipped vertically, and |
* we then return a pointer to the bottom of it with a negative stride. |
*/ |
if (rb->Name == 0) { |
y = rb->Height - y - h; |
} |
intel_miptree_map(intel, irb->mt, irb->mt_level, irb->mt_layer, |
x, y, w, h, mode, &map, &stride); |
if (rb->Name == 0) { |
map += (h - 1) * stride; |
stride = -stride; |
} |
DBG("%s: rb %d (%s) mt mapped: (%d, %d) (%dx%d) -> %p/%d\n", |
__FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format), |
x, y, w, h, map, stride); |
*out_map = map; |
*out_stride = stride; |
} |
/** |
* \see dd_function_table::UnmapRenderbuffer |
*/ |
static void |
intel_unmap_renderbuffer(struct gl_context *ctx, |
struct gl_renderbuffer *rb) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
DBG("%s: rb %d (%s)\n", __FUNCTION__, |
rb->Name, _mesa_get_format_name(rb->Format)); |
if (srb->Buffer) { |
/* this is a malloc'd renderbuffer (accum buffer) */ |
/* nothing to do */ |
return; |
} |
intel_miptree_unmap(intel, irb->mt, irb->mt_level, irb->mt_layer); |
} |
/** |
* Called via glRenderbufferStorageEXT() to set the format and allocate |
* storage for a user-created renderbuffer. |
*/ |
static GLboolean |
intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, |
GLuint width, GLuint height) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
switch (internalFormat) { |
default: |
/* Use the same format-choice logic as for textures. |
* Renderbuffers aren't any different from textures for us, |
* except they're less useful because you can't texture with |
* them. |
*/ |
rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, GL_TEXTURE_2D, |
internalFormat, |
GL_NONE, GL_NONE); |
break; |
case GL_STENCIL_INDEX: |
case GL_STENCIL_INDEX1_EXT: |
case GL_STENCIL_INDEX4_EXT: |
case GL_STENCIL_INDEX8_EXT: |
case GL_STENCIL_INDEX16_EXT: |
/* These aren't actual texture formats, so force them here. */ |
rb->Format = MESA_FORMAT_S8_Z24; |
break; |
} |
rb->Width = width; |
rb->Height = height; |
rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); |
intel_miptree_release(&irb->mt); |
DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(internalFormat), |
_mesa_get_format_name(rb->Format), width, height); |
if (width == 0 || height == 0) |
return true; |
irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format, |
width, height); |
if (!irb->mt) |
return false; |
return true; |
} |
static void |
intel_image_target_renderbuffer_storage(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
void *image_handle) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_renderbuffer *irb; |
__DRIscreen *screen; |
__DRIimage *image; |
screen = intel->intelScreen->driScrnPriv; |
image = screen->dri2.image->lookupEGLImage(screen, image_handle, |
screen->loaderPrivate); |
if (image == NULL) |
return; |
/* __DRIimage is opaque to the core so it has to be checked here */ |
switch (image->format) { |
case MESA_FORMAT_RGBA8888_REV: |
_mesa_error(&intel->ctx, GL_INVALID_OPERATION, |
"glEGLImageTargetRenderbufferStorage(unsupported image format"); |
return; |
break; |
default: |
break; |
} |
irb = intel_renderbuffer(rb); |
intel_miptree_release(&irb->mt); |
irb->mt = intel_miptree_create_for_bo(intel, |
image->region->bo, |
image->format, |
image->offset, |
image->region->width, |
image->region->height, |
image->region->pitch, |
image->region->tiling); |
if (!irb->mt) |
return; |
rb->InternalFormat = image->internal_format; |
rb->Width = image->region->width; |
rb->Height = image->region->height; |
rb->Format = image->format; |
rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx, |
image->internal_format); |
rb->NeedsFinishRenderTexture = true; |
} |
/** |
* Called by _mesa_resize_framebuffer() for each hardware renderbuffer when a |
* window system framebuffer is resized. |
* |
* Any actual buffer reallocations for hardware renderbuffers (which would |
* have triggered _mesa_resize_framebuffer()) were done by |
* intel_process_dri2_buffer(). |
*/ |
static GLboolean |
intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, GLuint width, GLuint height) |
{ |
ASSERT(rb->Name == 0); |
rb->Width = width; |
rb->Height = height; |
rb->InternalFormat = internalFormat; |
return true; |
} |
/** Dummy function for gl_renderbuffer::AllocStorage() */ |
static GLboolean |
intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, GLuint width, GLuint height) |
{ |
_mesa_problem(ctx, "intel_op_alloc_storage should never be called."); |
return false; |
} |
/** |
* Create a new intel_renderbuffer which corresponds to an on-screen window, |
* not a user-created renderbuffer. |
*/ |
struct intel_renderbuffer * |
intel_create_renderbuffer(gl_format format) |
{ |
struct intel_renderbuffer *irb; |
struct gl_renderbuffer *rb; |
GET_CURRENT_CONTEXT(ctx); |
irb = CALLOC_STRUCT(intel_renderbuffer); |
if (!irb) { |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); |
return NULL; |
} |
rb = &irb->Base.Base; |
_mesa_init_renderbuffer(rb, 0); |
rb->ClassID = INTEL_RB_CLASS; |
rb->_BaseFormat = _mesa_get_format_base_format(format); |
rb->Format = format; |
rb->InternalFormat = rb->_BaseFormat; |
/* intel-specific methods */ |
rb->Delete = intel_delete_renderbuffer; |
rb->AllocStorage = intel_alloc_window_storage; |
return irb; |
} |
/** |
* Private window-system buffers (as opposed to ones shared with the display |
* server created with intel_create_renderbuffer()) are most similar in their |
* handling to user-created renderbuffers, but they have a resize handler that |
* may be called at intel_update_renderbuffers() time. |
*/ |
struct intel_renderbuffer * |
intel_create_private_renderbuffer(gl_format format) |
{ |
struct intel_renderbuffer *irb; |
irb = intel_create_renderbuffer(format); |
irb->Base.Base.AllocStorage = intel_alloc_renderbuffer_storage; |
return irb; |
} |
/** |
* Create a new renderbuffer object. |
* Typically called via glBindRenderbufferEXT(). |
*/ |
static struct gl_renderbuffer * |
intel_new_renderbuffer(struct gl_context * ctx, GLuint name) |
{ |
/*struct intel_context *intel = intel_context(ctx); */ |
struct intel_renderbuffer *irb; |
struct gl_renderbuffer *rb; |
irb = CALLOC_STRUCT(intel_renderbuffer); |
if (!irb) { |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); |
return NULL; |
} |
rb = &irb->Base.Base; |
_mesa_init_renderbuffer(rb, name); |
rb->ClassID = INTEL_RB_CLASS; |
/* intel-specific methods */ |
rb->Delete = intel_delete_renderbuffer; |
rb->AllocStorage = intel_alloc_renderbuffer_storage; |
/* span routines set in alloc_storage function */ |
return rb; |
} |
/** |
* Called via glBindFramebufferEXT(). |
*/ |
static void |
intel_bind_framebuffer(struct gl_context * ctx, GLenum target, |
struct gl_framebuffer *fb, struct gl_framebuffer *fbread) |
{ |
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { |
intel_draw_buffer(ctx); |
} |
else { |
/* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ |
} |
} |
/** |
* Called via glFramebufferRenderbufferEXT(). |
*/ |
static void |
intel_framebuffer_renderbuffer(struct gl_context * ctx, |
struct gl_framebuffer *fb, |
GLenum attachment, struct gl_renderbuffer *rb) |
{ |
DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0); |
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); |
intel_draw_buffer(ctx); |
} |
static bool |
intel_renderbuffer_update_wrapper(struct intel_context *intel, |
struct intel_renderbuffer *irb, |
struct gl_texture_image *image, |
uint32_t layer) |
{ |
struct gl_renderbuffer *rb = &irb->Base.Base; |
struct intel_texture_image *intel_image = intel_texture_image(image); |
struct intel_mipmap_tree *mt = intel_image->mt; |
int level = image->Level; |
rb->Depth = image->Depth; |
rb->AllocStorage = intel_nop_alloc_storage; |
intel_miptree_check_level_layer(mt, level, layer); |
irb->mt_level = level; |
irb->mt_layer = layer; |
intel_miptree_reference(&irb->mt, mt); |
intel_renderbuffer_set_draw_offset(irb); |
return true; |
} |
void |
intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb) |
{ |
unsigned int dst_x, dst_y; |
/* compute offset of the particular 2D image within the texture region */ |
intel_miptree_get_image_offset(irb->mt, |
irb->mt_level, |
irb->mt_layer, |
&dst_x, &dst_y); |
irb->draw_x = dst_x; |
irb->draw_y = dst_y; |
} |
/** |
* Called by glFramebufferTexture[123]DEXT() (and other places) to |
* prepare for rendering into texture memory. This might be called |
* many times to choose different texture levels, cube faces, etc |
* before intel_finish_render_texture() is ever called. |
*/ |
static void |
intel_render_texture(struct gl_context * ctx, |
struct gl_framebuffer *fb, |
struct gl_renderbuffer_attachment *att) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct gl_renderbuffer *rb = att->Renderbuffer; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
struct gl_texture_image *image = rb->TexImage; |
struct intel_texture_image *intel_image = intel_texture_image(image); |
struct intel_mipmap_tree *mt = intel_image->mt; |
int layer; |
(void) fb; |
if (att->CubeMapFace > 0) { |
assert(att->Zoffset == 0); |
layer = att->CubeMapFace; |
} else { |
layer = att->Zoffset; |
} |
if (!intel_image->mt) { |
/* Fallback on drawing to a texture that doesn't have a miptree |
* (has a border, width/height 0, etc.) |
*/ |
_swrast_render_texture(ctx, fb, att); |
return; |
} |
intel_miptree_check_level_layer(mt, att->TextureLevel, layer); |
if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { |
_swrast_render_texture(ctx, fb, att); |
return; |
} |
DBG("Begin render %s texture tex=%u w=%d h=%d d=%d refcount=%d\n", |
_mesa_get_format_name(image->TexFormat), |
att->Texture->Name, image->Width, image->Height, image->Depth, |
rb->RefCount); |
/* update drawing region, etc */ |
intel_draw_buffer(ctx); |
} |
/** |
* Called by Mesa when rendering to a texture is done. |
*/ |
static void |
intel_finish_render_texture(struct gl_context * ctx, struct gl_renderbuffer *rb) |
{ |
struct intel_context *intel = intel_context(ctx); |
DBG("Finish render %s texture\n", _mesa_get_format_name(rb->Format)); |
/* Since we've (probably) rendered to the texture and will (likely) use |
* it in the texture domain later on in this batchbuffer, flush the |
* batch. Once again, we wish for a domain tracker in libdrm to cover |
* usage inside of a batchbuffer like GEM does in the kernel. |
*/ |
intel_batchbuffer_emit_mi_flush(intel); |
} |
#define fbo_incomplete(fb, ...) do { \ |
static GLuint msg_id = 0; \ |
if (unlikely(ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT)) { \ |
_mesa_gl_debug(ctx, &msg_id, \ |
MESA_DEBUG_TYPE_OTHER, \ |
MESA_DEBUG_SEVERITY_MEDIUM, \ |
__VA_ARGS__); \ |
} \ |
DBG(__VA_ARGS__); \ |
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; \ |
} while (0) |
/** |
* Do additional "completeness" testing of a framebuffer object. |
*/ |
static void |
intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_renderbuffer *depthRb = |
intel_get_renderbuffer(fb, BUFFER_DEPTH); |
struct intel_renderbuffer *stencilRb = |
intel_get_renderbuffer(fb, BUFFER_STENCIL); |
struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL; |
int i; |
DBG("%s() on fb %p (%s)\n", __FUNCTION__, |
fb, (fb == ctx->DrawBuffer ? "drawbuffer" : |
(fb == ctx->ReadBuffer ? "readbuffer" : "other buffer"))); |
if (depthRb) |
depth_mt = depthRb->mt; |
if (stencilRb) |
stencil_mt = stencilRb->mt; |
if (depth_mt && stencil_mt) { |
/* Make sure that the depth and stencil buffers are actually the same |
* slice of the same miptree, since we only support packed |
* depth/stencil. |
*/ |
if (depth_mt == stencil_mt) { |
if (depthRb->mt_level != stencilRb->mt_level || |
depthRb->mt_layer != stencilRb->mt_layer) { |
fbo_incomplete(fb, |
"FBO incomplete: depth image level/layer %d/%d != " |
"stencil image %d/%d\n", |
depthRb->mt_level, |
depthRb->mt_layer, |
stencilRb->mt_level, |
stencilRb->mt_layer); |
} |
} else { |
fbo_incomplete(fb, "FBO incomplete: separate stencil unsupported\n"); |
} |
} |
for (i = 0; i < Elements(fb->Attachment); i++) { |
struct gl_renderbuffer *rb; |
struct intel_renderbuffer *irb; |
if (fb->Attachment[i].Type == GL_NONE) |
continue; |
/* A supported attachment will have a Renderbuffer set either |
* from being a Renderbuffer or being a texture that got the |
* intel_wrap_texture() treatment. |
*/ |
rb = fb->Attachment[i].Renderbuffer; |
if (rb == NULL) { |
fbo_incomplete(fb, "FBO incomplete: attachment without " |
"renderbuffer\n"); |
continue; |
} |
if (fb->Attachment[i].Type == GL_TEXTURE) { |
if (rb->TexImage->Border) { |
fbo_incomplete(fb, "FBO incomplete: texture with border\n"); |
continue; |
} |
} |
irb = intel_renderbuffer(rb); |
if (irb == NULL) { |
fbo_incomplete(fb, "FBO incomplete: software rendering " |
"renderbuffer\n"); |
continue; |
} |
if (!intel->vtbl.render_target_supported(intel, rb)) { |
fbo_incomplete(fb, "FBO incomplete: Unsupported HW " |
"texture/renderbuffer format attached: %s\n", |
_mesa_get_format_name(intel_rb_format(irb))); |
} |
} |
} |
/** |
* Try to do a glBlitFramebuffer using glCopyTexSubImage2D |
* We can do this when the dst renderbuffer is actually a texture and |
* there is no scaling, mirroring or scissoring. |
* |
* \return new buffer mask indicating the buffers left to blit using the |
* normal path. |
*/ |
static GLbitfield |
intel_blit_framebuffer_with_blitter(struct gl_context *ctx, |
GLint srcX0, GLint srcY0, |
GLint srcX1, GLint srcY1, |
GLint dstX0, GLint dstY0, |
GLint dstX1, GLint dstY1, |
GLbitfield mask, GLenum filter) |
{ |
struct intel_context *intel = intel_context(ctx); |
if (mask & GL_COLOR_BUFFER_BIT) { |
GLint i; |
const struct gl_framebuffer *drawFb = ctx->DrawBuffer; |
const struct gl_framebuffer *readFb = ctx->ReadBuffer; |
struct gl_renderbuffer *src_rb = readFb->_ColorReadBuffer; |
struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb); |
if (!src_irb) { |
perf_debug("glBlitFramebuffer(): missing src renderbuffer. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
/* If the source and destination are the same size with no mirroring, |
* the rectangles are within the size of the texture and there is no |
* scissor, then we can probably use the blit engine. |
*/ |
if (!(srcX0 - srcX1 == dstX0 - dstX1 && |
srcY0 - srcY1 == dstY0 - dstY1 && |
srcX1 >= srcX0 && |
srcY1 >= srcY0 && |
srcX0 >= 0 && srcX1 <= readFb->Width && |
srcY0 >= 0 && srcY1 <= readFb->Height && |
dstX0 >= 0 && dstX1 <= drawFb->Width && |
dstY0 >= 0 && dstY1 <= drawFb->Height && |
!ctx->Scissor.Enabled)) { |
perf_debug("glBlitFramebuffer(): non-1:1 blit. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
/* Blit to all active draw buffers. We don't do any pre-checking, |
* because we assume that copying to MRTs is rare, and failure midway |
* through copying is even more rare. Even if it was to occur, it's |
* safe to let meta start the copy over from scratch, because |
* glBlitFramebuffer completely overwrites the destination pixels, and |
* results are undefined if any destination pixels have a dependency on |
* source pixels. |
*/ |
for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { |
struct gl_renderbuffer *dst_rb = ctx->DrawBuffer->_ColorDrawBuffers[i]; |
struct intel_renderbuffer *dst_irb = intel_renderbuffer(dst_rb); |
if (!dst_irb) { |
perf_debug("glBlitFramebuffer(): missing dst renderbuffer. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
gl_format src_format = _mesa_get_srgb_format_linear(src_rb->Format); |
gl_format dst_format = _mesa_get_srgb_format_linear(dst_rb->Format); |
if (src_format != dst_format) { |
perf_debug("glBlitFramebuffer(): unsupported blit from %s to %s. " |
"Falling back to software rendering.\n", |
_mesa_get_format_name(src_format), |
_mesa_get_format_name(dst_format)); |
return mask; |
} |
if (!intel_miptree_blit(intel, |
src_irb->mt, |
src_irb->mt_level, src_irb->mt_layer, |
srcX0, srcY0, src_rb->Name == 0, |
dst_irb->mt, |
dst_irb->mt_level, dst_irb->mt_layer, |
dstX0, dstY0, dst_rb->Name == 0, |
dstX1 - dstX0, dstY1 - dstY0, GL_COPY)) { |
perf_debug("glBlitFramebuffer(): unknown blit failure. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
} |
mask &= ~GL_COLOR_BUFFER_BIT; |
} |
return mask; |
} |
static void |
intel_blit_framebuffer(struct gl_context *ctx, |
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, |
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, |
GLbitfield mask, GLenum filter) |
{ |
/* Try using the BLT engine. */ |
mask = intel_blit_framebuffer_with_blitter(ctx, |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
mask, filter); |
if (mask == 0x0) |
return; |
_mesa_meta_BlitFramebuffer(ctx, |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
mask, filter); |
} |
/** |
* Do one-time context initializations related to GL_EXT_framebuffer_object. |
* Hook in device driver functions. |
*/ |
void |
intel_fbo_init(struct intel_context *intel) |
{ |
intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer; |
intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer; |
intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer; |
intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer; |
intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer; |
intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer; |
intel->ctx.Driver.RenderTexture = intel_render_texture; |
intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; |
intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer; |
intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer; |
intel->ctx.Driver.EGLImageTargetRenderbufferStorage = |
intel_image_target_renderbuffer_storage; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_fbo.h |
---|
0,0 → 1,167 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_FBO_H |
#define INTEL_FBO_H |
#include <stdbool.h> |
#include <assert.h> |
#include "main/formats.h" |
#include "main/macros.h" |
#include "intel_context.h" |
#include "intel_mipmap_tree.h" |
#include "intel_screen.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
struct intel_context; |
struct intel_mipmap_tree; |
struct intel_texture_image; |
/** |
* Intel renderbuffer, derived from gl_renderbuffer. |
*/ |
struct intel_renderbuffer |
{ |
struct swrast_renderbuffer Base; |
struct intel_mipmap_tree *mt; /**< The renderbuffer storage. */ |
/** |
* \name Miptree view |
* \{ |
* |
* Multiple renderbuffers may simultaneously wrap a single texture and each |
* provide a different view into that texture. The fields below indicate |
* which miptree slice is wrapped by this renderbuffer. The fields' values |
* are consistent with the 'level' and 'layer' parameters of |
* glFramebufferTextureLayer(). |
* |
* For renderbuffers not created with glFramebufferTexture*(), mt_level and |
* mt_layer are 0. |
*/ |
unsigned int mt_level; |
unsigned int mt_layer; |
/** \} */ |
GLuint draw_x, draw_y; /**< Offset of drawing within the region */ |
}; |
/** |
* gl_renderbuffer is a base class which we subclass. The Class field |
* is used for simple run-time type checking. |
*/ |
#define INTEL_RB_CLASS 0x12345678 |
/** |
* Return a gl_renderbuffer ptr casted to intel_renderbuffer. |
* NULL will be returned if the rb isn't really an intel_renderbuffer. |
* This is determined by checking the ClassID. |
*/ |
static INLINE struct intel_renderbuffer * |
intel_renderbuffer(struct gl_renderbuffer *rb) |
{ |
struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb; |
if (irb && irb->Base.Base.ClassID == INTEL_RB_CLASS) { |
/*_mesa_warning(NULL, "Returning non-intel Rb\n");*/ |
return irb; |
} |
else |
return NULL; |
} |
/** |
* \brief Return the framebuffer attachment specified by attIndex. |
* |
* If the framebuffer lacks the specified attachment, then return null. |
* |
* If the attached renderbuffer is a wrapper, then return wrapped |
* renderbuffer. |
*/ |
static INLINE struct intel_renderbuffer * |
intel_get_renderbuffer(struct gl_framebuffer *fb, gl_buffer_index attIndex) |
{ |
struct gl_renderbuffer *rb; |
assert((unsigned)attIndex < ARRAY_SIZE(fb->Attachment)); |
rb = fb->Attachment[attIndex].Renderbuffer; |
if (!rb) |
return NULL; |
return intel_renderbuffer(rb); |
} |
static INLINE gl_format |
intel_rb_format(const struct intel_renderbuffer *rb) |
{ |
return rb->Base.Base.Format; |
} |
extern struct intel_renderbuffer * |
intel_create_renderbuffer(gl_format format); |
struct intel_renderbuffer * |
intel_create_private_renderbuffer(gl_format format); |
struct gl_renderbuffer* |
intel_create_wrapped_renderbuffer(struct gl_context * ctx, |
int width, int height, |
gl_format format); |
extern void |
intel_fbo_init(struct intel_context *intel); |
extern void |
intel_flip_renderbuffers(struct gl_framebuffer *fb); |
void |
intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb); |
static inline uint32_t |
intel_renderbuffer_get_tile_offsets(struct intel_renderbuffer *irb, |
uint32_t *tile_x, |
uint32_t *tile_y) |
{ |
return intel_miptree_get_tile_offsets(irb->mt, irb->mt_level, irb->mt_layer, |
tile_x, tile_y); |
} |
struct intel_region* |
intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex); |
#ifdef __cplusplus |
} |
#endif |
#endif /* INTEL_FBO_H */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_mipmap_tree.c |
---|
0,0 → 1,921 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#include <GL/gl.h> |
#include <GL/internal/dri_interface.h> |
#include "intel_batchbuffer.h" |
#include "intel_chipset.h" |
#include "intel_context.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_tex_layout.h" |
#include "intel_tex.h" |
#include "intel_blit.h" |
#include "main/enums.h" |
#include "main/formats.h" |
#include "main/glformats.h" |
#include "main/teximage.h" |
#define FILE_DEBUG_FLAG DEBUG_MIPTREE |
static GLenum |
target_to_target(GLenum target) |
{ |
switch (target) { |
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: |
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: |
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: |
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: |
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: |
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: |
return GL_TEXTURE_CUBE_MAP_ARB; |
default: |
return target; |
} |
} |
/** |
* @param for_bo Indicates that the caller is |
* intel_miptree_create_for_bo(). If true, then do not create |
* \c stencil_mt. |
*/ |
struct intel_mipmap_tree * |
intel_miptree_create_layout(struct intel_context *intel, |
GLenum target, |
gl_format format, |
GLuint first_level, |
GLuint last_level, |
GLuint width0, |
GLuint height0, |
GLuint depth0, |
bool for_bo) |
{ |
struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1); |
if (!mt) |
return NULL; |
DBG("%s target %s format %s level %d..%d <-- %p\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(target), |
_mesa_get_format_name(format), |
first_level, last_level, mt); |
mt->target = target_to_target(target); |
mt->format = format; |
mt->first_level = first_level; |
mt->last_level = last_level; |
mt->logical_width0 = width0; |
mt->logical_height0 = height0; |
mt->logical_depth0 = depth0; |
/* The cpp is bytes per (1, blockheight)-sized block for compressed |
* textures. This is why you'll see divides by blockheight all over |
*/ |
unsigned bw, bh; |
_mesa_get_format_block_size(format, &bw, &bh); |
assert(_mesa_get_format_bytes(mt->format) % bw == 0); |
mt->cpp = _mesa_get_format_bytes(mt->format) / bw; |
mt->compressed = _mesa_is_format_compressed(format); |
mt->refcount = 1; |
if (target == GL_TEXTURE_CUBE_MAP) { |
assert(depth0 == 1); |
depth0 = 6; |
} |
mt->physical_width0 = width0; |
mt->physical_height0 = height0; |
mt->physical_depth0 = depth0; |
intel_get_texture_alignment_unit(intel, mt->format, |
&mt->align_w, &mt->align_h); |
(void) intel; |
if (intel->is_945) |
i945_miptree_layout(mt); |
else |
i915_miptree_layout(mt); |
return mt; |
} |
/** |
* \brief Helper function for intel_miptree_create(). |
*/ |
static uint32_t |
intel_miptree_choose_tiling(struct intel_context *intel, |
gl_format format, |
uint32_t width0, |
enum intel_miptree_tiling_mode requested, |
struct intel_mipmap_tree *mt) |
{ |
/* Some usages may want only one type of tiling, like depth miptrees (Y |
* tiled), or temporary BOs for uploading data once (linear). |
*/ |
switch (requested) { |
case INTEL_MIPTREE_TILING_ANY: |
break; |
case INTEL_MIPTREE_TILING_Y: |
return I915_TILING_Y; |
case INTEL_MIPTREE_TILING_NONE: |
return I915_TILING_NONE; |
} |
int minimum_pitch = mt->total_width * mt->cpp; |
/* If the width is much smaller than a tile, don't bother tiling. */ |
if (minimum_pitch < 64) |
return I915_TILING_NONE; |
if (ALIGN(minimum_pitch, 512) >= 32768) { |
perf_debug("%dx%d miptree too large to blit, falling back to untiled", |
mt->total_width, mt->total_height); |
return I915_TILING_NONE; |
} |
/* We don't have BLORP to handle Y-tiled blits, so use X-tiling. */ |
return I915_TILING_X; |
} |
struct intel_mipmap_tree * |
intel_miptree_create(struct intel_context *intel, |
GLenum target, |
gl_format format, |
GLuint first_level, |
GLuint last_level, |
GLuint width0, |
GLuint height0, |
GLuint depth0, |
bool expect_accelerated_upload, |
enum intel_miptree_tiling_mode requested_tiling) |
{ |
struct intel_mipmap_tree *mt; |
GLuint total_width, total_height; |
mt = intel_miptree_create_layout(intel, target, format, |
first_level, last_level, width0, |
height0, depth0, |
false); |
/* |
* pitch == 0 || height == 0 indicates the null texture |
*/ |
if (!mt || !mt->total_width || !mt->total_height) { |
intel_miptree_release(&mt); |
return NULL; |
} |
total_width = mt->total_width; |
total_height = mt->total_height; |
uint32_t tiling = intel_miptree_choose_tiling(intel, format, width0, |
requested_tiling, |
mt); |
bool y_or_x = tiling == (I915_TILING_Y | I915_TILING_X); |
mt->region = intel_region_alloc(intel->intelScreen, |
y_or_x ? I915_TILING_Y : tiling, |
mt->cpp, |
total_width, |
total_height, |
expect_accelerated_upload); |
/* If the region is too large to fit in the aperture, we need to use the |
* BLT engine to support it. The BLT paths can't currently handle Y-tiling, |
* so we need to fall back to X. |
*/ |
if (y_or_x && mt->region->bo->size >= intel->max_gtt_map_object_size) { |
perf_debug("%dx%d miptree larger than aperture; falling back to X-tiled\n", |
mt->total_width, mt->total_height); |
intel_region_release(&mt->region); |
mt->region = intel_region_alloc(intel->intelScreen, |
I915_TILING_X, |
mt->cpp, |
total_width, |
total_height, |
expect_accelerated_upload); |
} |
mt->offset = 0; |
if (!mt->region) { |
intel_miptree_release(&mt); |
return NULL; |
} |
return mt; |
} |
struct intel_mipmap_tree * |
intel_miptree_create_for_bo(struct intel_context *intel, |
drm_intel_bo *bo, |
gl_format format, |
uint32_t offset, |
uint32_t width, |
uint32_t height, |
int pitch, |
uint32_t tiling) |
{ |
struct intel_mipmap_tree *mt; |
struct intel_region *region = calloc(1, sizeof(*region)); |
if (!region) |
return NULL; |
/* Nothing will be able to use this miptree with the BO if the offset isn't |
* aligned. |
*/ |
if (tiling != I915_TILING_NONE) |
assert(offset % 4096 == 0); |
/* miptrees can't handle negative pitch. If you need flipping of images, |
* that's outside of the scope of the mt. |
*/ |
assert(pitch >= 0); |
mt = intel_miptree_create_layout(intel, GL_TEXTURE_2D, format, |
0, 0, |
width, height, 1, |
true); |
if (!mt) |
return mt; |
region->cpp = mt->cpp; |
region->width = width; |
region->height = height; |
region->pitch = pitch; |
region->refcount = 1; |
drm_intel_bo_reference(bo); |
region->bo = bo; |
region->tiling = tiling; |
mt->region = region; |
mt->offset = offset; |
return mt; |
} |
/** |
* For a singlesample DRI2 buffer, this simply wraps the given region with a miptree. |
* |
* For a multisample DRI2 buffer, this wraps the given region with |
* a singlesample miptree, then creates a multisample miptree into which the |
* singlesample miptree is embedded as a child. |
*/ |
struct intel_mipmap_tree* |
intel_miptree_create_for_dri2_buffer(struct intel_context *intel, |
unsigned dri_attachment, |
gl_format format, |
struct intel_region *region) |
{ |
struct intel_mipmap_tree *mt = NULL; |
/* Only the front and back buffers, which are color buffers, are shared |
* through DRI2. |
*/ |
assert(dri_attachment == __DRI_BUFFER_BACK_LEFT || |
dri_attachment == __DRI_BUFFER_FRONT_LEFT || |
dri_attachment == __DRI_BUFFER_FAKE_FRONT_LEFT); |
assert(_mesa_get_format_base_format(format) == GL_RGB || |
_mesa_get_format_base_format(format) == GL_RGBA); |
mt = intel_miptree_create_for_bo(intel, |
region->bo, |
format, |
0, |
region->width, |
region->height, |
region->pitch, |
region->tiling); |
if (!mt) |
return NULL; |
mt->region->name = region->name; |
return mt; |
} |
struct intel_mipmap_tree* |
intel_miptree_create_for_renderbuffer(struct intel_context *intel, |
gl_format format, |
uint32_t width, |
uint32_t height) |
{ |
uint32_t depth = 1; |
return intel_miptree_create(intel, GL_TEXTURE_2D, format, 0, 0, |
width, height, depth, true, |
INTEL_MIPTREE_TILING_ANY); |
} |
void |
intel_miptree_reference(struct intel_mipmap_tree **dst, |
struct intel_mipmap_tree *src) |
{ |
if (*dst == src) |
return; |
intel_miptree_release(dst); |
if (src) { |
src->refcount++; |
DBG("%s %p refcount now %d\n", __FUNCTION__, src, src->refcount); |
} |
*dst = src; |
} |
void |
intel_miptree_release(struct intel_mipmap_tree **mt) |
{ |
if (!*mt) |
return; |
DBG("%s %p refcount will be %d\n", __FUNCTION__, *mt, (*mt)->refcount - 1); |
if (--(*mt)->refcount <= 0) { |
GLuint i; |
DBG("%s deleting %p\n", __FUNCTION__, *mt); |
intel_region_release(&((*mt)->region)); |
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { |
free((*mt)->level[i].slice); |
} |
free(*mt); |
} |
*mt = NULL; |
} |
void |
intel_miptree_get_dimensions_for_image(struct gl_texture_image *image, |
int *width, int *height, int *depth) |
{ |
switch (image->TexObject->Target) { |
case GL_TEXTURE_1D_ARRAY: |
*width = image->Width; |
*height = 1; |
*depth = image->Height; |
break; |
default: |
*width = image->Width; |
*height = image->Height; |
*depth = image->Depth; |
break; |
} |
} |
/** |
* Can the image be pulled into a unified mipmap tree? This mirrors |
* the completeness test in a lot of ways. |
* |
* Not sure whether I want to pass gl_texture_image here. |
*/ |
bool |
intel_miptree_match_image(struct intel_mipmap_tree *mt, |
struct gl_texture_image *image) |
{ |
struct intel_texture_image *intelImage = intel_texture_image(image); |
GLuint level = intelImage->base.Base.Level; |
int width, height, depth; |
/* glTexImage* choose the texture object based on the target passed in, and |
* objects can't change targets over their lifetimes, so this should be |
* true. |
*/ |
assert(target_to_target(image->TexObject->Target) == mt->target); |
gl_format mt_format = mt->format; |
if (image->TexFormat != mt_format) |
return false; |
intel_miptree_get_dimensions_for_image(image, &width, &height, &depth); |
if (mt->target == GL_TEXTURE_CUBE_MAP) |
depth = 6; |
/* Test image dimensions against the base level image adjusted for |
* minification. This will also catch images not present in the |
* tree, changed targets, etc. |
*/ |
if (mt->target == GL_TEXTURE_2D_MULTISAMPLE || |
mt->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { |
/* nonzero level here is always bogus */ |
assert(level == 0); |
if (width != mt->logical_width0 || |
height != mt->logical_height0 || |
depth != mt->logical_depth0) { |
return false; |
} |
} |
else { |
/* all normal textures, renderbuffers, etc */ |
if (width != mt->level[level].width || |
height != mt->level[level].height || |
depth != mt->level[level].depth) { |
return false; |
} |
} |
return true; |
} |
void |
intel_miptree_set_level_info(struct intel_mipmap_tree *mt, |
GLuint level, |
GLuint x, GLuint y, |
GLuint w, GLuint h, GLuint d) |
{ |
mt->level[level].width = w; |
mt->level[level].height = h; |
mt->level[level].depth = d; |
mt->level[level].level_x = x; |
mt->level[level].level_y = y; |
DBG("%s level %d size: %d,%d,%d offset %d,%d\n", __FUNCTION__, |
level, w, h, d, x, y); |
assert(mt->level[level].slice == NULL); |
mt->level[level].slice = calloc(d, sizeof(*mt->level[0].slice)); |
mt->level[level].slice[0].x_offset = mt->level[level].level_x; |
mt->level[level].slice[0].y_offset = mt->level[level].level_y; |
} |
void |
intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, |
GLuint level, GLuint img, |
GLuint x, GLuint y) |
{ |
if (img == 0 && level == 0) |
assert(x == 0 && y == 0); |
assert(img < mt->level[level].depth); |
mt->level[level].slice[img].x_offset = mt->level[level].level_x + x; |
mt->level[level].slice[img].y_offset = mt->level[level].level_y + y; |
DBG("%s level %d img %d pos %d,%d\n", |
__FUNCTION__, level, img, |
mt->level[level].slice[img].x_offset, |
mt->level[level].slice[img].y_offset); |
} |
void |
intel_miptree_get_image_offset(struct intel_mipmap_tree *mt, |
GLuint level, GLuint slice, |
GLuint *x, GLuint *y) |
{ |
assert(slice < mt->level[level].depth); |
*x = mt->level[level].slice[slice].x_offset; |
*y = mt->level[level].slice[slice].y_offset; |
} |
/** |
* Rendering with tiled buffers requires that the base address of the buffer |
* be aligned to a page boundary. For renderbuffers, and sometimes with |
* textures, we may want the surface to point at a texture image level that |
* isn't at a page boundary. |
* |
* This function returns an appropriately-aligned base offset |
* according to the tiling restrictions, plus any required x/y offset |
* from there. |
*/ |
uint32_t |
intel_miptree_get_tile_offsets(struct intel_mipmap_tree *mt, |
GLuint level, GLuint slice, |
uint32_t *tile_x, |
uint32_t *tile_y) |
{ |
struct intel_region *region = mt->region; |
uint32_t x, y; |
uint32_t mask_x, mask_y; |
intel_region_get_tile_masks(region, &mask_x, &mask_y, false); |
intel_miptree_get_image_offset(mt, level, slice, &x, &y); |
*tile_x = x & mask_x; |
*tile_y = y & mask_y; |
return intel_region_get_aligned_offset(region, x & ~mask_x, y & ~mask_y, |
false); |
} |
static void |
intel_miptree_copy_slice_sw(struct intel_context *intel, |
struct intel_mipmap_tree *dst_mt, |
struct intel_mipmap_tree *src_mt, |
int level, |
int slice, |
int width, |
int height) |
{ |
void *src, *dst; |
int src_stride, dst_stride; |
int cpp = dst_mt->cpp; |
intel_miptree_map(intel, src_mt, |
level, slice, |
0, 0, |
width, height, |
GL_MAP_READ_BIT, |
&src, &src_stride); |
intel_miptree_map(intel, dst_mt, |
level, slice, |
0, 0, |
width, height, |
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, |
&dst, &dst_stride); |
DBG("sw blit %s mt %p %p/%d -> %s mt %p %p/%d (%dx%d)\n", |
_mesa_get_format_name(src_mt->format), |
src_mt, src, src_stride, |
_mesa_get_format_name(dst_mt->format), |
dst_mt, dst, dst_stride, |
width, height); |
int row_size = cpp * width; |
if (src_stride == row_size && |
dst_stride == row_size) { |
memcpy(dst, src, row_size * height); |
} else { |
for (int i = 0; i < height; i++) { |
memcpy(dst, src, row_size); |
dst += dst_stride; |
src += src_stride; |
} |
} |
intel_miptree_unmap(intel, dst_mt, level, slice); |
intel_miptree_unmap(intel, src_mt, level, slice); |
} |
static void |
intel_miptree_copy_slice(struct intel_context *intel, |
struct intel_mipmap_tree *dst_mt, |
struct intel_mipmap_tree *src_mt, |
int level, |
int face, |
int depth) |
{ |
gl_format format = src_mt->format; |
uint32_t width = src_mt->level[level].width; |
uint32_t height = src_mt->level[level].height; |
int slice; |
if (face > 0) |
slice = face; |
else |
slice = depth; |
assert(depth < src_mt->level[level].depth); |
assert(src_mt->format == dst_mt->format); |
if (dst_mt->compressed) { |
height = ALIGN(height, dst_mt->align_h) / dst_mt->align_h; |
width = ALIGN(width, dst_mt->align_w); |
} |
uint32_t dst_x, dst_y, src_x, src_y; |
intel_miptree_get_image_offset(dst_mt, level, slice, &dst_x, &dst_y); |
intel_miptree_get_image_offset(src_mt, level, slice, &src_x, &src_y); |
DBG("validate blit mt %s %p %d,%d/%d -> mt %s %p %d,%d/%d (%dx%d)\n", |
_mesa_get_format_name(src_mt->format), |
src_mt, src_x, src_y, src_mt->region->pitch, |
_mesa_get_format_name(dst_mt->format), |
dst_mt, dst_x, dst_y, dst_mt->region->pitch, |
width, height); |
if (!intel_miptree_blit(intel, |
src_mt, level, slice, 0, 0, false, |
dst_mt, level, slice, 0, 0, false, |
width, height, GL_COPY)) { |
perf_debug("miptree validate blit for %s failed\n", |
_mesa_get_format_name(format)); |
intel_miptree_copy_slice_sw(intel, dst_mt, src_mt, level, slice, |
width, height); |
} |
} |
/** |
* Copies the image's current data to the given miptree, and associates that |
* miptree with the image. |
* |
* If \c invalidate is true, then the actual image data does not need to be |
* copied, but the image still needs to be associated to the new miptree (this |
* is set to true if we're about to clear the image). |
*/ |
void |
intel_miptree_copy_teximage(struct intel_context *intel, |
struct intel_texture_image *intelImage, |
struct intel_mipmap_tree *dst_mt, |
bool invalidate) |
{ |
struct intel_mipmap_tree *src_mt = intelImage->mt; |
struct intel_texture_object *intel_obj = |
intel_texture_object(intelImage->base.Base.TexObject); |
int level = intelImage->base.Base.Level; |
int face = intelImage->base.Base.Face; |
GLuint depth = intelImage->base.Base.Depth; |
if (!invalidate) { |
for (int slice = 0; slice < depth; slice++) { |
intel_miptree_copy_slice(intel, dst_mt, src_mt, level, face, slice); |
} |
} |
intel_miptree_reference(&intelImage->mt, dst_mt); |
intel_obj->needs_validate = true; |
} |
void * |
intel_miptree_map_raw(struct intel_context *intel, struct intel_mipmap_tree *mt) |
{ |
drm_intel_bo *bo = mt->region->bo; |
if (unlikely(INTEL_DEBUG & DEBUG_PERF)) { |
if (drm_intel_bo_busy(bo)) { |
perf_debug("Mapping a busy BO, causing a stall on the GPU.\n"); |
} |
} |
intel_flush(&intel->ctx); |
if (mt->region->tiling != I915_TILING_NONE) |
drm_intel_gem_bo_map_gtt(bo); |
else |
drm_intel_bo_map(bo, true); |
return bo->virtual; |
} |
void |
intel_miptree_unmap_raw(struct intel_context *intel, |
struct intel_mipmap_tree *mt) |
{ |
drm_intel_bo_unmap(mt->region->bo); |
} |
static void |
intel_miptree_map_gtt(struct intel_context *intel, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, unsigned int slice) |
{ |
unsigned int bw, bh; |
void *base; |
unsigned int image_x, image_y; |
int x = map->x; |
int y = map->y; |
/* For compressed formats, the stride is the number of bytes per |
* row of blocks. intel_miptree_get_image_offset() already does |
* the divide. |
*/ |
_mesa_get_format_block_size(mt->format, &bw, &bh); |
assert(y % bh == 0); |
y /= bh; |
base = intel_miptree_map_raw(intel, mt) + mt->offset; |
if (base == NULL) |
map->ptr = NULL; |
else { |
/* Note that in the case of cube maps, the caller must have passed the |
* slice number referencing the face. |
*/ |
intel_miptree_get_image_offset(mt, level, slice, &image_x, &image_y); |
x += image_x; |
y += image_y; |
map->stride = mt->region->pitch; |
map->ptr = base + y * map->stride + x * mt->cpp; |
} |
DBG("%s: %d,%d %dx%d from mt %p (%s) %d,%d = %p/%d\n", __FUNCTION__, |
map->x, map->y, map->w, map->h, |
mt, _mesa_get_format_name(mt->format), |
x, y, map->ptr, map->stride); |
} |
static void |
intel_miptree_unmap_gtt(struct intel_context *intel, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, |
unsigned int slice) |
{ |
intel_miptree_unmap_raw(intel, mt); |
} |
static void |
intel_miptree_map_blit(struct intel_context *intel, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, unsigned int slice) |
{ |
map->mt = intel_miptree_create(intel, GL_TEXTURE_2D, mt->format, |
0, 0, |
map->w, map->h, 1, |
false, |
INTEL_MIPTREE_TILING_NONE); |
if (!map->mt) { |
fprintf(stderr, "Failed to allocate blit temporary\n"); |
goto fail; |
} |
map->stride = map->mt->region->pitch; |
if (!intel_miptree_blit(intel, |
mt, level, slice, |
map->x, map->y, false, |
map->mt, 0, 0, |
0, 0, false, |
map->w, map->h, GL_COPY)) { |
fprintf(stderr, "Failed to blit\n"); |
goto fail; |
} |
intel_batchbuffer_flush(intel); |
map->ptr = intel_miptree_map_raw(intel, map->mt); |
DBG("%s: %d,%d %dx%d from mt %p (%s) %d,%d = %p/%d\n", __FUNCTION__, |
map->x, map->y, map->w, map->h, |
mt, _mesa_get_format_name(mt->format), |
level, slice, map->ptr, map->stride); |
return; |
fail: |
intel_miptree_release(&map->mt); |
map->ptr = NULL; |
map->stride = 0; |
} |
static void |
intel_miptree_unmap_blit(struct intel_context *intel, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, |
unsigned int slice) |
{ |
struct gl_context *ctx = &intel->ctx; |
intel_miptree_unmap_raw(intel, map->mt); |
if (map->mode & GL_MAP_WRITE_BIT) { |
bool ok = intel_miptree_blit(intel, |
map->mt, 0, 0, |
0, 0, false, |
mt, level, slice, |
map->x, map->y, false, |
map->w, map->h, GL_COPY); |
WARN_ONCE(!ok, "Failed to blit from linear temporary mapping"); |
} |
intel_miptree_release(&map->mt); |
} |
/** |
* Create and attach a map to the miptree at (level, slice). Return the |
* attached map. |
*/ |
static struct intel_miptree_map* |
intel_miptree_attach_map(struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice, |
unsigned int x, |
unsigned int y, |
unsigned int w, |
unsigned int h, |
GLbitfield mode) |
{ |
struct intel_miptree_map *map = calloc(1, sizeof(*map)); |
if (!map) |
return NULL; |
assert(mt->level[level].slice[slice].map == NULL); |
mt->level[level].slice[slice].map = map; |
map->mode = mode; |
map->x = x; |
map->y = y; |
map->w = w; |
map->h = h; |
return map; |
} |
/** |
* Release the map at (level, slice). |
*/ |
static void |
intel_miptree_release_map(struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice) |
{ |
struct intel_miptree_map **map; |
map = &mt->level[level].slice[slice].map; |
free(*map); |
*map = NULL; |
} |
void |
intel_miptree_map(struct intel_context *intel, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice, |
unsigned int x, |
unsigned int y, |
unsigned int w, |
unsigned int h, |
GLbitfield mode, |
void **out_ptr, |
int *out_stride) |
{ |
struct intel_miptree_map *map; |
map = intel_miptree_attach_map(mt, level, slice, x, y, w, h, mode); |
if (!map){ |
*out_ptr = NULL; |
*out_stride = 0; |
return; |
} |
/* See intel_miptree_blit() for details on the 32k pitch limit. */ |
if (mt->region->tiling != I915_TILING_NONE && |
mt->region->bo->size >= intel->max_gtt_map_object_size) { |
assert(mt->region->pitch < 32768); |
intel_miptree_map_blit(intel, mt, map, level, slice); |
} else { |
intel_miptree_map_gtt(intel, mt, map, level, slice); |
} |
*out_ptr = map->ptr; |
*out_stride = map->stride; |
if (map->ptr == NULL) |
intel_miptree_release_map(mt, level, slice); |
} |
void |
intel_miptree_unmap(struct intel_context *intel, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice) |
{ |
struct intel_miptree_map *map = mt->level[level].slice[slice].map; |
if (!map) |
return; |
DBG("%s: mt %p (%s) level %d slice %d\n", __FUNCTION__, |
mt, _mesa_get_format_name(mt->format), level, slice); |
if (map->mt) { |
intel_miptree_unmap_blit(intel, mt, map, level, slice); |
} else { |
intel_miptree_unmap_gtt(intel, mt, map, level, slice); |
} |
intel_miptree_release_map(mt, level, slice); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_mipmap_tree.h |
---|
0,0 → 1,367 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_MIPMAP_TREE_H |
#define INTEL_MIPMAP_TREE_H |
#include <assert.h> |
#include "intel_regions.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
/* A layer on top of the intel_regions code which adds: |
* |
* - Code to size and layout a region to hold a set of mipmaps. |
* - Query to determine if a new image fits in an existing tree. |
* - More refcounting |
* - maybe able to remove refcounting from intel_region? |
* - ? |
* |
* The fixed mipmap layout of intel hardware where one offset |
* specifies the position of all images in a mipmap hierachy |
* complicates the implementation of GL texture image commands, |
* compared to hardware where each image is specified with an |
* independent offset. |
* |
* In an ideal world, each texture object would be associated with a |
* single bufmgr buffer or 2d intel_region, and all the images within |
* the texture object would slot into the tree as they arrive. The |
* reality can be a little messier, as images can arrive from the user |
* with sizes that don't fit in the existing tree, or in an order |
* where the tree layout cannot be guessed immediately. |
* |
* This structure encodes an idealized mipmap tree. The GL image |
* commands build these where possible, otherwise store the images in |
* temporary system buffers. |
*/ |
struct intel_texture_image; |
struct intel_miptree_map { |
/** Bitfield of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_BIT */ |
GLbitfield mode; |
/** Region of interest for the map. */ |
int x, y, w, h; |
/** Possibly malloced temporary buffer for the mapping. */ |
void *buffer; |
/** Possible pointer to a temporary linear miptree for the mapping. */ |
struct intel_mipmap_tree *mt; |
/** Pointer to the start of (map_x, map_y) returned by the mapping. */ |
void *ptr; |
/** Stride of the mapping. */ |
int stride; |
}; |
/** |
* Describes the location of each texture image within a texture region. |
*/ |
struct intel_mipmap_level |
{ |
/** Offset to this miptree level, used in computing x_offset. */ |
GLuint level_x; |
/** Offset to this miptree level, used in computing y_offset. */ |
GLuint level_y; |
GLuint width; |
GLuint height; |
/** |
* \brief Number of 2D slices in this miplevel. |
* |
* The exact semantics of depth varies according to the texture target: |
* - For GL_TEXTURE_CUBE_MAP, depth is 6. |
* - For GL_TEXTURE_2D_ARRAY, depth is the number of array slices. It is |
* identical for all miplevels in the texture. |
* - For GL_TEXTURE_3D, it is the texture's depth at this miplevel. Its |
* value, like width and height, varies with miplevel. |
* - For other texture types, depth is 1. |
*/ |
GLuint depth; |
/** |
* \brief List of 2D images in this mipmap level. |
* |
* This may be a list of cube faces, array slices in 2D array texture, or |
* layers in a 3D texture. The list's length is \c depth. |
*/ |
struct intel_mipmap_slice { |
/** |
* \name Offset to slice |
* \{ |
* |
* Hardware formats are so diverse that that there is no unified way to |
* compute the slice offsets, so we store them in this table. |
* |
* The (x, y) offset to slice \c s at level \c l relative the miptrees |
* base address is |
* \code |
* x = mt->level[l].slice[s].x_offset |
* y = mt->level[l].slice[s].y_offset |
*/ |
GLuint x_offset; |
GLuint y_offset; |
/** \} */ |
/** |
* Mapping information. Persistent for the duration of |
* intel_miptree_map/unmap on this slice. |
*/ |
struct intel_miptree_map *map; |
} *slice; |
}; |
struct intel_mipmap_tree |
{ |
/* Effectively the key: |
*/ |
GLenum target; |
/** |
* This is just the same as the gl_texture_image->TexFormat or |
* gl_renderbuffer->Format. |
*/ |
gl_format format; |
/** |
* The X offset of each image in the miptree must be aligned to this. See |
* the "Alignment Unit Size" section of the BSpec. |
*/ |
unsigned int align_w; |
unsigned int align_h; /**< \see align_w */ |
GLuint first_level; |
GLuint last_level; |
/** |
* Level zero image dimensions. These dimensions correspond to the |
* physical layout of data in memory. Accordingly, they account for the |
* extra width, height, and or depth that must be allocated in order to |
* accommodate multisample formats, and they account for the extra factor |
* of 6 in depth that must be allocated in order to accommodate cubemap |
* textures. |
*/ |
GLuint physical_width0, physical_height0, physical_depth0; |
GLuint cpp; |
bool compressed; |
/** |
* Level zero image dimensions. These dimensions correspond to the |
* logical width, height, and depth of the region as seen by client code. |
* Accordingly, they do not account for the extra width, height, and/or |
* depth that must be allocated in order to accommodate multisample |
* formats, nor do they account for the extra factor of 6 in depth that |
* must be allocated in order to accommodate cubemap textures. |
*/ |
uint32_t logical_width0, logical_height0, logical_depth0; |
/** |
* For 1D array, 2D array, cube, and 2D multisampled surfaces on Gen7: true |
* if the surface only contains LOD 0, and hence no space is for LOD's |
* other than 0 in between array slices. |
* |
* Corresponds to the surface_array_spacing bit in gen7_surface_state. |
*/ |
bool array_spacing_lod0; |
/* Derived from the above: |
*/ |
GLuint total_width; |
GLuint total_height; |
/* Includes image offset tables: |
*/ |
struct intel_mipmap_level level[MAX_TEXTURE_LEVELS]; |
/* The data is held here: |
*/ |
struct intel_region *region; |
/* Offset into region bo where miptree starts: |
*/ |
uint32_t offset; |
/* These are also refcounted: |
*/ |
GLuint refcount; |
}; |
enum intel_miptree_tiling_mode { |
INTEL_MIPTREE_TILING_ANY, |
INTEL_MIPTREE_TILING_Y, |
INTEL_MIPTREE_TILING_NONE, |
}; |
struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel, |
GLenum target, |
gl_format format, |
GLuint first_level, |
GLuint last_level, |
GLuint width0, |
GLuint height0, |
GLuint depth0, |
bool expect_accelerated_upload, |
enum intel_miptree_tiling_mode); |
struct intel_mipmap_tree * |
intel_miptree_create_layout(struct intel_context *intel, |
GLenum target, |
gl_format format, |
GLuint first_level, |
GLuint last_level, |
GLuint width0, |
GLuint height0, |
GLuint depth0, |
bool for_bo); |
struct intel_mipmap_tree * |
intel_miptree_create_for_bo(struct intel_context *intel, |
drm_intel_bo *bo, |
gl_format format, |
uint32_t offset, |
uint32_t width, |
uint32_t height, |
int pitch, |
uint32_t tiling); |
struct intel_mipmap_tree* |
intel_miptree_create_for_dri2_buffer(struct intel_context *intel, |
unsigned dri_attachment, |
gl_format format, |
struct intel_region *region); |
/** |
* Create a miptree appropriate as the storage for a non-texture renderbuffer. |
* The miptree has the following properties: |
* - The target is GL_TEXTURE_2D. |
* - There are no levels other than the base level 0. |
* - Depth is 1. |
*/ |
struct intel_mipmap_tree* |
intel_miptree_create_for_renderbuffer(struct intel_context *intel, |
gl_format format, |
uint32_t width, |
uint32_t height); |
/** \brief Assert that the level and layer are valid for the miptree. */ |
static inline void |
intel_miptree_check_level_layer(struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t layer) |
{ |
assert(level >= mt->first_level); |
assert(level <= mt->last_level); |
assert(layer < mt->level[level].depth); |
} |
int intel_miptree_pitch_align (struct intel_context *intel, |
struct intel_mipmap_tree *mt, |
uint32_t tiling, |
int pitch); |
void intel_miptree_reference(struct intel_mipmap_tree **dst, |
struct intel_mipmap_tree *src); |
void intel_miptree_release(struct intel_mipmap_tree **mt); |
/* Check if an image fits an existing mipmap tree layout |
*/ |
bool intel_miptree_match_image(struct intel_mipmap_tree *mt, |
struct gl_texture_image *image); |
void |
intel_miptree_get_image_offset(struct intel_mipmap_tree *mt, |
GLuint level, GLuint slice, |
GLuint *x, GLuint *y); |
void |
intel_miptree_get_dimensions_for_image(struct gl_texture_image *image, |
int *width, int *height, int *depth); |
uint32_t |
intel_miptree_get_tile_offsets(struct intel_mipmap_tree *mt, |
GLuint level, GLuint slice, |
uint32_t *tile_x, |
uint32_t *tile_y); |
void intel_miptree_set_level_info(struct intel_mipmap_tree *mt, |
GLuint level, |
GLuint x, GLuint y, |
GLuint w, GLuint h, GLuint d); |
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, |
GLuint level, |
GLuint img, GLuint x, GLuint y); |
void |
intel_miptree_copy_teximage(struct intel_context *intel, |
struct intel_texture_image *intelImage, |
struct intel_mipmap_tree *dst_mt, bool invalidate); |
/**\}*/ |
/* i915_mipmap_tree.c: |
*/ |
void i915_miptree_layout(struct intel_mipmap_tree *mt); |
void i945_miptree_layout(struct intel_mipmap_tree *mt); |
void brw_miptree_layout(struct intel_context *intel, |
struct intel_mipmap_tree *mt); |
void *intel_miptree_map_raw(struct intel_context *intel, |
struct intel_mipmap_tree *mt); |
void intel_miptree_unmap_raw(struct intel_context *intel, |
struct intel_mipmap_tree *mt); |
void |
intel_miptree_map(struct intel_context *intel, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice, |
unsigned int x, |
unsigned int y, |
unsigned int w, |
unsigned int h, |
GLbitfield mode, |
void **out_ptr, |
int *out_stride); |
void |
intel_miptree_unmap(struct intel_context *intel, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice); |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_pixel.c |
---|
0,0 → 1,135 |
/************************************************************************** |
* |
* 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 portionsalloc |
* 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 "main/accum.h" |
#include "main/enums.h" |
#include "main/state.h" |
#include "main/bufferobj.h" |
#include "main/context.h" |
#include "swrast/swrast.h" |
#include "intel_context.h" |
#include "intel_pixel.h" |
#include "intel_regions.h" |
#define FILE_DEBUG_FLAG DEBUG_PIXEL |
static GLenum |
effective_func(GLenum func, bool src_alpha_is_one) |
{ |
if (src_alpha_is_one) { |
if (func == GL_SRC_ALPHA) |
return GL_ONE; |
if (func == GL_ONE_MINUS_SRC_ALPHA) |
return GL_ZERO; |
} |
return func; |
} |
/** |
* Check if any fragment operations are in effect which might effect |
* glDraw/CopyPixels. |
*/ |
bool |
intel_check_blit_fragment_ops(struct gl_context * ctx, bool src_alpha_is_one) |
{ |
if (ctx->NewState) |
_mesa_update_state(ctx); |
if (ctx->FragmentProgram._Enabled) { |
DBG("fallback due to fragment program\n"); |
return false; |
} |
if (ctx->Color.BlendEnabled && |
(effective_func(ctx->Color.Blend[0].SrcRGB, src_alpha_is_one) != GL_ONE || |
effective_func(ctx->Color.Blend[0].DstRGB, src_alpha_is_one) != GL_ZERO || |
ctx->Color.Blend[0].EquationRGB != GL_FUNC_ADD || |
effective_func(ctx->Color.Blend[0].SrcA, src_alpha_is_one) != GL_ONE || |
effective_func(ctx->Color.Blend[0].DstA, src_alpha_is_one) != GL_ZERO || |
ctx->Color.Blend[0].EquationA != GL_FUNC_ADD)) { |
DBG("fallback due to blend\n"); |
return false; |
} |
if (ctx->Texture._EnabledUnits) { |
DBG("fallback due to texturing\n"); |
return false; |
} |
if (!(ctx->Color.ColorMask[0][0] && |
ctx->Color.ColorMask[0][1] && |
ctx->Color.ColorMask[0][2] && |
ctx->Color.ColorMask[0][3])) { |
DBG("fallback due to color masking\n"); |
return false; |
} |
if (ctx->Color.AlphaEnabled) { |
DBG("fallback due to alpha\n"); |
return false; |
} |
if (ctx->Depth.Test) { |
DBG("fallback due to depth test\n"); |
return false; |
} |
if (ctx->Fog.Enabled) { |
DBG("fallback due to fog\n"); |
return false; |
} |
if (ctx->_ImageTransferState) { |
DBG("fallback due to image transfer\n"); |
return false; |
} |
if (ctx->Stencil._Enabled) { |
DBG("fallback due to image stencil\n"); |
return false; |
} |
if (ctx->RenderMode != GL_RENDER) { |
DBG("fallback due to render mode\n"); |
return false; |
} |
return true; |
} |
void |
intelInitPixelFuncs(struct dd_function_table *functions) |
{ |
functions->Accum = _mesa_accum; |
functions->Bitmap = intelBitmap; |
functions->CopyPixels = intelCopyPixels; |
functions->DrawPixels = intelDrawPixels; |
functions->ReadPixels = intelReadPixels; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_pixel.h |
---|
0,0 → 1,63 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_PIXEL_H |
#define INTEL_PIXEL_H |
#include "main/mtypes.h" |
void intelInitPixelFuncs(struct dd_function_table *functions); |
bool intel_check_blit_fragment_ops(struct gl_context * ctx, |
bool src_alpha_is_one); |
void intelReadPixels(struct gl_context * ctx, |
GLint x, GLint y, |
GLsizei width, GLsizei height, |
GLenum format, GLenum type, |
const struct gl_pixelstore_attrib *pack, |
GLvoid * pixels); |
void intelDrawPixels(struct gl_context * ctx, |
GLint x, GLint y, |
GLsizei width, GLsizei height, |
GLenum format, |
GLenum type, |
const struct gl_pixelstore_attrib *unpack, |
const GLvoid * pixels); |
void intelCopyPixels(struct gl_context * ctx, |
GLint srcx, GLint srcy, |
GLsizei width, GLsizei height, |
GLint destx, GLint desty, GLenum type); |
void intelBitmap(struct gl_context * ctx, |
GLint x, GLint y, |
GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte * pixels); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_pixel_bitmap.c |
---|
0,0 → 1,358 |
/************************************************************************** |
* |
* 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 portionsalloc |
* 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 "main/glheader.h" |
#include "main/enums.h" |
#include "main/image.h" |
#include "main/colormac.h" |
#include "main/condrender.h" |
#include "main/mtypes.h" |
#include "main/macros.h" |
#include "main/pbo.h" |
#include "main/bufferobj.h" |
#include "main/state.h" |
#include "main/texobj.h" |
#include "main/context.h" |
#include "main/fbobject.h" |
#include "swrast/swrast.h" |
#include "drivers/common/meta.h" |
#include "intel_screen.h" |
#include "intel_context.h" |
#include "intel_batchbuffer.h" |
#include "intel_blit.h" |
#include "intel_fbo.h" |
#include "intel_regions.h" |
#include "intel_buffers.h" |
#include "intel_pixel.h" |
#include "intel_reg.h" |
#define FILE_DEBUG_FLAG DEBUG_PIXEL |
/* Unlike the other intel_pixel_* functions, the expectation here is |
* that the incoming data is not in a PBO. With the XY_TEXT blit |
* method, there's no benefit haveing it in a PBO, but we could |
* implement a path based on XY_MONO_SRC_COPY_BLIT which might benefit |
* PBO bitmaps. I think they are probably pretty rare though - I |
* wonder if Xgl uses them? |
*/ |
static const GLubyte *map_pbo( struct gl_context *ctx, |
GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte *bitmap ) |
{ |
GLubyte *buf; |
if (!_mesa_validate_pbo_access(2, unpack, width, height, 1, |
GL_COLOR_INDEX, GL_BITMAP, |
INT_MAX, (const GLvoid *) bitmap)) { |
_mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)"); |
return NULL; |
} |
buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, |
GL_MAP_READ_BIT, |
unpack->BufferObj); |
if (!buf) { |
_mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)"); |
return NULL; |
} |
return ADD_POINTERS(buf, bitmap); |
} |
static bool test_bit( const GLubyte *src, GLuint bit ) |
{ |
return (src[bit/8] & (1<<(bit % 8))) ? 1 : 0; |
} |
static void set_bit( GLubyte *dest, GLuint bit ) |
{ |
dest[bit/8] |= 1 << (bit % 8); |
} |
/* Extract a rectangle's worth of data from the bitmap. Called |
* per chunk of HW-sized bitmap. |
*/ |
static GLuint get_bitmap_rect(GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte *bitmap, |
GLuint x, GLuint y, |
GLuint w, GLuint h, |
GLubyte *dest, |
GLuint row_align, |
bool invert) |
{ |
GLuint src_offset = (x + unpack->SkipPixels) & 0x7; |
GLuint mask = unpack->LsbFirst ? 0 : 7; |
GLuint bit = 0; |
GLint row, col; |
GLint first, last; |
GLint incr; |
GLuint count = 0; |
DBG("%s %d,%d %dx%d bitmap %dx%d skip %d src_offset %d mask %d\n", |
__FUNCTION__, x,y,w,h,width,height,unpack->SkipPixels, src_offset, mask); |
if (invert) { |
first = h-1; |
last = 0; |
incr = -1; |
} |
else { |
first = 0; |
last = h-1; |
incr = 1; |
} |
/* Require that dest be pre-zero'd. |
*/ |
for (row = first; row != (last+incr); row += incr) { |
const GLubyte *rowsrc = _mesa_image_address2d(unpack, bitmap, |
width, height, |
GL_COLOR_INDEX, GL_BITMAP, |
y + row, x); |
for (col = 0; col < w; col++, bit++) { |
if (test_bit(rowsrc, (col + src_offset) ^ mask)) { |
set_bit(dest, bit ^ 7); |
count++; |
} |
} |
if (row_align) |
bit = ALIGN(bit, row_align); |
} |
return count; |
} |
/** |
* Returns the low Y value of the vertical range given, flipped according to |
* whether the framebuffer is or not. |
*/ |
static INLINE int |
y_flip(struct gl_framebuffer *fb, int y, int height) |
{ |
if (_mesa_is_user_fbo(fb)) |
return y; |
else |
return fb->Height - y - height; |
} |
/* |
* Render a bitmap. |
*/ |
static bool |
do_blit_bitmap( struct gl_context *ctx, |
GLint dstx, GLint dsty, |
GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte *bitmap ) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct intel_renderbuffer *irb; |
GLfloat tmpColor[4]; |
GLubyte ubcolor[4]; |
GLuint color; |
GLsizei bitmap_width = width; |
GLsizei bitmap_height = height; |
GLint px, py; |
GLuint stipple[32]; |
GLint orig_dstx = dstx; |
GLint orig_dsty = dsty; |
/* Update draw buffer bounds */ |
_mesa_update_state(ctx); |
if (ctx->Depth.Test) { |
/* The blit path produces incorrect results when depth testing is on. |
* It seems the blit Z coord is always 1.0 (the far plane) so fragments |
* will likely be obscured by other, closer geometry. |
*/ |
return false; |
} |
intel_prepare_render(intel); |
if (fb->_NumColorDrawBuffers != 1) { |
perf_debug("accelerated glBitmap() only supports rendering to a " |
"single color buffer\n"); |
return false; |
} |
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); |
if (_mesa_is_bufferobj(unpack->BufferObj)) { |
bitmap = map_pbo(ctx, width, height, unpack, bitmap); |
if (bitmap == NULL) |
return true; /* even though this is an error, we're done */ |
} |
COPY_4V(tmpColor, ctx->Current.RasterColor); |
if (_mesa_need_secondary_color(ctx)) { |
ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor); |
} |
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[0], tmpColor[0]); |
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[1], tmpColor[1]); |
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]); |
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]); |
switch (irb->mt->format) { |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_XRGB8888: |
color = PACK_COLOR_8888(ubcolor[3], ubcolor[0], ubcolor[1], ubcolor[2]); |
break; |
case MESA_FORMAT_RGB565: |
color = PACK_COLOR_565(ubcolor[0], ubcolor[1], ubcolor[2]); |
break; |
default: |
perf_debug("Unsupported format %s in accelerated glBitmap()\n", |
_mesa_get_format_name(irb->mt->format)); |
return false; |
} |
if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F)) |
return false; |
/* Clip to buffer bounds and scissor. */ |
if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, |
fb->_Xmax, fb->_Ymax, |
&dstx, &dsty, &width, &height)) |
goto out; |
dsty = y_flip(fb, dsty, height); |
#define DY 32 |
#define DX 32 |
/* Chop it all into chunks that can be digested by hardware: */ |
for (py = 0; py < height; py += DY) { |
for (px = 0; px < width; px += DX) { |
int h = MIN2(DY, height - py); |
int w = MIN2(DX, width - px); |
GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8; |
GLenum logic_op = ctx->Color.ColorLogicOpEnabled ? |
ctx->Color.LogicOp : GL_COPY; |
assert(sz <= sizeof(stipple)); |
memset(stipple, 0, sz); |
/* May need to adjust this when padding has been introduced in |
* sz above: |
* |
* Have to translate destination coordinates back into source |
* coordinates. |
*/ |
int count = get_bitmap_rect(bitmap_width, bitmap_height, unpack, |
bitmap, |
-orig_dstx + (dstx + px), |
-orig_dsty + y_flip(fb, dsty + py, h), |
w, h, |
(GLubyte *)stipple, |
8, |
_mesa_is_winsys_fbo(fb)); |
if (count == 0) |
continue; |
if (!intelEmitImmediateColorExpandBlit(intel, |
irb->mt->cpp, |
(GLubyte *)stipple, |
sz, |
color, |
irb->mt->region->pitch, |
irb->mt->region->bo, |
0, |
irb->mt->region->tiling, |
dstx + px, |
dsty + py, |
w, h, |
logic_op)) { |
return false; |
} |
if (ctx->Query.CurrentOcclusionObject) |
ctx->Query.CurrentOcclusionObject->Result += count; |
} |
} |
out: |
if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) |
intel_batchbuffer_flush(intel); |
if (_mesa_is_bufferobj(unpack->BufferObj)) { |
/* done with PBO so unmap it now */ |
ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); |
} |
intel_check_front_buffer_rendering(intel); |
return true; |
} |
/* There are a large number of possible ways to implement bitmap on |
* this hardware, most of them have some sort of drawback. Here are a |
* few that spring to mind: |
* |
* Blit: |
* - XY_MONO_SRC_BLT_CMD |
* - use XY_SETUP_CLIP_BLT for cliprect clipping. |
* - XY_TEXT_BLT |
* - XY_TEXT_IMMEDIATE_BLT |
* - blit per cliprect, subject to maximum immediate data size. |
* - XY_COLOR_BLT |
* - per pixel or run of pixels |
* - XY_PIXEL_BLT |
* - good for sparse bitmaps |
* |
* 3D engine: |
* - Point per pixel |
* - Translate bitmap to an alpha texture and render as a quad |
* - Chop bitmap up into 32x32 squares and render w/polygon stipple. |
*/ |
void |
intelBitmap(struct gl_context * ctx, |
GLint x, GLint y, |
GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte * pixels) |
{ |
if (!_mesa_check_conditional_render(ctx)) |
return; |
if (do_blit_bitmap(ctx, x, y, width, height, |
unpack, pixels)) |
return; |
_mesa_meta_Bitmap(ctx, x, y, width, height, unpack, pixels); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_pixel_copy.c |
---|
0,0 → 1,210 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/image.h" |
#include "main/state.h" |
#include "main/mtypes.h" |
#include "main/condrender.h" |
#include "main/fbobject.h" |
#include "drivers/common/meta.h" |
#include "intel_context.h" |
#include "intel_buffers.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_pixel.h" |
#include "intel_fbo.h" |
#include "intel_blit.h" |
#define FILE_DEBUG_FLAG DEBUG_PIXEL |
/** |
* CopyPixels with the blitter. Don't support zooming, pixel transfer, etc. |
*/ |
static bool |
do_blit_copypixels(struct gl_context * ctx, |
GLint srcx, GLint srcy, |
GLsizei width, GLsizei height, |
GLint dstx, GLint dsty, GLenum type) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct gl_framebuffer *read_fb = ctx->ReadBuffer; |
GLint orig_dstx; |
GLint orig_dsty; |
GLint orig_srcx; |
GLint orig_srcy; |
struct intel_renderbuffer *draw_irb = NULL; |
struct intel_renderbuffer *read_irb = NULL; |
/* Update draw buffer bounds */ |
_mesa_update_state(ctx); |
switch (type) { |
case GL_COLOR: |
if (fb->_NumColorDrawBuffers != 1) { |
perf_debug("glCopyPixels() fallback: MRT\n"); |
return false; |
} |
draw_irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); |
read_irb = intel_renderbuffer(read_fb->_ColorReadBuffer); |
break; |
case GL_DEPTH_STENCIL_EXT: |
draw_irb = intel_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); |
read_irb = |
intel_renderbuffer(read_fb->Attachment[BUFFER_DEPTH].Renderbuffer); |
break; |
case GL_DEPTH: |
perf_debug("glCopyPixels() fallback: GL_DEPTH\n"); |
return false; |
case GL_STENCIL: |
perf_debug("glCopyPixels() fallback: GL_STENCIL\n"); |
return false; |
default: |
perf_debug("glCopyPixels(): Unknown type\n"); |
return false; |
} |
if (!draw_irb) { |
perf_debug("glCopyPixels() fallback: missing draw buffer\n"); |
return false; |
} |
if (!read_irb) { |
perf_debug("glCopyPixels() fallback: missing read buffer\n"); |
return false; |
} |
if (ctx->_ImageTransferState) { |
perf_debug("glCopyPixels(): Unsupported image transfer state\n"); |
return false; |
} |
if (ctx->Depth.Test) { |
perf_debug("glCopyPixels(): Unsupported depth test state\n"); |
return false; |
} |
if (ctx->Stencil._Enabled) { |
perf_debug("glCopyPixels(): Unsupported stencil test state\n"); |
return false; |
} |
if (ctx->Fog.Enabled || |
ctx->Texture._EnabledUnits || |
ctx->FragmentProgram._Enabled) { |
perf_debug("glCopyPixels(): Unsupported fragment shader state\n"); |
return false; |
} |
if (ctx->Color.AlphaEnabled || |
ctx->Color.BlendEnabled) { |
perf_debug("glCopyPixels(): Unsupported blend state\n"); |
return false; |
} |
if (!ctx->Color.ColorMask[0][0] || |
!ctx->Color.ColorMask[0][1] || |
!ctx->Color.ColorMask[0][2] || |
!ctx->Color.ColorMask[0][3]) { |
perf_debug("glCopyPixels(): Unsupported color mask state\n"); |
return false; |
} |
if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) { |
perf_debug("glCopyPixles(): Unsupported pixel zoom\n"); |
return false; |
} |
intel_prepare_render(intel); |
intel_flush(&intel->ctx); |
/* Clip to destination buffer. */ |
orig_dstx = dstx; |
orig_dsty = dsty; |
if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, |
fb->_Xmax, fb->_Ymax, |
&dstx, &dsty, &width, &height)) |
goto out; |
/* Adjust src coords for our post-clipped destination origin */ |
srcx += dstx - orig_dstx; |
srcy += dsty - orig_dsty; |
/* Clip to source buffer. */ |
orig_srcx = srcx; |
orig_srcy = srcy; |
if (!_mesa_clip_to_region(0, 0, |
read_fb->Width, read_fb->Height, |
&srcx, &srcy, &width, &height)) |
goto out; |
/* Adjust dst coords for our post-clipped source origin */ |
dstx += srcx - orig_srcx; |
dsty += srcy - orig_srcy; |
if (!intel_miptree_blit(intel, |
read_irb->mt, read_irb->mt_level, read_irb->mt_layer, |
srcx, srcy, _mesa_is_winsys_fbo(read_fb), |
draw_irb->mt, draw_irb->mt_level, draw_irb->mt_layer, |
dstx, dsty, _mesa_is_winsys_fbo(fb), |
width, height, |
(ctx->Color.ColorLogicOpEnabled ? |
ctx->Color.LogicOp : GL_COPY))) { |
DBG("%s: blit failure\n", __FUNCTION__); |
return false; |
} |
if (ctx->Query.CurrentOcclusionObject) |
ctx->Query.CurrentOcclusionObject->Result += width * height; |
out: |
intel_check_front_buffer_rendering(intel); |
DBG("%s: success\n", __FUNCTION__); |
return true; |
} |
void |
intelCopyPixels(struct gl_context * ctx, |
GLint srcx, GLint srcy, |
GLsizei width, GLsizei height, |
GLint destx, GLint desty, GLenum type) |
{ |
DBG("%s\n", __FUNCTION__); |
if (!_mesa_check_conditional_render(ctx)) |
return; |
if (do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type)) |
return; |
/* this will use swrast if needed */ |
_mesa_meta_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_pixel_draw.c |
---|
0,0 → 1,58 |
/************************************************************************** |
* |
* 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 portionsalloc |
* 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 "main/glheader.h" |
#include "main/enums.h" |
#include "main/image.h" |
#include "main/mtypes.h" |
#include "main/teximage.h" |
#include "main/texobj.h" |
#include "main/texstate.h" |
#include "swrast/swrast.h" |
#include "drivers/common/meta.h" |
#include "intel_context.h" |
#include "intel_pixel.h" |
void |
intelDrawPixels(struct gl_context * ctx, |
GLint x, GLint y, |
GLsizei width, GLsizei height, |
GLenum format, |
GLenum type, |
const struct gl_pixelstore_attrib *unpack, |
const GLvoid * pixels) |
{ |
if (format == GL_STENCIL_INDEX) { |
_swrast_DrawPixels(ctx, x, y, width, height, format, type, |
unpack, pixels); |
return; |
} |
_mesa_meta_DrawPixels(ctx, x, y, width, height, format, type, |
unpack, pixels); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_pixel_read.c |
---|
0,0 → 1,202 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/enums.h" |
#include "main/mtypes.h" |
#include "main/macros.h" |
#include "main/fbobject.h" |
#include "main/image.h" |
#include "main/bufferobj.h" |
#include "main/readpix.h" |
#include "main/state.h" |
#include "intel_screen.h" |
#include "intel_context.h" |
#include "intel_blit.h" |
#include "intel_buffers.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_pixel.h" |
#include "intel_buffer_objects.h" |
#define FILE_DEBUG_FLAG DEBUG_PIXEL |
/* For many applications, the new ability to pull the source buffers |
* back out of the GTT and then do the packing/conversion operations |
* in software will be as much of an improvement as trying to get the |
* blitter and/or texture engine to do the work. |
* |
* This step is gated on private backbuffers. |
* |
* Obviously the frontbuffer can't be pulled back, so that is either |
* an argument for blit/texture readpixels, or for blitting to a |
* temporary and then pulling that back. |
* |
* When the destination is a pbo, however, it's not clear if it is |
* ever going to be pulled to main memory (though the access param |
* will be a good hint). So it sounds like we do want to be able to |
* choose between blit/texture implementation on the gpu and pullback |
* and cpu-based copying. |
* |
* Unless you can magically turn client memory into a PBO for the |
* duration of this call, there will be a cpu-based copying step in |
* any case. |
*/ |
static bool |
do_blit_readpixels(struct gl_context * ctx, |
GLint x, GLint y, GLsizei width, GLsizei height, |
GLenum format, GLenum type, |
const struct gl_pixelstore_attrib *pack, GLvoid * pixels) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj); |
GLuint dst_offset; |
drm_intel_bo *dst_buffer; |
bool all; |
GLint dst_x, dst_y; |
GLuint dirty; |
DBG("%s\n", __FUNCTION__); |
assert(_mesa_is_bufferobj(pack->BufferObj)); |
struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
if (ctx->_ImageTransferState || |
!_mesa_format_matches_format_and_type(irb->mt->format, format, type, |
false)) { |
DBG("%s - bad format for blit\n", __FUNCTION__); |
return false; |
} |
if (pack->SwapBytes || pack->LsbFirst) { |
DBG("%s: bad packing params\n", __FUNCTION__); |
return false; |
} |
int dst_stride = _mesa_image_row_stride(pack, width, format, type); |
bool dst_flip = false; |
/* Mesa flips the dst_stride for pack->Invert, but we want our mt to have a |
* normal dst_stride. |
*/ |
if (pack->Invert) { |
dst_stride = -dst_stride; |
dst_flip = true; |
} |
dst_offset = (GLintptr)pixels; |
dst_offset += _mesa_image_offset(2, pack, width, height, |
format, type, 0, 0, 0); |
if (!_mesa_clip_copytexsubimage(ctx, |
&dst_x, &dst_y, |
&x, &y, |
&width, &height)) { |
return true; |
} |
dirty = intel->front_buffer_dirty; |
intel_prepare_render(intel); |
intel->front_buffer_dirty = dirty; |
all = (width * height * irb->mt->cpp == dst->Base.Size && |
x == 0 && dst_offset == 0); |
dst_buffer = intel_bufferobj_buffer(intel, dst, |
all ? INTEL_WRITE_FULL : |
INTEL_WRITE_PART); |
struct intel_mipmap_tree *pbo_mt = |
intel_miptree_create_for_bo(intel, |
dst_buffer, |
irb->mt->format, |
dst_offset, |
width, height, |
dst_stride, I915_TILING_NONE); |
if (!intel_miptree_blit(intel, |
irb->mt, irb->mt_level, irb->mt_layer, |
x, y, _mesa_is_winsys_fbo(ctx->ReadBuffer), |
pbo_mt, 0, 0, |
0, 0, dst_flip, |
width, height, GL_COPY)) { |
return false; |
} |
intel_miptree_release(&pbo_mt); |
DBG("%s - DONE\n", __FUNCTION__); |
return true; |
} |
void |
intelReadPixels(struct gl_context * ctx, |
GLint x, GLint y, GLsizei width, GLsizei height, |
GLenum format, GLenum type, |
const struct gl_pixelstore_attrib *pack, GLvoid * pixels) |
{ |
struct intel_context *intel = intel_context(ctx); |
bool dirty; |
intel_flush_rendering_to_batch(ctx); |
DBG("%s\n", __FUNCTION__); |
if (_mesa_is_bufferobj(pack->BufferObj)) { |
/* Using PBOs, so try the BLT based path. */ |
if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, |
pixels)) { |
return; |
} |
perf_debug("%s: fallback to CPU mapping in PBO case\n", __FUNCTION__); |
} |
/* glReadPixels() wont dirty the front buffer, so reset the dirty |
* flag after calling intel_prepare_render(). */ |
dirty = intel->front_buffer_dirty; |
intel_prepare_render(intel); |
intel->front_buffer_dirty = dirty; |
/* Update Mesa state before calling _mesa_readpixels(). |
* XXX this may not be needed since ReadPixels no longer uses the |
* span code. |
*/ |
if (ctx->NewState) |
_mesa_update_state(ctx); |
_mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels); |
/* There's an intel_prepare_render() call in intelSpanRenderStart(). */ |
intel->front_buffer_dirty = dirty; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_reg.h |
---|
0,0 → 1,233 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#define CMD_MI (0x0 << 29) |
#define CMD_2D (0x2 << 29) |
#define CMD_3D (0x3 << 29) |
#define MI_NOOP (CMD_MI | 0) |
#define MI_BATCH_BUFFER_END (CMD_MI | 0xA << 23) |
#define MI_FLUSH (CMD_MI | (4 << 23)) |
#define FLUSH_MAP_CACHE (1 << 0) |
#define INHIBIT_FLUSH_RENDER_CACHE (1 << 2) |
#define MI_LOAD_REGISTER_IMM (CMD_MI | (0x22 << 23)) |
#define MI_FLUSH_DW (CMD_MI | (0x26 << 23) | 2) |
/* Stalls command execution waiting for the given events to have occurred. */ |
#define MI_WAIT_FOR_EVENT (CMD_MI | (0x3 << 23)) |
#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6) |
#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) |
#define MI_STORE_REGISTER_MEM (CMD_MI | (0x24 << 23)) |
# define MI_STORE_REGISTER_MEM_USE_GGTT (1 << 22) |
/* p189 */ |
#define _3DSTATE_LOAD_STATE_IMMEDIATE_1 (CMD_3D | (0x1d<<24) | (0x04<<16)) |
#define I1_LOAD_S(n) (1<<(4+n)) |
#define _3DSTATE_DRAWRECT_INFO (CMD_3D | (0x1d<<24) | (0x80<<16) | 0x3) |
/** @} */ |
/** @{ |
* 915 definitions |
* |
* 915 documents say that bits 31:28 and 1 are "undefined, must be zero." |
*/ |
#define S0_VB_OFFSET_MASK 0x0ffffffc |
#define S0_AUTO_CACHE_INV_DISABLE (1<<0) |
/** @} */ |
/** @{ |
* 830 definitions |
*/ |
#define S0_VB_OFFSET_MASK_830 0xffffff80 |
#define S0_VB_PITCH_SHIFT_830 1 |
#define S0_VB_ENABLE_830 (1<<0) |
/** @} */ |
#define S1_VERTEX_WIDTH_SHIFT 24 |
#define S1_VERTEX_WIDTH_MASK (0x3f<<24) |
#define S1_VERTEX_PITCH_SHIFT 16 |
#define S1_VERTEX_PITCH_MASK (0x3f<<16) |
#define TEXCOORDFMT_2D 0x0 |
#define TEXCOORDFMT_3D 0x1 |
#define TEXCOORDFMT_4D 0x2 |
#define TEXCOORDFMT_1D 0x3 |
#define TEXCOORDFMT_2D_16 0x4 |
#define TEXCOORDFMT_4D_16 0x5 |
#define TEXCOORDFMT_NOT_PRESENT 0xf |
#define S2_TEXCOORD_FMT0_MASK 0xf |
#define S2_TEXCOORD_FMT1_SHIFT 4 |
#define S2_TEXCOORD_FMT(unit, type) ((type)<<(unit*4)) |
#define S2_TEXCOORD_NONE (~0) |
#define S2_TEX_COUNT_SHIFT_830 12 |
#define S2_VERTEX_1_WIDTH_SHIFT_830 0 |
#define S2_VERTEX_0_WIDTH_SHIFT_830 6 |
/* S3 not interesting */ |
#define S4_POINT_WIDTH_SHIFT 23 |
#define S4_POINT_WIDTH_MASK (0x1ff<<23) |
#define S4_LINE_WIDTH_SHIFT 19 |
#define S4_LINE_WIDTH_ONE (0x2<<19) |
#define S4_LINE_WIDTH_MASK (0xf<<19) |
#define S4_FLATSHADE_ALPHA (1<<18) |
#define S4_FLATSHADE_FOG (1<<17) |
#define S4_FLATSHADE_SPECULAR (1<<16) |
#define S4_FLATSHADE_COLOR (1<<15) |
#define S4_CULLMODE_BOTH (0<<13) |
#define S4_CULLMODE_NONE (1<<13) |
#define S4_CULLMODE_CW (2<<13) |
#define S4_CULLMODE_CCW (3<<13) |
#define S4_CULLMODE_MASK (3<<13) |
#define S4_VFMT_POINT_WIDTH (1<<12) |
#define S4_VFMT_SPEC_FOG (1<<11) |
#define S4_VFMT_COLOR (1<<10) |
#define S4_VFMT_DEPTH_OFFSET (1<<9) |
#define S4_VFMT_XYZ (1<<6) |
#define S4_VFMT_XYZW (2<<6) |
#define S4_VFMT_XY (3<<6) |
#define S4_VFMT_XYW (4<<6) |
#define S4_VFMT_XYZW_MASK (7<<6) |
#define S4_FORCE_DEFAULT_DIFFUSE (1<<5) |
#define S4_FORCE_DEFAULT_SPECULAR (1<<4) |
#define S4_LOCAL_DEPTH_OFFSET_ENABLE (1<<3) |
#define S4_VFMT_FOG_PARAM (1<<2) |
#define S4_SPRITE_POINT_ENABLE (1<<1) |
#define S4_LINE_ANTIALIAS_ENABLE (1<<0) |
#define S4_VFMT_MASK (S4_VFMT_POINT_WIDTH | \ |
S4_VFMT_SPEC_FOG | \ |
S4_VFMT_COLOR | \ |
S4_VFMT_DEPTH_OFFSET | \ |
S4_VFMT_XYZW_MASK | \ |
S4_VFMT_FOG_PARAM) |
#define S5_WRITEDISABLE_ALPHA (1<<31) |
#define S5_WRITEDISABLE_RED (1<<30) |
#define S5_WRITEDISABLE_GREEN (1<<29) |
#define S5_WRITEDISABLE_BLUE (1<<28) |
#define S5_WRITEDISABLE_MASK (0xf<<28) |
#define S5_FORCE_DEFAULT_POINT_SIZE (1<<27) |
#define S5_LAST_PIXEL_ENABLE (1<<26) |
#define S5_GLOBAL_DEPTH_OFFSET_ENABLE (1<<25) |
#define S5_FOG_ENABLE (1<<24) |
#define S5_STENCIL_REF_SHIFT 16 |
#define S5_STENCIL_REF_MASK (0xff<<16) |
#define S5_STENCIL_TEST_FUNC_SHIFT 13 |
#define S5_STENCIL_TEST_FUNC_MASK (0x7<<13) |
#define S5_STENCIL_FAIL_SHIFT 10 |
#define S5_STENCIL_FAIL_MASK (0x7<<10) |
#define S5_STENCIL_PASS_Z_FAIL_SHIFT 7 |
#define S5_STENCIL_PASS_Z_FAIL_MASK (0x7<<7) |
#define S5_STENCIL_PASS_Z_PASS_SHIFT 4 |
#define S5_STENCIL_PASS_Z_PASS_MASK (0x7<<4) |
#define S5_STENCIL_WRITE_ENABLE (1<<3) |
#define S5_STENCIL_TEST_ENABLE (1<<2) |
#define S5_COLOR_DITHER_ENABLE (1<<1) |
#define S5_LOGICOP_ENABLE (1<<0) |
#define S6_ALPHA_TEST_ENABLE (1<<31) |
#define S6_ALPHA_TEST_FUNC_SHIFT 28 |
#define S6_ALPHA_TEST_FUNC_MASK (0x7<<28) |
#define S6_ALPHA_REF_SHIFT 20 |
#define S6_ALPHA_REF_MASK (0xff<<20) |
#define S6_DEPTH_TEST_ENABLE (1<<19) |
#define S6_DEPTH_TEST_FUNC_SHIFT 16 |
#define S6_DEPTH_TEST_FUNC_MASK (0x7<<16) |
#define S6_CBUF_BLEND_ENABLE (1<<15) |
#define S6_CBUF_BLEND_FUNC_SHIFT 12 |
#define S6_CBUF_BLEND_FUNC_MASK (0x7<<12) |
#define S6_CBUF_SRC_BLEND_FACT_SHIFT 8 |
#define S6_CBUF_SRC_BLEND_FACT_MASK (0xf<<8) |
#define S6_CBUF_DST_BLEND_FACT_SHIFT 4 |
#define S6_CBUF_DST_BLEND_FACT_MASK (0xf<<4) |
#define S6_DEPTH_WRITE_ENABLE (1<<3) |
#define S6_COLOR_WRITE_ENABLE (1<<2) |
#define S6_TRISTRIP_PV_SHIFT 0 |
#define S6_TRISTRIP_PV_MASK (0x3<<0) |
#define S7_DEPTH_OFFSET_CONST_MASK ~0 |
/* p143 */ |
#define _3DSTATE_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1) |
/* Dword 1 */ |
#define BUF_3D_ID_COLOR_BACK (0x3<<24) |
#define BUF_3D_ID_DEPTH (0x7<<24) |
#define BUF_3D_USE_FENCE (1<<23) |
#define BUF_3D_TILED_SURFACE (1<<22) |
#define BUF_3D_TILE_WALK_X 0 |
#define BUF_3D_TILE_WALK_Y (1<<21) |
#define BUF_3D_PITCH(x) (((x)/4)<<2) |
/* Dword 2 */ |
#define BUF_3D_ADDR(x) ((x) & ~0x3) |
/* Primitive dispatch on 830-945 */ |
#define _3DPRIMITIVE (CMD_3D | (0x1f << 24)) |
#define PRIM_INDIRECT (1<<23) |
#define PRIM_INLINE (0<<23) |
#define PRIM_INDIRECT_SEQUENTIAL (0<<17) |
#define PRIM_INDIRECT_ELTS (1<<17) |
#define PRIM3D_TRILIST (0x0<<18) |
#define PRIM3D_TRISTRIP (0x1<<18) |
#define PRIM3D_TRISTRIP_RVRSE (0x2<<18) |
#define PRIM3D_TRIFAN (0x3<<18) |
#define PRIM3D_POLY (0x4<<18) |
#define PRIM3D_LINELIST (0x5<<18) |
#define PRIM3D_LINESTRIP (0x6<<18) |
#define PRIM3D_RECTLIST (0x7<<18) |
#define PRIM3D_POINTLIST (0x8<<18) |
#define PRIM3D_DIB (0x9<<18) |
#define PRIM3D_MASK (0x1f<<18) |
#define XY_SETUP_BLT_CMD (CMD_2D | (0x01 << 22)) |
#define XY_COLOR_BLT_CMD (CMD_2D | (0x50 << 22)) |
#define XY_SRC_COPY_BLT_CMD (CMD_2D | (0x53 << 22)) |
#define XY_TEXT_IMMEDIATE_BLIT_CMD (CMD_2D | (0x31 << 22)) |
# define XY_TEXT_BYTE_PACKED (1 << 16) |
/* BR00 */ |
#define XY_BLT_WRITE_ALPHA (1 << 21) |
#define XY_BLT_WRITE_RGB (1 << 20) |
#define XY_SRC_TILED (1 << 15) |
#define XY_DST_TILED (1 << 11) |
/* BR13 */ |
#define BR13_8 (0x0 << 24) |
#define BR13_565 (0x1 << 24) |
#define BR13_8888 (0x3 << 24) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_regions.c |
---|
0,0 → 1,353 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
/* Provide additional functionality on top of bufmgr buffers: |
* - 2d semantics and blit operations |
* - refcounting of buffers for multiple images in a buffer. |
* - refcounting of buffer mappings. |
* - some logic for moving the buffers to the best memory pools for |
* given operations. |
* |
* Most of this is to make it easier to implement the fixed-layout |
* mipmap tree required by intel hardware in the face of GL's |
* programming interface where each image can be specifed in random |
* order and it isn't clear what layout the tree should have until the |
* last moment. |
*/ |
#include <sys/ioctl.h> |
#include <errno.h> |
#include "main/hash.h" |
#include "intel_context.h" |
#include "intel_regions.h" |
#include "intel_blit.h" |
#include "intel_buffer_objects.h" |
#include "intel_bufmgr.h" |
#include "intel_batchbuffer.h" |
#define FILE_DEBUG_FLAG DEBUG_REGION |
/* This should be set to the maximum backtrace size desired. |
* Set it to 0 to disable backtrace debugging. |
*/ |
#define DEBUG_BACKTRACE_SIZE 0 |
#if DEBUG_BACKTRACE_SIZE == 0 |
/* Use the standard debug output */ |
#define _DBG(...) DBG(__VA_ARGS__) |
#else |
/* Use backtracing debug output */ |
#define _DBG(...) {debug_backtrace(); DBG(__VA_ARGS__);} |
/* Backtracing debug support */ |
#include <execinfo.h> |
static void |
debug_backtrace(void) |
{ |
void *trace[DEBUG_BACKTRACE_SIZE]; |
char **strings = NULL; |
int traceSize; |
register int i; |
traceSize = backtrace(trace, DEBUG_BACKTRACE_SIZE); |
strings = backtrace_symbols(trace, traceSize); |
if (strings == NULL) { |
DBG("no backtrace:"); |
return; |
} |
/* Spit out all the strings with a colon separator. Ignore |
* the first, since we don't really care about the call |
* to debug_backtrace() itself. Skip until the final "/" in |
* the trace to avoid really long lines. |
*/ |
for (i = 1; i < traceSize; i++) { |
char *p = strings[i], *slash = strings[i]; |
while (*p) { |
if (*p++ == '/') { |
slash = p; |
} |
} |
DBG("%s:", slash); |
} |
/* Free up the memory, and we're done */ |
free(strings); |
} |
#endif |
static struct intel_region * |
intel_region_alloc_internal(struct intel_screen *screen, |
GLuint cpp, |
GLuint width, GLuint height, GLuint pitch, |
uint32_t tiling, drm_intel_bo *buffer) |
{ |
struct intel_region *region; |
region = calloc(sizeof(*region), 1); |
if (region == NULL) |
return region; |
region->cpp = cpp; |
region->width = width; |
region->height = height; |
region->pitch = pitch; |
region->refcount = 1; |
region->bo = buffer; |
region->tiling = tiling; |
_DBG("%s <-- %p\n", __FUNCTION__, region); |
return region; |
} |
struct intel_region * |
intel_region_alloc(struct intel_screen *screen, |
uint32_t tiling, |
GLuint cpp, GLuint width, GLuint height, |
bool expect_accelerated_upload) |
{ |
drm_intel_bo *buffer; |
unsigned long flags = 0; |
unsigned long aligned_pitch; |
struct intel_region *region; |
if (expect_accelerated_upload) |
flags |= BO_ALLOC_FOR_RENDER; |
buffer = drm_intel_bo_alloc_tiled(screen->bufmgr, "region", |
width, height, cpp, |
&tiling, &aligned_pitch, flags); |
if (buffer == NULL) |
return NULL; |
region = intel_region_alloc_internal(screen, cpp, width, height, |
aligned_pitch, tiling, buffer); |
if (region == NULL) { |
drm_intel_bo_unreference(buffer); |
return NULL; |
} |
return region; |
} |
bool |
intel_region_flink(struct intel_region *region, uint32_t *name) |
{ |
if (region->name == 0) { |
if (drm_intel_bo_flink(region->bo, ®ion->name)) |
return false; |
} |
*name = region->name; |
return true; |
} |
struct intel_region * |
intel_region_alloc_for_handle(struct intel_screen *screen, |
GLuint cpp, |
GLuint width, GLuint height, GLuint pitch, |
GLuint handle, const char *name) |
{ |
struct intel_region *region; |
drm_intel_bo *buffer; |
int ret; |
uint32_t bit_6_swizzle, tiling; |
buffer = intel_bo_gem_create_from_name(screen->bufmgr, name, handle); |
if (buffer == NULL) |
return NULL; |
ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle); |
if (ret != 0) { |
fprintf(stderr, "Couldn't get tiling of buffer %d (%s): %s\n", |
handle, name, strerror(-ret)); |
drm_intel_bo_unreference(buffer); |
return NULL; |
} |
region = intel_region_alloc_internal(screen, cpp, |
width, height, pitch, tiling, buffer); |
if (region == NULL) { |
drm_intel_bo_unreference(buffer); |
return NULL; |
} |
region->name = handle; |
return region; |
} |
struct intel_region * |
intel_region_alloc_for_fd(struct intel_screen *screen, |
GLuint cpp, |
GLuint width, GLuint height, GLuint pitch, |
int fd, const char *name) |
{ |
struct intel_region *region; |
drm_intel_bo *buffer; |
int ret; |
uint32_t bit_6_swizzle, tiling; |
buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr, |
fd, height * pitch); |
if (buffer == NULL) |
return NULL; |
ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle); |
if (ret != 0) { |
fprintf(stderr, "Couldn't get tiling of buffer (%s): %s\n", |
name, strerror(-ret)); |
drm_intel_bo_unreference(buffer); |
return NULL; |
} |
region = intel_region_alloc_internal(screen, cpp, |
width, height, pitch, tiling, buffer); |
if (region == NULL) { |
drm_intel_bo_unreference(buffer); |
return NULL; |
} |
return region; |
} |
void |
intel_region_reference(struct intel_region **dst, struct intel_region *src) |
{ |
_DBG("%s: %p(%d) -> %p(%d)\n", __FUNCTION__, |
*dst, *dst ? (*dst)->refcount : 0, src, src ? src->refcount : 0); |
if (src != *dst) { |
if (*dst) |
intel_region_release(dst); |
if (src) |
src->refcount++; |
*dst = src; |
} |
} |
void |
intel_region_release(struct intel_region **region_handle) |
{ |
struct intel_region *region = *region_handle; |
if (region == NULL) { |
_DBG("%s NULL\n", __FUNCTION__); |
return; |
} |
_DBG("%s %p %d\n", __FUNCTION__, region, region->refcount - 1); |
ASSERT(region->refcount > 0); |
region->refcount--; |
if (region->refcount == 0) { |
drm_intel_bo_unreference(region->bo); |
free(region); |
} |
*region_handle = NULL; |
} |
/** |
* This function computes masks that may be used to select the bits of the X |
* and Y coordinates that indicate the offset within a tile. If the region is |
* untiled, the masks are set to 0. |
*/ |
void |
intel_region_get_tile_masks(struct intel_region *region, |
uint32_t *mask_x, uint32_t *mask_y, |
bool map_stencil_as_y_tiled) |
{ |
int cpp = region->cpp; |
uint32_t tiling = region->tiling; |
if (map_stencil_as_y_tiled) |
tiling = I915_TILING_Y; |
switch (tiling) { |
default: |
assert(false); |
case I915_TILING_NONE: |
*mask_x = *mask_y = 0; |
break; |
case I915_TILING_X: |
*mask_x = 512 / cpp - 1; |
*mask_y = 7; |
break; |
case I915_TILING_Y: |
*mask_x = 128 / cpp - 1; |
*mask_y = 31; |
break; |
} |
} |
/** |
* Compute the offset (in bytes) from the start of the region to the given x |
* and y coordinate. For tiled regions, caller must ensure that x and y are |
* multiples of the tile size. |
*/ |
uint32_t |
intel_region_get_aligned_offset(struct intel_region *region, uint32_t x, |
uint32_t y, bool map_stencil_as_y_tiled) |
{ |
int cpp = region->cpp; |
uint32_t pitch = region->pitch; |
uint32_t tiling = region->tiling; |
if (map_stencil_as_y_tiled) { |
tiling = I915_TILING_Y; |
/* When mapping a W-tiled stencil buffer as Y-tiled, each 64-high W-tile |
* gets transformed into a 32-high Y-tile. Accordingly, the pitch of |
* the resulting region is twice the pitch of the original region, since |
* each row in the Y-tiled view corresponds to two rows in the actual |
* W-tiled surface. So we need to correct the pitch before computing |
* the offsets. |
*/ |
pitch *= 2; |
} |
switch (tiling) { |
default: |
assert(false); |
case I915_TILING_NONE: |
return y * pitch + x * cpp; |
case I915_TILING_X: |
assert((x % (512 / cpp)) == 0); |
assert((y % 8) == 0); |
return y * pitch + x / (512 / cpp) * 4096; |
case I915_TILING_Y: |
assert((x % (128 / cpp)) == 0); |
assert((y % 32) == 0); |
return y * pitch + x / (128 / cpp) * 4096; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_regions.h |
---|
0,0 → 1,160 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_REGIONS_H |
#define INTEL_REGIONS_H |
/** @file intel_regions.h |
* |
* Structure definitions and prototypes for intel_region handling, |
* which is the basic structure for rectangular collections of pixels |
* stored in a drm_intel_bo. |
*/ |
#include <stdbool.h> |
#include <xf86drm.h> |
#include "main/mtypes.h" |
#include "intel_bufmgr.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
struct intel_context; |
struct intel_screen; |
struct intel_buffer_object; |
/** |
* A layer on top of the bufmgr buffers that adds a few useful things: |
* |
* - Refcounting for local buffer references. |
* - Refcounting for buffer maps |
* - Buffer dimensions - pitch and height. |
* - Blitter commands for copying 2D regions between buffers. (really???) |
*/ |
struct intel_region |
{ |
drm_intel_bo *bo; /**< buffer manager's buffer */ |
GLuint refcount; /**< Reference count for region */ |
GLuint cpp; /**< bytes per pixel */ |
GLuint width; /**< in pixels */ |
GLuint height; /**< in pixels */ |
GLuint pitch; /**< in bytes */ |
uint32_t tiling; /**< Which tiling mode the region is in */ |
uint32_t name; /**< Global name for the bo */ |
}; |
/* Allocate a refcounted region. Pointers to regions should only be |
* copied by calling intel_reference_region(). |
*/ |
struct intel_region *intel_region_alloc(struct intel_screen *screen, |
uint32_t tiling, |
GLuint cpp, GLuint width, |
GLuint height, |
bool expect_accelerated_upload); |
struct intel_region * |
intel_region_alloc_for_handle(struct intel_screen *screen, |
GLuint cpp, |
GLuint width, GLuint height, GLuint pitch, |
unsigned int handle, const char *name); |
struct intel_region * |
intel_region_alloc_for_fd(struct intel_screen *screen, |
GLuint cpp, |
GLuint width, GLuint height, GLuint pitch, |
int fd, const char *name); |
bool |
intel_region_flink(struct intel_region *region, uint32_t *name); |
void intel_region_reference(struct intel_region **dst, |
struct intel_region *src); |
void intel_region_release(struct intel_region **ib); |
void intel_recreate_static_regions(struct intel_context *intel); |
void |
intel_region_get_tile_masks(struct intel_region *region, |
uint32_t *mask_x, uint32_t *mask_y, |
bool map_stencil_as_y_tiled); |
uint32_t |
intel_region_get_aligned_offset(struct intel_region *region, uint32_t x, |
uint32_t y, bool map_stencil_as_y_tiled); |
/** |
* Used with images created with image_from_names |
* to help support planar images. |
*/ |
struct intel_image_format { |
int fourcc; |
int components; |
int nplanes; |
struct { |
int buffer_index; |
int width_shift; |
int height_shift; |
uint32_t dri_format; |
int cpp; |
} planes[3]; |
}; |
struct __DRIimageRec { |
struct intel_region *region; |
GLenum internal_format; |
uint32_t dri_format; |
GLuint format; |
uint32_t offset; |
/* |
* Need to save these here between calls to |
* image_from_names and calls to image_from_planar. |
*/ |
uint32_t strides[3]; |
uint32_t offsets[3]; |
struct intel_image_format *planar_format; |
/* particular miptree level */ |
GLuint width; |
GLuint height; |
GLuint tile_x; |
GLuint tile_y; |
void *data; |
}; |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_render.c |
---|
0,0 → 1,287 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
/* |
* Render unclipped vertex buffers by emitting vertices directly to |
* dma buffers. Use strip/fan hardware acceleration where possible. |
* |
*/ |
#include "main/glheader.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/imports.h" |
#include "main/mtypes.h" |
#include "main/enums.h" |
#include "math/m_xform.h" |
#include "tnl/t_context.h" |
#include "tnl/t_vertex.h" |
#include "tnl/t_pipeline.h" |
#include "intel_screen.h" |
#include "intel_context.h" |
#include "intel_tris.h" |
#include "intel_batchbuffer.h" |
#include "intel_reg.h" |
/* |
* Render unclipped vertex buffers by emitting vertices directly to |
* dma buffers. Use strip/fan hardware primitives where possible. |
* Try to simulate missing primitives with indexed vertices. |
*/ |
#define HAVE_POINTS 0 /* Has it, but can't use because subpixel has to |
* be adjusted for points on the INTEL/I845G |
*/ |
#define HAVE_LINES 1 |
#define HAVE_LINE_STRIPS 1 |
#define HAVE_TRIANGLES 1 |
#define HAVE_TRI_STRIPS 1 |
#define HAVE_TRI_STRIP_1 0 /* has it, template can't use it yet */ |
#define HAVE_TRI_FANS 1 |
#define HAVE_POLYGONS 1 |
#define HAVE_QUADS 0 |
#define HAVE_QUAD_STRIPS 0 |
#define HAVE_ELTS 0 |
static uint32_t hw_prim[GL_POLYGON + 1] = { |
0, |
PRIM3D_LINELIST, |
PRIM3D_LINESTRIP, |
PRIM3D_LINESTRIP, |
PRIM3D_TRILIST, |
PRIM3D_TRISTRIP, |
PRIM3D_TRIFAN, |
0, |
0, |
PRIM3D_POLY |
}; |
static const GLenum reduced_prim[GL_POLYGON + 1] = { |
GL_POINTS, |
GL_LINES, |
GL_LINES, |
GL_LINES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES |
}; |
static const int scale_prim[GL_POLYGON + 1] = { |
0, /* fallback case */ |
1, |
2, |
2, |
1, |
3, |
3, |
0, /* fallback case */ |
0, /* fallback case */ |
3 |
}; |
static void |
intelDmaPrimitive(struct intel_context *intel, GLenum prim) |
{ |
if (0) |
fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); |
INTEL_FIREVERTICES(intel); |
intel->vtbl.reduced_primitive_state(intel, reduced_prim[prim]); |
intel_set_prim(intel, hw_prim[prim]); |
} |
#define INTEL_NO_VBO_STATE_RESERVED 1500 |
static INLINE GLuint intel_get_vb_max(struct intel_context *intel) |
{ |
GLuint ret; |
if (intel->intelScreen->no_vbo) { |
ret = intel->batch.bo->size - INTEL_NO_VBO_STATE_RESERVED; |
} else |
ret = INTEL_VB_SIZE; |
ret /= (intel->vertex_size * 4); |
return ret; |
} |
static INLINE GLuint intel_get_current_max(struct intel_context *intel) |
{ |
GLuint ret; |
if (intel->intelScreen->no_vbo) { |
ret = intel_batchbuffer_space(intel); |
ret = ret <= INTEL_NO_VBO_STATE_RESERVED ? 0 : ret - INTEL_NO_VBO_STATE_RESERVED; |
} else |
ret = (INTEL_VB_SIZE - intel->prim.current_offset); |
return ret / (intel->vertex_size * 4); |
} |
#define LOCAL_VARS struct intel_context *intel = intel_context(ctx) |
#define INIT( prim ) \ |
do { \ |
intelDmaPrimitive( intel, prim ); \ |
} while (0) |
#define FLUSH() INTEL_FIREVERTICES(intel) |
#define GET_SUBSEQUENT_VB_MAX_VERTS() intel_get_vb_max(intel) |
#define GET_CURRENT_VB_MAX_VERTS() intel_get_current_max(intel) |
#define ALLOC_VERTS(nr) intel_get_prim_space(intel, nr) |
#define EMIT_VERTS( ctx, j, nr, buf ) \ |
_tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf ) |
#define TAG(x) intel_##x |
#include "tnl_dd/t_dd_dmatmp.h" |
/**********************************************************************/ |
/* Render pipeline stage */ |
/**********************************************************************/ |
/* Heuristic to choose between the two render paths: |
*/ |
static bool |
choose_render(struct intel_context *intel, struct vertex_buffer *VB) |
{ |
int vertsz = intel->vertex_size; |
int cost_render = 0; |
int cost_fallback = 0; |
int nr_prims = 0; |
int nr_rprims = 0; |
int nr_rverts = 0; |
int rprim = intel->reduced_primitive; |
int i = 0; |
for (i = 0; i < VB->PrimitiveCount; i++) { |
GLuint prim = VB->Primitive[i].mode; |
GLuint length = VB->Primitive[i].count; |
if (!length) |
continue; |
nr_prims++; |
nr_rverts += length * scale_prim[prim & PRIM_MODE_MASK]; |
if (reduced_prim[prim & PRIM_MODE_MASK] != rprim) { |
nr_rprims++; |
rprim = reduced_prim[prim & PRIM_MODE_MASK]; |
} |
} |
/* One point for each generated primitive: |
*/ |
cost_render = nr_prims; |
cost_fallback = nr_rprims; |
/* One point for every 1024 dwords (4k) of dma: |
*/ |
cost_render += (vertsz * i) / 1024; |
cost_fallback += (vertsz * nr_rverts) / 1024; |
if (0) |
fprintf(stderr, "cost render: %d fallback: %d\n", |
cost_render, cost_fallback); |
if (cost_render > cost_fallback) |
return false; |
return true; |
} |
static GLboolean |
intel_run_render(struct gl_context * ctx, struct tnl_pipeline_stage *stage) |
{ |
struct intel_context *intel = intel_context(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLuint i; |
intel->vtbl.render_prevalidate( intel ); |
/* Don't handle clipping or indexed vertices. |
*/ |
if (intel->RenderIndex != 0 || |
!intel_validate_render(ctx, VB) || !choose_render(intel, VB)) { |
return true; |
} |
tnl->clipspace.new_inputs |= VERT_BIT_POS; |
tnl->Driver.Render.Start(ctx); |
for (i = 0; i < VB->PrimitiveCount; i++) { |
GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); |
GLuint start = VB->Primitive[i].start; |
GLuint length = VB->Primitive[i].count; |
if (!length) |
continue; |
intel_render_tab_verts[prim & PRIM_MODE_MASK] (ctx, start, |
start + length, prim); |
} |
tnl->Driver.Render.Finish(ctx); |
INTEL_FIREVERTICES(intel); |
return false; /* finished the pipe */ |
} |
static const struct tnl_pipeline_stage _intel_render_stage = { |
"intel render", |
NULL, |
NULL, |
NULL, |
NULL, |
intel_run_render /* run */ |
}; |
const struct tnl_pipeline_stage *intel_pipeline[] = { |
&_tnl_vertex_transform_stage, |
&_tnl_normal_transform_stage, |
&_tnl_lighting_stage, |
&_tnl_fog_coordinate_stage, |
&_tnl_texgen_stage, |
&_tnl_texture_transform_stage, |
&_tnl_point_attenuation_stage, |
&_tnl_vertex_program_stage, |
#if 1 |
&_intel_render_stage, /* ADD: unclipped rastersetup-to-dma */ |
#endif |
&_tnl_render_stage, |
0, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_screen.c |
---|
0,0 → 1,1233 |
/************************************************************************** |
* |
* 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 <errno.h> |
#include <time.h> |
#include "main/glheader.h" |
#include "main/context.h" |
#include "main/framebuffer.h" |
#include "main/renderbuffer.h" |
#include "main/texobj.h" |
#include "main/hash.h" |
#include "main/fbobject.h" |
#include "main/version.h" |
#include "swrast/s_renderbuffer.h" |
#include "utils.h" |
#include "xmlpool.h" |
PUBLIC const char __driConfigOptions[] = |
DRI_CONF_BEGIN |
DRI_CONF_SECTION_PERFORMANCE |
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_ALWAYS_SYNC) |
/* Options correspond to DRI_CONF_BO_REUSE_DISABLED, |
* DRI_CONF_BO_REUSE_ALL |
*/ |
DRI_CONF_OPT_BEGIN_V(bo_reuse, enum, 1, "0:1") |
DRI_CONF_DESC_BEGIN(en, "Buffer object reuse") |
DRI_CONF_ENUM(0, "Disable buffer object reuse") |
DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects") |
DRI_CONF_DESC_END |
DRI_CONF_OPT_END |
DRI_CONF_OPT_BEGIN_B(early_z, "false") |
DRI_CONF_DESC(en, "Enable early Z in classic mode (unstable, 945-only).") |
DRI_CONF_OPT_END |
DRI_CONF_SECTION_END |
DRI_CONF_SECTION_QUALITY |
DRI_CONF_FORCE_S3TC_ENABLE("false") |
DRI_CONF_SECTION_END |
DRI_CONF_SECTION_DEBUG |
DRI_CONF_NO_RAST("false") |
DRI_CONF_ALWAYS_FLUSH_BATCH("false") |
DRI_CONF_ALWAYS_FLUSH_CACHE("false") |
DRI_CONF_DISABLE_THROTTLING("false") |
DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN("false") |
DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS("false") |
DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED("false") |
DRI_CONF_OPT_BEGIN_B(shader_precompile, "true") |
DRI_CONF_DESC(en, "Perform code generation at shader link time.") |
DRI_CONF_OPT_END |
DRI_CONF_SECTION_END |
DRI_CONF_END; |
const GLuint __driNConfigOptions = 12; |
#include "intel_batchbuffer.h" |
#include "intel_buffers.h" |
#include "intel_bufmgr.h" |
#include "intel_chipset.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_screen.h" |
#include "intel_tex.h" |
#include "intel_regions.h" |
#include "i915_drm.h" |
#ifdef USE_NEW_INTERFACE |
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; |
#endif /*USE_NEW_INTERFACE */ |
/** |
* For debugging purposes, this returns a time in seconds. |
*/ |
double |
get_time(void) |
{ |
struct timespec tp; |
clock_gettime(CLOCK_MONOTONIC, &tp); |
return tp.tv_sec + tp.tv_nsec / 1000000000.0; |
} |
void |
aub_dump_bmp(struct gl_context *ctx) |
{ |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
for (int i = 0; i < fb->_NumColorDrawBuffers; i++) { |
struct intel_renderbuffer *irb = |
intel_renderbuffer(fb->_ColorDrawBuffers[i]); |
if (irb && irb->mt) { |
enum aub_dump_bmp_format format; |
switch (irb->Base.Base.Format) { |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_XRGB8888: |
format = AUB_DUMP_BMP_FORMAT_ARGB_8888; |
break; |
default: |
continue; |
} |
assert(irb->mt->region->pitch % irb->mt->region->cpp == 0); |
drm_intel_gem_bo_aub_dump_bmp(irb->mt->region->bo, |
irb->draw_x, |
irb->draw_y, |
irb->Base.Base.Width, |
irb->Base.Base.Height, |
format, |
irb->mt->region->pitch, |
0); |
} |
} |
} |
static const __DRItexBufferExtension intelTexBufferExtension = { |
.base = { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, |
.setTexBuffer = intelSetTexBuffer, |
.setTexBuffer2 = intelSetTexBuffer2, |
.releaseTexBuffer = NULL, |
}; |
static void |
intelDRI2Flush(__DRIdrawable *drawable) |
{ |
GET_CURRENT_CONTEXT(ctx); |
struct intel_context *intel = intel_context(ctx); |
if (intel == NULL) |
return; |
INTEL_FIREVERTICES(intel); |
intel->need_throttle = true; |
if (intel->batch.used) |
intel_batchbuffer_flush(intel); |
if (INTEL_DEBUG & DEBUG_AUB) { |
aub_dump_bmp(ctx); |
} |
} |
static const struct __DRI2flushExtensionRec intelFlushExtension = { |
.base = { __DRI2_FLUSH, 3 }, |
.flush = intelDRI2Flush, |
.invalidate = dri2InvalidateDrawable, |
}; |
static struct intel_image_format intel_image_formats[] = { |
{ __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } }, |
{ __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_COMPONENTS_RGB, 1, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } }, |
{ __DRI_IMAGE_FOURCC_YUV410, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } }, |
{ __DRI_IMAGE_FOURCC_YUV411, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, |
{ __DRI_IMAGE_FOURCC_YUV420, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } }, |
{ __DRI_IMAGE_FOURCC_YUV422, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, |
{ __DRI_IMAGE_FOURCC_YUV444, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, |
{ __DRI_IMAGE_FOURCC_NV12, __DRI_IMAGE_COMPONENTS_Y_UV, 2, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } }, |
{ __DRI_IMAGE_FOURCC_NV16, __DRI_IMAGE_COMPONENTS_Y_UV, 2, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } }, |
/* For YUYV buffers, we set up two overlapping DRI images and treat |
* them as planar buffers in the compositors. Plane 0 is GR88 and |
* samples YU or YV pairs and places Y into the R component, while |
* plane 1 is ARGB and samples YUYV clusters and places pairs and |
* places U into the G component and V into A. This lets the |
* texture sampler interpolate the Y components correctly when |
* sampling from plane 0, and interpolate U and V correctly when |
* sampling from plane 1. */ |
{ __DRI_IMAGE_FOURCC_YUYV, __DRI_IMAGE_COMPONENTS_Y_XUXV, 2, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, |
{ 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } } |
}; |
static __DRIimage * |
intel_allocate_image(int dri_format, void *loaderPrivate) |
{ |
__DRIimage *image; |
image = calloc(1, sizeof *image); |
if (image == NULL) |
return NULL; |
image->dri_format = dri_format; |
image->offset = 0; |
switch (dri_format) { |
case __DRI_IMAGE_FORMAT_RGB565: |
image->format = MESA_FORMAT_RGB565; |
break; |
case __DRI_IMAGE_FORMAT_XRGB8888: |
image->format = MESA_FORMAT_XRGB8888; |
break; |
case __DRI_IMAGE_FORMAT_ARGB8888: |
image->format = MESA_FORMAT_ARGB8888; |
break; |
case __DRI_IMAGE_FORMAT_ABGR8888: |
image->format = MESA_FORMAT_RGBA8888_REV; |
break; |
case __DRI_IMAGE_FORMAT_XBGR8888: |
image->format = MESA_FORMAT_RGBX8888_REV; |
break; |
case __DRI_IMAGE_FORMAT_R8: |
image->format = MESA_FORMAT_R8; |
break; |
case __DRI_IMAGE_FORMAT_GR88: |
image->format = MESA_FORMAT_GR88; |
break; |
case __DRI_IMAGE_FORMAT_NONE: |
image->format = MESA_FORMAT_NONE; |
break; |
default: |
free(image); |
return NULL; |
} |
image->internal_format = _mesa_get_format_base_format(image->format); |
image->data = loaderPrivate; |
return image; |
} |
/** |
* Sets up a DRIImage structure to point to our shared image in a region |
*/ |
static void |
intel_setup_image_from_mipmap_tree(struct intel_context *intel, __DRIimage *image, |
struct intel_mipmap_tree *mt, GLuint level, |
GLuint zoffset) |
{ |
unsigned int draw_x, draw_y; |
uint32_t mask_x, mask_y; |
intel_miptree_check_level_layer(mt, level, zoffset); |
intel_region_get_tile_masks(mt->region, &mask_x, &mask_y, false); |
intel_miptree_get_image_offset(mt, level, zoffset, &draw_x, &draw_y); |
image->width = mt->level[level].width; |
image->height = mt->level[level].height; |
image->tile_x = draw_x & mask_x; |
image->tile_y = draw_y & mask_y; |
image->offset = intel_region_get_aligned_offset(mt->region, |
draw_x & ~mask_x, |
draw_y & ~mask_y, |
false); |
intel_region_reference(&image->region, mt->region); |
} |
static void |
intel_setup_image_from_dimensions(__DRIimage *image) |
{ |
image->width = image->region->width; |
image->height = image->region->height; |
image->tile_x = 0; |
image->tile_y = 0; |
} |
static inline uint32_t |
intel_dri_format(GLuint format) |
{ |
switch (format) { |
case MESA_FORMAT_RGB565: |
return __DRI_IMAGE_FORMAT_RGB565; |
case MESA_FORMAT_XRGB8888: |
return __DRI_IMAGE_FORMAT_XRGB8888; |
case MESA_FORMAT_ARGB8888: |
return __DRI_IMAGE_FORMAT_ARGB8888; |
case MESA_FORMAT_RGBA8888_REV: |
return __DRI_IMAGE_FORMAT_ABGR8888; |
case MESA_FORMAT_R8: |
return __DRI_IMAGE_FORMAT_R8; |
case MESA_FORMAT_RG88: |
return __DRI_IMAGE_FORMAT_GR88; |
} |
return MESA_FORMAT_NONE; |
} |
static __DRIimage * |
intel_create_image_from_name(__DRIscreen *screen, |
int width, int height, int format, |
int name, int pitch, void *loaderPrivate) |
{ |
struct intel_screen *intelScreen = screen->driverPrivate; |
__DRIimage *image; |
int cpp; |
image = intel_allocate_image(format, loaderPrivate); |
if (image == NULL) |
return NULL; |
if (image->format == MESA_FORMAT_NONE) |
cpp = 1; |
else |
cpp = _mesa_get_format_bytes(image->format); |
image->region = intel_region_alloc_for_handle(intelScreen, |
cpp, width, height, |
pitch * cpp, name, "image"); |
if (image->region == NULL) { |
free(image); |
return NULL; |
} |
intel_setup_image_from_dimensions(image); |
return image; |
} |
static __DRIimage * |
intel_create_image_from_renderbuffer(__DRIcontext *context, |
int renderbuffer, void *loaderPrivate) |
{ |
__DRIimage *image; |
struct intel_context *intel = context->driverPrivate; |
struct gl_renderbuffer *rb; |
struct intel_renderbuffer *irb; |
rb = _mesa_lookup_renderbuffer(&intel->ctx, renderbuffer); |
if (!rb) { |
_mesa_error(&intel->ctx, |
GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); |
return NULL; |
} |
irb = intel_renderbuffer(rb); |
image = calloc(1, sizeof *image); |
if (image == NULL) |
return NULL; |
image->internal_format = rb->InternalFormat; |
image->format = rb->Format; |
image->offset = 0; |
image->data = loaderPrivate; |
intel_region_reference(&image->region, irb->mt->region); |
intel_setup_image_from_dimensions(image); |
image->dri_format = intel_dri_format(image->format); |
rb->NeedsFinishRenderTexture = true; |
return image; |
} |
static __DRIimage * |
intel_create_image_from_texture(__DRIcontext *context, int target, |
unsigned texture, int zoffset, |
int level, |
unsigned *error, |
void *loaderPrivate) |
{ |
__DRIimage *image; |
struct intel_context *intel = context->driverPrivate; |
struct gl_texture_object *obj; |
struct intel_texture_object *iobj; |
GLuint face = 0; |
obj = _mesa_lookup_texture(&intel->ctx, texture); |
if (!obj || obj->Target != target) { |
*error = __DRI_IMAGE_ERROR_BAD_PARAMETER; |
return NULL; |
} |
if (target == GL_TEXTURE_CUBE_MAP) |
face = zoffset; |
_mesa_test_texobj_completeness(&intel->ctx, obj); |
iobj = intel_texture_object(obj); |
if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) { |
*error = __DRI_IMAGE_ERROR_BAD_PARAMETER; |
return NULL; |
} |
if (level < obj->BaseLevel || level > obj->_MaxLevel) { |
*error = __DRI_IMAGE_ERROR_BAD_MATCH; |
return NULL; |
} |
if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < zoffset) { |
*error = __DRI_IMAGE_ERROR_BAD_MATCH; |
return NULL; |
} |
image = calloc(1, sizeof *image); |
if (image == NULL) { |
*error = __DRI_IMAGE_ERROR_BAD_ALLOC; |
return NULL; |
} |
image->internal_format = obj->Image[face][level]->InternalFormat; |
image->format = obj->Image[face][level]->TexFormat; |
image->data = loaderPrivate; |
intel_setup_image_from_mipmap_tree(intel, image, iobj->mt, level, zoffset); |
image->dri_format = intel_dri_format(image->format); |
if (image->dri_format == MESA_FORMAT_NONE) { |
*error = __DRI_IMAGE_ERROR_BAD_PARAMETER; |
free(image); |
return NULL; |
} |
*error = __DRI_IMAGE_ERROR_SUCCESS; |
return image; |
} |
static void |
intel_destroy_image(__DRIimage *image) |
{ |
intel_region_release(&image->region); |
free(image); |
} |
static __DRIimage * |
intel_create_image(__DRIscreen *screen, |
int width, int height, int format, |
unsigned int use, |
void *loaderPrivate) |
{ |
__DRIimage *image; |
struct intel_screen *intelScreen = screen->driverPrivate; |
uint32_t tiling; |
int cpp; |
tiling = I915_TILING_X; |
if (use & __DRI_IMAGE_USE_CURSOR) { |
if (width != 64 || height != 64) |
return NULL; |
tiling = I915_TILING_NONE; |
} |
image = intel_allocate_image(format, loaderPrivate); |
if (image == NULL) |
return NULL; |
cpp = _mesa_get_format_bytes(image->format); |
image->region = |
intel_region_alloc(intelScreen, tiling, cpp, width, height, true); |
if (image->region == NULL) { |
free(image); |
return NULL; |
} |
intel_setup_image_from_dimensions(image); |
return image; |
} |
static GLboolean |
intel_query_image(__DRIimage *image, int attrib, int *value) |
{ |
switch (attrib) { |
case __DRI_IMAGE_ATTRIB_STRIDE: |
*value = image->region->pitch; |
return true; |
case __DRI_IMAGE_ATTRIB_HANDLE: |
*value = image->region->bo->handle; |
return true; |
case __DRI_IMAGE_ATTRIB_NAME: |
return intel_region_flink(image->region, (uint32_t *) value); |
case __DRI_IMAGE_ATTRIB_FORMAT: |
*value = image->dri_format; |
return true; |
case __DRI_IMAGE_ATTRIB_WIDTH: |
*value = image->region->width; |
return true; |
case __DRI_IMAGE_ATTRIB_HEIGHT: |
*value = image->region->height; |
return true; |
case __DRI_IMAGE_ATTRIB_COMPONENTS: |
if (image->planar_format == NULL) |
return false; |
*value = image->planar_format->components; |
return true; |
case __DRI_IMAGE_ATTRIB_FD: |
if (drm_intel_bo_gem_export_to_prime(image->region->bo, value) == 0) |
return true; |
return false; |
default: |
return false; |
} |
} |
static __DRIimage * |
intel_dup_image(__DRIimage *orig_image, void *loaderPrivate) |
{ |
__DRIimage *image; |
image = calloc(1, sizeof *image); |
if (image == NULL) |
return NULL; |
intel_region_reference(&image->region, orig_image->region); |
if (image->region == NULL) { |
free(image); |
return NULL; |
} |
image->internal_format = orig_image->internal_format; |
image->planar_format = orig_image->planar_format; |
image->dri_format = orig_image->dri_format; |
image->format = orig_image->format; |
image->offset = orig_image->offset; |
image->width = orig_image->width; |
image->height = orig_image->height; |
image->tile_x = orig_image->tile_x; |
image->tile_y = orig_image->tile_y; |
image->data = loaderPrivate; |
memcpy(image->strides, orig_image->strides, sizeof(image->strides)); |
memcpy(image->offsets, orig_image->offsets, sizeof(image->offsets)); |
return image; |
} |
static GLboolean |
intel_validate_usage(__DRIimage *image, unsigned int use) |
{ |
if (use & __DRI_IMAGE_USE_CURSOR) { |
if (image->region->width != 64 || image->region->height != 64) |
return GL_FALSE; |
} |
return GL_TRUE; |
} |
static __DRIimage * |
intel_create_image_from_names(__DRIscreen *screen, |
int width, int height, int fourcc, |
int *names, int num_names, |
int *strides, int *offsets, |
void *loaderPrivate) |
{ |
struct intel_image_format *f = NULL; |
__DRIimage *image; |
int i, index; |
if (screen == NULL || names == NULL || num_names != 1) |
return NULL; |
for (i = 0; i < ARRAY_SIZE(intel_image_formats); i++) { |
if (intel_image_formats[i].fourcc == fourcc) { |
f = &intel_image_formats[i]; |
} |
} |
if (f == NULL) |
return NULL; |
image = intel_create_image_from_name(screen, width, height, |
__DRI_IMAGE_FORMAT_NONE, |
names[0], strides[0], |
loaderPrivate); |
if (image == NULL) |
return NULL; |
image->planar_format = f; |
for (i = 0; i < f->nplanes; i++) { |
index = f->planes[i].buffer_index; |
image->offsets[index] = offsets[index]; |
image->strides[index] = strides[index]; |
} |
return image; |
} |
static __DRIimage * |
intel_create_image_from_fds(__DRIscreen *screen, |
int width, int height, int fourcc, |
int *fds, int num_fds, int *strides, int *offsets, |
void *loaderPrivate) |
{ |
struct intel_screen *intelScreen = screen->driverPrivate; |
struct intel_image_format *f = NULL; |
__DRIimage *image; |
int i, index; |
if (fds == NULL || num_fds != 1) |
return NULL; |
for (i = 0; i < ARRAY_SIZE(intel_image_formats); i++) { |
if (intel_image_formats[i].fourcc == fourcc) { |
f = &intel_image_formats[i]; |
} |
} |
if (f == NULL) |
return NULL; |
image = intel_allocate_image(__DRI_IMAGE_FORMAT_NONE, loaderPrivate); |
if (image == NULL) |
return NULL; |
image->region = intel_region_alloc_for_fd(intelScreen, |
1, width, height, |
strides[0], fds[0], "image"); |
if (image->region == NULL) { |
free(image); |
return NULL; |
} |
image->planar_format = f; |
for (i = 0; i < f->nplanes; i++) { |
index = f->planes[i].buffer_index; |
image->offsets[index] = offsets[index]; |
image->strides[index] = strides[index]; |
} |
return image; |
} |
static __DRIimage * |
intel_from_planar(__DRIimage *parent, int plane, void *loaderPrivate) |
{ |
int width, height, offset, stride, dri_format, index; |
struct intel_image_format *f; |
uint32_t mask_x, mask_y; |
__DRIimage *image; |
if (parent == NULL || parent->planar_format == NULL) |
return NULL; |
f = parent->planar_format; |
if (plane >= f->nplanes) |
return NULL; |
width = parent->region->width >> f->planes[plane].width_shift; |
height = parent->region->height >> f->planes[plane].height_shift; |
dri_format = f->planes[plane].dri_format; |
index = f->planes[plane].buffer_index; |
offset = parent->offsets[index]; |
stride = parent->strides[index]; |
image = intel_allocate_image(dri_format, loaderPrivate); |
if (image == NULL) |
return NULL; |
if (offset + height * stride > parent->region->bo->size) { |
_mesa_warning(NULL, "intel_create_sub_image: subimage out of bounds"); |
free(image); |
return NULL; |
} |
image->region = calloc(sizeof(*image->region), 1); |
if (image->region == NULL) { |
free(image); |
return NULL; |
} |
image->region->cpp = _mesa_get_format_bytes(image->format); |
image->region->width = width; |
image->region->height = height; |
image->region->pitch = stride; |
image->region->refcount = 1; |
image->region->bo = parent->region->bo; |
drm_intel_bo_reference(image->region->bo); |
image->region->tiling = parent->region->tiling; |
image->offset = offset; |
intel_setup_image_from_dimensions(image); |
intel_region_get_tile_masks(image->region, &mask_x, &mask_y, false); |
if (offset & mask_x) |
_mesa_warning(NULL, |
"intel_create_sub_image: offset not on tile boundary"); |
return image; |
} |
static struct __DRIimageExtensionRec intelImageExtension = { |
.base = { __DRI_IMAGE, 7 }, |
.createImageFromName = intel_create_image_from_name, |
.createImageFromRenderbuffer = intel_create_image_from_renderbuffer, |
.destroyImage = intel_destroy_image, |
.createImage = intel_create_image, |
.queryImage = intel_query_image, |
.dupImage = intel_dup_image, |
.validateUsage = intel_validate_usage, |
.createImageFromNames = intel_create_image_from_names, |
.fromPlanar = intel_from_planar, |
.createImageFromTexture = intel_create_image_from_texture, |
.createImageFromFds = intel_create_image_from_fds |
}; |
static const __DRIextension *intelScreenExtensions[] = { |
&intelTexBufferExtension.base, |
&intelFlushExtension.base, |
&intelImageExtension.base, |
&dri2ConfigQueryExtension.base, |
NULL |
}; |
static bool |
intel_get_param(__DRIscreen *psp, int param, int *value) |
{ |
int ret; |
struct drm_i915_getparam gp; |
memset(&gp, 0, sizeof(gp)); |
gp.param = param; |
gp.value = value; |
ret = drmCommandWriteRead(psp->fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); |
if (ret) { |
if (ret != -EINVAL) |
_mesa_warning(NULL, "drm_i915_getparam: %d", ret); |
return false; |
} |
return true; |
} |
static bool |
intel_get_boolean(__DRIscreen *psp, int param) |
{ |
int value = 0; |
return intel_get_param(psp, param, &value) && value; |
} |
static void |
intelDestroyScreen(__DRIscreen * sPriv) |
{ |
struct intel_screen *intelScreen = sPriv->driverPrivate; |
dri_bufmgr_destroy(intelScreen->bufmgr); |
driDestroyOptionInfo(&intelScreen->optionCache); |
free(intelScreen); |
sPriv->driverPrivate = NULL; |
} |
/** |
* This is called when we need to set up GL rendering to a new X window. |
*/ |
static GLboolean |
intelCreateBuffer(__DRIscreen * driScrnPriv, |
__DRIdrawable * driDrawPriv, |
const struct gl_config * mesaVis, GLboolean isPixmap) |
{ |
struct intel_renderbuffer *rb; |
gl_format rgbFormat; |
struct gl_framebuffer *fb; |
if (isPixmap) |
return false; |
fb = CALLOC_STRUCT(gl_framebuffer); |
if (!fb) |
return false; |
_mesa_initialize_window_framebuffer(fb, mesaVis); |
if (mesaVis->redBits == 5) |
rgbFormat = MESA_FORMAT_RGB565; |
else if (mesaVis->sRGBCapable) |
rgbFormat = MESA_FORMAT_SARGB8; |
else if (mesaVis->alphaBits == 0) |
rgbFormat = MESA_FORMAT_XRGB8888; |
else |
rgbFormat = MESA_FORMAT_ARGB8888; |
/* setup the hardware-based renderbuffers */ |
rb = intel_create_renderbuffer(rgbFormat); |
_mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &rb->Base.Base); |
if (mesaVis->doubleBufferMode) { |
rb = intel_create_renderbuffer(rgbFormat); |
_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &rb->Base.Base); |
} |
/* |
* Assert here that the gl_config has an expected depth/stencil bit |
* combination: one of d24/s8, d16/s0, d0/s0. (See intelInitScreen2(), |
* which constructs the advertised configs.) |
*/ |
if (mesaVis->depthBits == 24) { |
assert(mesaVis->stencilBits == 8); |
/* |
* Use combined depth/stencil. Note that the renderbuffer is |
* attached to two attachment points. |
*/ |
rb = intel_create_private_renderbuffer(MESA_FORMAT_S8_Z24); |
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base); |
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &rb->Base.Base); |
} |
else if (mesaVis->depthBits == 16) { |
assert(mesaVis->stencilBits == 0); |
rb = intel_create_private_renderbuffer(MESA_FORMAT_Z16); |
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base); |
} |
else { |
assert(mesaVis->depthBits == 0); |
assert(mesaVis->stencilBits == 0); |
} |
/* now add any/all software-based renderbuffers we may need */ |
_swrast_add_soft_renderbuffers(fb, |
false, /* never sw color */ |
false, /* never sw depth */ |
false, /* never sw stencil */ |
mesaVis->accumRedBits > 0, |
false, /* never sw alpha */ |
false /* never sw aux */ ); |
driDrawPriv->driverPrivate = fb; |
return true; |
} |
static void |
intelDestroyBuffer(__DRIdrawable * driDrawPriv) |
{ |
struct gl_framebuffer *fb = driDrawPriv->driverPrivate; |
_mesa_reference_framebuffer(&fb, NULL); |
} |
/* There are probably better ways to do this, such as an |
* init-designated function to register chipids and createcontext |
* functions. |
*/ |
extern bool |
i830CreateContext(int api, |
const struct gl_config *mesaVis, |
__DRIcontext *driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
unsigned *error, |
void *sharedContextPrivate); |
extern bool |
i915CreateContext(int api, |
const struct gl_config *mesaVis, |
__DRIcontext *driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
unsigned *error, |
void *sharedContextPrivate); |
static GLboolean |
intelCreateContext(gl_api api, |
const struct gl_config * mesaVis, |
__DRIcontext * driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
uint32_t flags, |
unsigned *error, |
void *sharedContextPrivate) |
{ |
bool success = false; |
__DRIscreen *sPriv = driContextPriv->driScreenPriv; |
struct intel_screen *intelScreen = sPriv->driverPrivate; |
if (IS_9XX(intelScreen->deviceID)) { |
success = i915CreateContext(api, mesaVis, driContextPriv, |
major_version, minor_version, error, |
sharedContextPrivate); |
} else { |
intelScreen->no_vbo = true; |
success = i830CreateContext(api, mesaVis, driContextPriv, |
major_version, minor_version, error, |
sharedContextPrivate); |
} |
if (success) |
return true; |
if (driContextPriv->driverPrivate != NULL) |
intelDestroyContext(driContextPriv); |
return false; |
} |
static bool |
intel_init_bufmgr(struct intel_screen *intelScreen) |
{ |
__DRIscreen *spriv = intelScreen->driScrnPriv; |
intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL; |
intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ); |
if (intelScreen->bufmgr == NULL) { |
fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n", |
__func__, __LINE__); |
return false; |
} |
drm_intel_bufmgr_gem_enable_fenced_relocs(intelScreen->bufmgr); |
if (!intel_get_boolean(spriv, I915_PARAM_HAS_RELAXED_DELTA)) { |
fprintf(stderr, "[%s: %u] Kernel 2.6.39 required.\n", __func__, __LINE__); |
return false; |
} |
return true; |
} |
static bool |
intel_detect_swizzling(struct intel_screen *screen) |
{ |
drm_intel_bo *buffer; |
unsigned long flags = 0; |
unsigned long aligned_pitch; |
uint32_t tiling = I915_TILING_X; |
uint32_t swizzle_mode = 0; |
buffer = drm_intel_bo_alloc_tiled(screen->bufmgr, "swizzle test", |
64, 64, 4, |
&tiling, &aligned_pitch, flags); |
if (buffer == NULL) |
return false; |
drm_intel_bo_get_tiling(buffer, &tiling, &swizzle_mode); |
drm_intel_bo_unreference(buffer); |
if (swizzle_mode == I915_BIT_6_SWIZZLE_NONE) |
return false; |
else |
return true; |
} |
static __DRIconfig** |
intel_screen_make_configs(__DRIscreen *dri_screen) |
{ |
static const gl_format formats[] = { |
MESA_FORMAT_RGB565, |
MESA_FORMAT_ARGB8888 |
}; |
/* GLX_SWAP_COPY_OML is not supported due to page flipping. */ |
static const GLenum back_buffer_modes[] = { |
GLX_SWAP_UNDEFINED_OML, GLX_NONE, |
}; |
static const uint8_t singlesample_samples[1] = {0}; |
uint8_t depth_bits[4], stencil_bits[4]; |
__DRIconfig **configs = NULL; |
/* Generate singlesample configs without accumulation buffer. */ |
for (int i = 0; i < ARRAY_SIZE(formats); i++) { |
__DRIconfig **new_configs; |
int num_depth_stencil_bits = 2; |
/* Starting with DRI2 protocol version 1.1 we can request a depth/stencil |
* buffer that has a different number of bits per pixel than the color |
* buffer. |
*/ |
depth_bits[0] = 0; |
stencil_bits[0] = 0; |
if (formats[i] == MESA_FORMAT_RGB565) { |
depth_bits[1] = 16; |
stencil_bits[1] = 0; |
} else { |
depth_bits[1] = 24; |
stencil_bits[1] = 8; |
} |
new_configs = driCreateConfigs(formats[i], |
depth_bits, |
stencil_bits, |
num_depth_stencil_bits, |
back_buffer_modes, 2, |
singlesample_samples, 1, |
false); |
configs = driConcatConfigs(configs, new_configs); |
} |
/* Generate the minimum possible set of configs that include an |
* accumulation buffer. |
*/ |
for (int i = 0; i < ARRAY_SIZE(formats); i++) { |
__DRIconfig **new_configs; |
if (formats[i] == MESA_FORMAT_RGB565) { |
depth_bits[0] = 16; |
stencil_bits[0] = 0; |
} else { |
depth_bits[0] = 24; |
stencil_bits[0] = 8; |
} |
new_configs = driCreateConfigs(formats[i], |
depth_bits, stencil_bits, 1, |
back_buffer_modes, 1, |
singlesample_samples, 1, |
true); |
configs = driConcatConfigs(configs, new_configs); |
} |
if (configs == NULL) { |
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, |
__LINE__); |
return NULL; |
} |
return configs; |
} |
static void |
set_max_gl_versions(struct intel_screen *screen) |
{ |
int gl_version_override = _mesa_get_gl_version_override(); |
switch (screen->gen) { |
case 3: |
screen->max_gl_core_version = 0; |
screen->max_gl_es1_version = 11; |
screen->max_gl_compat_version = 21; |
screen->max_gl_es2_version = 20; |
break; |
case 2: |
screen->max_gl_core_version = 0; |
screen->max_gl_compat_version = 13; |
screen->max_gl_es1_version = 11; |
screen->max_gl_es2_version = 0; |
break; |
default: |
assert(!"unrecognized intel_screen::gen"); |
break; |
} |
if (gl_version_override >= 31) { |
screen->max_gl_core_version = MAX2(screen->max_gl_core_version, |
gl_version_override); |
} else { |
screen->max_gl_compat_version = MAX2(screen->max_gl_compat_version, |
gl_version_override); |
} |
#ifndef FEATURE_ES1 |
screen->max_gl_es1_version = 0; |
#endif |
#ifndef FEATURE_ES2 |
screen->max_gl_es2_version = 0; |
#endif |
} |
/** |
* This is the driver specific part of the createNewScreen entry point. |
* Called when using DRI2. |
* |
* \return the struct gl_config supported by this driver |
*/ |
static const |
__DRIconfig **intelInitScreen2(__DRIscreen *psp) |
{ |
struct intel_screen *intelScreen; |
if (psp->dri2.loader->base.version <= 2 || |
psp->dri2.loader->getBuffersWithFormat == NULL) { |
fprintf(stderr, |
"\nERROR! DRI2 loader with getBuffersWithFormat() " |
"support required\n"); |
return false; |
} |
/* Allocate the private area */ |
intelScreen = calloc(1, sizeof *intelScreen); |
if (!intelScreen) { |
fprintf(stderr, "\nERROR! Allocating private area failed\n"); |
return false; |
} |
/* parse information in __driConfigOptions */ |
driParseOptionInfo(&intelScreen->optionCache, |
__driConfigOptions, __driNConfigOptions); |
intelScreen->driScrnPriv = psp; |
psp->driverPrivate = (void *) intelScreen; |
if (!intel_init_bufmgr(intelScreen)) |
return false; |
intelScreen->deviceID = drm_intel_bufmgr_gem_get_devid(intelScreen->bufmgr); |
if (IS_9XX(intelScreen->deviceID)) { |
intelScreen->gen = 3; |
} else { |
intelScreen->gen = 2; |
} |
intelScreen->hw_has_swizzling = intel_detect_swizzling(intelScreen); |
set_max_gl_versions(intelScreen); |
psp->api_mask = (1 << __DRI_API_OPENGL); |
if (intelScreen->max_gl_core_version > 0) |
psp->api_mask |= (1 << __DRI_API_OPENGL_CORE); |
if (intelScreen->max_gl_es1_version > 0) |
psp->api_mask |= (1 << __DRI_API_GLES); |
if (intelScreen->max_gl_es2_version > 0) |
psp->api_mask |= (1 << __DRI_API_GLES2); |
if (intelScreen->max_gl_es2_version >= 30) |
psp->api_mask |= (1 << __DRI_API_GLES3); |
psp->extensions = intelScreenExtensions; |
return (const __DRIconfig**) intel_screen_make_configs(psp); |
} |
struct intel_buffer { |
__DRIbuffer base; |
struct intel_region *region; |
}; |
static __DRIbuffer * |
intelAllocateBuffer(__DRIscreen *screen, |
unsigned attachment, unsigned format, |
int width, int height) |
{ |
struct intel_buffer *intelBuffer; |
struct intel_screen *intelScreen = screen->driverPrivate; |
assert(attachment == __DRI_BUFFER_FRONT_LEFT || |
attachment == __DRI_BUFFER_BACK_LEFT); |
intelBuffer = calloc(1, sizeof *intelBuffer); |
if (intelBuffer == NULL) |
return NULL; |
/* The front and back buffers are color buffers, which are X tiled. */ |
intelBuffer->region = intel_region_alloc(intelScreen, |
I915_TILING_X, |
format / 8, |
width, |
height, |
true); |
if (intelBuffer->region == NULL) { |
free(intelBuffer); |
return NULL; |
} |
intel_region_flink(intelBuffer->region, &intelBuffer->base.name); |
intelBuffer->base.attachment = attachment; |
intelBuffer->base.cpp = intelBuffer->region->cpp; |
intelBuffer->base.pitch = intelBuffer->region->pitch; |
return &intelBuffer->base; |
} |
static void |
intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) |
{ |
struct intel_buffer *intelBuffer = (struct intel_buffer *) buffer; |
intel_region_release(&intelBuffer->region); |
free(intelBuffer); |
} |
const struct __DriverAPIRec driDriverAPI = { |
.InitScreen = intelInitScreen2, |
.DestroyScreen = intelDestroyScreen, |
.CreateContext = intelCreateContext, |
.DestroyContext = intelDestroyContext, |
.CreateBuffer = intelCreateBuffer, |
.DestroyBuffer = intelDestroyBuffer, |
.MakeCurrent = intelMakeCurrent, |
.UnbindContext = intelUnbindContext, |
.AllocateBuffer = intelAllocateBuffer, |
.ReleaseBuffer = intelReleaseBuffer |
}; |
/* This is the table of extensions that the loader will dlsym() for. */ |
PUBLIC const __DRIextension *__driDriverExtensions[] = { |
&driCoreExtension.base, |
&driDRI2Extension.base, |
NULL |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_screen.h |
---|
0,0 → 1,75 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef _INTEL_INIT_H_ |
#define _INTEL_INIT_H_ |
#include <stdbool.h> |
#include <sys/time.h> |
#include "dri_util.h" |
#include "intel_bufmgr.h" |
#include "i915_drm.h" |
#include "xmlconfig.h" |
struct intel_screen |
{ |
int deviceID; |
int gen; |
int max_gl_core_version; |
int max_gl_compat_version; |
int max_gl_es1_version; |
int max_gl_es2_version; |
__DRIscreen *driScrnPriv; |
bool no_hw; |
bool hw_has_swizzling; |
bool no_vbo; |
dri_bufmgr *bufmgr; |
/** |
* Configuration cache with default values for all contexts |
*/ |
driOptionCache optionCache; |
}; |
extern void intelDestroyContext(__DRIcontext * driContextPriv); |
extern GLboolean intelUnbindContext(__DRIcontext * driContextPriv); |
extern GLboolean |
intelMakeCurrent(__DRIcontext * driContextPriv, |
__DRIdrawable * driDrawPriv, |
__DRIdrawable * driReadPriv); |
double get_time(void); |
void aub_dump_bmp(struct gl_context *ctx); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_state.c |
---|
0,0 → 1,195 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "main/colormac.h" |
#include "main/dd.h" |
#include "intel_screen.h" |
#include "intel_context.h" |
int |
intel_translate_shadow_compare_func(GLenum func) |
{ |
switch (func) { |
case GL_NEVER: |
return COMPAREFUNC_ALWAYS; |
case GL_LESS: |
return COMPAREFUNC_LEQUAL; |
case GL_LEQUAL: |
return COMPAREFUNC_LESS; |
case GL_GREATER: |
return COMPAREFUNC_GEQUAL; |
case GL_GEQUAL: |
return COMPAREFUNC_GREATER; |
case GL_NOTEQUAL: |
return COMPAREFUNC_EQUAL; |
case GL_EQUAL: |
return COMPAREFUNC_NOTEQUAL; |
case GL_ALWAYS: |
return COMPAREFUNC_NEVER; |
} |
fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, func); |
return COMPAREFUNC_NEVER; |
} |
int |
intel_translate_compare_func(GLenum func) |
{ |
switch (func) { |
case GL_NEVER: |
return COMPAREFUNC_NEVER; |
case GL_LESS: |
return COMPAREFUNC_LESS; |
case GL_LEQUAL: |
return COMPAREFUNC_LEQUAL; |
case GL_GREATER: |
return COMPAREFUNC_GREATER; |
case GL_GEQUAL: |
return COMPAREFUNC_GEQUAL; |
case GL_NOTEQUAL: |
return COMPAREFUNC_NOTEQUAL; |
case GL_EQUAL: |
return COMPAREFUNC_EQUAL; |
case GL_ALWAYS: |
return COMPAREFUNC_ALWAYS; |
} |
fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, func); |
return COMPAREFUNC_ALWAYS; |
} |
int |
intel_translate_stencil_op(GLenum op) |
{ |
switch (op) { |
case GL_KEEP: |
return STENCILOP_KEEP; |
case GL_ZERO: |
return STENCILOP_ZERO; |
case GL_REPLACE: |
return STENCILOP_REPLACE; |
case GL_INCR: |
return STENCILOP_INCRSAT; |
case GL_DECR: |
return STENCILOP_DECRSAT; |
case GL_INCR_WRAP: |
return STENCILOP_INCR; |
case GL_DECR_WRAP: |
return STENCILOP_DECR; |
case GL_INVERT: |
return STENCILOP_INVERT; |
default: |
return STENCILOP_ZERO; |
} |
} |
int |
intel_translate_blend_factor(GLenum factor) |
{ |
switch (factor) { |
case GL_ZERO: |
return BLENDFACT_ZERO; |
case GL_SRC_ALPHA: |
return BLENDFACT_SRC_ALPHA; |
case GL_ONE: |
return BLENDFACT_ONE; |
case GL_SRC_COLOR: |
return BLENDFACT_SRC_COLR; |
case GL_ONE_MINUS_SRC_COLOR: |
return BLENDFACT_INV_SRC_COLR; |
case GL_DST_COLOR: |
return BLENDFACT_DST_COLR; |
case GL_ONE_MINUS_DST_COLOR: |
return BLENDFACT_INV_DST_COLR; |
case GL_ONE_MINUS_SRC_ALPHA: |
return BLENDFACT_INV_SRC_ALPHA; |
case GL_DST_ALPHA: |
return BLENDFACT_DST_ALPHA; |
case GL_ONE_MINUS_DST_ALPHA: |
return BLENDFACT_INV_DST_ALPHA; |
case GL_SRC_ALPHA_SATURATE: |
return BLENDFACT_SRC_ALPHA_SATURATE; |
case GL_CONSTANT_COLOR: |
return BLENDFACT_CONST_COLOR; |
case GL_ONE_MINUS_CONSTANT_COLOR: |
return BLENDFACT_INV_CONST_COLOR; |
case GL_CONSTANT_ALPHA: |
return BLENDFACT_CONST_ALPHA; |
case GL_ONE_MINUS_CONSTANT_ALPHA: |
return BLENDFACT_INV_CONST_ALPHA; |
} |
fprintf(stderr, "Unknown value in %s: %x\n", __FUNCTION__, factor); |
return BLENDFACT_ZERO; |
} |
int |
intel_translate_logic_op(GLenum opcode) |
{ |
switch (opcode) { |
case GL_CLEAR: |
return LOGICOP_CLEAR; |
case GL_AND: |
return LOGICOP_AND; |
case GL_AND_REVERSE: |
return LOGICOP_AND_RVRSE; |
case GL_COPY: |
return LOGICOP_COPY; |
case GL_COPY_INVERTED: |
return LOGICOP_COPY_INV; |
case GL_AND_INVERTED: |
return LOGICOP_AND_INV; |
case GL_NOOP: |
return LOGICOP_NOOP; |
case GL_XOR: |
return LOGICOP_XOR; |
case GL_OR: |
return LOGICOP_OR; |
case GL_OR_INVERTED: |
return LOGICOP_OR_INV; |
case GL_NOR: |
return LOGICOP_NOR; |
case GL_EQUIV: |
return LOGICOP_EQUIV; |
case GL_INVERT: |
return LOGICOP_INV; |
case GL_OR_REVERSE: |
return LOGICOP_OR_RVRSE; |
case GL_NAND: |
return LOGICOP_NAND; |
case GL_SET: |
return LOGICOP_SET; |
default: |
return LOGICOP_SET; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_syncobj.c |
---|
0,0 → 1,124 |
/* |
* Copyright © 2008 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
/** @file intel_syncobj.c |
* |
* Support for ARB_sync |
* |
* ARB_sync is implemented by flushing the current batchbuffer and keeping a |
* reference on it. We can then check for completion or wait for completion |
* using the normal buffer object mechanisms. This does mean that if an |
* application is using many sync objects, it will emit small batchbuffers |
* which may end up being a significant overhead. In other tests of removing |
* gratuitous batchbuffer syncs in Mesa, it hasn't appeared to be a significant |
* performance bottleneck, though. |
*/ |
#include "main/simple_list.h" |
#include "main/imports.h" |
#include "intel_context.h" |
#include "intel_batchbuffer.h" |
#include "intel_reg.h" |
static struct gl_sync_object * |
intel_new_sync_object(struct gl_context *ctx, GLuint id) |
{ |
struct intel_sync_object *sync; |
sync = calloc(1, sizeof(struct intel_sync_object)); |
return &sync->Base; |
} |
static void |
intel_delete_sync_object(struct gl_context *ctx, struct gl_sync_object *s) |
{ |
struct intel_sync_object *sync = (struct intel_sync_object *)s; |
drm_intel_bo_unreference(sync->bo); |
free(sync); |
} |
static void |
intel_fence_sync(struct gl_context *ctx, struct gl_sync_object *s, |
GLenum condition, GLbitfield flags) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_sync_object *sync = (struct intel_sync_object *)s; |
assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE); |
intel_batchbuffer_emit_mi_flush(intel); |
sync->bo = intel->batch.bo; |
drm_intel_bo_reference(sync->bo); |
intel_flush(ctx); |
} |
static void intel_client_wait_sync(struct gl_context *ctx, struct gl_sync_object *s, |
GLbitfield flags, GLuint64 timeout) |
{ |
struct intel_sync_object *sync = (struct intel_sync_object *)s; |
if (sync->bo && drm_intel_gem_bo_wait(sync->bo, timeout) == 0) { |
s->StatusFlag = 1; |
drm_intel_bo_unreference(sync->bo); |
sync->bo = NULL; |
} |
} |
/* We have nothing to do for WaitSync. Our GL command stream is sequential, |
* so given that the sync object has already flushed the batchbuffer, |
* any batchbuffers coming after this waitsync will naturally not occur until |
* the previous one is done. |
*/ |
static void intel_server_wait_sync(struct gl_context *ctx, struct gl_sync_object *s, |
GLbitfield flags, GLuint64 timeout) |
{ |
} |
static void intel_check_sync(struct gl_context *ctx, struct gl_sync_object *s) |
{ |
struct intel_sync_object *sync = (struct intel_sync_object *)s; |
if (sync->bo && !drm_intel_bo_busy(sync->bo)) { |
drm_intel_bo_unreference(sync->bo); |
sync->bo = NULL; |
s->StatusFlag = 1; |
} |
} |
void intel_init_syncobj_functions(struct dd_function_table *functions) |
{ |
functions->NewSyncObject = intel_new_sync_object; |
functions->DeleteSyncObject = intel_delete_sync_object; |
functions->FenceSync = intel_fence_sync; |
functions->CheckSync = intel_check_sync; |
functions->ClientWaitSync = intel_client_wait_sync; |
functions->ServerWaitSync = intel_server_wait_sync; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_tex.c |
---|
0,0 → 1,182 |
#include "swrast/swrast.h" |
#include "main/renderbuffer.h" |
#include "main/texobj.h" |
#include "main/teximage.h" |
#include "main/mipmap.h" |
#include "drivers/common/meta.h" |
#include "intel_context.h" |
#include "intel_mipmap_tree.h" |
#include "intel_tex.h" |
#include "intel_fbo.h" |
#define FILE_DEBUG_FLAG DEBUG_TEXTURE |
static struct gl_texture_image * |
intelNewTextureImage(struct gl_context * ctx) |
{ |
DBG("%s\n", __FUNCTION__); |
(void) ctx; |
return (struct gl_texture_image *) CALLOC_STRUCT(intel_texture_image); |
} |
static void |
intelDeleteTextureImage(struct gl_context * ctx, struct gl_texture_image *img) |
{ |
/* nothing special (yet) for intel_texture_image */ |
_mesa_delete_texture_image(ctx, img); |
} |
static struct gl_texture_object * |
intelNewTextureObject(struct gl_context * ctx, GLuint name, GLenum target) |
{ |
struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object); |
(void) ctx; |
DBG("%s\n", __FUNCTION__); |
if (obj == NULL) |
return NULL; |
_mesa_initialize_texture_object(ctx, &obj->base, name, target); |
obj->needs_validate = true; |
return &obj->base; |
} |
static void |
intelDeleteTextureObject(struct gl_context *ctx, |
struct gl_texture_object *texObj) |
{ |
struct intel_texture_object *intelObj = intel_texture_object(texObj); |
intel_miptree_release(&intelObj->mt); |
_mesa_delete_texture_object(ctx, texObj); |
} |
static GLboolean |
intel_alloc_texture_image_buffer(struct gl_context *ctx, |
struct gl_texture_image *image) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_texture_image *intel_image = intel_texture_image(image); |
struct gl_texture_object *texobj = image->TexObject; |
struct intel_texture_object *intel_texobj = intel_texture_object(texobj); |
assert(image->Border == 0); |
/* Because the driver uses AllocTextureImageBuffer() internally, it may end |
* up mismatched with FreeTextureImageBuffer(), but that is safe to call |
* multiple times. |
*/ |
ctx->Driver.FreeTextureImageBuffer(ctx, image); |
if (!_swrast_init_texture_image(image)) |
return false; |
if (intel_texobj->mt && |
intel_miptree_match_image(intel_texobj->mt, image)) { |
intel_miptree_reference(&intel_image->mt, intel_texobj->mt); |
DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n", |
__FUNCTION__, texobj, image->Level, |
image->Width, image->Height, image->Depth, intel_texobj->mt); |
} else { |
intel_image->mt = intel_miptree_create_for_teximage(intel, intel_texobj, |
intel_image, |
false); |
/* Even if the object currently has a mipmap tree associated |
* with it, this one is a more likely candidate to represent the |
* whole object since our level didn't fit what was there |
* before, and any lower levels would fit into our miptree. |
*/ |
intel_miptree_reference(&intel_texobj->mt, intel_image->mt); |
DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n", |
__FUNCTION__, texobj, image->Level, |
image->Width, image->Height, image->Depth, intel_image->mt); |
} |
intel_texobj->needs_validate = true; |
return true; |
} |
static void |
intel_free_texture_image_buffer(struct gl_context * ctx, |
struct gl_texture_image *texImage) |
{ |
struct intel_texture_image *intelImage = intel_texture_image(texImage); |
DBG("%s\n", __FUNCTION__); |
intel_miptree_release(&intelImage->mt); |
_swrast_free_texture_image_buffer(ctx, texImage); |
} |
/** |
* Map texture memory/buffer into user space. |
* Note: the region of interest parameters are ignored here. |
* \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT |
* \param mapOut returns start of mapping of region of interest |
* \param rowStrideOut returns row stride in bytes |
*/ |
static void |
intel_map_texture_image(struct gl_context *ctx, |
struct gl_texture_image *tex_image, |
GLuint slice, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **map, |
GLint *stride) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_texture_image *intel_image = intel_texture_image(tex_image); |
struct intel_mipmap_tree *mt = intel_image->mt; |
/* Our texture data is always stored in a miptree. */ |
assert(mt); |
/* Check that our caller wasn't confused about how to map a 1D texture. */ |
assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY || |
h == 1); |
/* intel_miptree_map operates on a unified "slice" number that references the |
* cube face, since it's all just slices to the miptree code. |
*/ |
if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP) |
slice = tex_image->Face; |
intel_miptree_map(intel, mt, tex_image->Level, slice, x, y, w, h, mode, |
(void **)map, stride); |
} |
static void |
intel_unmap_texture_image(struct gl_context *ctx, |
struct gl_texture_image *tex_image, GLuint slice) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_texture_image *intel_image = intel_texture_image(tex_image); |
struct intel_mipmap_tree *mt = intel_image->mt; |
if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP) |
slice = tex_image->Face; |
intel_miptree_unmap(intel, mt, tex_image->Level, slice); |
} |
void |
intelInitTextureFuncs(struct dd_function_table *functions) |
{ |
functions->NewTextureObject = intelNewTextureObject; |
functions->NewTextureImage = intelNewTextureImage; |
functions->DeleteTextureImage = intelDeleteTextureImage; |
functions->DeleteTexture = intelDeleteTextureObject; |
functions->AllocTextureImageBuffer = intel_alloc_texture_image_buffer; |
functions->FreeTextureImageBuffer = intel_free_texture_image_buffer; |
functions->MapTextureImage = intel_map_texture_image; |
functions->UnmapTextureImage = intel_unmap_texture_image; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_tex.h |
---|
0,0 → 1,71 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTELTEX_INC |
#define INTELTEX_INC |
#include "main/mtypes.h" |
#include "main/formats.h" |
#include "intel_context.h" |
struct intel_renderbuffer; |
void intelInitTextureFuncs(struct dd_function_table *functions); |
void intelInitTextureImageFuncs(struct dd_function_table *functions); |
void intelInitTextureSubImageFuncs(struct dd_function_table *functions); |
void intelInitTextureCopyImageFuncs(struct dd_function_table *functions); |
void intelSetTexBuffer(__DRIcontext *pDRICtx, |
GLint target, __DRIdrawable *pDraw); |
void intelSetTexBuffer2(__DRIcontext *pDRICtx, |
GLint target, GLint format, __DRIdrawable *pDraw); |
struct intel_mipmap_tree * |
intel_miptree_create_for_teximage(struct intel_context *intel, |
struct intel_texture_object *intelObj, |
struct intel_texture_image *intelImage, |
bool expect_accelerated_upload); |
GLuint intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit); |
void intel_tex_map_level_images(struct intel_context *intel, |
struct intel_texture_object *intelObj, |
int level, |
GLbitfield mode); |
void intel_tex_unmap_level_images(struct intel_context *intel, |
struct intel_texture_object *intelObj, |
int level); |
bool |
intel_tex_image_s8z24_create_renderbuffers(struct intel_context *intel, |
struct intel_texture_image *image); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_tex_copy.c |
---|
0,0 → 1,111 |
/************************************************************************** |
* |
* 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 "main/mtypes.h" |
#include "main/enums.h" |
#include "main/image.h" |
#include "main/teximage.h" |
#include "main/texstate.h" |
#include "main/fbobject.h" |
#include "drivers/common/meta.h" |
#include "intel_screen.h" |
#include "intel_context.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_fbo.h" |
#include "intel_tex.h" |
#include "intel_blit.h" |
#define FILE_DEBUG_FLAG DEBUG_TEXTURE |
static bool |
intel_copy_texsubimage(struct intel_context *intel, |
struct intel_texture_image *intelImage, |
GLint dstx, GLint dsty, GLint slice, |
struct intel_renderbuffer *irb, |
GLint x, GLint y, GLsizei width, GLsizei height) |
{ |
const GLenum internalFormat = intelImage->base.Base.InternalFormat; |
intel_prepare_render(intel); |
if (!intelImage->mt || !irb || !irb->mt) { |
if (unlikely(INTEL_DEBUG & DEBUG_PERF)) |
fprintf(stderr, "%s fail %p %p (0x%08x)\n", |
__FUNCTION__, intelImage->mt, irb, internalFormat); |
return false; |
} |
/* blit from src buffer to texture */ |
if (!intel_miptree_blit(intel, |
irb->mt, irb->mt_level, irb->mt_layer, |
x, y, irb->Base.Base.Name == 0, |
intelImage->mt, intelImage->base.Base.Level, |
intelImage->base.Base.Face + slice, |
dstx, dsty, false, |
width, height, GL_COPY)) { |
return false; |
} |
return true; |
} |
static void |
intelCopyTexSubImage(struct gl_context *ctx, GLuint dims, |
struct gl_texture_image *texImage, |
GLint xoffset, GLint yoffset, GLint slice, |
struct gl_renderbuffer *rb, |
GLint x, GLint y, |
GLsizei width, GLsizei height) |
{ |
struct intel_context *intel = intel_context(ctx); |
/* Try the BLT engine. */ |
if (intel_copy_texsubimage(intel, |
intel_texture_image(texImage), |
xoffset, yoffset, slice, |
intel_renderbuffer(rb), x, y, width, height)) { |
return; |
} |
/* Otherwise, fall back to meta. This will likely be slow. */ |
perf_debug("%s - fallback to swrast\n", __FUNCTION__); |
_mesa_meta_CopyTexSubImage(ctx, dims, texImage, |
xoffset, yoffset, slice, |
rb, x, y, width, height); |
} |
void |
intelInitTextureCopyImageFuncs(struct dd_function_table *functions) |
{ |
functions->CopyTexSubImage = intelCopyTexSubImage; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_tex_image.c |
---|
0,0 → 1,370 |
#include "main/glheader.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/enums.h" |
#include "main/bufferobj.h" |
#include "main/context.h" |
#include "main/formats.h" |
#include "main/image.h" |
#include "main/pbo.h" |
#include "main/renderbuffer.h" |
#include "main/texcompress.h" |
#include "main/texgetimage.h" |
#include "main/texobj.h" |
#include "main/teximage.h" |
#include "main/texstore.h" |
#include "intel_context.h" |
#include "intel_mipmap_tree.h" |
#include "intel_buffer_objects.h" |
#include "intel_batchbuffer.h" |
#include "intel_tex.h" |
#include "intel_blit.h" |
#include "intel_fbo.h" |
#define FILE_DEBUG_FLAG DEBUG_TEXTURE |
/* Work back from the specified level of the image to the baselevel and create a |
* miptree of that size. |
*/ |
struct intel_mipmap_tree * |
intel_miptree_create_for_teximage(struct intel_context *intel, |
struct intel_texture_object *intelObj, |
struct intel_texture_image *intelImage, |
bool expect_accelerated_upload) |
{ |
GLuint firstLevel; |
GLuint lastLevel; |
int width, height, depth; |
GLuint i; |
intel_miptree_get_dimensions_for_image(&intelImage->base.Base, |
&width, &height, &depth); |
DBG("%s\n", __FUNCTION__); |
if (intelImage->base.Base.Level > intelObj->base.BaseLevel && |
(width == 1 || |
(intelObj->base.Target != GL_TEXTURE_1D && height == 1) || |
(intelObj->base.Target == GL_TEXTURE_3D && depth == 1))) { |
/* For this combination, we're at some lower mipmap level and |
* some important dimension is 1. We can't extrapolate up to a |
* likely base level width/height/depth for a full mipmap stack |
* from this info, so just allocate this one level. |
*/ |
firstLevel = intelImage->base.Base.Level; |
lastLevel = intelImage->base.Base.Level; |
} else { |
/* If this image disrespects BaseLevel, allocate from level zero. |
* Usually BaseLevel == 0, so it's unlikely to happen. |
*/ |
if (intelImage->base.Base.Level < intelObj->base.BaseLevel) |
firstLevel = 0; |
else |
firstLevel = intelObj->base.BaseLevel; |
/* Figure out image dimensions at start level. */ |
for (i = intelImage->base.Base.Level; i > firstLevel; i--) { |
width <<= 1; |
if (height != 1) |
height <<= 1; |
if (depth != 1) |
depth <<= 1; |
} |
/* Guess a reasonable value for lastLevel. This is probably going |
* to be wrong fairly often and might mean that we have to look at |
* resizable buffers, or require that buffers implement lazy |
* pagetable arrangements. |
*/ |
if ((intelObj->base.Sampler.MinFilter == GL_NEAREST || |
intelObj->base.Sampler.MinFilter == GL_LINEAR) && |
intelImage->base.Base.Level == firstLevel) { |
lastLevel = firstLevel; |
} else { |
lastLevel = (firstLevel + |
_mesa_get_tex_max_num_levels(intelObj->base.Target, |
width, height, depth) - 1); |
} |
} |
return intel_miptree_create(intel, |
intelObj->base.Target, |
intelImage->base.Base.TexFormat, |
firstLevel, |
lastLevel, |
width, |
height, |
depth, |
expect_accelerated_upload, |
INTEL_MIPTREE_TILING_ANY); |
} |
/* XXX: Do this for TexSubImage also: |
*/ |
static bool |
try_pbo_upload(struct gl_context *ctx, |
struct gl_texture_image *image, |
const struct gl_pixelstore_attrib *unpack, |
GLenum format, GLenum type, const void *pixels) |
{ |
struct intel_texture_image *intelImage = intel_texture_image(image); |
struct intel_context *intel = intel_context(ctx); |
struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj); |
GLuint src_offset; |
drm_intel_bo *src_buffer; |
if (!_mesa_is_bufferobj(unpack->BufferObj)) |
return false; |
DBG("trying pbo upload\n"); |
if (intel->ctx._ImageTransferState || |
unpack->SkipPixels || unpack->SkipRows) { |
DBG("%s: image transfer\n", __FUNCTION__); |
return false; |
} |
ctx->Driver.AllocTextureImageBuffer(ctx, image); |
if (!intelImage->mt) { |
DBG("%s: no miptree\n", __FUNCTION__); |
return false; |
} |
if (!_mesa_format_matches_format_and_type(intelImage->mt->format, |
format, type, false)) { |
DBG("%s: format mismatch (upload to %s with format 0x%x, type 0x%x)\n", |
__FUNCTION__, _mesa_get_format_name(intelImage->mt->format), |
format, type); |
return false; |
} |
if (image->TexObject->Target == GL_TEXTURE_1D_ARRAY || |
image->TexObject->Target == GL_TEXTURE_2D_ARRAY) { |
DBG("%s: no support for array textures\n", __FUNCTION__); |
return false; |
} |
src_buffer = intel_bufferobj_source(intel, pbo, 64, &src_offset); |
/* note: potential 64-bit ptr to 32-bit int cast */ |
src_offset += (GLuint) (unsigned long) pixels; |
int src_stride = |
_mesa_image_row_stride(unpack, image->Width, format, type); |
struct intel_mipmap_tree *pbo_mt = |
intel_miptree_create_for_bo(intel, |
src_buffer, |
intelImage->mt->format, |
src_offset, |
image->Width, image->Height, |
src_stride, I915_TILING_NONE); |
if (!pbo_mt) |
return false; |
if (!intel_miptree_blit(intel, |
pbo_mt, 0, 0, |
0, 0, false, |
intelImage->mt, image->Level, image->Face, |
0, 0, false, |
image->Width, image->Height, GL_COPY)) { |
DBG("%s: blit failed\n", __FUNCTION__); |
intel_miptree_release(&pbo_mt); |
return false; |
} |
intel_miptree_release(&pbo_mt); |
DBG("%s: success\n", __FUNCTION__); |
return true; |
} |
static void |
intelTexImage(struct gl_context * ctx, |
GLuint dims, |
struct gl_texture_image *texImage, |
GLenum format, GLenum type, const void *pixels, |
const struct gl_pixelstore_attrib *unpack) |
{ |
DBG("%s target %s level %d %dx%dx%d\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(texImage->TexObject->Target), |
texImage->Level, texImage->Width, texImage->Height, texImage->Depth); |
/* Attempt to use the blitter for PBO image uploads. |
*/ |
if (dims <= 2 && |
try_pbo_upload(ctx, texImage, unpack, format, type, pixels)) { |
return; |
} |
DBG("%s: upload image %dx%dx%d pixels %p\n", |
__FUNCTION__, texImage->Width, texImage->Height, texImage->Depth, |
pixels); |
_mesa_store_teximage(ctx, dims, texImage, |
format, type, pixels, unpack); |
} |
/** |
* Binds a region to a texture image, like it was uploaded by glTexImage2D(). |
* |
* Used for GLX_EXT_texture_from_pixmap and EGL image extensions, |
*/ |
static void |
intel_set_texture_image_region(struct gl_context *ctx, |
struct gl_texture_image *image, |
struct intel_region *region, |
GLenum target, |
GLenum internalFormat, |
gl_format format, |
uint32_t offset, |
GLuint width, |
GLuint height, |
GLuint tile_x, |
GLuint tile_y) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_texture_image *intel_image = intel_texture_image(image); |
struct gl_texture_object *texobj = image->TexObject; |
struct intel_texture_object *intel_texobj = intel_texture_object(texobj); |
bool has_surface_tile_offset = false; |
uint32_t draw_x, draw_y; |
_mesa_init_teximage_fields(&intel->ctx, image, |
width, height, 1, |
0, internalFormat, format); |
ctx->Driver.FreeTextureImageBuffer(ctx, image); |
intel_image->mt = intel_miptree_create_layout(intel, target, image->TexFormat, |
0, 0, |
width, height, 1, |
true); |
if (intel_image->mt == NULL) |
return; |
intel_region_reference(&intel_image->mt->region, region); |
intel_image->mt->total_width = width; |
intel_image->mt->total_height = height; |
intel_image->mt->level[0].slice[0].x_offset = tile_x; |
intel_image->mt->level[0].slice[0].y_offset = tile_y; |
intel_miptree_get_tile_offsets(intel_image->mt, 0, 0, &draw_x, &draw_y); |
/* From "OES_EGL_image" error reporting. We report GL_INVALID_OPERATION |
* for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has |
* trouble resolving back to destination image due to alignment issues. |
*/ |
if (!has_surface_tile_offset && |
(draw_x != 0 || draw_y != 0)) { |
_mesa_error(ctx, GL_INVALID_OPERATION, __func__); |
intel_miptree_release(&intel_image->mt); |
return; |
} |
intel_texobj->needs_validate = true; |
intel_image->mt->offset = offset; |
assert(region->pitch % region->cpp == 0); |
intel_image->base.RowStride = region->pitch / region->cpp; |
/* Immediately validate the image to the object. */ |
intel_miptree_reference(&intel_texobj->mt, intel_image->mt); |
} |
void |
intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, |
GLint texture_format, |
__DRIdrawable *dPriv) |
{ |
struct gl_framebuffer *fb = dPriv->driverPrivate; |
struct intel_context *intel = pDRICtx->driverPrivate; |
struct gl_context *ctx = &intel->ctx; |
struct intel_texture_object *intelObj; |
struct intel_renderbuffer *rb; |
struct gl_texture_object *texObj; |
struct gl_texture_image *texImage; |
int level = 0, internalFormat = 0; |
gl_format texFormat = MESA_FORMAT_NONE; |
texObj = _mesa_get_current_tex_object(ctx, target); |
intelObj = intel_texture_object(texObj); |
if (!intelObj) |
return; |
if (dPriv->lastStamp != dPriv->dri2.stamp || |
!pDRICtx->driScreenPriv->dri2.useInvalidate) |
intel_update_renderbuffers(pDRICtx, dPriv); |
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
/* If the region isn't set, then intel_update_renderbuffers was unable |
* to get the buffers for the drawable. |
*/ |
if (!rb || !rb->mt) |
return; |
if (rb->mt->cpp == 4) { |
if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { |
internalFormat = GL_RGB; |
texFormat = MESA_FORMAT_XRGB8888; |
} |
else { |
internalFormat = GL_RGBA; |
texFormat = MESA_FORMAT_ARGB8888; |
} |
} else if (rb->mt->cpp == 2) { |
internalFormat = GL_RGB; |
texFormat = MESA_FORMAT_RGB565; |
} |
_mesa_lock_texture(&intel->ctx, texObj); |
texImage = _mesa_get_tex_image(ctx, texObj, target, level); |
intel_set_texture_image_region(ctx, texImage, rb->mt->region, target, |
internalFormat, texFormat, 0, |
rb->mt->region->width, |
rb->mt->region->height, |
0, 0); |
_mesa_unlock_texture(&intel->ctx, texObj); |
} |
void |
intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv) |
{ |
/* The old interface didn't have the format argument, so copy our |
* implementation's behavior at the time. |
*/ |
intelSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); |
} |
static void |
intel_image_target_texture_2d(struct gl_context *ctx, GLenum target, |
struct gl_texture_object *texObj, |
struct gl_texture_image *texImage, |
GLeglImageOES image_handle) |
{ |
struct intel_context *intel = intel_context(ctx); |
__DRIscreen *screen; |
__DRIimage *image; |
screen = intel->intelScreen->driScrnPriv; |
image = screen->dri2.image->lookupEGLImage(screen, image_handle, |
screen->loaderPrivate); |
if (image == NULL) |
return; |
intel_set_texture_image_region(ctx, texImage, image->region, |
target, image->internal_format, |
image->format, image->offset, |
image->width, image->height, |
image->tile_x, image->tile_y); |
} |
void |
intelInitTextureImageFuncs(struct dd_function_table *functions) |
{ |
functions->TexImage = intelTexImage; |
functions->EGLImageTargetTexture2D = intel_image_target_texture_2d; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_tex_layout.c |
---|
0,0 → 1,189 |
/************************************************************************** |
* |
* 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 "intel_mipmap_tree.h" |
#include "intel_tex_layout.h" |
#include "intel_context.h" |
#include "main/image.h" |
#include "main/macros.h" |
static unsigned int |
intel_horizontal_texture_alignment_unit(struct intel_context *intel, |
gl_format format) |
{ |
/** |
* From the "Alignment Unit Size" section of various specs, namely: |
* - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4 |
* - i965 and G45 PRMs: Volume 1, Section 6.17.3.4. |
* - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4 |
* - BSpec (for Ivybridge and slight variations in separate stencil) |
* |
* +----------------------------------------------------------------------+ |
* | | alignment unit width ("i") | |
* | Surface Property |-----------------------------| |
* | | 915 | 965 | ILK | SNB | IVB | |
* +----------------------------------------------------------------------+ |
* | YUV 4:2:2 format | 8 | 4 | 4 | 4 | 4 | |
* | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 | |
* | FXT1 compressed format | 8 | 8 | 8 | 8 | 8 | |
* | Depth Buffer (16-bit) | 4 | 4 | 4 | 4 | 8 | |
* | Depth Buffer (other) | 4 | 4 | 4 | 4 | 4 | |
* | Separate Stencil Buffer | N/A | N/A | 8 | 8 | 8 | |
* | All Others | 4 | 4 | 4 | 4 | 4 | |
* +----------------------------------------------------------------------+ |
* |
* On IVB+, non-special cases can be overridden by setting the SURFACE_STATE |
* "Surface Horizontal Alignment" field to HALIGN_4 or HALIGN_8. |
*/ |
if (_mesa_is_format_compressed(format)) { |
/* The hardware alignment requirements for compressed textures |
* happen to match the block boundaries. |
*/ |
unsigned int i, j; |
_mesa_get_format_block_size(format, &i, &j); |
return i; |
} |
return 4; |
} |
static unsigned int |
intel_vertical_texture_alignment_unit(struct intel_context *intel, |
gl_format format) |
{ |
/** |
* From the "Alignment Unit Size" section of various specs, namely: |
* - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4 |
* - i965 and G45 PRMs: Volume 1, Section 6.17.3.4. |
* - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4 |
* - BSpec (for Ivybridge and slight variations in separate stencil) |
* |
* +----------------------------------------------------------------------+ |
* | | alignment unit height ("j") | |
* | Surface Property |-----------------------------| |
* | | 915 | 965 | ILK | SNB | IVB | |
* +----------------------------------------------------------------------+ |
* | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 | |
* | FXT1 compressed format | 4 | 4 | 4 | 4 | 4 | |
* | Depth Buffer | 2 | 2 | 2 | 4 | 4 | |
* | Separate Stencil Buffer | N/A | N/A | N/A | 4 | 8 | |
* | Multisampled (4x or 8x) render target | N/A | N/A | N/A | 4 | 4 | |
* | All Others | 2 | 2 | 2 | 2 | 2 | |
* +----------------------------------------------------------------------+ |
* |
* On SNB+, non-special cases can be overridden by setting the SURFACE_STATE |
* "Surface Vertical Alignment" field to VALIGN_2 or VALIGN_4. |
* |
* We currently don't support multisampling. |
*/ |
if (_mesa_is_format_compressed(format)) |
return 4; |
return 2; |
} |
void |
intel_get_texture_alignment_unit(struct intel_context *intel, |
gl_format format, |
unsigned int *w, unsigned int *h) |
{ |
*w = intel_horizontal_texture_alignment_unit(intel, format); |
*h = intel_vertical_texture_alignment_unit(intel, format); |
} |
void i945_miptree_layout_2d(struct intel_mipmap_tree *mt) |
{ |
GLuint level; |
GLuint x = 0; |
GLuint y = 0; |
GLuint width = mt->physical_width0; |
GLuint height = mt->physical_height0; |
GLuint depth = mt->physical_depth0; /* number of array layers. */ |
mt->total_width = mt->physical_width0; |
if (mt->compressed) { |
mt->total_width = ALIGN(mt->physical_width0, mt->align_w); |
} |
/* May need to adjust width to accomodate the placement of |
* the 2nd mipmap. This occurs when the alignment |
* constraints of mipmap placement push the right edge of the |
* 2nd mipmap out past the width of its parent. |
*/ |
if (mt->first_level != mt->last_level) { |
GLuint mip1_width; |
if (mt->compressed) { |
mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) + |
ALIGN(minify(mt->physical_width0, 2), mt->align_w); |
} else { |
mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) + |
minify(mt->physical_width0, 2); |
} |
if (mip1_width > mt->total_width) { |
mt->total_width = mip1_width; |
} |
} |
mt->total_height = 0; |
for ( level = mt->first_level ; level <= mt->last_level ; level++ ) { |
GLuint img_height; |
intel_miptree_set_level_info(mt, level, x, y, width, |
height, depth); |
img_height = ALIGN(height, mt->align_h); |
if (mt->compressed) |
img_height /= mt->align_h; |
/* Because the images are packed better, the final offset |
* might not be the maximal one: |
*/ |
mt->total_height = MAX2(mt->total_height, y + img_height); |
/* Layout_below: step right after second mipmap. |
*/ |
if (level == mt->first_level + 1) { |
x += ALIGN(width, mt->align_w); |
} |
else { |
y += img_height; |
} |
width = minify(width, 1); |
height = minify(height, 1); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_tex_layout.h |
---|
0,0 → 1,40 |
/************************************************************************** |
* |
* 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 "main/macros.h" |
extern void i945_miptree_layout_2d(struct intel_mipmap_tree *mt); |
void |
intel_get_texture_alignment_unit(struct intel_context *intel, |
gl_format format, |
unsigned int *w, unsigned int *h); |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_tex_obj.h |
---|
0,0 → 1,84 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef _INTEL_TEX_OBJ_H |
#define _INTEL_TEX_OBJ_H |
#include "swrast/s_context.h" |
struct intel_texture_object |
{ |
struct gl_texture_object base; |
/* This is a mirror of base._MaxLevel, updated at validate time, |
* except that we don't bother with the non-base levels for |
* non-mipmapped textures. |
*/ |
unsigned int _MaxLevel; |
/* On validation any active images held in main memory or in other |
* regions will be copied to this region and the old storage freed. |
*/ |
struct intel_mipmap_tree *mt; |
/** |
* Set when mipmap trees in the texture images of this texture object |
* might not all be the mipmap tree above. |
*/ |
bool needs_validate; |
}; |
/** |
* intel_texture_image is a subclass of swrast_texture_image because we |
* sometimes fall back to using the swrast module for software rendering. |
*/ |
struct intel_texture_image |
{ |
struct swrast_texture_image base; |
/* If intelImage->mt != NULL, image data is stored here. |
* Else if intelImage->base.Buffer != NULL, image is stored there. |
* Else there is no image data. |
*/ |
struct intel_mipmap_tree *mt; |
}; |
static INLINE struct intel_texture_object * |
intel_texture_object(struct gl_texture_object *obj) |
{ |
return (struct intel_texture_object *) obj; |
} |
static INLINE struct intel_texture_image * |
intel_texture_image(struct gl_texture_image *img) |
{ |
return (struct intel_texture_image *) img; |
} |
#endif /* _INTEL_TEX_OBJ_H */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_tex_subimage.c |
---|
0,0 → 1,155 |
/************************************************************************** |
* |
* 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 "main/bufferobj.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/pbo.h" |
#include "main/texobj.h" |
#include "main/texstore.h" |
#include "main/texcompress.h" |
#include "main/enums.h" |
#include "intel_batchbuffer.h" |
#include "intel_context.h" |
#include "intel_tex.h" |
#include "intel_mipmap_tree.h" |
#include "intel_blit.h" |
#define FILE_DEBUG_FLAG DEBUG_TEXTURE |
static bool |
intel_blit_texsubimage(struct gl_context * ctx, |
struct gl_texture_image *texImage, |
GLint xoffset, GLint yoffset, |
GLint width, GLint height, |
GLenum format, GLenum type, const void *pixels, |
const struct gl_pixelstore_attrib *packing) |
{ |
struct intel_context *intel = intel_context(ctx); |
struct intel_texture_image *intelImage = intel_texture_image(texImage); |
/* Try to do a blit upload of the subimage if the texture is |
* currently busy. |
*/ |
if (!intelImage->mt) |
return false; |
/* The blitter can't handle Y tiling */ |
if (intelImage->mt->region->tiling == I915_TILING_Y) |
return false; |
if (texImage->TexObject->Target != GL_TEXTURE_2D) |
return false; |
if (!drm_intel_bo_busy(intelImage->mt->region->bo)) |
return false; |
DBG("BLT subimage %s target %s level %d offset %d,%d %dx%d\n", |
__FUNCTION__, |
_mesa_lookup_enum_by_nr(texImage->TexObject->Target), |
texImage->Level, xoffset, yoffset, width, height); |
pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, |
format, type, pixels, packing, |
"glTexSubImage"); |
if (!pixels) |
return false; |
struct intel_mipmap_tree *temp_mt = |
intel_miptree_create(intel, GL_TEXTURE_2D, texImage->TexFormat, |
0, 0, |
width, height, 1, |
false, INTEL_MIPTREE_TILING_NONE); |
if (!temp_mt) |
goto err; |
GLubyte *dst = intel_miptree_map_raw(intel, temp_mt); |
if (!dst) |
goto err; |
if (!_mesa_texstore(ctx, 2, texImage->_BaseFormat, |
texImage->TexFormat, |
temp_mt->region->pitch, |
&dst, |
width, height, 1, |
format, type, pixels, packing)) { |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); |
} |
intel_miptree_unmap_raw(intel, temp_mt); |
bool ret; |
ret = intel_miptree_blit(intel, |
temp_mt, 0, 0, |
0, 0, false, |
intelImage->mt, texImage->Level, texImage->Face, |
xoffset, yoffset, false, |
width, height, GL_COPY); |
assert(ret); |
intel_miptree_release(&temp_mt); |
_mesa_unmap_teximage_pbo(ctx, packing); |
return ret; |
err: |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); |
intel_miptree_release(&temp_mt); |
_mesa_unmap_teximage_pbo(ctx, packing); |
return false; |
} |
static void |
intelTexSubImage(struct gl_context * ctx, |
GLuint dims, |
struct gl_texture_image *texImage, |
GLint xoffset, GLint yoffset, GLint zoffset, |
GLsizei width, GLsizei height, GLsizei depth, |
GLenum format, GLenum type, |
const GLvoid * pixels, |
const struct gl_pixelstore_attrib *packing) |
{ |
/* The intel_blit_texsubimage() function only handles 2D images */ |
if (dims != 2 || !intel_blit_texsubimage(ctx, texImage, |
xoffset, yoffset, |
width, height, |
format, type, pixels, packing)) { |
_mesa_store_texsubimage(ctx, dims, texImage, |
xoffset, yoffset, zoffset, |
width, height, depth, |
format, type, pixels, packing); |
} |
} |
void |
intelInitTextureSubImageFuncs(struct dd_function_table *functions) |
{ |
functions->TexSubImage = intelTexSubImage; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_tex_validate.c |
---|
0,0 → 1,140 |
#include "main/mtypes.h" |
#include "main/macros.h" |
#include "main/samplerobj.h" |
#include "main/texobj.h" |
#include "intel_context.h" |
#include "intel_mipmap_tree.h" |
#include "intel_blit.h" |
#include "intel_tex.h" |
#include "intel_tex_layout.h" |
#define FILE_DEBUG_FLAG DEBUG_TEXTURE |
/** |
* When validating, we only care about the texture images that could |
* be seen, so for non-mipmapped modes we want to ignore everything |
* but BaseLevel. |
*/ |
static void |
intel_update_max_level(struct intel_texture_object *intelObj, |
struct gl_sampler_object *sampler) |
{ |
struct gl_texture_object *tObj = &intelObj->base; |
int maxlevel; |
if (sampler->MinFilter == GL_NEAREST || |
sampler->MinFilter == GL_LINEAR) { |
maxlevel = tObj->BaseLevel; |
} else { |
maxlevel = tObj->_MaxLevel; |
} |
if (intelObj->_MaxLevel != maxlevel) { |
intelObj->_MaxLevel = maxlevel; |
intelObj->needs_validate = true; |
} |
} |
/* |
*/ |
GLuint |
intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit) |
{ |
struct gl_context *ctx = &intel->ctx; |
struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current; |
struct intel_texture_object *intelObj = intel_texture_object(tObj); |
struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); |
GLuint face, i; |
GLuint nr_faces = 0; |
struct intel_texture_image *firstImage; |
int width, height, depth; |
/* TBOs require no validation -- they always just point to their BO. */ |
if (tObj->Target == GL_TEXTURE_BUFFER) |
return true; |
/* We know/require this is true by now: |
*/ |
assert(intelObj->base._BaseComplete); |
/* What levels must the tree include at a minimum? |
*/ |
intel_update_max_level(intelObj, sampler); |
if (intelObj->mt && intelObj->mt->first_level != tObj->BaseLevel) |
intelObj->needs_validate = true; |
if (!intelObj->needs_validate) |
return true; |
firstImage = intel_texture_image(tObj->Image[0][tObj->BaseLevel]); |
/* Check tree can hold all active levels. Check tree matches |
* target, imageFormat, etc. |
* |
* For pre-gen4, we have to match first_level == tObj->BaseLevel, |
* because we don't have the control that gen4 does to make min/mag |
* determination happen at a nonzero (hardware) baselevel. Because |
* of that, we just always relayout on baselevel change. |
*/ |
if (intelObj->mt && |
(!intel_miptree_match_image(intelObj->mt, &firstImage->base.Base) || |
intelObj->mt->first_level != tObj->BaseLevel || |
intelObj->mt->last_level < intelObj->_MaxLevel)) { |
intel_miptree_release(&intelObj->mt); |
} |
/* May need to create a new tree: |
*/ |
if (!intelObj->mt) { |
intel_miptree_get_dimensions_for_image(&firstImage->base.Base, |
&width, &height, &depth); |
perf_debug("Creating new %s %dx%dx%d %d..%d miptree to handle finalized " |
"texture miptree.\n", |
_mesa_get_format_name(firstImage->base.Base.TexFormat), |
width, height, depth, tObj->BaseLevel, intelObj->_MaxLevel); |
intelObj->mt = intel_miptree_create(intel, |
intelObj->base.Target, |
firstImage->base.Base.TexFormat, |
tObj->BaseLevel, |
intelObj->_MaxLevel, |
width, |
height, |
depth, |
true, |
INTEL_MIPTREE_TILING_ANY); |
if (!intelObj->mt) |
return false; |
} |
/* Pull in any images not in the object's tree: |
*/ |
nr_faces = _mesa_num_tex_faces(intelObj->base.Target); |
for (face = 0; face < nr_faces; face++) { |
for (i = tObj->BaseLevel; i <= intelObj->_MaxLevel; i++) { |
struct intel_texture_image *intelImage = |
intel_texture_image(intelObj->base.Image[face][i]); |
/* skip too small size mipmap */ |
if (intelImage == NULL) |
break; |
if (intelObj->mt != intelImage->mt) { |
intel_miptree_copy_teximage(intel, intelImage, intelObj->mt, |
false /* invalidate */); |
} |
/* After we're done, we'd better agree that our layout is |
* appropriate, or we'll end up hitting this function again on the |
* next draw |
*/ |
assert(intel_miptree_match_image(intelObj->mt, &intelImage->base.Base)); |
} |
} |
intelObj->needs_validate = false; |
return true; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_tris.c |
---|
0,0 → 1,1301 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
/** @file intel_tris.c |
* |
* This file contains functions for managing the vertex buffer and emitting |
* primitives into it. |
*/ |
#include "main/glheader.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "main/texobj.h" |
#include "main/state.h" |
#include "main/dd.h" |
#include "main/fbobject.h" |
#include "swrast/swrast.h" |
#include "swrast_setup/swrast_setup.h" |
#include "tnl/t_context.h" |
#include "tnl/t_pipeline.h" |
#include "tnl/t_vertex.h" |
#include "intel_screen.h" |
#include "intel_context.h" |
#include "intel_tris.h" |
#include "intel_batchbuffer.h" |
#include "intel_buffers.h" |
#include "intel_reg.h" |
#include "i830_context.h" |
#include "i830_reg.h" |
#include "i915_context.h" |
static void intelRenderPrimitive(struct gl_context * ctx, GLenum prim); |
static void intelRasterPrimitive(struct gl_context * ctx, GLenum rprim, |
GLuint hwprim); |
static void |
intel_flush_inline_primitive(struct intel_context *intel) |
{ |
GLuint used = intel->batch.used - intel->prim.start_ptr; |
assert(intel->prim.primitive != ~0); |
/* printf("/\n"); */ |
if (used < 2) |
goto do_discard; |
intel->batch.map[intel->prim.start_ptr] = |
_3DPRIMITIVE | intel->prim.primitive | (used - 2); |
goto finished; |
do_discard: |
intel->batch.used = intel->prim.start_ptr; |
finished: |
intel->prim.primitive = ~0; |
intel->prim.start_ptr = 0; |
intel->prim.flush = 0; |
} |
static void intel_start_inline(struct intel_context *intel, uint32_t prim) |
{ |
BATCH_LOCALS; |
intel->vtbl.emit_state(intel); |
intel->no_batch_wrap = true; |
/* Emit a slot which will be filled with the inline primitive |
* command later. |
*/ |
BEGIN_BATCH(1); |
intel->prim.start_ptr = intel->batch.used; |
intel->prim.primitive = prim; |
intel->prim.flush = intel_flush_inline_primitive; |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
intel->no_batch_wrap = false; |
/* printf(">"); */ |
} |
static void intel_wrap_inline(struct intel_context *intel) |
{ |
GLuint prim = intel->prim.primitive; |
intel_flush_inline_primitive(intel); |
intel_batchbuffer_flush(intel); |
intel_start_inline(intel, prim); /* ??? */ |
} |
static GLuint *intel_extend_inline(struct intel_context *intel, GLuint dwords) |
{ |
GLuint *ptr; |
assert(intel->prim.flush == intel_flush_inline_primitive); |
if (intel_batchbuffer_space(intel) < dwords * sizeof(GLuint)) |
intel_wrap_inline(intel); |
/* printf("."); */ |
intel->vtbl.assert_not_dirty(intel); |
ptr = intel->batch.map + intel->batch.used; |
intel->batch.used += dwords; |
return ptr; |
} |
/** Sets the primitive type for a primitive sequence, flushing as needed. */ |
void intel_set_prim(struct intel_context *intel, uint32_t prim) |
{ |
/* if we have no VBOs */ |
if (intel->intelScreen->no_vbo) { |
intel_start_inline(intel, prim); |
return; |
} |
if (prim != intel->prim.primitive) { |
INTEL_FIREVERTICES(intel); |
intel->prim.primitive = prim; |
} |
} |
/** Returns mapped VB space for the given number of vertices */ |
uint32_t *intel_get_prim_space(struct intel_context *intel, unsigned int count) |
{ |
uint32_t *addr; |
if (intel->intelScreen->no_vbo) { |
return intel_extend_inline(intel, count * intel->vertex_size); |
} |
/* Check for space in the existing VB */ |
if (intel->prim.vb_bo == NULL || |
(intel->prim.current_offset + |
count * intel->vertex_size * 4) > INTEL_VB_SIZE || |
(intel->prim.count + count) >= (1 << 16)) { |
/* Flush existing prim if any */ |
INTEL_FIREVERTICES(intel); |
intel_finish_vb(intel); |
/* Start a new VB */ |
if (intel->prim.vb == NULL) |
intel->prim.vb = malloc(INTEL_VB_SIZE); |
intel->prim.vb_bo = drm_intel_bo_alloc(intel->bufmgr, "vb", |
INTEL_VB_SIZE, 4); |
intel->prim.start_offset = 0; |
intel->prim.current_offset = 0; |
} |
intel->prim.flush = intel_flush_prim; |
addr = (uint32_t *)(intel->prim.vb + intel->prim.current_offset); |
intel->prim.current_offset += intel->vertex_size * 4 * count; |
intel->prim.count += count; |
return addr; |
} |
/** Dispatches the accumulated primitive to the batchbuffer. */ |
void intel_flush_prim(struct intel_context *intel) |
{ |
drm_intel_bo *aper_array[2]; |
drm_intel_bo *vb_bo; |
unsigned int offset, count; |
BATCH_LOCALS; |
/* Must be called after an intel_start_prim. */ |
assert(intel->prim.primitive != ~0); |
if (intel->prim.count == 0) |
return; |
/* Clear the current prims out of the context state so that a batch flush |
* flush triggered by emit_state doesn't loop back to flush_prim again. |
*/ |
vb_bo = intel->prim.vb_bo; |
drm_intel_bo_reference(vb_bo); |
count = intel->prim.count; |
intel->prim.count = 0; |
offset = intel->prim.start_offset; |
intel->prim.start_offset = intel->prim.current_offset; |
if (intel->gen < 3) |
intel->prim.current_offset = intel->prim.start_offset = ALIGN(intel->prim.start_offset, 128); |
intel->prim.flush = NULL; |
intel->vtbl.emit_state(intel); |
aper_array[0] = intel->batch.bo; |
aper_array[1] = vb_bo; |
if (dri_bufmgr_check_aperture_space(aper_array, 2)) { |
intel_batchbuffer_flush(intel); |
intel->vtbl.emit_state(intel); |
} |
/* Ensure that we don't start a new batch for the following emit, which |
* depends on the state just emitted. emit_state should be making sure we |
* have the space for this. |
*/ |
intel->no_batch_wrap = true; |
if (intel->always_flush_cache) { |
intel_batchbuffer_emit_mi_flush(intel); |
} |
#if 0 |
printf("emitting %d..%d=%d vertices size %d\n", offset, |
intel->prim.current_offset, count, |
intel->vertex_size * 4); |
#endif |
if (intel->gen >= 3) { |
struct i915_context *i915 = i915_context(&intel->ctx); |
unsigned int cmd = 0, len = 0; |
if (vb_bo != i915->current_vb_bo) { |
cmd |= I1_LOAD_S(0); |
len++; |
} |
if (intel->vertex_size != i915->current_vertex_size) { |
cmd |= I1_LOAD_S(1); |
len++; |
} |
if (len) |
len++; |
BEGIN_BATCH(2+len); |
if (cmd) |
OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | cmd | (len - 2)); |
if (vb_bo != i915->current_vb_bo) { |
OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, 0); |
i915->current_vb_bo = vb_bo; |
} |
if (intel->vertex_size != i915->current_vertex_size) { |
OUT_BATCH((intel->vertex_size << S1_VERTEX_WIDTH_SHIFT) | |
(intel->vertex_size << S1_VERTEX_PITCH_SHIFT)); |
i915->current_vertex_size = intel->vertex_size; |
} |
OUT_BATCH(_3DPRIMITIVE | |
PRIM_INDIRECT | |
PRIM_INDIRECT_SEQUENTIAL | |
intel->prim.primitive | |
count); |
OUT_BATCH(offset / (intel->vertex_size * 4)); |
ADVANCE_BATCH(); |
} else { |
struct i830_context *i830 = i830_context(&intel->ctx); |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | |
I1_LOAD_S(0) | I1_LOAD_S(2) | 1); |
/* S0 */ |
assert((offset & ~S0_VB_OFFSET_MASK_830) == 0); |
OUT_RELOC(vb_bo, I915_GEM_DOMAIN_VERTEX, 0, |
offset | (intel->vertex_size << S0_VB_PITCH_SHIFT_830) | |
S0_VB_ENABLE_830); |
/* S2 |
* This is somewhat unfortunate -- VB width is tied up with |
* vertex format data that we've already uploaded through |
* _3DSTATE_VFT[01]_CMD. We may want to replace emits of VFT state with |
* STATE_IMMEDIATE_1 like this to avoid duplication. |
*/ |
OUT_BATCH((i830->state.Ctx[I830_CTXREG_VF] & VFT0_TEX_COUNT_MASK) >> |
VFT0_TEX_COUNT_SHIFT << S2_TEX_COUNT_SHIFT_830 | |
(i830->state.Ctx[I830_CTXREG_VF2] << 16) | |
intel->vertex_size << S2_VERTEX_0_WIDTH_SHIFT_830); |
OUT_BATCH(_3DPRIMITIVE | |
PRIM_INDIRECT | |
PRIM_INDIRECT_SEQUENTIAL | |
intel->prim.primitive | |
count); |
OUT_BATCH(0); /* Beginning vertex index */ |
ADVANCE_BATCH(); |
} |
if (intel->always_flush_cache) { |
intel_batchbuffer_emit_mi_flush(intel); |
} |
intel->no_batch_wrap = false; |
drm_intel_bo_unreference(vb_bo); |
} |
/** |
* Uploads the locally-accumulated VB into the buffer object. |
* |
* This avoids us thrashing the cachelines in and out as the buffer gets |
* filled, dispatched, then reused as the hardware completes rendering from it, |
* and also lets us clflush less if we dispatch with a partially-filled VB. |
* |
* This is called normally from get_space when we're finishing a BO, but also |
* at batch flush time so that we don't try accessing the contents of a |
* just-dispatched buffer. |
*/ |
void intel_finish_vb(struct intel_context *intel) |
{ |
if (intel->prim.vb_bo == NULL) |
return; |
drm_intel_bo_subdata(intel->prim.vb_bo, 0, intel->prim.start_offset, |
intel->prim.vb); |
drm_intel_bo_unreference(intel->prim.vb_bo); |
intel->prim.vb_bo = NULL; |
} |
/*********************************************************************** |
* Emit primitives as inline vertices * |
***********************************************************************/ |
#ifdef __i386__ |
#define COPY_DWORDS( j, vb, vertsize, v ) \ |
do { \ |
int __tmp; \ |
__asm__ __volatile__( "rep ; movsl" \ |
: "=%c" (j), "=D" (vb), "=S" (__tmp) \ |
: "0" (vertsize), \ |
"D" ((long)vb), \ |
"S" ((long)v) ); \ |
} while (0) |
#else |
#define COPY_DWORDS( j, vb, vertsize, v ) \ |
do { \ |
for ( j = 0 ; j < vertsize ; j++ ) { \ |
vb[j] = ((GLuint *)v)[j]; \ |
} \ |
vb += vertsize; \ |
} while (0) |
#endif |
static void |
intel_draw_quad(struct intel_context *intel, |
intelVertexPtr v0, |
intelVertexPtr v1, intelVertexPtr v2, intelVertexPtr v3) |
{ |
GLuint vertsize = intel->vertex_size; |
GLuint *vb = intel_get_prim_space(intel, 6); |
int j; |
COPY_DWORDS(j, vb, vertsize, v0); |
COPY_DWORDS(j, vb, vertsize, v1); |
/* If smooth shading, draw like a trifan which gives better |
* rasterization. Otherwise draw as two triangles with provoking |
* vertex in third position as required for flat shading. |
*/ |
if (intel->ctx.Light.ShadeModel == GL_FLAT) { |
COPY_DWORDS(j, vb, vertsize, v3); |
COPY_DWORDS(j, vb, vertsize, v1); |
} |
else { |
COPY_DWORDS(j, vb, vertsize, v2); |
COPY_DWORDS(j, vb, vertsize, v0); |
} |
COPY_DWORDS(j, vb, vertsize, v2); |
COPY_DWORDS(j, vb, vertsize, v3); |
} |
static void |
intel_draw_triangle(struct intel_context *intel, |
intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2) |
{ |
GLuint vertsize = intel->vertex_size; |
GLuint *vb = intel_get_prim_space(intel, 3); |
int j; |
COPY_DWORDS(j, vb, vertsize, v0); |
COPY_DWORDS(j, vb, vertsize, v1); |
COPY_DWORDS(j, vb, vertsize, v2); |
} |
static void |
intel_draw_line(struct intel_context *intel, |
intelVertexPtr v0, intelVertexPtr v1) |
{ |
GLuint vertsize = intel->vertex_size; |
GLuint *vb = intel_get_prim_space(intel, 2); |
int j; |
COPY_DWORDS(j, vb, vertsize, v0); |
COPY_DWORDS(j, vb, vertsize, v1); |
} |
static void |
intel_draw_point(struct intel_context *intel, intelVertexPtr v0) |
{ |
GLuint vertsize = intel->vertex_size; |
GLuint *vb = intel_get_prim_space(intel, 1); |
int j; |
/* Adjust for sub pixel position -- still required for conform. */ |
*(float *) &vb[0] = v0->v.x; |
*(float *) &vb[1] = v0->v.y; |
for (j = 2; j < vertsize; j++) |
vb[j] = v0->ui[j]; |
} |
/*********************************************************************** |
* Fixup for ARB_point_parameters * |
***********************************************************************/ |
/* Currently not working - VERT_ATTRIB_POINTSIZE isn't correctly |
* represented in the fragment program InputsRead field. |
*/ |
static void |
intel_atten_point(struct intel_context *intel, intelVertexPtr v0) |
{ |
struct gl_context *ctx = &intel->ctx; |
GLfloat psz[4], col[4], restore_psz, restore_alpha; |
_tnl_get_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz); |
_tnl_get_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col); |
restore_psz = psz[0]; |
restore_alpha = col[3]; |
if (psz[0] >= ctx->Point.Threshold) { |
psz[0] = MIN2(psz[0], ctx->Point.MaxSize); |
} |
else { |
GLfloat dsize = psz[0] / ctx->Point.Threshold; |
psz[0] = MAX2(ctx->Point.Threshold, ctx->Point.MinSize); |
col[3] *= dsize * dsize; |
} |
if (psz[0] < 1.0) |
psz[0] = 1.0; |
if (restore_psz != psz[0] || restore_alpha != col[3]) { |
_tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz); |
_tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col); |
intel_draw_point(intel, v0); |
psz[0] = restore_psz; |
col[3] = restore_alpha; |
_tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz); |
_tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col); |
} |
else |
intel_draw_point(intel, v0); |
} |
/*********************************************************************** |
* Fixup for I915 WPOS texture coordinate * |
***********************************************************************/ |
static void |
intel_emit_fragcoord(struct intel_context *intel, intelVertexPtr v) |
{ |
struct gl_context *ctx = &intel->ctx; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
GLuint offset = intel->wpos_offset; |
float *vertex_position = (float *)v; |
float *fragcoord = (float *)((char *)v + offset); |
fragcoord[0] = vertex_position[0]; |
if (_mesa_is_user_fbo(fb)) |
fragcoord[1] = vertex_position[1]; |
else |
fragcoord[1] = fb->Height - vertex_position[1]; |
fragcoord[2] = vertex_position[2]; |
fragcoord[3] = vertex_position[3]; |
} |
static void |
intel_wpos_triangle(struct intel_context *intel, |
intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2) |
{ |
intel_emit_fragcoord(intel, v0); |
intel_emit_fragcoord(intel, v1); |
intel_emit_fragcoord(intel, v2); |
intel_draw_triangle(intel, v0, v1, v2); |
} |
static void |
intel_wpos_line(struct intel_context *intel, |
intelVertexPtr v0, intelVertexPtr v1) |
{ |
intel_emit_fragcoord(intel, v0); |
intel_emit_fragcoord(intel, v1); |
intel_draw_line(intel, v0, v1); |
} |
static void |
intel_wpos_point(struct intel_context *intel, intelVertexPtr v0) |
{ |
intel_emit_fragcoord(intel, v0); |
intel_draw_point(intel, v0); |
} |
/*********************************************************************** |
* Macros for t_dd_tritmp.h to draw basic primitives * |
***********************************************************************/ |
#define TRI( a, b, c ) \ |
do { \ |
if (DO_FALLBACK) \ |
intel->draw_tri( intel, a, b, c ); \ |
else \ |
intel_draw_triangle( intel, a, b, c ); \ |
} while (0) |
#define QUAD( a, b, c, d ) \ |
do { \ |
if (DO_FALLBACK) { \ |
intel->draw_tri( intel, a, b, d ); \ |
intel->draw_tri( intel, b, c, d ); \ |
} else \ |
intel_draw_quad( intel, a, b, c, d ); \ |
} while (0) |
#define LINE( v0, v1 ) \ |
do { \ |
if (DO_FALLBACK) \ |
intel->draw_line( intel, v0, v1 ); \ |
else \ |
intel_draw_line( intel, v0, v1 ); \ |
} while (0) |
#define POINT( v0 ) \ |
do { \ |
if (DO_FALLBACK) \ |
intel->draw_point( intel, v0 ); \ |
else \ |
intel_draw_point( intel, v0 ); \ |
} while (0) |
/*********************************************************************** |
* Build render functions from dd templates * |
***********************************************************************/ |
#define INTEL_OFFSET_BIT 0x01 |
#define INTEL_TWOSIDE_BIT 0x02 |
#define INTEL_UNFILLED_BIT 0x04 |
#define INTEL_FALLBACK_BIT 0x08 |
#define INTEL_MAX_TRIFUNC 0x10 |
static struct |
{ |
tnl_points_func points; |
tnl_line_func line; |
tnl_triangle_func triangle; |
tnl_quad_func quad; |
} rast_tab[INTEL_MAX_TRIFUNC]; |
#define DO_FALLBACK (IND & INTEL_FALLBACK_BIT) |
#define DO_OFFSET (IND & INTEL_OFFSET_BIT) |
#define DO_UNFILLED (IND & INTEL_UNFILLED_BIT) |
#define DO_TWOSIDE (IND & INTEL_TWOSIDE_BIT) |
#define DO_FLAT 0 |
#define DO_TRI 1 |
#define DO_QUAD 1 |
#define DO_LINE 1 |
#define DO_POINTS 1 |
#define DO_FULL_QUAD 1 |
#define HAVE_SPEC 1 |
#define HAVE_BACK_COLORS 0 |
#define HAVE_HW_FLATSHADE 1 |
#define VERTEX intelVertex |
#define TAB rast_tab |
/* Only used to pull back colors into vertices (ie, we know color is |
* floating point). |
*/ |
#define INTEL_COLOR( dst, src ) \ |
do { \ |
UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \ |
UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \ |
UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \ |
UNCLAMPED_FLOAT_TO_UBYTE((dst)[3], (src)[3]); \ |
} while (0) |
#define INTEL_SPEC( dst, src ) \ |
do { \ |
UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \ |
UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \ |
UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \ |
} while (0) |
#define DEPTH_SCALE (ctx->DrawBuffer->Visual.depthBits == 16 ? 1.0 : 2.0) |
#define UNFILLED_TRI unfilled_tri |
#define UNFILLED_QUAD unfilled_quad |
#define VERT_X(_v) _v->v.x |
#define VERT_Y(_v) _v->v.y |
#define VERT_Z(_v) _v->v.z |
#define AREA_IS_CCW( a ) (a > 0) |
#define GET_VERTEX(e) (intel->verts + (e * intel->vertex_size * sizeof(GLuint))) |
#define VERT_SET_RGBA( v, c ) if (coloroffset) INTEL_COLOR( v->ub4[coloroffset], c ) |
#define VERT_COPY_RGBA( v0, v1 ) if (coloroffset) v0->ui[coloroffset] = v1->ui[coloroffset] |
#define VERT_SAVE_RGBA( idx ) if (coloroffset) color[idx] = v[idx]->ui[coloroffset] |
#define VERT_RESTORE_RGBA( idx ) if (coloroffset) v[idx]->ui[coloroffset] = color[idx] |
#define VERT_SET_SPEC( v, c ) if (specoffset) INTEL_SPEC( v->ub4[specoffset], c ) |
#define VERT_COPY_SPEC( v0, v1 ) if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset]) |
#define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset] |
#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] |
#define LOCAL_VARS(n) \ |
struct intel_context *intel = intel_context(ctx); \ |
GLuint color[n] = { 0, }, spec[n] = { 0, }; \ |
GLuint coloroffset = intel->coloroffset; \ |
GLuint specoffset = intel->specoffset; \ |
(void) color; (void) spec; (void) coloroffset; (void) specoffset; |
/*********************************************************************** |
* Helpers for rendering unfilled primitives * |
***********************************************************************/ |
static const GLuint hw_prim[GL_POLYGON + 1] = { |
PRIM3D_POINTLIST, |
PRIM3D_LINELIST, |
PRIM3D_LINELIST, |
PRIM3D_LINELIST, |
PRIM3D_TRILIST, |
PRIM3D_TRILIST, |
PRIM3D_TRILIST, |
PRIM3D_TRILIST, |
PRIM3D_TRILIST, |
PRIM3D_TRILIST |
}; |
#define RASTERIZE(x) intelRasterPrimitive( ctx, x, hw_prim[x] ) |
#define RENDER_PRIMITIVE intel->render_primitive |
#define TAG(x) x |
#define IND INTEL_FALLBACK_BIT |
#include "tnl_dd/t_dd_unfilled.h" |
#undef IND |
/*********************************************************************** |
* Generate GL render functions * |
***********************************************************************/ |
#define IND (0) |
#define TAG(x) x |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_OFFSET_BIT) |
#define TAG(x) x##_offset |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_TWOSIDE_BIT) |
#define TAG(x) x##_twoside |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT) |
#define TAG(x) x##_twoside_offset |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_UNFILLED_BIT) |
#define TAG(x) x##_unfilled |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT) |
#define TAG(x) x##_offset_unfilled |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT) |
#define TAG(x) x##_twoside_unfilled |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT) |
#define TAG(x) x##_twoside_offset_unfilled |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_FALLBACK_BIT) |
#define TAG(x) x##_fallback |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT) |
#define TAG(x) x##_offset_fallback |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_TWOSIDE_BIT|INTEL_FALLBACK_BIT) |
#define TAG(x) x##_twoside_fallback |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT) |
#define TAG(x) x##_twoside_offset_fallback |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT) |
#define TAG(x) x##_unfilled_fallback |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT) |
#define TAG(x) x##_offset_unfilled_fallback |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT) |
#define TAG(x) x##_twoside_unfilled_fallback |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT| \ |
INTEL_FALLBACK_BIT) |
#define TAG(x) x##_twoside_offset_unfilled_fallback |
#include "tnl_dd/t_dd_tritmp.h" |
static void |
init_rast_tab(void) |
{ |
init(); |
init_offset(); |
init_twoside(); |
init_twoside_offset(); |
init_unfilled(); |
init_offset_unfilled(); |
init_twoside_unfilled(); |
init_twoside_offset_unfilled(); |
init_fallback(); |
init_offset_fallback(); |
init_twoside_fallback(); |
init_twoside_offset_fallback(); |
init_unfilled_fallback(); |
init_offset_unfilled_fallback(); |
init_twoside_unfilled_fallback(); |
init_twoside_offset_unfilled_fallback(); |
} |
/*********************************************************************** |
* Rasterization fallback helpers * |
***********************************************************************/ |
/* This code is hit only when a mix of accelerated and unaccelerated |
* primitives are being drawn, and only for the unaccelerated |
* primitives. |
*/ |
static void |
intel_fallback_tri(struct intel_context *intel, |
intelVertex * v0, intelVertex * v1, intelVertex * v2) |
{ |
struct gl_context *ctx = &intel->ctx; |
SWvertex v[3]; |
if (0) |
fprintf(stderr, "\n%s\n", __FUNCTION__); |
INTEL_FIREVERTICES(intel); |
_swsetup_Translate(ctx, v0, &v[0]); |
_swsetup_Translate(ctx, v1, &v[1]); |
_swsetup_Translate(ctx, v2, &v[2]); |
_swrast_render_start(ctx); |
_swrast_Triangle(ctx, &v[0], &v[1], &v[2]); |
_swrast_render_finish(ctx); |
} |
static void |
intel_fallback_line(struct intel_context *intel, |
intelVertex * v0, intelVertex * v1) |
{ |
struct gl_context *ctx = &intel->ctx; |
SWvertex v[2]; |
if (0) |
fprintf(stderr, "\n%s\n", __FUNCTION__); |
INTEL_FIREVERTICES(intel); |
_swsetup_Translate(ctx, v0, &v[0]); |
_swsetup_Translate(ctx, v1, &v[1]); |
_swrast_render_start(ctx); |
_swrast_Line(ctx, &v[0], &v[1]); |
_swrast_render_finish(ctx); |
} |
static void |
intel_fallback_point(struct intel_context *intel, |
intelVertex * v0) |
{ |
struct gl_context *ctx = &intel->ctx; |
SWvertex v[1]; |
if (0) |
fprintf(stderr, "\n%s\n", __FUNCTION__); |
INTEL_FIREVERTICES(intel); |
_swsetup_Translate(ctx, v0, &v[0]); |
_swrast_render_start(ctx); |
_swrast_Point(ctx, &v[0]); |
_swrast_render_finish(ctx); |
} |
/**********************************************************************/ |
/* Render unclipped begin/end objects */ |
/**********************************************************************/ |
#define IND 0 |
#define V(x) (intelVertex *)(vertptr + ((x)*vertsize*sizeof(GLuint))) |
#define RENDER_POINTS( start, count ) \ |
for ( ; start < count ; start++) POINT( V(ELT(start)) ); |
#define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) ) |
#define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) ) |
#define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) ) |
#define INIT(x) intelRenderPrimitive( ctx, x ) |
#undef LOCAL_VARS |
#define LOCAL_VARS \ |
struct intel_context *intel = intel_context(ctx); \ |
GLubyte *vertptr = (GLubyte *)intel->verts; \ |
const GLuint vertsize = intel->vertex_size; \ |
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ |
(void) elt; |
#define RESET_STIPPLE |
#define RESET_OCCLUSION |
#define PRESERVE_VB_DEFS |
#define ELT(x) x |
#define TAG(x) intel_##x##_verts |
#include "tnl/t_vb_rendertmp.h" |
#undef ELT |
#undef TAG |
#define TAG(x) intel_##x##_elts |
#define ELT(x) elt[x] |
#include "tnl/t_vb_rendertmp.h" |
/**********************************************************************/ |
/* Render clipped primitives */ |
/**********************************************************************/ |
static void |
intelRenderClippedPoly(struct gl_context * ctx, const GLuint * elts, GLuint n) |
{ |
struct intel_context *intel = intel_context(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
GLuint prim = intel->render_primitive; |
/* Render the new vertices as an unclipped polygon. |
*/ |
{ |
GLuint *tmp = VB->Elts; |
VB->Elts = (GLuint *) elts; |
tnl->Driver.Render.PrimTabElts[GL_POLYGON] (ctx, 0, n, |
PRIM_BEGIN | PRIM_END); |
VB->Elts = tmp; |
} |
/* Restore the render primitive |
*/ |
if (prim != GL_POLYGON) |
tnl->Driver.Render.PrimitiveNotify(ctx, prim); |
} |
static void |
intelRenderClippedLine(struct gl_context * ctx, GLuint ii, GLuint jj) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
tnl->Driver.Render.Line(ctx, ii, jj); |
} |
static void |
intelFastRenderClippedPoly(struct gl_context * ctx, const GLuint * elts, GLuint n) |
{ |
struct intel_context *intel = intel_context(ctx); |
const GLuint vertsize = intel->vertex_size; |
GLuint *vb = intel_get_prim_space(intel, (n - 2) * 3); |
GLubyte *vertptr = (GLubyte *) intel->verts; |
const GLuint *start = (const GLuint *) V(elts[0]); |
int i, j; |
for (i = 2; i < n; i++) { |
COPY_DWORDS(j, vb, vertsize, V(elts[i - 1])); |
COPY_DWORDS(j, vb, vertsize, V(elts[i])); |
COPY_DWORDS(j, vb, vertsize, start); |
} |
} |
/**********************************************************************/ |
/* Choose render functions */ |
/**********************************************************************/ |
#define DD_TRI_LIGHT_TWOSIDE (1 << 1) |
#define DD_TRI_UNFILLED (1 << 2) |
#define DD_TRI_STIPPLE (1 << 4) |
#define DD_TRI_OFFSET (1 << 5) |
#define DD_LINE_STIPPLE (1 << 7) |
#define DD_POINT_ATTEN (1 << 9) |
#define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN) |
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED) |
void |
intelChooseRenderState(struct gl_context * ctx) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct intel_context *intel = intel_context(ctx); |
GLuint flags = |
((ctx->Light.Enabled && |
ctx->Light.Model.TwoSide) ? DD_TRI_LIGHT_TWOSIDE : 0) | |
((ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL) ? DD_TRI_UNFILLED : 0) | |
(ctx->Polygon.StippleFlag ? DD_TRI_STIPPLE : 0) | |
((ctx->Polygon.OffsetPoint || |
ctx->Polygon.OffsetLine || |
ctx->Polygon.OffsetFill) ? DD_TRI_OFFSET : 0) | |
(ctx->Line.StippleFlag ? DD_LINE_STIPPLE : 0) | |
(ctx->Point._Attenuated ? DD_POINT_ATTEN : 0); |
const struct gl_fragment_program *fprog = ctx->FragmentProgram._Current; |
bool have_wpos = (fprog && (fprog->Base.InputsRead & VARYING_BIT_POS)); |
GLuint index = 0; |
if (INTEL_DEBUG & DEBUG_STATE) |
fprintf(stderr, "\n%s\n", __FUNCTION__); |
if ((flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) || have_wpos) { |
if (flags & ANY_RASTER_FLAGS) { |
if (flags & DD_TRI_LIGHT_TWOSIDE) |
index |= INTEL_TWOSIDE_BIT; |
if (flags & DD_TRI_OFFSET) |
index |= INTEL_OFFSET_BIT; |
if (flags & DD_TRI_UNFILLED) |
index |= INTEL_UNFILLED_BIT; |
} |
if (have_wpos) { |
intel->draw_point = intel_wpos_point; |
intel->draw_line = intel_wpos_line; |
intel->draw_tri = intel_wpos_triangle; |
/* Make sure these get called: |
*/ |
index |= INTEL_FALLBACK_BIT; |
} |
else { |
intel->draw_point = intel_draw_point; |
intel->draw_line = intel_draw_line; |
intel->draw_tri = intel_draw_triangle; |
} |
/* Hook in fallbacks for specific primitives. |
*/ |
if (flags & ANY_FALLBACK_FLAGS) { |
if (flags & DD_LINE_STIPPLE) |
intel->draw_line = intel_fallback_line; |
if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple) |
intel->draw_tri = intel_fallback_tri; |
if (flags & DD_POINT_ATTEN) { |
if (0) |
intel->draw_point = intel_atten_point; |
else |
intel->draw_point = intel_fallback_point; |
} |
index |= INTEL_FALLBACK_BIT; |
} |
} |
if (intel->RenderIndex != index) { |
intel->RenderIndex = index; |
tnl->Driver.Render.Points = rast_tab[index].points; |
tnl->Driver.Render.Line = rast_tab[index].line; |
tnl->Driver.Render.Triangle = rast_tab[index].triangle; |
tnl->Driver.Render.Quad = rast_tab[index].quad; |
if (index == 0) { |
tnl->Driver.Render.PrimTabVerts = intel_render_tab_verts; |
tnl->Driver.Render.PrimTabElts = intel_render_tab_elts; |
tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */ |
tnl->Driver.Render.ClippedPolygon = intelFastRenderClippedPoly; |
} |
else { |
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; |
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; |
tnl->Driver.Render.ClippedLine = intelRenderClippedLine; |
tnl->Driver.Render.ClippedPolygon = intelRenderClippedPoly; |
} |
} |
} |
static const GLenum reduced_prim[GL_POLYGON + 1] = { |
GL_POINTS, |
GL_LINES, |
GL_LINES, |
GL_LINES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES |
}; |
/**********************************************************************/ |
/* High level hooks for t_vb_render.c */ |
/**********************************************************************/ |
static void |
intelRunPipeline(struct gl_context * ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
_mesa_lock_context_textures(ctx); |
if (ctx->NewState) |
_mesa_update_state_locked(ctx); |
/* We need to get this done before we start the pipeline, or a |
* change in the INTEL_FALLBACK() of its intel_draw_buffers() call |
* while the pipeline is running will result in mismatched swrast |
* map/unmaps, and later assertion failures. |
*/ |
intel_prepare_render(intel); |
if (intel->NewGLState) { |
if (intel->NewGLState & _NEW_TEXTURE) { |
intel->vtbl.update_texture_state(intel); |
} |
if (!intel->Fallback) { |
if (intel->NewGLState & _INTEL_NEW_RENDERSTATE) |
intelChooseRenderState(ctx); |
} |
intel->NewGLState = 0; |
} |
intel->tnl_pipeline_running = true; |
_tnl_run_pipeline(ctx); |
intel->tnl_pipeline_running = false; |
_mesa_unlock_context_textures(ctx); |
} |
static void |
intelRenderStart(struct gl_context * ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
intel_check_front_buffer_rendering(intel); |
intel->vtbl.render_start(intel_context(ctx)); |
intel->vtbl.emit_state(intel); |
} |
static void |
intelRenderFinish(struct gl_context * ctx) |
{ |
struct intel_context *intel = intel_context(ctx); |
if (intel->RenderIndex & INTEL_FALLBACK_BIT) |
_swrast_flush(ctx); |
INTEL_FIREVERTICES(intel); |
} |
/* System to flush dma and emit state changes based on the rasterized |
* primitive. |
*/ |
static void |
intelRasterPrimitive(struct gl_context * ctx, GLenum rprim, GLuint hwprim) |
{ |
struct intel_context *intel = intel_context(ctx); |
if (0) |
fprintf(stderr, "%s %s %x\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(rprim), hwprim); |
intel->vtbl.reduced_primitive_state(intel, rprim); |
/* Start a new primitive. Arrange to have it flushed later on. |
*/ |
if (hwprim != intel->prim.primitive) { |
INTEL_FIREVERTICES(intel); |
intel_set_prim(intel, hwprim); |
} |
} |
/* |
*/ |
static void |
intelRenderPrimitive(struct gl_context * ctx, GLenum prim) |
{ |
struct intel_context *intel = intel_context(ctx); |
GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL); |
if (0) |
fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim)); |
/* Let some clipping routines know which primitive they're dealing |
* with. |
*/ |
intel->render_primitive = prim; |
/* Shortcircuit this when called for unfilled triangles. The rasterized |
* primitive will always be reset by lower level functions in that case, |
* potentially pingponging the state: |
*/ |
if (reduced_prim[prim] == GL_TRIANGLES && unfilled) |
return; |
/* Set some primitive-dependent state and Start? a new primitive. |
*/ |
intelRasterPrimitive(ctx, reduced_prim[prim], hw_prim[prim]); |
} |
/**********************************************************************/ |
/* Transition to/from hardware rasterization. */ |
/**********************************************************************/ |
static char *fallbackStrings[] = { |
[0] = "Draw buffer", |
[1] = "Read buffer", |
[2] = "Depth buffer", |
[3] = "Stencil buffer", |
[4] = "User disable", |
[5] = "Render mode", |
[12] = "Texture", |
[13] = "Color mask", |
[14] = "Stencil", |
[15] = "Stipple", |
[16] = "Program", |
[17] = "Logic op", |
[18] = "Smooth polygon", |
[19] = "Smooth point", |
[20] = "point sprite coord origin", |
[21] = "depth/color drawing offset", |
[22] = "coord replace(SPRITE POINT ENABLE)", |
}; |
static char * |
getFallbackString(GLuint bit) |
{ |
int i = 0; |
while (bit > 1) { |
i++; |
bit >>= 1; |
} |
return fallbackStrings[i]; |
} |
/** |
* Enable/disable a fallback flag. |
* \param bit one of INTEL_FALLBACK_x flags. |
*/ |
void |
intelFallback(struct intel_context *intel, GLbitfield bit, bool mode) |
{ |
struct gl_context *ctx = &intel->ctx; |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
const GLbitfield oldfallback = intel->Fallback; |
if (mode) { |
intel->Fallback |= bit; |
if (oldfallback == 0) { |
assert(!intel->tnl_pipeline_running); |
intel_flush(ctx); |
if (INTEL_DEBUG & DEBUG_PERF) |
fprintf(stderr, "ENTER FALLBACK %x: %s\n", |
bit, getFallbackString(bit)); |
_swsetup_Wakeup(ctx); |
intel->RenderIndex = ~0; |
} |
} |
else { |
intel->Fallback &= ~bit; |
if (oldfallback == bit) { |
assert(!intel->tnl_pipeline_running); |
_swrast_flush(ctx); |
if (INTEL_DEBUG & DEBUG_PERF) |
fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString(bit)); |
tnl->Driver.Render.Start = intelRenderStart; |
tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive; |
tnl->Driver.Render.Finish = intelRenderFinish; |
tnl->Driver.Render.BuildVertices = _tnl_build_vertices; |
tnl->Driver.Render.CopyPV = _tnl_copy_pv; |
tnl->Driver.Render.Interp = _tnl_interp; |
_tnl_invalidate_vertex_state(ctx, ~0); |
_tnl_invalidate_vertices(ctx, ~0); |
_tnl_install_attrs(ctx, |
intel->vertex_attrs, |
intel->vertex_attr_count, |
intel->ViewportMatrix.m, 0); |
intel->NewGLState |= _INTEL_NEW_RENDERSTATE; |
} |
} |
} |
union fi |
{ |
GLfloat f; |
GLint i; |
}; |
/**********************************************************************/ |
/* Initialization. */ |
/**********************************************************************/ |
void |
intelInitTriFuncs(struct gl_context * ctx) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
static int firsttime = 1; |
if (firsttime) { |
init_rast_tab(); |
firsttime = 0; |
} |
tnl->Driver.RunPipeline = intelRunPipeline; |
tnl->Driver.Render.Start = intelRenderStart; |
tnl->Driver.Render.Finish = intelRenderFinish; |
tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive; |
tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; |
tnl->Driver.Render.BuildVertices = _tnl_build_vertices; |
tnl->Driver.Render.CopyPV = _tnl_copy_pv; |
tnl->Driver.Render.Interp = _tnl_interp; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i915/intel_tris.h |
---|
0,0 → 1,52 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTELTRIS_INC |
#define INTELTRIS_INC |
#include "main/mtypes.h" |
#define INTEL_VB_SIZE (32 * 1024) |
/** 3 dwords of state_immediate and 2 of 3dprim, in intel_flush_prim */ |
#define INTEL_PRIM_EMIT_SIZE (5 * 4) |
#define _INTEL_NEW_RENDERSTATE (_NEW_LINE | \ |
_NEW_POLYGON | \ |
_NEW_LIGHT | \ |
_NEW_PROGRAM | \ |
_NEW_POLYGONSTIPPLE) |
extern void intelInitTriFuncs(struct gl_context * ctx); |
extern void intelChooseRenderState(struct gl_context * ctx); |
void intel_set_prim(struct intel_context *intel, uint32_t prim); |
GLuint *intel_get_prim_space(struct intel_context *intel, unsigned int count); |
void intel_flush_prim(struct intel_context *intel); |
void intel_finish_vb(struct intel_context *intel); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/Android.mk |
---|
0,0 → 1,57 |
# |
# Copyright (C) 2011 Intel Corporation |
# Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com> |
# Copyright (C) 2010-2011 LunarG |
# |
# 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) |
include $(CLEAR_VARS) |
LOCAL_MODULE := i965_dri |
LOCAL_MODULE_PATH := $(MESA_DRI_MODULE_PATH) |
LOCAL_UNSTRIPPED_PATH := $(MESA_DRI_MODULE_UNSTRIPPED_PATH) |
# Import variables i965_*. |
include $(LOCAL_PATH)/Makefile.sources |
LOCAL_CFLAGS := \ |
$(MESA_DRI_CFLAGS) |
LOCAL_C_INCLUDES := \ |
$(i965_INCLUDES) \ |
$(MESA_DRI_C_INCLUDES) \ |
$(DRM_TOP)/intel |
LOCAL_SRC_FILES := \ |
$(i965_FILES) |
LOCAL_WHOLE_STATIC_LIBRARIES := \ |
$(MESA_DRI_WHOLE_STATIC_LIBRARIES) |
LOCAL_SHARED_LIBRARIES := \ |
$(MESA_DRI_SHARED_LIBRARIES) \ |
libdrm_intel |
LOCAL_GENERATED_SOURCES := \ |
$(MESA_DRI_OPTIONS_H) |
include $(MESA_COMMON_MK) |
include $(BUILD_SHARED_LIBRARY) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/Makefile.am |
---|
0,0 → 1,99 |
# Copyright © 2011 Intel Corporation |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
# copy of this software and associated documentation files (the "Software"), |
# to deal in the Software without restriction, including without limitation |
# the rights to use, copy, modify, merge, publish, distribute, sublicense, |
# and/or sell copies of the Software, and to permit persons to whom the |
# Software is furnished to do so, subject to the following conditions: |
# |
# The above copyright notice and this permission notice (including the next |
# paragraph) shall be included in all copies or substantial portions of the |
# Software. |
# |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
# IN THE SOFTWARE. |
include Makefile.sources |
if HAVE_I965_DRI |
AM_CFLAGS = \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
-I$(top_srcdir)/src/mesa/drivers/dri/common \ |
-I$(top_srcdir)/src/mesa/drivers/dri/intel/server \ |
-I$(top_srcdir)/src/gtest/include \ |
-I$(top_builddir)/src/mesa/drivers/dri/common \ |
$(DEFINES) \ |
$(VISIBILITY_CFLAGS) \ |
$(INTEL_CFLAGS) |
if HAVE_OPENGL_ES1 |
AM_CFLAGS += \ |
-DFEATURE_ES1=1 |
endif |
if HAVE_OPENGL_ES2 |
AM_CFLAGS += \ |
-DFEATURE_ES2=1 |
endif |
AM_CXXFLAGS = $(AM_CFLAGS) |
dridir = $(DRI_DRIVER_INSTALL_DIR) |
noinst_LTLIBRARIES = libi965_dri.la |
dri_LTLIBRARIES = i965_dri.la |
libi965_dri_la_SOURCES = $(i965_FILES) |
# list of libs to be linked against by i965_dri.so and i965 test programs. |
COMMON_LIBS = \ |
libi965_dri.la \ |
../common/libdricommon.la \ |
$(DRI_LIB_DEPS) \ |
$(INTEL_LIBS) |
TEST_LIBS = \ |
$(COMMON_LIBS) \ |
-lrt \ |
../common/libdri_test_stubs.la |
i965_dri_la_SOURCES = |
nodist_EXTRA_i965_dri_la_SOURCES = dummy2.cpp |
i965_dri_la_LIBADD = $(COMMON_LIBS) |
i965_dri_la_LDFLAGS = -module -avoid-version -shared |
TESTS = \ |
test_eu_compact \ |
test_vec4_register_coalesce |
check_PROGRAMS = $(TESTS) |
test_vec4_register_coalesce_SOURCES = \ |
test_vec4_register_coalesce.cpp |
test_vec4_register_coalesce_LDADD = \ |
$(TEST_LIBS) \ |
$(top_builddir)/src/gtest/libgtest.la |
test_eu_compact_SOURCES = \ |
test_eu_compact.c |
nodist_EXTRA_test_eu_compact_SOURCES = dummy.cpp |
test_eu_compact_LDADD = $(TEST_LIBS) |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
all-local: i965_dri.la |
$(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
ln -f .libs/i965_dri.so $(top_builddir)/$(LIB_DIR)/i965_dri.so; |
endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/Makefile.in |
---|
0,0 → 1,1673 |
# 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 © 2011 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 = $(srcdir)/Makefile.sources $(srcdir)/Makefile.in \ |
$(srcdir)/Makefile.am $(top_srcdir)/bin/depcomp \ |
$(top_srcdir)/bin/test-driver |
@HAVE_I965_DRI_TRUE@@HAVE_OPENGL_ES1_TRUE@am__append_1 = \ |
@HAVE_I965_DRI_TRUE@@HAVE_OPENGL_ES1_TRUE@ -DFEATURE_ES1=1 |
@HAVE_I965_DRI_TRUE@@HAVE_OPENGL_ES2_TRUE@am__append_2 = \ |
@HAVE_I965_DRI_TRUE@@HAVE_OPENGL_ES2_TRUE@ -DFEATURE_ES2=1 |
@HAVE_I965_DRI_TRUE@TESTS = test_eu_compact$(EXEEXT) \ |
@HAVE_I965_DRI_TRUE@ test_vec4_register_coalesce$(EXEEXT) |
@HAVE_I965_DRI_TRUE@check_PROGRAMS = $(am__EXEEXT_1) |
subdir = src/mesa/drivers/dri/i965 |
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 = |
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; |
am__vpath_adj = case $$p in \ |
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |
*) f=$$p;; \ |
esac; |
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; |
am__install_max = 40 |
am__nobase_strip_setup = \ |
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` |
am__nobase_strip = \ |
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" |
am__nobase_list = $(am__nobase_strip_setup); \ |
for p in $$list; do echo "$$p $$p"; done | \ |
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ |
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ |
if (++n[$$2] == $(am__install_max)) \ |
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ |
END { for (dir in files) print dir, files[dir] }' |
am__base_list = \ |
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ |
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' |
am__uninstall_files_from_dir = { \ |
test -z "$$files" \ |
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ |
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \ |
$(am__cd) "$$dir" && rm -f $$files; }; \ |
} |
am__installdirs = "$(DESTDIR)$(dridir)" |
LTLIBRARIES = $(dri_LTLIBRARIES) $(noinst_LTLIBRARIES) |
am__DEPENDENCIES_1 = |
@HAVE_I965_DRI_TRUE@am__DEPENDENCIES_2 = libi965_dri.la \ |
@HAVE_I965_DRI_TRUE@ ../common/libdricommon.la \ |
@HAVE_I965_DRI_TRUE@ $(am__DEPENDENCIES_1) \ |
@HAVE_I965_DRI_TRUE@ $(am__DEPENDENCIES_1) |
@HAVE_I965_DRI_TRUE@i965_dri_la_DEPENDENCIES = $(am__DEPENDENCIES_2) |
am_i965_dri_la_OBJECTS = |
i965_dri_la_OBJECTS = $(am_i965_dri_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 = |
i965_dri_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ |
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ |
$(CXXFLAGS) $(i965_dri_la_LDFLAGS) $(LDFLAGS) -o $@ |
@HAVE_I965_DRI_TRUE@am_i965_dri_la_rpath = -rpath $(dridir) |
libi965_dri_la_LIBADD = |
am__libi965_dri_la_SOURCES_DIST = intel_batchbuffer.c intel_blit.c \ |
intel_buffer_objects.c intel_buffers.c intel_context.c \ |
intel_extensions.c intel_fbo.c intel_mipmap_tree.c \ |
intel_regions.c intel_resolve_map.c intel_screen.c \ |
intel_pixel.c intel_pixel_bitmap.c intel_pixel_copy.c \ |
intel_pixel_draw.c intel_pixel_read.c intel_state.c \ |
intel_syncobj.c intel_tex.c intel_tex_copy.c intel_tex_image.c \ |
intel_tex_subimage.c intel_tex_validate.c brw_blorp.cpp \ |
brw_blorp_blit.cpp brw_blorp_clear.cpp brw_cc.c brw_cfg.cpp \ |
brw_clear.c brw_clip.c brw_clip_line.c brw_clip_point.c \ |
brw_clip_state.c brw_clip_tri.c brw_clip_unfilled.c \ |
brw_clip_util.c brw_context.c brw_cubemap_normalize.cpp \ |
brw_curbe.c brw_disasm.c brw_draw.c brw_draw_upload.c brw_eu.c \ |
brw_eu_compact.c brw_eu_emit.c brw_eu_util.c brw_fs.cpp \ |
brw_fs_channel_expressions.cpp brw_fs_copy_propagation.cpp \ |
brw_fs_cse.cpp brw_fs_emit.cpp brw_fs_fp.cpp \ |
brw_fs_live_variables.cpp brw_fs_reg_allocate.cpp \ |
brw_fs_vector_splitting.cpp brw_fs_visitor.cpp brw_gs.c \ |
brw_gs_emit.c brw_gs_state.c brw_lower_texture_gradients.cpp \ |
brw_misc_state.c brw_program.c brw_primitive_restart.c \ |
brw_queryobj.c brw_schedule_instructions.cpp brw_sf.c \ |
brw_sf_emit.c brw_sf_state.c brw_shader.cpp brw_state_batch.c \ |
brw_state_cache.c brw_state_dump.c brw_state_upload.c \ |
brw_surface_formats.c brw_tex.c brw_tex_layout.c brw_urb.c \ |
brw_util.c brw_vec4.cpp brw_vec4_copy_propagation.cpp \ |
brw_vec4_emit.cpp brw_vec4_live_variables.cpp \ |
brw_vec4_reg_allocate.cpp brw_vec4_visitor.cpp brw_vec4_vp.cpp \ |
brw_vs.c brw_vs_state.c brw_vs_surface_state.c brw_vtbl.c \ |
brw_wm.c brw_wm_iz.cpp brw_wm_sampler_state.c brw_wm_state.c \ |
brw_wm_surface_state.c gen6_blorp.cpp gen6_cc.c \ |
gen6_clip_state.c gen6_depthstencil.c gen6_gs_state.c \ |
gen6_multisample_state.c gen6_queryobj.c gen6_sampler_state.c \ |
gen6_scissor_state.c gen6_sf_state.c gen6_sol.c gen6_urb.c \ |
gen6_viewport_state.c gen6_vs_state.c gen6_wm_state.c \ |
gen7_blorp.cpp gen7_clip_state.c gen7_disable.c \ |
gen7_misc_state.c gen7_sampler_state.c gen7_sf_state.c \ |
gen7_sol_state.c gen7_urb.c gen7_viewport_state.c \ |
gen7_vs_state.c gen7_wm_state.c gen7_wm_surface_state.c |
am__objects_1 = intel_batchbuffer.lo intel_blit.lo \ |
intel_buffer_objects.lo intel_buffers.lo intel_context.lo \ |
intel_extensions.lo intel_fbo.lo intel_mipmap_tree.lo \ |
intel_regions.lo intel_resolve_map.lo intel_screen.lo \ |
intel_pixel.lo intel_pixel_bitmap.lo intel_pixel_copy.lo \ |
intel_pixel_draw.lo intel_pixel_read.lo intel_state.lo \ |
intel_syncobj.lo intel_tex.lo intel_tex_copy.lo \ |
intel_tex_image.lo intel_tex_subimage.lo intel_tex_validate.lo \ |
brw_blorp.lo brw_blorp_blit.lo brw_blorp_clear.lo brw_cc.lo \ |
brw_cfg.lo brw_clear.lo brw_clip.lo brw_clip_line.lo \ |
brw_clip_point.lo brw_clip_state.lo brw_clip_tri.lo \ |
brw_clip_unfilled.lo brw_clip_util.lo brw_context.lo \ |
brw_cubemap_normalize.lo brw_curbe.lo brw_disasm.lo \ |
brw_draw.lo brw_draw_upload.lo brw_eu.lo brw_eu_compact.lo \ |
brw_eu_emit.lo brw_eu_util.lo brw_fs.lo \ |
brw_fs_channel_expressions.lo brw_fs_copy_propagation.lo \ |
brw_fs_cse.lo brw_fs_emit.lo brw_fs_fp.lo \ |
brw_fs_live_variables.lo brw_fs_reg_allocate.lo \ |
brw_fs_vector_splitting.lo brw_fs_visitor.lo brw_gs.lo \ |
brw_gs_emit.lo brw_gs_state.lo brw_lower_texture_gradients.lo \ |
brw_misc_state.lo brw_program.lo brw_primitive_restart.lo \ |
brw_queryobj.lo brw_schedule_instructions.lo brw_sf.lo \ |
brw_sf_emit.lo brw_sf_state.lo brw_shader.lo \ |
brw_state_batch.lo brw_state_cache.lo brw_state_dump.lo \ |
brw_state_upload.lo brw_surface_formats.lo brw_tex.lo \ |
brw_tex_layout.lo brw_urb.lo brw_util.lo brw_vec4.lo \ |
brw_vec4_copy_propagation.lo brw_vec4_emit.lo \ |
brw_vec4_live_variables.lo brw_vec4_reg_allocate.lo \ |
brw_vec4_visitor.lo brw_vec4_vp.lo brw_vs.lo brw_vs_state.lo \ |
brw_vs_surface_state.lo brw_vtbl.lo brw_wm.lo brw_wm_iz.lo \ |
brw_wm_sampler_state.lo brw_wm_state.lo \ |
brw_wm_surface_state.lo gen6_blorp.lo gen6_cc.lo \ |
gen6_clip_state.lo gen6_depthstencil.lo gen6_gs_state.lo \ |
gen6_multisample_state.lo gen6_queryobj.lo \ |
gen6_sampler_state.lo gen6_scissor_state.lo gen6_sf_state.lo \ |
gen6_sol.lo gen6_urb.lo gen6_viewport_state.lo \ |
gen6_vs_state.lo gen6_wm_state.lo gen7_blorp.lo \ |
gen7_clip_state.lo gen7_disable.lo gen7_misc_state.lo \ |
gen7_sampler_state.lo gen7_sf_state.lo gen7_sol_state.lo \ |
gen7_urb.lo gen7_viewport_state.lo gen7_vs_state.lo \ |
gen7_wm_state.lo gen7_wm_surface_state.lo |
@HAVE_I965_DRI_TRUE@am_libi965_dri_la_OBJECTS = $(am__objects_1) |
libi965_dri_la_OBJECTS = $(am_libi965_dri_la_OBJECTS) |
@HAVE_I965_DRI_TRUE@am_libi965_dri_la_rpath = |
@HAVE_I965_DRI_TRUE@am__EXEEXT_1 = test_eu_compact$(EXEEXT) \ |
@HAVE_I965_DRI_TRUE@ test_vec4_register_coalesce$(EXEEXT) |
am__test_eu_compact_SOURCES_DIST = test_eu_compact.c |
@HAVE_I965_DRI_TRUE@am_test_eu_compact_OBJECTS = \ |
@HAVE_I965_DRI_TRUE@ test_eu_compact.$(OBJEXT) |
test_eu_compact_OBJECTS = $(am_test_eu_compact_OBJECTS) |
@HAVE_I965_DRI_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2) \ |
@HAVE_I965_DRI_TRUE@ ../common/libdri_test_stubs.la |
@HAVE_I965_DRI_TRUE@test_eu_compact_DEPENDENCIES = \ |
@HAVE_I965_DRI_TRUE@ $(am__DEPENDENCIES_3) |
am__test_vec4_register_coalesce_SOURCES_DIST = \ |
test_vec4_register_coalesce.cpp |
@HAVE_I965_DRI_TRUE@am_test_vec4_register_coalesce_OBJECTS = \ |
@HAVE_I965_DRI_TRUE@ test_vec4_register_coalesce.$(OBJEXT) |
test_vec4_register_coalesce_OBJECTS = \ |
$(am_test_vec4_register_coalesce_OBJECTS) |
@HAVE_I965_DRI_TRUE@test_vec4_register_coalesce_DEPENDENCIES = \ |
@HAVE_I965_DRI_TRUE@ $(am__DEPENDENCIES_3) \ |
@HAVE_I965_DRI_TRUE@ $(top_builddir)/src/gtest/libgtest.la |
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 = |
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ |
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) |
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ |
$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ |
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ |
$(AM_CXXFLAGS) $(CXXFLAGS) |
AM_V_CXX = $(am__v_CXX_@AM_V@) |
am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) |
am__v_CXX_0 = @echo " CXX " $@; |
am__v_CXX_1 = |
CXXLD = $(CXX) |
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ |
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ |
$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ |
AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) |
am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) |
am__v_CXXLD_0 = @echo " CXXLD " $@; |
am__v_CXXLD_1 = |
SOURCES = $(i965_dri_la_SOURCES) $(nodist_EXTRA_i965_dri_la_SOURCES) \ |
$(libi965_dri_la_SOURCES) $(test_eu_compact_SOURCES) \ |
$(nodist_EXTRA_test_eu_compact_SOURCES) \ |
$(test_vec4_register_coalesce_SOURCES) |
DIST_SOURCES = $(i965_dri_la_SOURCES) \ |
$(am__libi965_dri_la_SOURCES_DIST) \ |
$(am__test_eu_compact_SOURCES_DIST) \ |
$(am__test_vec4_register_coalesce_SOURCES_DIST) |
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 |
am__tty_colors_dummy = \ |
mgn= red= grn= lgn= blu= brg= std=; \ |
am__color_tests=no |
am__tty_colors = { \ |
$(am__tty_colors_dummy); \ |
if test "X$(AM_COLOR_TESTS)" = Xno; then \ |
am__color_tests=no; \ |
elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ |
am__color_tests=yes; \ |
elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ |
am__color_tests=yes; \ |
fi; \ |
if test $$am__color_tests = yes; then \ |
red='[0;31m'; \ |
grn='[0;32m'; \ |
lgn='[1;32m'; \ |
blu='[1;34m'; \ |
mgn='[0;35m'; \ |
brg='[1m'; \ |
std='[m'; \ |
fi; \ |
} |
am__recheck_rx = ^[ ]*:recheck:[ ]* |
am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* |
am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* |
# A command that, given a newline-separated list of test names on the |
# standard input, print the name of the tests that are to be re-run |
# upon "make recheck". |
am__list_recheck_tests = $(AWK) '{ \ |
recheck = 1; \ |
while ((rc = (getline line < ($$0 ".trs"))) != 0) \ |
{ \ |
if (rc < 0) \ |
{ \ |
if ((getline line2 < ($$0 ".log")) < 0) \ |
recheck = 0; \ |
break; \ |
} \ |
else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ |
{ \ |
recheck = 0; \ |
break; \ |
} \ |
else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ |
{ \ |
break; \ |
} \ |
}; \ |
if (recheck) \ |
print $$0; \ |
close ($$0 ".trs"); \ |
close ($$0 ".log"); \ |
}' |
# A command that, given a newline-separated list of test names on the |
# standard input, create the global log from their .trs and .log files. |
am__create_global_log = $(AWK) ' \ |
function fatal(msg) \ |
{ \ |
print "fatal: making $@: " msg | "cat >&2"; \ |
exit 1; \ |
} \ |
function rst_section(header) \ |
{ \ |
print header; \ |
len = length(header); \ |
for (i = 1; i <= len; i = i + 1) \ |
printf "="; \ |
printf "\n\n"; \ |
} \ |
{ \ |
copy_in_global_log = 1; \ |
global_test_result = "RUN"; \ |
while ((rc = (getline line < ($$0 ".trs"))) != 0) \ |
{ \ |
if (rc < 0) \ |
fatal("failed to read from " $$0 ".trs"); \ |
if (line ~ /$(am__global_test_result_rx)/) \ |
{ \ |
sub("$(am__global_test_result_rx)", "", line); \ |
sub("[ ]*$$", "", line); \ |
global_test_result = line; \ |
} \ |
else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ |
copy_in_global_log = 0; \ |
}; \ |
if (copy_in_global_log) \ |
{ \ |
rst_section(global_test_result ": " $$0); \ |
while ((rc = (getline line < ($$0 ".log"))) != 0) \ |
{ \ |
if (rc < 0) \ |
fatal("failed to read from " $$0 ".log"); \ |
print line; \ |
}; \ |
printf "\n"; \ |
}; \ |
close ($$0 ".trs"); \ |
close ($$0 ".log"); \ |
}' |
# Restructured Text title. |
am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } |
# Solaris 10 'make', and several other traditional 'make' implementations, |
# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it |
# by disabling -e (using the XSI extension "set +e") if it's set. |
am__sh_e_setup = case $$- in *e*) set +e;; esac |
# Default flags passed to test drivers. |
am__common_driver_flags = \ |
--color-tests "$$am__color_tests" \ |
--enable-hard-errors "$$am__enable_hard_errors" \ |
--expect-failure "$$am__expect_failure" |
# To be inserted before the command running the test. Creates the |
# directory for the log if needed. Stores in $dir the directory |
# containing $f, in $tst the test, in $log the log. Executes the |
# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and |
# passes TESTS_ENVIRONMENT. Set up options for the wrapper that |
# will run the test scripts (or their associated LOG_COMPILER, if |
# thy have one). |
am__check_pre = \ |
$(am__sh_e_setup); \ |
$(am__vpath_adj_setup) $(am__vpath_adj) \ |
$(am__tty_colors); \ |
srcdir=$(srcdir); export srcdir; \ |
case "$@" in \ |
*/*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ |
*) am__odir=.;; \ |
esac; \ |
test "x$$am__odir" = x"." || test -d "$$am__odir" \ |
|| $(MKDIR_P) "$$am__odir" || exit $$?; \ |
if test -f "./$$f"; then dir=./; \ |
elif test -f "$$f"; then dir=; \ |
else dir="$(srcdir)/"; fi; \ |
tst=$$dir$$f; log='$@'; \ |
if test -n '$(DISABLE_HARD_ERRORS)'; then \ |
am__enable_hard_errors=no; \ |
else \ |
am__enable_hard_errors=yes; \ |
fi; \ |
case " $(XFAIL_TESTS) " in \ |
*[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ |
am__expect_failure=yes;; \ |
*) \ |
am__expect_failure=no;; \ |
esac; \ |
$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) |
# A shell command to get the names of the tests scripts with any registered |
# extension removed (i.e., equivalently, the names of the test logs, with |
# the '.log' extension removed). The result is saved in the shell variable |
# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, |
# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", |
# since that might cause problem with VPATH rewrites for suffix-less tests. |
# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. |
am__set_TESTS_bases = \ |
bases='$(TEST_LOGS)'; \ |
bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ |
bases=`echo $$bases` |
RECHECK_LOGS = $(TEST_LOGS) |
AM_RECURSIVE_TARGETS = check recheck |
TEST_SUITE_LOG = test-suite.log |
TEST_EXTENSIONS = @EXEEXT@ .test |
LOG_DRIVER = $(SHELL) $(top_srcdir)/bin/test-driver |
LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) |
am__set_b = \ |
case '$@' in \ |
*/*) \ |
case '$*' in \ |
*/*) b='$*';; \ |
*) b=`echo '$@' | sed 's/\.log$$//'`; \ |
esac;; \ |
*) \ |
b='$*';; \ |
esac |
am__test_logs1 = $(TESTS:=.log) |
am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) |
TEST_LOGS = $(am__test_logs2:.test.log=.log) |
TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/bin/test-driver |
TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ |
$(TEST_LOG_FLAGS) |
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@ |
i965_INCLUDES = \ |
$(MESA_TOP)/src \ |
$(MESA_TOP)/src/mesa/drivers/dri/intel |
i965_FILES = \ |
intel_batchbuffer.c \ |
intel_blit.c \ |
intel_buffer_objects.c \ |
intel_buffers.c \ |
intel_context.c \ |
intel_extensions.c \ |
intel_fbo.c \ |
intel_mipmap_tree.c \ |
intel_regions.c \ |
intel_resolve_map.c \ |
intel_screen.c \ |
intel_pixel.c \ |
intel_pixel_bitmap.c \ |
intel_pixel_copy.c \ |
intel_pixel_draw.c \ |
intel_pixel_read.c \ |
intel_state.c \ |
intel_syncobj.c \ |
intel_tex.c \ |
intel_tex_copy.c \ |
intel_tex_image.c \ |
intel_tex_subimage.c \ |
intel_tex_validate.c \ |
brw_blorp.cpp \ |
brw_blorp_blit.cpp \ |
brw_blorp_clear.cpp \ |
brw_cc.c \ |
brw_cfg.cpp \ |
brw_clear.c \ |
brw_clip.c \ |
brw_clip_line.c \ |
brw_clip_point.c \ |
brw_clip_state.c \ |
brw_clip_tri.c \ |
brw_clip_unfilled.c \ |
brw_clip_util.c \ |
brw_context.c \ |
brw_cubemap_normalize.cpp \ |
brw_curbe.c \ |
brw_disasm.c \ |
brw_draw.c \ |
brw_draw_upload.c \ |
brw_eu.c \ |
brw_eu_compact.c \ |
brw_eu_emit.c \ |
brw_eu_util.c \ |
brw_fs.cpp \ |
brw_fs_channel_expressions.cpp \ |
brw_fs_copy_propagation.cpp \ |
brw_fs_cse.cpp \ |
brw_fs_emit.cpp \ |
brw_fs_fp.cpp \ |
brw_fs_live_variables.cpp \ |
brw_fs_reg_allocate.cpp \ |
brw_fs_vector_splitting.cpp \ |
brw_fs_visitor.cpp \ |
brw_gs.c \ |
brw_gs_emit.c \ |
brw_gs_state.c \ |
brw_lower_texture_gradients.cpp \ |
brw_misc_state.c \ |
brw_program.c \ |
brw_primitive_restart.c \ |
brw_queryobj.c \ |
brw_schedule_instructions.cpp \ |
brw_sf.c \ |
brw_sf_emit.c \ |
brw_sf_state.c \ |
brw_shader.cpp \ |
brw_state_batch.c \ |
brw_state_cache.c \ |
brw_state_dump.c \ |
brw_state_upload.c \ |
brw_surface_formats.c \ |
brw_tex.c \ |
brw_tex_layout.c \ |
brw_urb.c \ |
brw_util.c \ |
brw_vec4.cpp \ |
brw_vec4_copy_propagation.cpp \ |
brw_vec4_emit.cpp \ |
brw_vec4_live_variables.cpp \ |
brw_vec4_reg_allocate.cpp \ |
brw_vec4_visitor.cpp \ |
brw_vec4_vp.cpp \ |
brw_vs.c \ |
brw_vs_state.c \ |
brw_vs_surface_state.c \ |
brw_vtbl.c \ |
brw_wm.c \ |
brw_wm_iz.cpp \ |
brw_wm_sampler_state.c \ |
brw_wm_state.c \ |
brw_wm_surface_state.c \ |
gen6_blorp.cpp \ |
gen6_cc.c \ |
gen6_clip_state.c \ |
gen6_depthstencil.c \ |
gen6_gs_state.c \ |
gen6_multisample_state.c \ |
gen6_queryobj.c \ |
gen6_sampler_state.c \ |
gen6_scissor_state.c \ |
gen6_sf_state.c \ |
gen6_sol.c \ |
gen6_urb.c \ |
gen6_viewport_state.c \ |
gen6_vs_state.c \ |
gen6_wm_state.c \ |
gen7_blorp.cpp \ |
gen7_clip_state.c \ |
gen7_disable.c \ |
gen7_misc_state.c \ |
gen7_sampler_state.c \ |
gen7_sf_state.c \ |
gen7_sol_state.c \ |
gen7_urb.c \ |
gen7_viewport_state.c \ |
gen7_vs_state.c \ |
gen7_wm_state.c \ |
gen7_wm_surface_state.c \ |
$() |
@HAVE_I965_DRI_TRUE@AM_CFLAGS = -I$(top_srcdir)/include \ |
@HAVE_I965_DRI_TRUE@ -I$(top_srcdir)/src/ \ |
@HAVE_I965_DRI_TRUE@ -I$(top_srcdir)/src/mapi \ |
@HAVE_I965_DRI_TRUE@ -I$(top_srcdir)/src/mesa/ \ |
@HAVE_I965_DRI_TRUE@ -I$(top_srcdir)/src/mesa/drivers/dri/common \ |
@HAVE_I965_DRI_TRUE@ -I$(top_srcdir)/src/mesa/drivers/dri/intel/server \ |
@HAVE_I965_DRI_TRUE@ -I$(top_srcdir)/src/gtest/include \ |
@HAVE_I965_DRI_TRUE@ -I$(top_builddir)/src/mesa/drivers/dri/common \ |
@HAVE_I965_DRI_TRUE@ $(DEFINES) $(VISIBILITY_CFLAGS) \ |
@HAVE_I965_DRI_TRUE@ $(INTEL_CFLAGS) $(am__append_1) \ |
@HAVE_I965_DRI_TRUE@ $(am__append_2) |
@HAVE_I965_DRI_TRUE@AM_CXXFLAGS = $(AM_CFLAGS) |
@HAVE_I965_DRI_TRUE@dridir = $(DRI_DRIVER_INSTALL_DIR) |
@HAVE_I965_DRI_TRUE@noinst_LTLIBRARIES = libi965_dri.la |
@HAVE_I965_DRI_TRUE@dri_LTLIBRARIES = i965_dri.la |
@HAVE_I965_DRI_TRUE@libi965_dri_la_SOURCES = $(i965_FILES) |
# list of libs to be linked against by i965_dri.so and i965 test programs. |
@HAVE_I965_DRI_TRUE@COMMON_LIBS = \ |
@HAVE_I965_DRI_TRUE@ libi965_dri.la \ |
@HAVE_I965_DRI_TRUE@ ../common/libdricommon.la \ |
@HAVE_I965_DRI_TRUE@ $(DRI_LIB_DEPS) \ |
@HAVE_I965_DRI_TRUE@ $(INTEL_LIBS) |
@HAVE_I965_DRI_TRUE@TEST_LIBS = \ |
@HAVE_I965_DRI_TRUE@ $(COMMON_LIBS) \ |
@HAVE_I965_DRI_TRUE@ -lrt \ |
@HAVE_I965_DRI_TRUE@ ../common/libdri_test_stubs.la |
@HAVE_I965_DRI_TRUE@i965_dri_la_SOURCES = |
@HAVE_I965_DRI_TRUE@nodist_EXTRA_i965_dri_la_SOURCES = dummy2.cpp |
@HAVE_I965_DRI_TRUE@i965_dri_la_LIBADD = $(COMMON_LIBS) |
@HAVE_I965_DRI_TRUE@i965_dri_la_LDFLAGS = -module -avoid-version -shared |
@HAVE_I965_DRI_TRUE@test_vec4_register_coalesce_SOURCES = \ |
@HAVE_I965_DRI_TRUE@ test_vec4_register_coalesce.cpp |
@HAVE_I965_DRI_TRUE@test_vec4_register_coalesce_LDADD = \ |
@HAVE_I965_DRI_TRUE@ $(TEST_LIBS) \ |
@HAVE_I965_DRI_TRUE@ $(top_builddir)/src/gtest/libgtest.la |
@HAVE_I965_DRI_TRUE@test_eu_compact_SOURCES = \ |
@HAVE_I965_DRI_TRUE@ test_eu_compact.c |
@HAVE_I965_DRI_TRUE@nodist_EXTRA_test_eu_compact_SOURCES = dummy.cpp |
@HAVE_I965_DRI_TRUE@test_eu_compact_LDADD = $(TEST_LIBS) |
all: all-am |
.SUFFIXES: |
.SUFFIXES: .c .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(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/mesa/drivers/dri/i965/Makefile'; \ |
$(am__cd) $(top_srcdir) && \ |
$(AUTOMAKE) --foreign src/mesa/drivers/dri/i965/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; |
$(srcdir)/Makefile.sources: |
$(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): |
install-driLTLIBRARIES: $(dri_LTLIBRARIES) |
@$(NORMAL_INSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
list2=; for p in $$list; do \ |
if test -f $$p; then \ |
list2="$$list2 $$p"; \ |
else :; fi; \ |
done; \ |
test -z "$$list2" || { \ |
echo " $(MKDIR_P) '$(DESTDIR)$(dridir)'"; \ |
$(MKDIR_P) "$(DESTDIR)$(dridir)" || exit 1; \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(dridir)'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(dridir)"; \ |
} |
uninstall-driLTLIBRARIES: |
@$(NORMAL_UNINSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
for p in $$list; do \ |
$(am__strip_dir) \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(dridir)/$$f'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(dridir)/$$f"; \ |
done |
clean-driLTLIBRARIES: |
-test -z "$(dri_LTLIBRARIES)" || rm -f $(dri_LTLIBRARIES) |
@list='$(dri_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}; \ |
} |
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}; \ |
} |
i965_dri.la: $(i965_dri_la_OBJECTS) $(i965_dri_la_DEPENDENCIES) $(EXTRA_i965_dri_la_DEPENDENCIES) |
$(AM_V_CXXLD)$(i965_dri_la_LINK) $(am_i965_dri_la_rpath) $(i965_dri_la_OBJECTS) $(i965_dri_la_LIBADD) $(LIBS) |
libi965_dri.la: $(libi965_dri_la_OBJECTS) $(libi965_dri_la_DEPENDENCIES) $(EXTRA_libi965_dri_la_DEPENDENCIES) |
$(AM_V_CXXLD)$(CXXLINK) $(am_libi965_dri_la_rpath) $(libi965_dri_la_OBJECTS) $(libi965_dri_la_LIBADD) $(LIBS) |
clean-checkPROGRAMS: |
@list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ |
echo " rm -f" $$list; \ |
rm -f $$list || exit $$?; \ |
test -n "$(EXEEXT)" || exit 0; \ |
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ |
echo " rm -f" $$list; \ |
rm -f $$list |
test_eu_compact$(EXEEXT): $(test_eu_compact_OBJECTS) $(test_eu_compact_DEPENDENCIES) $(EXTRA_test_eu_compact_DEPENDENCIES) |
@rm -f test_eu_compact$(EXEEXT) |
$(AM_V_CXXLD)$(CXXLINK) $(test_eu_compact_OBJECTS) $(test_eu_compact_LDADD) $(LIBS) |
test_vec4_register_coalesce$(EXEEXT): $(test_vec4_register_coalesce_OBJECTS) $(test_vec4_register_coalesce_DEPENDENCIES) $(EXTRA_test_vec4_register_coalesce_DEPENDENCIES) |
@rm -f test_vec4_register_coalesce$(EXEEXT) |
$(AM_V_CXXLD)$(CXXLINK) $(test_vec4_register_coalesce_OBJECTS) $(test_vec4_register_coalesce_LDADD) $(LIBS) |
mostlyclean-compile: |
-rm -f *.$(OBJEXT) |
distclean-compile: |
-rm -f *.tab.c |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_blorp.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_blorp_blit.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_blorp_clear.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_cc.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_cfg.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_clear.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_clip.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_clip_line.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_clip_point.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_clip_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_clip_tri.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_clip_unfilled.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_clip_util.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_cubemap_normalize.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_curbe.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_disasm.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_draw.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_draw_upload.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_eu.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_eu_compact.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_eu_emit.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_eu_util.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_fs.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_fs_channel_expressions.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_fs_copy_propagation.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_fs_cse.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_fs_emit.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_fs_fp.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_fs_live_variables.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_fs_reg_allocate.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_fs_vector_splitting.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_fs_visitor.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_gs.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_gs_emit.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_gs_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_lower_texture_gradients.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_misc_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_primitive_restart.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_program.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_queryobj.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_schedule_instructions.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_sf.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_sf_emit.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_sf_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_shader.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_state_batch.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_state_cache.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_state_dump.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_state_upload.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_surface_formats.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_tex.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_tex_layout.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_urb.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_util.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_vec4.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_vec4_copy_propagation.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_vec4_emit.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_vec4_live_variables.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_vec4_reg_allocate.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_vec4_visitor.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_vec4_vp.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_vs.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_vs_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_vs_surface_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_vtbl.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_wm.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_wm_iz.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_wm_sampler_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_wm_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/brw_wm_surface_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dummy2.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_blorp.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_cc.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_clip_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_depthstencil.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_gs_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_multisample_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_queryobj.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_sampler_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_scissor_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_sf_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_sol.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_urb.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_viewport_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_vs_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen6_wm_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_blorp.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_clip_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_disable.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_misc_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_sampler_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_sf_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_sol_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_urb.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_viewport_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_vs_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_wm_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gen7_wm_surface_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_batchbuffer.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_blit.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_buffer_objects.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_buffers.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_extensions.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_fbo.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_mipmap_tree.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_pixel.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_pixel_bitmap.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_pixel_copy.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_pixel_draw.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_pixel_read.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_regions.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_resolve_map.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_screen.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_syncobj.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tex.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tex_copy.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tex_image.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tex_subimage.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intel_tex_validate.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_eu_compact.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_vec4_register_coalesce.Po@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 $@ $< |
.cpp.o: |
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< |
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po |
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< |
.cpp.obj: |
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` |
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po |
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` |
.cpp.lo: |
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< |
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo |
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -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 |
# Recover from deleted '.trs' file; this should ensure that |
# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create |
# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells |
# to avoid problems with "make -n". |
.log.trs: |
rm -f $< $@ |
$(MAKE) $(AM_MAKEFLAGS) $< |
# Leading 'am--fnord' is there to ensure the list of targets does not |
# expand to empty, as could happen e.g. with make check TESTS=''. |
am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) |
am--force-recheck: |
@: |
$(TEST_SUITE_LOG): $(TEST_LOGS) |
@$(am__set_TESTS_bases); \ |
am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ |
redo_bases=`for i in $$bases; do \ |
am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ |
done`; \ |
if test -n "$$redo_bases"; then \ |
redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ |
redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ |
if $(am__make_dryrun); then :; else \ |
rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ |
fi; \ |
fi; \ |
if test -n "$$am__remaking_logs"; then \ |
echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ |
"recursion detected" >&2; \ |
else \ |
am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ |
fi; \ |
if $(am__make_dryrun); then :; else \ |
st=0; \ |
errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ |
for i in $$redo_bases; do \ |
test -f $$i.trs && test -r $$i.trs \ |
|| { echo "$$errmsg $$i.trs" >&2; st=1; }; \ |
test -f $$i.log && test -r $$i.log \ |
|| { echo "$$errmsg $$i.log" >&2; st=1; }; \ |
done; \ |
test $$st -eq 0 || exit 1; \ |
fi |
@$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ |
ws='[ ]'; \ |
results=`for b in $$bases; do echo $$b.trs; done`; \ |
test -n "$$results" || results=/dev/null; \ |
all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ |
pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ |
fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ |
skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ |
xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ |
xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ |
error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ |
if test `expr $$fail + $$xpass + $$error` -eq 0; then \ |
success=true; \ |
else \ |
success=false; \ |
fi; \ |
br='==================='; br=$$br$$br$$br$$br; \ |
result_count () \ |
{ \ |
if test x"$$1" = x"--maybe-color"; then \ |
maybe_colorize=yes; \ |
elif test x"$$1" = x"--no-color"; then \ |
maybe_colorize=no; \ |
else \ |
echo "$@: invalid 'result_count' usage" >&2; exit 4; \ |
fi; \ |
shift; \ |
desc=$$1 count=$$2; \ |
if test $$maybe_colorize = yes && test $$count -gt 0; then \ |
color_start=$$3 color_end=$$std; \ |
else \ |
color_start= color_end=; \ |
fi; \ |
echo "$${color_start}# $$desc $$count$${color_end}"; \ |
}; \ |
create_testsuite_report () \ |
{ \ |
result_count $$1 "TOTAL:" $$all "$$brg"; \ |
result_count $$1 "PASS: " $$pass "$$grn"; \ |
result_count $$1 "SKIP: " $$skip "$$blu"; \ |
result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ |
result_count $$1 "FAIL: " $$fail "$$red"; \ |
result_count $$1 "XPASS:" $$xpass "$$red"; \ |
result_count $$1 "ERROR:" $$error "$$mgn"; \ |
}; \ |
{ \ |
echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ |
$(am__rst_title); \ |
create_testsuite_report --no-color; \ |
echo; \ |
echo ".. contents:: :depth: 2"; \ |
echo; \ |
for b in $$bases; do echo $$b; done \ |
| $(am__create_global_log); \ |
} >$(TEST_SUITE_LOG).tmp || exit 1; \ |
mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ |
if $$success; then \ |
col="$$grn"; \ |
else \ |
col="$$red"; \ |
test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ |
fi; \ |
echo "$${col}$$br$${std}"; \ |
echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ |
echo "$${col}$$br$${std}"; \ |
create_testsuite_report --maybe-color; \ |
echo "$$col$$br$$std"; \ |
if $$success; then :; else \ |
echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ |
if test -n "$(PACKAGE_BUGREPORT)"; then \ |
echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ |
fi; \ |
echo "$$col$$br$$std"; \ |
fi; \ |
$$success || exit 1 |
check-TESTS: |
@list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list |
@list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list |
@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) |
@set +e; $(am__set_TESTS_bases); \ |
log_list=`for i in $$bases; do echo $$i.log; done`; \ |
trs_list=`for i in $$bases; do echo $$i.trs; done`; \ |
log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ |
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ |
exit $$?; |
recheck: all $(check_PROGRAMS) |
@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) |
@set +e; $(am__set_TESTS_bases); \ |
bases=`for i in $$bases; do echo $$i; done \ |
| $(am__list_recheck_tests)` || exit 1; \ |
log_list=`for i in $$bases; do echo $$i.log; done`; \ |
log_list=`echo $$log_list`; \ |
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ |
am__force_recheck=am--force-recheck \ |
TEST_LOGS="$$log_list"; \ |
exit $$? |
test_eu_compact.log: test_eu_compact$(EXEEXT) |
@p='test_eu_compact$(EXEEXT)'; \ |
b='test_eu_compact'; \ |
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ |
--log-file $$b.log --trs-file $$b.trs \ |
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ |
"$$tst" $(AM_TESTS_FD_REDIRECT) |
test_vec4_register_coalesce.log: test_vec4_register_coalesce$(EXEEXT) |
@p='test_vec4_register_coalesce$(EXEEXT)'; \ |
b='test_vec4_register_coalesce'; \ |
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ |
--log-file $$b.log --trs-file $$b.trs \ |
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ |
"$$tst" $(AM_TESTS_FD_REDIRECT) |
.test.log: |
@p='$<'; \ |
$(am__set_b); \ |
$(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ |
--log-file $$b.log --trs-file $$b.trs \ |
$(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ |
"$$tst" $(AM_TESTS_FD_REDIRECT) |
@am__EXEEXT_TRUE@.test$(EXEEXT).log: |
@am__EXEEXT_TRUE@ @p='$<'; \ |
@am__EXEEXT_TRUE@ $(am__set_b); \ |
@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ |
@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ |
@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ |
@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) |
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 |
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) |
$(MAKE) $(AM_MAKEFLAGS) check-TESTS |
check: check-am |
@HAVE_I965_DRI_FALSE@all-local: |
all-am: Makefile $(LTLIBRARIES) all-local |
installdirs: |
for dir in "$(DESTDIR)$(dridir)"; do \ |
test -z "$$dir" || $(MKDIR_P) "$$dir"; \ |
done |
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: |
-test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) |
-test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) |
-test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) |
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-checkPROGRAMS clean-driLTLIBRARIES 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-driLTLIBRARIES |
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: uninstall-driLTLIBRARIES |
.MAKE: check-am install-am install-strip |
.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-TESTS \ |
check-am clean clean-checkPROGRAMS clean-driLTLIBRARIES \ |
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-driLTLIBRARIES \ |
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 recheck tags tags-am \ |
uninstall uninstall-am uninstall-driLTLIBRARIES |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
@HAVE_I965_DRI_TRUE@all-local: i965_dri.la |
@HAVE_I965_DRI_TRUE@ $(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
@HAVE_I965_DRI_TRUE@ ln -f .libs/i965_dri.so $(top_builddir)/$(LIB_DIR)/i965_dri.so; |
# 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/src/mesa/drivers/dri/i965/Makefile.sources |
---|
0,0 → 1,127 |
i965_INCLUDES = \ |
$(MESA_TOP)/src \ |
$(MESA_TOP)/src/mesa/drivers/dri/intel |
i965_FILES = \ |
intel_batchbuffer.c \ |
intel_blit.c \ |
intel_buffer_objects.c \ |
intel_buffers.c \ |
intel_context.c \ |
intel_extensions.c \ |
intel_fbo.c \ |
intel_mipmap_tree.c \ |
intel_regions.c \ |
intel_resolve_map.c \ |
intel_screen.c \ |
intel_pixel.c \ |
intel_pixel_bitmap.c \ |
intel_pixel_copy.c \ |
intel_pixel_draw.c \ |
intel_pixel_read.c \ |
intel_state.c \ |
intel_syncobj.c \ |
intel_tex.c \ |
intel_tex_copy.c \ |
intel_tex_image.c \ |
intel_tex_subimage.c \ |
intel_tex_validate.c \ |
brw_blorp.cpp \ |
brw_blorp_blit.cpp \ |
brw_blorp_clear.cpp \ |
brw_cc.c \ |
brw_cfg.cpp \ |
brw_clear.c \ |
brw_clip.c \ |
brw_clip_line.c \ |
brw_clip_point.c \ |
brw_clip_state.c \ |
brw_clip_tri.c \ |
brw_clip_unfilled.c \ |
brw_clip_util.c \ |
brw_context.c \ |
brw_cubemap_normalize.cpp \ |
brw_curbe.c \ |
brw_disasm.c \ |
brw_draw.c \ |
brw_draw_upload.c \ |
brw_eu.c \ |
brw_eu_compact.c \ |
brw_eu_emit.c \ |
brw_eu_util.c \ |
brw_fs.cpp \ |
brw_fs_channel_expressions.cpp \ |
brw_fs_copy_propagation.cpp \ |
brw_fs_cse.cpp \ |
brw_fs_emit.cpp \ |
brw_fs_fp.cpp \ |
brw_fs_live_variables.cpp \ |
brw_fs_reg_allocate.cpp \ |
brw_fs_vector_splitting.cpp \ |
brw_fs_visitor.cpp \ |
brw_gs.c \ |
brw_gs_emit.c \ |
brw_gs_state.c \ |
brw_lower_texture_gradients.cpp \ |
brw_misc_state.c \ |
brw_program.c \ |
brw_primitive_restart.c \ |
brw_queryobj.c \ |
brw_schedule_instructions.cpp \ |
brw_sf.c \ |
brw_sf_emit.c \ |
brw_sf_state.c \ |
brw_shader.cpp \ |
brw_state_batch.c \ |
brw_state_cache.c \ |
brw_state_dump.c \ |
brw_state_upload.c \ |
brw_surface_formats.c \ |
brw_tex.c \ |
brw_tex_layout.c \ |
brw_urb.c \ |
brw_util.c \ |
brw_vec4.cpp \ |
brw_vec4_copy_propagation.cpp \ |
brw_vec4_emit.cpp \ |
brw_vec4_live_variables.cpp \ |
brw_vec4_reg_allocate.cpp \ |
brw_vec4_visitor.cpp \ |
brw_vec4_vp.cpp \ |
brw_vs.c \ |
brw_vs_state.c \ |
brw_vs_surface_state.c \ |
brw_vtbl.c \ |
brw_wm.c \ |
brw_wm_iz.cpp \ |
brw_wm_sampler_state.c \ |
brw_wm_state.c \ |
brw_wm_surface_state.c \ |
gen6_blorp.cpp \ |
gen6_cc.c \ |
gen6_clip_state.c \ |
gen6_depthstencil.c \ |
gen6_gs_state.c \ |
gen6_multisample_state.c \ |
gen6_queryobj.c \ |
gen6_sampler_state.c \ |
gen6_scissor_state.c \ |
gen6_sf_state.c \ |
gen6_sol.c \ |
gen6_urb.c \ |
gen6_viewport_state.c \ |
gen6_vs_state.c \ |
gen6_wm_state.c \ |
gen7_blorp.cpp \ |
gen7_clip_state.c \ |
gen7_disable.c \ |
gen7_misc_state.c \ |
gen7_sampler_state.c \ |
gen7_sf_state.c \ |
gen7_sol_state.c \ |
gen7_urb.c \ |
gen7_viewport_state.c \ |
gen7_vs_state.c \ |
gen7_wm_state.c \ |
gen7_wm_surface_state.c \ |
$() |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_blorp.cpp |
---|
0,0 → 1,279 |
/* |
* 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 "intel_batchbuffer.h" |
#include "intel_fbo.h" |
#include "brw_blorp.h" |
#include "brw_defines.h" |
#include "gen6_blorp.h" |
#include "gen7_blorp.h" |
#define FILE_DEBUG_FLAG DEBUG_BLORP |
brw_blorp_mip_info::brw_blorp_mip_info() |
: mt(NULL), |
level(0), |
layer(0), |
width(0), |
height(0), |
x_offset(0), |
y_offset(0) |
{ |
} |
brw_blorp_surface_info::brw_blorp_surface_info() |
: map_stencil_as_y_tiled(false), |
num_samples(0) |
{ |
} |
void |
brw_blorp_mip_info::set(struct intel_mipmap_tree *mt, |
unsigned int level, unsigned int layer) |
{ |
intel_miptree_check_level_layer(mt, level, layer); |
this->mt = mt; |
this->level = level; |
this->layer = layer; |
this->width = mt->level[level].width; |
this->height = mt->level[level].height; |
intel_miptree_get_image_offset(mt, level, layer, &x_offset, &y_offset); |
} |
void |
brw_blorp_surface_info::set(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, unsigned int layer) |
{ |
brw_blorp_mip_info::set(mt, level, layer); |
this->num_samples = mt->num_samples; |
this->array_spacing_lod0 = mt->array_spacing_lod0; |
this->map_stencil_as_y_tiled = false; |
this->msaa_layout = mt->msaa_layout; |
switch (mt->format) { |
case MESA_FORMAT_S8: |
/* The miptree is a W-tiled stencil buffer. Surface states can't be set |
* up for W tiling, so we'll need to use Y tiling and have the WM |
* program swizzle the coordinates. |
*/ |
this->map_stencil_as_y_tiled = true; |
this->brw_surfaceformat = BRW_SURFACEFORMAT_R8_UNORM; |
break; |
case MESA_FORMAT_X8_Z24: |
case MESA_FORMAT_Z32_FLOAT: |
/* The miptree consists of 32 bits per pixel, arranged either as 24-bit |
* depth values interleaved with 8 "don't care" bits, or as 32-bit |
* floating point depth values. Since depth values don't require any |
* blending, it doesn't matter how we interpret the bit pattern as long |
* as we copy the right amount of data, so just map it as 8-bit BGRA. |
*/ |
this->brw_surfaceformat = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; |
break; |
case MESA_FORMAT_Z16: |
/* The miptree consists of 16 bits per pixel of depth data. Since depth |
* values don't require any blending, it doesn't matter how we interpret |
* the bit pattern as long as we copy the right amount of data, so just |
* map is as 8-bit RG. |
*/ |
this->brw_surfaceformat = BRW_SURFACEFORMAT_R8G8_UNORM; |
break; |
default: |
/* Blorp blits don't support any sort of format conversion (except |
* between sRGB and linear), so we can safely assume that the format is |
* supported as a render target, even if this is the source image. So |
* we can convert to a surface format using brw->render_target_format. |
*/ |
assert(brw->format_supported_as_render_target[mt->format]); |
this->brw_surfaceformat = brw->render_target_format[mt->format]; |
break; |
} |
} |
/** |
* Split x_offset and y_offset into a base offset (in bytes) and a remaining |
* x/y offset (in pixels). Note: we can't do this by calling |
* intel_renderbuffer_tile_offsets(), because the offsets may have been |
* adjusted to account for Y vs. W tiling differences. So we compute it |
* directly from the adjusted offsets. |
*/ |
uint32_t |
brw_blorp_surface_info::compute_tile_offsets(uint32_t *tile_x, |
uint32_t *tile_y) const |
{ |
struct intel_region *region = mt->region; |
uint32_t mask_x, mask_y; |
intel_region_get_tile_masks(region, &mask_x, &mask_y, |
map_stencil_as_y_tiled); |
*tile_x = x_offset & mask_x; |
*tile_y = y_offset & mask_y; |
return intel_region_get_aligned_offset(region, x_offset & ~mask_x, |
y_offset & ~mask_y, |
map_stencil_as_y_tiled); |
} |
brw_blorp_params::brw_blorp_params() |
: x0(0), |
y0(0), |
x1(0), |
y1(0), |
depth_format(0), |
hiz_op(GEN6_HIZ_OP_NONE), |
fast_clear_op(GEN7_FAST_CLEAR_OP_NONE), |
num_samples(0), |
use_wm_prog(false) |
{ |
color_write_disable[0] = false; |
color_write_disable[1] = false; |
color_write_disable[2] = false; |
color_write_disable[3] = false; |
} |
extern "C" { |
void |
intel_hiz_exec(struct brw_context *brw, struct intel_mipmap_tree *mt, |
unsigned int level, unsigned int layer, gen6_hiz_op op) |
{ |
const char *opname = NULL; |
switch (op) { |
case GEN6_HIZ_OP_DEPTH_RESOLVE: |
opname = "depth resolve"; |
break; |
case GEN6_HIZ_OP_HIZ_RESOLVE: |
opname = "hiz ambiguate"; |
break; |
case GEN6_HIZ_OP_DEPTH_CLEAR: |
opname = "depth clear"; |
break; |
case GEN6_HIZ_OP_NONE: |
opname = "noop?"; |
break; |
} |
DBG("%s %s to mt %p level %d layer %d\n", |
__FUNCTION__, opname, mt, level, layer); |
brw_hiz_op_params params(mt, level, layer, op); |
brw_blorp_exec(brw, ¶ms); |
} |
} /* extern "C" */ |
void |
brw_blorp_exec(struct brw_context *brw, const brw_blorp_params *params) |
{ |
switch (brw->gen) { |
case 6: |
gen6_blorp_exec(brw, params); |
break; |
case 7: |
gen7_blorp_exec(brw, params); |
break; |
default: |
/* BLORP is not supported before Gen6. */ |
assert(false); |
break; |
} |
if (unlikely(brw->always_flush_batch)) |
intel_batchbuffer_flush(brw); |
/* We've smashed all state compared to what the normal 3D pipeline |
* rendering tracks for GL. |
*/ |
brw->state.dirty.brw = ~0; |
brw->state.dirty.cache = ~0; |
brw->state_batch_count = 0; |
brw->batch.need_workaround_flush = true; |
/* Flush the sampler cache so any texturing from the destination is |
* coherent. |
*/ |
intel_batchbuffer_emit_mi_flush(brw); |
} |
brw_hiz_op_params::brw_hiz_op_params(struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int layer, |
gen6_hiz_op op) |
{ |
this->hiz_op = op; |
depth.set(mt, level, layer); |
/* Align the rectangle primitive to 8x4 pixels. |
* |
* During fast depth clears, the emitted rectangle primitive must be |
* aligned to 8x4 pixels. From the Ivybridge PRM, Vol 2 Part 1 Section |
* 11.5.3.1 Depth Buffer Clear (and the matching section in the Sandybridge |
* PRM): |
* If Number of Multisamples is NUMSAMPLES_1, the rectangle must be |
* aligned to an 8x4 pixel block relative to the upper left corner |
* of the depth buffer [...] |
* |
* For hiz resolves, the rectangle must also be 8x4 aligned. Item |
* WaHizAmbiguate8x4Aligned from the Haswell workarounds page and the |
* Ivybridge simulator require the alignment. |
* |
* To be safe, let's just align the rect for all hiz operations and all |
* hardware generations. |
* |
* However, for some miptree slices of a Z24 texture, emitting an 8x4 |
* aligned rectangle that covers the slice may clobber adjacent slices if |
* we strictly adhered to the texture alignments specified in the PRM. The |
* Ivybridge PRM, Section "Alignment Unit Size", states that |
* SURFACE_STATE.Surface_Horizontal_Alignment should be 4 for Z24 surfaces, |
* not 8. But commit 1f112cc increased the alignment from 4 to 8, which |
* prevents the clobbering. |
*/ |
depth.width = ALIGN(depth.width, 8); |
depth.height = ALIGN(depth.height, 4); |
x1 = depth.width; |
y1 = depth.height; |
assert(intel_miptree_slice_has_hiz(mt, level, layer)); |
switch (mt->format) { |
case MESA_FORMAT_Z16: depth_format = BRW_DEPTHFORMAT_D16_UNORM; break; |
case MESA_FORMAT_Z32_FLOAT: depth_format = BRW_DEPTHFORMAT_D32_FLOAT; break; |
case MESA_FORMAT_X8_Z24: depth_format = BRW_DEPTHFORMAT_D24_UNORM_X8_UINT; break; |
default: assert(0); break; |
} |
} |
uint32_t |
brw_hiz_op_params::get_wm_prog(struct brw_context *brw, |
brw_blorp_prog_data **prog_data) const |
{ |
return 0; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_blorp.h |
---|
0,0 → 1,422 |
/* |
* 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. |
*/ |
#pragma once |
#include <stdint.h> |
#include "brw_context.h" |
#include "intel_mipmap_tree.h" |
struct brw_context; |
#ifdef __cplusplus |
extern "C" { |
#endif |
void |
brw_blorp_blit_miptrees(struct brw_context *brw, |
struct intel_mipmap_tree *src_mt, |
unsigned src_level, unsigned src_layer, |
struct intel_mipmap_tree *dst_mt, |
unsigned dst_level, unsigned dst_layer, |
float src_x0, float src_y0, |
float src_x1, float src_y1, |
float dst_x0, float dst_y0, |
float dst_x1, float dst_y1, |
bool mirror_x, bool mirror_y); |
bool |
brw_blorp_clear_color(struct brw_context *brw, struct gl_framebuffer *fb, |
bool partial_clear); |
void |
brw_blorp_resolve_color(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
#ifdef __cplusplus |
} /* end extern "C" */ |
/** |
* Binding table indices used by BLORP. |
*/ |
enum { |
BRW_BLORP_TEXTURE_BINDING_TABLE_INDEX, |
BRW_BLORP_RENDERBUFFER_BINDING_TABLE_INDEX, |
BRW_BLORP_NUM_BINDING_TABLE_ENTRIES |
}; |
class brw_blorp_mip_info |
{ |
public: |
brw_blorp_mip_info(); |
void set(struct intel_mipmap_tree *mt, |
unsigned int level, unsigned int layer); |
struct intel_mipmap_tree *mt; |
/** |
* The miplevel to use. |
*/ |
uint32_t level; |
/** |
* The 2D layer within the miplevel. Combined, level and layer define the |
* 2D miptree slice to use. |
*/ |
uint32_t layer; |
/** |
* Width of the miplevel to be used. For surfaces using |
* INTEL_MSAA_LAYOUT_IMS, this is measured in samples, not pixels. |
*/ |
uint32_t width; |
/** |
* Height of the miplevel to be used. For surfaces using |
* INTEL_MSAA_LAYOUT_IMS, this is measured in samples, not pixels. |
*/ |
uint32_t height; |
/** |
* X offset within the surface to texture from (or render to). For |
* surfaces using INTEL_MSAA_LAYOUT_IMS, this is measured in samples, not |
* pixels. |
*/ |
uint32_t x_offset; |
/** |
* Y offset within the surface to texture from (or render to). For |
* surfaces using INTEL_MSAA_LAYOUT_IMS, this is measured in samples, not |
* pixels. |
*/ |
uint32_t y_offset; |
}; |
class brw_blorp_surface_info : public brw_blorp_mip_info |
{ |
public: |
brw_blorp_surface_info(); |
void set(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, unsigned int layer); |
uint32_t compute_tile_offsets(uint32_t *tile_x, uint32_t *tile_y) const; |
/* Setting this flag indicates that the buffer's contents are W-tiled |
* stencil data, but the surface state should be set up for Y tiled |
* MESA_FORMAT_R8 data (this is necessary because surface states don't |
* support W tiling). |
* |
* Since W tiles are 64 pixels wide by 64 pixels high, whereas Y tiles of |
* MESA_FORMAT_R8 data are 128 pixels wide by 32 pixels high, the width and |
* pitch stored in the surface state will be multiplied by 2, and the |
* height will be halved. Also, since W and Y tiles store their data in a |
* different order, the width and height will be rounded up to a multiple |
* of the tile size, to ensure that the WM program can access the full |
* width and height of the buffer. |
*/ |
bool map_stencil_as_y_tiled; |
unsigned num_samples; |
/* Setting this flag indicates that the surface should be set up in |
* ARYSPC_LOD0 mode. Ignored prior to Gen7. |
*/ |
bool array_spacing_lod0; |
/** |
* Format that should be used when setting up the surface state for this |
* surface. Should correspond to one of the BRW_SURFACEFORMAT_* enums. |
*/ |
uint32_t brw_surfaceformat; |
/** |
* For MSAA surfaces, MSAA layout that should be used when setting up the |
* surface state for this surface. |
*/ |
intel_msaa_layout msaa_layout; |
}; |
struct brw_blorp_coord_transform_params |
{ |
void setup(GLfloat src0, GLfloat src1, GLfloat dst0, GLfloat dst1, |
bool mirror); |
float multiplier; |
float offset; |
}; |
struct brw_blorp_wm_push_constants |
{ |
uint32_t dst_x0; |
uint32_t dst_x1; |
uint32_t dst_y0; |
uint32_t dst_y1; |
/* Top right coordinates of the rectangular sample grid used for |
* multisample scaled blitting. |
*/ |
float sample_grid_x1; |
float sample_grid_y1; |
brw_blorp_coord_transform_params x_transform; |
brw_blorp_coord_transform_params y_transform; |
/* Pad out to an integral number of registers */ |
uint32_t pad[6]; |
}; |
/* Every 32 bytes of push constant data constitutes one GEN register. */ |
const unsigned int BRW_BLORP_NUM_PUSH_CONST_REGS = |
sizeof(brw_blorp_wm_push_constants) / 32; |
struct brw_blorp_prog_data |
{ |
unsigned int first_curbe_grf; |
/** |
* True if the WM program should be run in MSDISPMODE_PERSAMPLE with more |
* than one sample per pixel. |
*/ |
bool persample_msaa_dispatch; |
}; |
enum gen7_fast_clear_op { |
GEN7_FAST_CLEAR_OP_NONE, |
GEN7_FAST_CLEAR_OP_FAST_CLEAR, |
GEN7_FAST_CLEAR_OP_RESOLVE, |
}; |
class brw_blorp_params |
{ |
public: |
brw_blorp_params(); |
virtual uint32_t get_wm_prog(struct brw_context *brw, |
brw_blorp_prog_data **prog_data) const = 0; |
uint32_t x0; |
uint32_t y0; |
uint32_t x1; |
uint32_t y1; |
brw_blorp_mip_info depth; |
uint32_t depth_format; |
brw_blorp_surface_info src; |
brw_blorp_surface_info dst; |
enum gen6_hiz_op hiz_op; |
enum gen7_fast_clear_op fast_clear_op; |
unsigned num_samples; |
bool use_wm_prog; |
brw_blorp_wm_push_constants wm_push_consts; |
bool color_write_disable[4]; |
}; |
void |
brw_blorp_exec(struct brw_context *brw, const brw_blorp_params *params); |
/** |
* Parameters for a HiZ or depth resolve operation. |
* |
* For an overview of HiZ ops, see the following sections of the Sandy Bridge |
* PRM, Volume 1, Part 2: |
* - 7.5.3.1 Depth Buffer Clear |
* - 7.5.3.2 Depth Buffer Resolve |
* - 7.5.3.3 Hierarchical Depth Buffer Resolve |
*/ |
class brw_hiz_op_params : public brw_blorp_params |
{ |
public: |
brw_hiz_op_params(struct intel_mipmap_tree *mt, |
unsigned int level, unsigned int layer, |
gen6_hiz_op op); |
virtual uint32_t get_wm_prog(struct brw_context *brw, |
brw_blorp_prog_data **prog_data) const; |
}; |
struct brw_blorp_blit_prog_key |
{ |
/* Number of samples per pixel that have been configured in the surface |
* state for texturing from. |
*/ |
unsigned tex_samples; |
/* MSAA layout that has been configured in the surface state for texturing |
* from. |
*/ |
intel_msaa_layout tex_layout; |
/* Actual number of samples per pixel in the source image. */ |
unsigned src_samples; |
/* Actual MSAA layout used by the source image. */ |
intel_msaa_layout src_layout; |
/* Number of samples per pixel that have been configured in the render |
* target. |
*/ |
unsigned rt_samples; |
/* MSAA layout that has been configured in the render target. */ |
intel_msaa_layout rt_layout; |
/* Actual number of samples per pixel in the destination image. */ |
unsigned dst_samples; |
/* Actual MSAA layout used by the destination image. */ |
intel_msaa_layout dst_layout; |
/* Type of the data to be read from the texture (one of |
* BRW_REGISTER_TYPE_{UD,D,F}). |
*/ |
unsigned texture_data_type; |
/* True if the source image is W tiled. If true, the surface state for the |
* source image must be configured as Y tiled, and tex_samples must be 0. |
*/ |
bool src_tiled_w; |
/* True if the destination image is W tiled. If true, the surface state |
* for the render target must be configured as Y tiled, and rt_samples must |
* be 0. |
*/ |
bool dst_tiled_w; |
/* True if all source samples should be blended together to produce each |
* destination pixel. If true, src_tiled_w must be false, tex_samples must |
* equal src_samples, and tex_samples must be nonzero. |
*/ |
bool blend; |
/* True if the rectangle being sent through the rendering pipeline might be |
* larger than the destination rectangle, so the WM program should kill any |
* pixels that are outside the destination rectangle. |
*/ |
bool use_kill; |
/** |
* True if the WM program should be run in MSDISPMODE_PERSAMPLE with more |
* than one sample per pixel. |
*/ |
bool persample_msaa_dispatch; |
/* True for scaled blitting. */ |
bool blit_scaled; |
/* Scale factors between the pixel grid and the grid of samples. We're |
* using grid of samples for bilinear filetring in multisample scaled blits. |
*/ |
float x_scale; |
float y_scale; |
}; |
class brw_blorp_blit_params : public brw_blorp_params |
{ |
public: |
brw_blorp_blit_params(struct brw_context *brw, |
struct intel_mipmap_tree *src_mt, |
unsigned src_level, unsigned src_layer, |
struct intel_mipmap_tree *dst_mt, |
unsigned dst_level, unsigned dst_layer, |
GLfloat src_x0, GLfloat src_y0, |
GLfloat src_x1, GLfloat src_y1, |
GLfloat dst_x0, GLfloat dst_y0, |
GLfloat dst_x1, GLfloat dst_y1, |
bool mirror_x, bool mirror_y); |
virtual uint32_t get_wm_prog(struct brw_context *brw, |
brw_blorp_prog_data **prog_data) const; |
private: |
brw_blorp_blit_prog_key wm_prog_key; |
}; |
/** |
* \name BLORP internals |
* \{ |
* |
* Used internally by gen6_blorp_exec() and gen7_blorp_exec(). |
*/ |
void |
gen6_blorp_init(struct brw_context *brw); |
void |
gen6_blorp_emit_batch_head(struct brw_context *brw, |
const brw_blorp_params *params); |
void |
gen6_blorp_emit_state_base_address(struct brw_context *brw, |
const brw_blorp_params *params); |
void |
gen6_blorp_emit_vertices(struct brw_context *brw, |
const brw_blorp_params *params); |
uint32_t |
gen6_blorp_emit_blend_state(struct brw_context *brw, |
const brw_blorp_params *params); |
uint32_t |
gen6_blorp_emit_cc_state(struct brw_context *brw, |
const brw_blorp_params *params); |
uint32_t |
gen6_blorp_emit_wm_constants(struct brw_context *brw, |
const brw_blorp_params *params); |
void |
gen6_blorp_emit_vs_disable(struct brw_context *brw, |
const brw_blorp_params *params); |
uint32_t |
gen6_blorp_emit_binding_table(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t wm_surf_offset_renderbuffer, |
uint32_t wm_surf_offset_texture); |
uint32_t |
gen6_blorp_emit_depth_stencil_state(struct brw_context *brw, |
const brw_blorp_params *params); |
void |
gen6_blorp_emit_gs_disable(struct brw_context *brw, |
const brw_blorp_params *params); |
void |
gen6_blorp_emit_clip_disable(struct brw_context *brw, |
const brw_blorp_params *params); |
void |
gen6_blorp_emit_drawing_rectangle(struct brw_context *brw, |
const brw_blorp_params *params); |
/** \} */ |
#endif /* __cplusplus */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp |
---|
0,0 → 1,2297 |
/* |
* 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 "main/teximage.h" |
#include "main/fbobject.h" |
#include "main/renderbuffer.h" |
#include "glsl/ralloc.h" |
#include "intel_fbo.h" |
#include "brw_blorp.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_state.h" |
#define FILE_DEBUG_FLAG DEBUG_BLORP |
/** |
* Helper function for handling mirror image blits. |
* |
* If coord0 > coord1, swap them and invert the "mirror" boolean. |
*/ |
static inline void |
fixup_mirroring(bool &mirror, GLfloat &coord0, GLfloat &coord1) |
{ |
if (coord0 > coord1) { |
mirror = !mirror; |
GLfloat tmp = coord0; |
coord0 = coord1; |
coord1 = tmp; |
} |
} |
/** |
* Adjust {src,dst}_x{0,1} to account for clipping and scissoring of |
* destination coordinates. |
* |
* Return true if there is still blitting to do, false if all pixels got |
* rejected by the clip and/or scissor. |
* |
* For clarity, the nomenclature of this function assumes we are clipping and |
* scissoring the X coordinate; the exact same logic applies for Y |
* coordinates. |
* |
* Note: this function may also be used to account for clipping of source |
* coordinates, by swapping the roles of src and dst. |
*/ |
static inline bool |
clip_or_scissor(bool mirror, GLfloat &src_x0, GLfloat &src_x1, GLfloat &dst_x0, |
GLfloat &dst_x1, GLfloat fb_xmin, GLfloat fb_xmax) |
{ |
float scale = (float) (src_x1 - src_x0) / (dst_x1 - dst_x0); |
/* If we are going to scissor everything away, stop. */ |
if (!(fb_xmin < fb_xmax && |
dst_x0 < fb_xmax && |
fb_xmin < dst_x1 && |
dst_x0 < dst_x1)) { |
return false; |
} |
/* Clip the destination rectangle, and keep track of how many pixels we |
* clipped off of the left and right sides of it. |
*/ |
GLint pixels_clipped_left = 0; |
GLint pixels_clipped_right = 0; |
if (dst_x0 < fb_xmin) { |
pixels_clipped_left = fb_xmin - dst_x0; |
dst_x0 = fb_xmin; |
} |
if (fb_xmax < dst_x1) { |
pixels_clipped_right = dst_x1 - fb_xmax; |
dst_x1 = fb_xmax; |
} |
/* If we are mirrored, then before applying pixels_clipped_{left,right} to |
* the source coordinates, we need to flip them to account for the |
* mirroring. |
*/ |
if (mirror) { |
GLint tmp = pixels_clipped_left; |
pixels_clipped_left = pixels_clipped_right; |
pixels_clipped_right = tmp; |
} |
/* Adjust the source rectangle to remove the pixels corresponding to those |
* that were clipped/scissored out of the destination rectangle. |
*/ |
src_x0 += pixels_clipped_left * scale; |
src_x1 -= pixels_clipped_right * scale; |
return true; |
} |
static struct intel_mipmap_tree * |
find_miptree(GLbitfield buffer_bit, struct intel_renderbuffer *irb) |
{ |
struct intel_mipmap_tree *mt = irb->mt; |
if (buffer_bit == GL_STENCIL_BUFFER_BIT && mt->stencil_mt) |
mt = mt->stencil_mt; |
return mt; |
} |
void |
brw_blorp_blit_miptrees(struct brw_context *brw, |
struct intel_mipmap_tree *src_mt, |
unsigned src_level, unsigned src_layer, |
struct intel_mipmap_tree *dst_mt, |
unsigned dst_level, unsigned dst_layer, |
float src_x0, float src_y0, |
float src_x1, float src_y1, |
float dst_x0, float dst_y0, |
float dst_x1, float dst_y1, |
bool mirror_x, bool mirror_y) |
{ |
/* Get ready to blit. This includes depth resolving the src and dst |
* buffers if necessary. Note: it's not necessary to do a color resolve on |
* the destination buffer because we use the standard render path to render |
* to destination color buffers, and the standard render path is |
* fast-color-aware. |
*/ |
intel_miptree_resolve_color(brw, src_mt); |
intel_miptree_slice_resolve_depth(brw, src_mt, src_level, src_layer); |
intel_miptree_slice_resolve_depth(brw, dst_mt, dst_level, dst_layer); |
DBG("%s from %s mt %p %d %d (%f,%f) (%f,%f)" |
"to %s mt %p %d %d (%f,%f) (%f,%f) (flip %d,%d)\n", |
__FUNCTION__, |
_mesa_get_format_name(src_mt->format), src_mt, |
src_level, src_layer, src_x0, src_y0, src_x1, src_y1, |
_mesa_get_format_name(dst_mt->format), dst_mt, |
dst_level, dst_layer, dst_x0, dst_y0, dst_x1, dst_y1, |
mirror_x, mirror_y); |
brw_blorp_blit_params params(brw, |
src_mt, src_level, src_layer, |
dst_mt, dst_level, dst_layer, |
src_x0, src_y0, |
src_x1, src_y1, |
dst_x0, dst_y0, |
dst_x1, dst_y1, |
mirror_x, mirror_y); |
brw_blorp_exec(brw, ¶ms); |
intel_miptree_slice_set_needs_hiz_resolve(dst_mt, dst_level, dst_layer); |
} |
static void |
do_blorp_blit(struct brw_context *brw, GLbitfield buffer_bit, |
struct intel_renderbuffer *src_irb, |
struct intel_renderbuffer *dst_irb, |
GLfloat srcX0, GLfloat srcY0, GLfloat srcX1, GLfloat srcY1, |
GLfloat dstX0, GLfloat dstY0, GLfloat dstX1, GLfloat dstY1, |
bool mirror_x, bool mirror_y) |
{ |
/* Find source/dst miptrees */ |
struct intel_mipmap_tree *src_mt = find_miptree(buffer_bit, src_irb); |
struct intel_mipmap_tree *dst_mt = find_miptree(buffer_bit, dst_irb); |
/* Do the blit */ |
brw_blorp_blit_miptrees(brw, |
src_mt, src_irb->mt_level, src_irb->mt_layer, |
dst_mt, dst_irb->mt_level, dst_irb->mt_layer, |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
mirror_x, mirror_y); |
intel_renderbuffer_set_needs_downsample(dst_irb); |
} |
static bool |
color_formats_match(gl_format src_format, gl_format dst_format) |
{ |
gl_format linear_src_format = _mesa_get_srgb_format_linear(src_format); |
gl_format linear_dst_format = _mesa_get_srgb_format_linear(dst_format); |
/* Normally, we require the formats to be equal. However, we also support |
* blitting from ARGB to XRGB (discarding alpha), and from XRGB to ARGB |
* (overriding alpha to 1.0 via blending). |
*/ |
return linear_src_format == linear_dst_format || |
(linear_src_format == MESA_FORMAT_XRGB8888 && |
linear_dst_format == MESA_FORMAT_ARGB8888) || |
(linear_src_format == MESA_FORMAT_ARGB8888 && |
linear_dst_format == MESA_FORMAT_XRGB8888); |
} |
static bool |
formats_match(GLbitfield buffer_bit, struct intel_renderbuffer *src_irb, |
struct intel_renderbuffer *dst_irb) |
{ |
/* Note: don't just check gl_renderbuffer::Format, because in some cases |
* multiple gl_formats resolve to the same native type in the miptree (for |
* example MESA_FORMAT_X8_Z24 and MESA_FORMAT_S8_Z24), and we can blit |
* between those formats. |
*/ |
gl_format src_format = find_miptree(buffer_bit, src_irb)->format; |
gl_format dst_format = find_miptree(buffer_bit, dst_irb)->format; |
return color_formats_match(src_format, dst_format); |
} |
static bool |
try_blorp_blit(struct brw_context *brw, |
GLfloat srcX0, GLfloat srcY0, GLfloat srcX1, GLfloat srcY1, |
GLfloat dstX0, GLfloat dstY0, GLfloat dstX1, GLfloat dstY1, |
GLenum filter, GLbitfield buffer_bit) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* Sync up the state of window system buffers. We need to do this before |
* we go looking for the buffers. |
*/ |
intel_prepare_render(brw); |
const struct gl_framebuffer *read_fb = ctx->ReadBuffer; |
const struct gl_framebuffer *draw_fb = ctx->DrawBuffer; |
/* Detect if the blit needs to be mirrored */ |
bool mirror_x = false, mirror_y = false; |
fixup_mirroring(mirror_x, srcX0, srcX1); |
fixup_mirroring(mirror_x, dstX0, dstX1); |
fixup_mirroring(mirror_y, srcY0, srcY1); |
fixup_mirroring(mirror_y, dstY0, dstY1); |
/* Linear filtering is not yet implemented in blorp engine. So, fallback |
* to other blit paths. |
*/ |
if ((srcX1 - srcX0 != dstX1 - dstX0 || |
srcY1 - srcY0 != dstY1 - dstY0) && |
filter == GL_LINEAR) |
return false; |
/* If the destination rectangle needs to be clipped or scissored, do so. |
*/ |
if (!(clip_or_scissor(mirror_x, srcX0, srcX1, dstX0, dstX1, |
draw_fb->_Xmin, draw_fb->_Xmax) && |
clip_or_scissor(mirror_y, srcY0, srcY1, dstY0, dstY1, |
draw_fb->_Ymin, draw_fb->_Ymax))) { |
/* Everything got clipped/scissored away, so the blit was successful. */ |
return true; |
} |
/* If the source rectangle needs to be clipped or scissored, do so. */ |
if (!(clip_or_scissor(mirror_x, dstX0, dstX1, srcX0, srcX1, |
0, read_fb->Width) && |
clip_or_scissor(mirror_y, dstY0, dstY1, srcY0, srcY1, |
0, read_fb->Height))) { |
/* Everything got clipped/scissored away, so the blit was successful. */ |
return true; |
} |
/* Account for the fact that in the system framebuffer, the origin is at |
* the lower left. |
*/ |
if (_mesa_is_winsys_fbo(read_fb)) { |
GLint tmp = read_fb->Height - srcY0; |
srcY0 = read_fb->Height - srcY1; |
srcY1 = tmp; |
mirror_y = !mirror_y; |
} |
if (_mesa_is_winsys_fbo(draw_fb)) { |
GLint tmp = draw_fb->Height - dstY0; |
dstY0 = draw_fb->Height - dstY1; |
dstY1 = tmp; |
mirror_y = !mirror_y; |
} |
/* Find buffers */ |
struct intel_renderbuffer *src_irb; |
struct intel_renderbuffer *dst_irb; |
switch (buffer_bit) { |
case GL_COLOR_BUFFER_BIT: |
src_irb = intel_renderbuffer(read_fb->_ColorReadBuffer); |
for (unsigned i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; ++i) { |
dst_irb = intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[i]); |
if (dst_irb && !formats_match(buffer_bit, src_irb, dst_irb)) |
return false; |
} |
for (unsigned i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; ++i) { |
dst_irb = intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[i]); |
if (dst_irb) |
do_blorp_blit(brw, buffer_bit, src_irb, dst_irb, srcX0, srcY0, |
srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, |
mirror_x, mirror_y); |
} |
break; |
case GL_DEPTH_BUFFER_BIT: |
src_irb = |
intel_renderbuffer(read_fb->Attachment[BUFFER_DEPTH].Renderbuffer); |
dst_irb = |
intel_renderbuffer(draw_fb->Attachment[BUFFER_DEPTH].Renderbuffer); |
if (!formats_match(buffer_bit, src_irb, dst_irb)) |
return false; |
do_blorp_blit(brw, buffer_bit, src_irb, dst_irb, srcX0, srcY0, |
srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, |
mirror_x, mirror_y); |
break; |
case GL_STENCIL_BUFFER_BIT: |
src_irb = |
intel_renderbuffer(read_fb->Attachment[BUFFER_STENCIL].Renderbuffer); |
dst_irb = |
intel_renderbuffer(draw_fb->Attachment[BUFFER_STENCIL].Renderbuffer); |
if (!formats_match(buffer_bit, src_irb, dst_irb)) |
return false; |
do_blorp_blit(brw, buffer_bit, src_irb, dst_irb, srcX0, srcY0, |
srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, |
mirror_x, mirror_y); |
break; |
default: |
assert(false); |
} |
return true; |
} |
bool |
brw_blorp_copytexsubimage(struct brw_context *brw, |
struct gl_renderbuffer *src_rb, |
struct gl_texture_image *dst_image, |
int slice, |
int srcX0, int srcY0, |
int dstX0, int dstY0, |
int width, int height) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb); |
struct intel_texture_image *intel_image = intel_texture_image(dst_image); |
/* Sync up the state of window system buffers. We need to do this before |
* we go looking at the src renderbuffer's miptree. |
*/ |
intel_prepare_render(brw); |
struct intel_mipmap_tree *src_mt = src_irb->mt; |
struct intel_mipmap_tree *dst_mt = intel_image->mt; |
/* BLORP is not supported before Gen6. */ |
if (brw->gen < 6) |
return false; |
if (!color_formats_match(src_mt->format, dst_mt->format)) { |
return false; |
} |
/* Source clipping shouldn't be necessary, since copytexsubimage (in |
* src/mesa/main/teximage.c) calls _mesa_clip_copytexsubimage() which |
* takes care of it. |
* |
* Destination clipping shouldn't be necessary since the restrictions on |
* glCopyTexSubImage prevent the user from specifying a destination rectangle |
* that falls outside the bounds of the destination texture. |
* See error_check_subtexture_dimensions(). |
*/ |
int srcY1 = srcY0 + height; |
int srcX1 = srcX0 + width; |
int dstX1 = dstX0 + width; |
int dstY1 = dstY0 + height; |
/* Account for the fact that in the system framebuffer, the origin is at |
* the lower left. |
*/ |
bool mirror_y = false; |
if (_mesa_is_winsys_fbo(ctx->ReadBuffer)) { |
GLint tmp = src_rb->Height - srcY0; |
srcY0 = src_rb->Height - srcY1; |
srcY1 = tmp; |
mirror_y = true; |
} |
brw_blorp_blit_miptrees(brw, |
src_mt, src_irb->mt_level, src_irb->mt_layer, |
dst_mt, dst_image->Level, dst_image->Face + slice, |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
false, mirror_y); |
/* If we're copying to a packed depth stencil texture and the source |
* framebuffer has separate stencil, we need to also copy the stencil data |
* over. |
*/ |
src_rb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; |
if (_mesa_get_format_bits(dst_image->TexFormat, GL_STENCIL_BITS) > 0 && |
src_rb != NULL) { |
src_irb = intel_renderbuffer(src_rb); |
src_mt = src_irb->mt; |
if (src_mt->stencil_mt) |
src_mt = src_mt->stencil_mt; |
if (dst_mt->stencil_mt) |
dst_mt = dst_mt->stencil_mt; |
if (src_mt != dst_mt) { |
brw_blorp_blit_miptrees(brw, |
src_mt, src_irb->mt_level, src_irb->mt_layer, |
dst_mt, dst_image->Level, |
dst_image->Face + slice, |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
false, mirror_y); |
} |
} |
return true; |
} |
GLbitfield |
brw_blorp_framebuffer(struct brw_context *brw, |
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, |
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, |
GLbitfield mask, GLenum filter) |
{ |
/* BLORP is not supported before Gen6. */ |
if (brw->gen < 6) |
return mask; |
static GLbitfield buffer_bits[] = { |
GL_COLOR_BUFFER_BIT, |
GL_DEPTH_BUFFER_BIT, |
GL_STENCIL_BUFFER_BIT, |
}; |
for (unsigned int i = 0; i < ARRAY_SIZE(buffer_bits); ++i) { |
if ((mask & buffer_bits[i]) && |
try_blorp_blit(brw, |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
filter, buffer_bits[i])) { |
mask &= ~buffer_bits[i]; |
} |
} |
return mask; |
} |
/** |
* Enum to specify the order of arguments in a sampler message |
*/ |
enum sampler_message_arg |
{ |
SAMPLER_MESSAGE_ARG_U_FLOAT, |
SAMPLER_MESSAGE_ARG_V_FLOAT, |
SAMPLER_MESSAGE_ARG_U_INT, |
SAMPLER_MESSAGE_ARG_V_INT, |
SAMPLER_MESSAGE_ARG_SI_INT, |
SAMPLER_MESSAGE_ARG_MCS_INT, |
SAMPLER_MESSAGE_ARG_ZERO_INT, |
}; |
/** |
* Generator for WM programs used in BLORP blits. |
* |
* The bulk of the work done by the WM program is to wrap and unwrap the |
* coordinate transformations used by the hardware to store surfaces in |
* memory. The hardware transforms a pixel location (X, Y, S) (where S is the |
* sample index for a multisampled surface) to a memory offset by the |
* following formulas: |
* |
* offset = tile(tiling_format, encode_msaa(num_samples, layout, X, Y, S)) |
* (X, Y, S) = decode_msaa(num_samples, layout, detile(tiling_format, offset)) |
* |
* For a single-sampled surface, or for a multisampled surface using |
* INTEL_MSAA_LAYOUT_UMS, encode_msaa() and decode_msaa are the identity |
* function: |
* |
* encode_msaa(1, NONE, X, Y, 0) = (X, Y, 0) |
* decode_msaa(1, NONE, X, Y, 0) = (X, Y, 0) |
* encode_msaa(n, UMS, X, Y, S) = (X, Y, S) |
* decode_msaa(n, UMS, X, Y, S) = (X, Y, S) |
* |
* For a 4x multisampled surface using INTEL_MSAA_LAYOUT_IMS, encode_msaa() |
* embeds the sample number into bit 1 of the X and Y coordinates: |
* |
* encode_msaa(4, IMS, X, Y, S) = (X', Y', 0) |
* where X' = (X & ~0b1) << 1 | (S & 0b1) << 1 | (X & 0b1) |
* Y' = (Y & ~0b1 ) << 1 | (S & 0b10) | (Y & 0b1) |
* decode_msaa(4, IMS, X, Y, 0) = (X', Y', S) |
* where X' = (X & ~0b11) >> 1 | (X & 0b1) |
* Y' = (Y & ~0b11) >> 1 | (Y & 0b1) |
* S = (Y & 0b10) | (X & 0b10) >> 1 |
* |
* For an 8x multisampled surface using INTEL_MSAA_LAYOUT_IMS, encode_msaa() |
* embeds the sample number into bits 1 and 2 of the X coordinate and bit 1 of |
* the Y coordinate: |
* |
* encode_msaa(8, IMS, X, Y, S) = (X', Y', 0) |
* where X' = (X & ~0b1) << 2 | (S & 0b100) | (S & 0b1) << 1 | (X & 0b1) |
* Y' = (Y & ~0b1) << 1 | (S & 0b10) | (Y & 0b1) |
* decode_msaa(8, IMS, X, Y, 0) = (X', Y', S) |
* where X' = (X & ~0b111) >> 2 | (X & 0b1) |
* Y' = (Y & ~0b11) >> 1 | (Y & 0b1) |
* S = (X & 0b100) | (Y & 0b10) | (X & 0b10) >> 1 |
* |
* For X tiling, tile() combines together the low-order bits of the X and Y |
* coordinates in the pattern 0byyyxxxxxxxxx, creating 4k tiles that are 512 |
* bytes wide and 8 rows high: |
* |
* tile(x_tiled, X, Y, S) = A |
* where A = tile_num << 12 | offset |
* tile_num = (Y' >> 3) * tile_pitch + (X' >> 9) |
* offset = (Y' & 0b111) << 9 |
* | (X & 0b111111111) |
* X' = X * cpp |
* Y' = Y + S * qpitch |
* detile(x_tiled, A) = (X, Y, S) |
* where X = X' / cpp |
* Y = Y' % qpitch |
* S = Y' / qpitch |
* Y' = (tile_num / tile_pitch) << 3 |
* | (A & 0b111000000000) >> 9 |
* X' = (tile_num % tile_pitch) << 9 |
* | (A & 0b111111111) |
* |
* (In all tiling formulas, cpp is the number of bytes occupied by a single |
* sample ("chars per pixel"), tile_pitch is the number of 4k tiles required |
* to fill the width of the surface, and qpitch is the spacing (in rows) |
* between array slices). |
* |
* For Y tiling, tile() combines together the low-order bits of the X and Y |
* coordinates in the pattern 0bxxxyyyyyxxxx, creating 4k tiles that are 128 |
* bytes wide and 32 rows high: |
* |
* tile(y_tiled, X, Y, S) = A |
* where A = tile_num << 12 | offset |
* tile_num = (Y' >> 5) * tile_pitch + (X' >> 7) |
* offset = (X' & 0b1110000) << 5 |
* | (Y' & 0b11111) << 4 |
* | (X' & 0b1111) |
* X' = X * cpp |
* Y' = Y + S * qpitch |
* detile(y_tiled, A) = (X, Y, S) |
* where X = X' / cpp |
* Y = Y' % qpitch |
* S = Y' / qpitch |
* Y' = (tile_num / tile_pitch) << 5 |
* | (A & 0b111110000) >> 4 |
* X' = (tile_num % tile_pitch) << 7 |
* | (A & 0b111000000000) >> 5 |
* | (A & 0b1111) |
* |
* For W tiling, tile() combines together the low-order bits of the X and Y |
* coordinates in the pattern 0bxxxyyyyxyxyx, creating 4k tiles that are 64 |
* bytes wide and 64 rows high (note that W tiling is only used for stencil |
* buffers, which always have cpp = 1 and S=0): |
* |
* tile(w_tiled, X, Y, S) = A |
* where A = tile_num << 12 | offset |
* tile_num = (Y' >> 6) * tile_pitch + (X' >> 6) |
* offset = (X' & 0b111000) << 6 |
* | (Y' & 0b111100) << 3 |
* | (X' & 0b100) << 2 |
* | (Y' & 0b10) << 2 |
* | (X' & 0b10) << 1 |
* | (Y' & 0b1) << 1 |
* | (X' & 0b1) |
* X' = X * cpp = X |
* Y' = Y + S * qpitch |
* detile(w_tiled, A) = (X, Y, S) |
* where X = X' / cpp = X' |
* Y = Y' % qpitch = Y' |
* S = Y / qpitch = 0 |
* Y' = (tile_num / tile_pitch) << 6 |
* | (A & 0b111100000) >> 3 |
* | (A & 0b1000) >> 2 |
* | (A & 0b10) >> 1 |
* X' = (tile_num % tile_pitch) << 6 |
* | (A & 0b111000000000) >> 6 |
* | (A & 0b10000) >> 2 |
* | (A & 0b100) >> 1 |
* | (A & 0b1) |
* |
* Finally, for a non-tiled surface, tile() simply combines together the X and |
* Y coordinates in the natural way: |
* |
* tile(untiled, X, Y, S) = A |
* where A = Y * pitch + X' |
* X' = X * cpp |
* Y' = Y + S * qpitch |
* detile(untiled, A) = (X, Y, S) |
* where X = X' / cpp |
* Y = Y' % qpitch |
* S = Y' / qpitch |
* X' = A % pitch |
* Y' = A / pitch |
* |
* (In these formulas, pitch is the number of bytes occupied by a single row |
* of samples). |
*/ |
class brw_blorp_blit_program |
{ |
public: |
brw_blorp_blit_program(struct brw_context *brw, |
const brw_blorp_blit_prog_key *key); |
~brw_blorp_blit_program(); |
const GLuint *compile(struct brw_context *brw, GLuint *program_size); |
brw_blorp_prog_data prog_data; |
private: |
void alloc_regs(); |
void alloc_push_const_regs(int base_reg); |
void compute_frag_coords(); |
void translate_tiling(bool old_tiled_w, bool new_tiled_w); |
void encode_msaa(unsigned num_samples, intel_msaa_layout layout); |
void decode_msaa(unsigned num_samples, intel_msaa_layout layout); |
void kill_if_outside_dst_rect(); |
void translate_dst_to_src(); |
void single_to_blend(); |
void manual_blend_average(unsigned num_samples); |
void manual_blend_bilinear(unsigned num_samples); |
void sample(struct brw_reg dst); |
void texel_fetch(struct brw_reg dst); |
void mcs_fetch(); |
void texture_lookup(struct brw_reg dst, GLuint msg_type, |
const sampler_message_arg *args, int num_args); |
void render_target_write(); |
/** |
* Base-2 logarithm of the maximum number of samples that can be blended. |
*/ |
static const unsigned LOG2_MAX_BLEND_SAMPLES = 3; |
void *mem_ctx; |
struct brw_context *brw; |
const brw_blorp_blit_prog_key *key; |
struct brw_compile func; |
/* Thread dispatch header */ |
struct brw_reg R0; |
/* Pixel X/Y coordinates (always in R1). */ |
struct brw_reg R1; |
/* Push constants */ |
struct brw_reg dst_x0; |
struct brw_reg dst_x1; |
struct brw_reg dst_y0; |
struct brw_reg dst_y1; |
/* Top right coordinates of the rectangular sample grid used for |
* multisample scaled blitting. |
*/ |
struct brw_reg sample_grid_x1; |
struct brw_reg sample_grid_y1; |
struct { |
struct brw_reg multiplier; |
struct brw_reg offset; |
} x_transform, y_transform; |
/* Data read from texture (4 vec16's per array element) */ |
struct brw_reg texture_data[LOG2_MAX_BLEND_SAMPLES + 1]; |
/* Auxiliary storage for the contents of the MCS surface. |
* |
* Since the sampler always returns 8 registers worth of data, this is 8 |
* registers wide, even though we only use the first 2 registers of it. |
*/ |
struct brw_reg mcs_data; |
/* X coordinates. We have two of them so that we can perform coordinate |
* transformations easily. |
*/ |
struct brw_reg x_coords[2]; |
/* Y coordinates. We have two of them so that we can perform coordinate |
* transformations easily. |
*/ |
struct brw_reg y_coords[2]; |
/* X, Y coordinates of the pixel from which we need to fetch the specific |
* sample. These are used for multisample scaled blitting. |
*/ |
struct brw_reg x_sample_coords; |
struct brw_reg y_sample_coords; |
/* Fractional parts of the x and y coordinates, used as bilinear interpolation coefficients */ |
struct brw_reg x_frac; |
struct brw_reg y_frac; |
/* Which element of x_coords and y_coords is currently in use. |
*/ |
int xy_coord_index; |
/* True if, at the point in the program currently being compiled, the |
* sample index is known to be zero. |
*/ |
bool s_is_zero; |
/* Register storing the sample index when s_is_zero is false. */ |
struct brw_reg sample_index; |
/* Temporaries */ |
struct brw_reg t1; |
struct brw_reg t2; |
/* MRF used for sampling and render target writes */ |
GLuint base_mrf; |
}; |
brw_blorp_blit_program::brw_blorp_blit_program( |
struct brw_context *brw, |
const brw_blorp_blit_prog_key *key) |
: mem_ctx(ralloc_context(NULL)), |
brw(brw), |
key(key) |
{ |
brw_init_compile(brw, &func, mem_ctx); |
} |
brw_blorp_blit_program::~brw_blorp_blit_program() |
{ |
ralloc_free(mem_ctx); |
} |
const GLuint * |
brw_blorp_blit_program::compile(struct brw_context *brw, |
GLuint *program_size) |
{ |
/* Sanity checks */ |
if (key->dst_tiled_w && key->rt_samples > 0) { |
/* If the destination image is W tiled and multisampled, then the thread |
* must be dispatched once per sample, not once per pixel. This is |
* necessary because after conversion between W and Y tiling, there's no |
* guarantee that all samples corresponding to a single pixel will still |
* be together. |
*/ |
assert(key->persample_msaa_dispatch); |
} |
if (key->blend) { |
/* We are blending, which means we won't have an opportunity to |
* translate the tiling and sample count for the texture surface. So |
* the surface state for the texture must be configured with the correct |
* tiling and sample count. |
*/ |
assert(!key->src_tiled_w); |
assert(key->tex_samples == key->src_samples); |
assert(key->tex_layout == key->src_layout); |
assert(key->tex_samples > 0); |
} |
if (key->persample_msaa_dispatch) { |
/* It only makes sense to do persample dispatch if the render target is |
* configured as multisampled. |
*/ |
assert(key->rt_samples > 0); |
} |
/* Make sure layout is consistent with sample count */ |
assert((key->tex_layout == INTEL_MSAA_LAYOUT_NONE) == |
(key->tex_samples == 0)); |
assert((key->rt_layout == INTEL_MSAA_LAYOUT_NONE) == |
(key->rt_samples == 0)); |
assert((key->src_layout == INTEL_MSAA_LAYOUT_NONE) == |
(key->src_samples == 0)); |
assert((key->dst_layout == INTEL_MSAA_LAYOUT_NONE) == |
(key->dst_samples == 0)); |
/* Set up prog_data */ |
memset(&prog_data, 0, sizeof(prog_data)); |
prog_data.persample_msaa_dispatch = key->persample_msaa_dispatch; |
brw_set_compression_control(&func, BRW_COMPRESSION_NONE); |
alloc_regs(); |
compute_frag_coords(); |
/* Render target and texture hardware don't support W tiling. */ |
const bool rt_tiled_w = false; |
const bool tex_tiled_w = false; |
/* The address that data will be written to is determined by the |
* coordinates supplied to the WM thread and the tiling and sample count of |
* the render target, according to the formula: |
* |
* (X, Y, S) = decode_msaa(rt_samples, detile(rt_tiling, offset)) |
* |
* If the actual tiling and sample count of the destination surface are not |
* the same as the configuration of the render target, then these |
* coordinates are wrong and we have to adjust them to compensate for the |
* difference. |
*/ |
if (rt_tiled_w != key->dst_tiled_w || |
key->rt_samples != key->dst_samples || |
key->rt_layout != key->dst_layout) { |
encode_msaa(key->rt_samples, key->rt_layout); |
/* Now (X, Y, S) = detile(rt_tiling, offset) */ |
translate_tiling(rt_tiled_w, key->dst_tiled_w); |
/* Now (X, Y, S) = detile(dst_tiling, offset) */ |
decode_msaa(key->dst_samples, key->dst_layout); |
} |
/* Now (X, Y, S) = decode_msaa(dst_samples, detile(dst_tiling, offset)). |
* |
* That is: X, Y and S now contain the true coordinates and sample index of |
* the data that the WM thread should output. |
* |
* If we need to kill pixels that are outside the destination rectangle, |
* now is the time to do it. |
*/ |
if (key->use_kill) |
kill_if_outside_dst_rect(); |
/* Next, apply a translation to obtain coordinates in the source image. */ |
translate_dst_to_src(); |
/* If the source image is not multisampled, then we want to fetch sample |
* number 0, because that's the only sample there is. |
*/ |
if (key->src_samples == 0) |
s_is_zero = true; |
/* X, Y, and S are now the coordinates of the pixel in the source image |
* that we want to texture from. Exception: if we are blending, then S is |
* irrelevant, because we are going to fetch all samples. |
*/ |
if (key->blend && !key->blit_scaled) { |
if (brw->gen == 6) { |
/* Gen6 hardware an automatically blend using the SAMPLE message */ |
single_to_blend(); |
sample(texture_data[0]); |
} else { |
/* Gen7+ hardware doesn't automaticaly blend. */ |
manual_blend_average(key->src_samples); |
} |
} else if(key->blend && key->blit_scaled) { |
manual_blend_bilinear(key->src_samples); |
} else { |
/* We aren't blending, which means we just want to fetch a single sample |
* from the source surface. The address that we want to fetch from is |
* related to the X, Y and S values according to the formula: |
* |
* (X, Y, S) = decode_msaa(src_samples, detile(src_tiling, offset)). |
* |
* If the actual tiling and sample count of the source surface are not |
* the same as the configuration of the texture, then we need to adjust |
* the coordinates to compensate for the difference. |
*/ |
if (tex_tiled_w != key->src_tiled_w || |
key->tex_samples != key->src_samples || |
key->tex_layout != key->src_layout) { |
encode_msaa(key->src_samples, key->src_layout); |
/* Now (X, Y, S) = detile(src_tiling, offset) */ |
translate_tiling(key->src_tiled_w, tex_tiled_w); |
/* Now (X, Y, S) = detile(tex_tiling, offset) */ |
decode_msaa(key->tex_samples, key->tex_layout); |
} |
/* Now (X, Y, S) = decode_msaa(tex_samples, detile(tex_tiling, offset)). |
* |
* In other words: X, Y, and S now contain values which, when passed to |
* the texturing unit, will cause data to be read from the correct |
* memory location. So we can fetch the texel now. |
*/ |
if (key->tex_layout == INTEL_MSAA_LAYOUT_CMS) |
mcs_fetch(); |
texel_fetch(texture_data[0]); |
} |
/* Finally, write the fetched (or blended) value to the render target and |
* terminate the thread. |
*/ |
render_target_write(); |
if (unlikely(INTEL_DEBUG & DEBUG_BLORP)) { |
printf("Native code for BLORP blit:\n"); |
brw_dump_compile(&func, stdout, 0, func.next_insn_offset); |
printf("\n"); |
} |
return brw_get_program(&func, program_size); |
} |
void |
brw_blorp_blit_program::alloc_push_const_regs(int base_reg) |
{ |
#define CONST_LOC(name) offsetof(brw_blorp_wm_push_constants, name) |
#define ALLOC_REG(name) \ |
this->name = \ |
brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, \ |
base_reg + CONST_LOC(name) / 32, \ |
(CONST_LOC(name) % 32) / 4) |
ALLOC_REG(dst_x0); |
ALLOC_REG(dst_x1); |
ALLOC_REG(dst_y0); |
ALLOC_REG(dst_y1); |
ALLOC_REG(sample_grid_x1); |
ALLOC_REG(sample_grid_y1); |
ALLOC_REG(x_transform.multiplier); |
ALLOC_REG(x_transform.offset); |
ALLOC_REG(y_transform.multiplier); |
ALLOC_REG(y_transform.offset); |
#undef CONST_LOC |
#undef ALLOC_REG |
} |
void |
brw_blorp_blit_program::alloc_regs() |
{ |
int reg = 0; |
this->R0 = retype(brw_vec8_grf(reg++, 0), BRW_REGISTER_TYPE_UW); |
this->R1 = retype(brw_vec8_grf(reg++, 0), BRW_REGISTER_TYPE_UW); |
prog_data.first_curbe_grf = reg; |
alloc_push_const_regs(reg); |
reg += BRW_BLORP_NUM_PUSH_CONST_REGS; |
for (unsigned i = 0; i < ARRAY_SIZE(texture_data); ++i) { |
this->texture_data[i] = |
retype(vec16(brw_vec8_grf(reg, 0)), key->texture_data_type); |
reg += 8; |
} |
this->mcs_data = |
retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); reg += 8; |
for (int i = 0; i < 2; ++i) { |
this->x_coords[i] |
= retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); |
reg += 2; |
this->y_coords[i] |
= retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); |
reg += 2; |
} |
if (key->blit_scaled && key->blend) { |
this->x_sample_coords = brw_vec8_grf(reg, 0); |
reg += 2; |
this->y_sample_coords = brw_vec8_grf(reg, 0); |
reg += 2; |
this->x_frac = brw_vec8_grf(reg, 0); |
reg += 2; |
this->y_frac = brw_vec8_grf(reg, 0); |
reg += 2; |
} |
this->xy_coord_index = 0; |
this->sample_index |
= retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); |
reg += 2; |
this->t1 = retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); |
reg += 2; |
this->t2 = retype(brw_vec8_grf(reg, 0), BRW_REGISTER_TYPE_UD); |
reg += 2; |
/* Make sure we didn't run out of registers */ |
assert(reg <= GEN7_MRF_HACK_START); |
int mrf = 2; |
this->base_mrf = mrf; |
} |
/* In the code that follows, X and Y can be used to quickly refer to the |
* active elements of x_coords and y_coords, and Xp and Yp ("X prime" and "Y |
* prime") to the inactive elements. |
* |
* S can be used to quickly refer to sample_index. |
*/ |
#define X x_coords[xy_coord_index] |
#define Y y_coords[xy_coord_index] |
#define Xp x_coords[!xy_coord_index] |
#define Yp y_coords[!xy_coord_index] |
#define S sample_index |
/* Quickly swap the roles of (X, Y) and (Xp, Yp). Saves us from having to do |
* MOVs to transfor (Xp, Yp) to (X, Y) after a coordinate transformation. |
*/ |
#define SWAP_XY_AND_XPYP() xy_coord_index = !xy_coord_index; |
/** |
* Emit code to compute the X and Y coordinates of the pixels being rendered |
* by this WM invocation. |
* |
* Assuming the render target is set up for Y tiling, these (X, Y) values are |
* related to the address offset where outputs will be written by the formula: |
* |
* (X, Y, S) = decode_msaa(detile(offset)). |
* |
* (See brw_blorp_blit_program). |
*/ |
void |
brw_blorp_blit_program::compute_frag_coords() |
{ |
/* R1.2[15:0] = X coordinate of upper left pixel of subspan 0 (pixel 0) |
* R1.3[15:0] = X coordinate of upper left pixel of subspan 1 (pixel 4) |
* R1.4[15:0] = X coordinate of upper left pixel of subspan 2 (pixel 8) |
* R1.5[15:0] = X coordinate of upper left pixel of subspan 3 (pixel 12) |
* |
* Pixels within a subspan are laid out in this arrangement: |
* 0 1 |
* 2 3 |
* |
* So, to compute the coordinates of each pixel, we need to read every 2nd |
* 16-bit value (vstride=2) from R1, starting at the 4th 16-bit value |
* (suboffset=4), and duplicate each value 4 times (hstride=0, width=4). |
* In other words, the data we want to access is R1.4<2;4,0>UW. |
* |
* Then, we need to add the repeating sequence (0, 1, 0, 1, ...) to the |
* result, since pixels n+1 and n+3 are in the right half of the subspan. |
*/ |
brw_ADD(&func, vec16(retype(X, BRW_REGISTER_TYPE_UW)), |
stride(suboffset(R1, 4), 2, 4, 0), brw_imm_v(0x10101010)); |
/* Similarly, Y coordinates for subspans come from R1.2[31:16] through |
* R1.5[31:16], so to get pixel Y coordinates we need to start at the 5th |
* 16-bit value instead of the 4th (R1.5<2;4,0>UW instead of |
* R1.4<2;4,0>UW). |
* |
* And we need to add the repeating sequence (0, 0, 1, 1, ...), since |
* pixels n+2 and n+3 are in the bottom half of the subspan. |
*/ |
brw_ADD(&func, vec16(retype(Y, BRW_REGISTER_TYPE_UW)), |
stride(suboffset(R1, 5), 2, 4, 0), brw_imm_v(0x11001100)); |
/* Move the coordinates to UD registers. */ |
brw_MOV(&func, vec16(Xp), retype(X, BRW_REGISTER_TYPE_UW)); |
brw_MOV(&func, vec16(Yp), retype(Y, BRW_REGISTER_TYPE_UW)); |
SWAP_XY_AND_XPYP(); |
if (key->persample_msaa_dispatch) { |
switch (key->rt_samples) { |
case 4: { |
/* The WM will be run in MSDISPMODE_PERSAMPLE with num_samples == 4. |
* Therefore, subspan 0 will represent sample 0, subspan 1 will |
* represent sample 1, and so on. |
* |
* So we need to populate S with the sequence (0, 0, 0, 0, 1, 1, 1, |
* 1, 2, 2, 2, 2, 3, 3, 3, 3). The easiest way to do this is to |
* populate a temporary variable with the sequence (0, 1, 2, 3), and |
* then copy from it using vstride=1, width=4, hstride=0. |
*/ |
struct brw_reg t1_uw1 = retype(t1, BRW_REGISTER_TYPE_UW); |
brw_MOV(&func, vec16(t1_uw1), brw_imm_v(0x3210)); |
/* Move to UD sample_index register. */ |
brw_MOV(&func, S, stride(t1_uw1, 1, 4, 0)); |
brw_MOV(&func, offset(S, 1), suboffset(stride(t1_uw1, 1, 4, 0), 2)); |
break; |
} |
case 8: { |
/* The WM will be run in MSDISPMODE_PERSAMPLE with num_samples == 8. |
* Therefore, subspan 0 will represent sample N (where N is 0 or 4), |
* subspan 1 will represent sample 1, and so on. We can find the |
* value of N by looking at R0.0 bits 7:6 ("Starting Sample Pair |
* Index") and multiplying by two (since samples are always delivered |
* in pairs). That is, we compute 2*((R0.0 & 0xc0) >> 6) == (R0.0 & |
* 0xc0) >> 5. |
* |
* Then we need to add N to the sequence (0, 0, 0, 0, 1, 1, 1, 1, 2, |
* 2, 2, 2, 3, 3, 3, 3), which we compute by populating a temporary |
* variable with the sequence (0, 1, 2, 3), and then reading from it |
* using vstride=1, width=4, hstride=0. |
*/ |
struct brw_reg t1_ud1 = vec1(retype(t1, BRW_REGISTER_TYPE_UD)); |
struct brw_reg t2_uw1 = retype(t2, BRW_REGISTER_TYPE_UW); |
struct brw_reg r0_ud1 = vec1(retype(R0, BRW_REGISTER_TYPE_UD)); |
brw_AND(&func, t1_ud1, r0_ud1, brw_imm_ud(0xc0)); |
brw_SHR(&func, t1_ud1, t1_ud1, brw_imm_ud(5)); |
brw_MOV(&func, vec16(t2_uw1), brw_imm_v(0x3210)); |
brw_ADD(&func, vec16(S), retype(t1_ud1, BRW_REGISTER_TYPE_UW), |
stride(t2_uw1, 1, 4, 0)); |
brw_ADD(&func, offset(S, 1), |
retype(t1_ud1, BRW_REGISTER_TYPE_UW), |
suboffset(stride(t2_uw1, 1, 4, 0), 2)); |
break; |
} |
default: |
assert(!"Unrecognized sample count in " |
"brw_blorp_blit_program::compute_frag_coords()"); |
break; |
} |
s_is_zero = false; |
} else { |
/* Either the destination surface is single-sampled, or the WM will be |
* run in MSDISPMODE_PERPIXEL (which causes a single fragment dispatch |
* per pixel). In either case, it's not meaningful to compute a sample |
* value. Just set it to 0. |
*/ |
s_is_zero = true; |
} |
} |
/** |
* Emit code to compensate for the difference between Y and W tiling. |
* |
* This code modifies the X and Y coordinates according to the formula: |
* |
* (X', Y', S') = detile(new_tiling, tile(old_tiling, X, Y, S)) |
* |
* (See brw_blorp_blit_program). |
* |
* It can only translate between W and Y tiling, so new_tiling and old_tiling |
* are booleans where true represents W tiling and false represents Y tiling. |
*/ |
void |
brw_blorp_blit_program::translate_tiling(bool old_tiled_w, bool new_tiled_w) |
{ |
if (old_tiled_w == new_tiled_w) |
return; |
/* In the code that follows, we can safely assume that S = 0, because W |
* tiling formats always use IMS layout. |
*/ |
assert(s_is_zero); |
brw_set_compression_control(&func, BRW_COMPRESSION_COMPRESSED); |
if (new_tiled_w) { |
/* Given X and Y coordinates that describe an address using Y tiling, |
* translate to the X and Y coordinates that describe the same address |
* using W tiling. |
* |
* If we break down the low order bits of X and Y, using a |
* single letter to represent each low-order bit: |
* |
* X = A << 7 | 0bBCDEFGH |
* Y = J << 5 | 0bKLMNP (1) |
* |
* Then we can apply the Y tiling formula to see the memory offset being |
* addressed: |
* |
* offset = (J * tile_pitch + A) << 12 | 0bBCDKLMNPEFGH (2) |
* |
* If we apply the W detiling formula to this memory location, that the |
* corresponding X' and Y' coordinates are: |
* |
* X' = A << 6 | 0bBCDPFH (3) |
* Y' = J << 6 | 0bKLMNEG |
* |
* Combining (1) and (3), we see that to transform (X, Y) to (X', Y'), |
* we need to make the following computation: |
* |
* X' = (X & ~0b1011) >> 1 | (Y & 0b1) << 2 | X & 0b1 (4) |
* Y' = (Y & ~0b1) << 1 | (X & 0b1000) >> 2 | (X & 0b10) >> 1 |
*/ |
brw_AND(&func, t1, X, brw_imm_uw(0xfff4)); /* X & ~0b1011 */ |
brw_SHR(&func, t1, t1, brw_imm_uw(1)); /* (X & ~0b1011) >> 1 */ |
brw_AND(&func, t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ |
brw_SHL(&func, t2, t2, brw_imm_uw(2)); /* (Y & 0b1) << 2 */ |
brw_OR(&func, t1, t1, t2); /* (X & ~0b1011) >> 1 | (Y & 0b1) << 2 */ |
brw_AND(&func, t2, X, brw_imm_uw(1)); /* X & 0b1 */ |
brw_OR(&func, Xp, t1, t2); |
brw_AND(&func, t1, Y, brw_imm_uw(0xfffe)); /* Y & ~0b1 */ |
brw_SHL(&func, t1, t1, brw_imm_uw(1)); /* (Y & ~0b1) << 1 */ |
brw_AND(&func, t2, X, brw_imm_uw(8)); /* X & 0b1000 */ |
brw_SHR(&func, t2, t2, brw_imm_uw(2)); /* (X & 0b1000) >> 2 */ |
brw_OR(&func, t1, t1, t2); /* (Y & ~0b1) << 1 | (X & 0b1000) >> 2 */ |
brw_AND(&func, t2, X, brw_imm_uw(2)); /* X & 0b10 */ |
brw_SHR(&func, t2, t2, brw_imm_uw(1)); /* (X & 0b10) >> 1 */ |
brw_OR(&func, Yp, t1, t2); |
SWAP_XY_AND_XPYP(); |
} else { |
/* Applying the same logic as above, but in reverse, we obtain the |
* formulas: |
* |
* X' = (X & ~0b101) << 1 | (Y & 0b10) << 2 | (Y & 0b1) << 1 | X & 0b1 |
* Y' = (Y & ~0b11) >> 1 | (X & 0b100) >> 2 |
*/ |
brw_AND(&func, t1, X, brw_imm_uw(0xfffa)); /* X & ~0b101 */ |
brw_SHL(&func, t1, t1, brw_imm_uw(1)); /* (X & ~0b101) << 1 */ |
brw_AND(&func, t2, Y, brw_imm_uw(2)); /* Y & 0b10 */ |
brw_SHL(&func, t2, t2, brw_imm_uw(2)); /* (Y & 0b10) << 2 */ |
brw_OR(&func, t1, t1, t2); /* (X & ~0b101) << 1 | (Y & 0b10) << 2 */ |
brw_AND(&func, t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ |
brw_SHL(&func, t2, t2, brw_imm_uw(1)); /* (Y & 0b1) << 1 */ |
brw_OR(&func, t1, t1, t2); /* (X & ~0b101) << 1 | (Y & 0b10) << 2 |
| (Y & 0b1) << 1 */ |
brw_AND(&func, t2, X, brw_imm_uw(1)); /* X & 0b1 */ |
brw_OR(&func, Xp, t1, t2); |
brw_AND(&func, t1, Y, brw_imm_uw(0xfffc)); /* Y & ~0b11 */ |
brw_SHR(&func, t1, t1, brw_imm_uw(1)); /* (Y & ~0b11) >> 1 */ |
brw_AND(&func, t2, X, brw_imm_uw(4)); /* X & 0b100 */ |
brw_SHR(&func, t2, t2, brw_imm_uw(2)); /* (X & 0b100) >> 2 */ |
brw_OR(&func, Yp, t1, t2); |
SWAP_XY_AND_XPYP(); |
} |
brw_set_compression_control(&func, BRW_COMPRESSION_NONE); |
} |
/** |
* Emit code to compensate for the difference between MSAA and non-MSAA |
* surfaces. |
* |
* This code modifies the X and Y coordinates according to the formula: |
* |
* (X', Y', S') = encode_msaa(num_samples, IMS, X, Y, S) |
* |
* (See brw_blorp_blit_program). |
*/ |
void |
brw_blorp_blit_program::encode_msaa(unsigned num_samples, |
intel_msaa_layout layout) |
{ |
brw_set_compression_control(&func, BRW_COMPRESSION_COMPRESSED); |
switch (layout) { |
case INTEL_MSAA_LAYOUT_NONE: |
/* No translation necessary, and S should already be zero. */ |
assert(s_is_zero); |
break; |
case INTEL_MSAA_LAYOUT_CMS: |
/* We can't compensate for compressed layout since at this point in the |
* program we haven't read from the MCS buffer. |
*/ |
assert(!"Bad layout in encode_msaa"); |
break; |
case INTEL_MSAA_LAYOUT_UMS: |
/* No translation necessary. */ |
break; |
case INTEL_MSAA_LAYOUT_IMS: |
switch (num_samples) { |
case 4: |
/* encode_msaa(4, IMS, X, Y, S) = (X', Y', 0) |
* where X' = (X & ~0b1) << 1 | (S & 0b1) << 1 | (X & 0b1) |
* Y' = (Y & ~0b1) << 1 | (S & 0b10) | (Y & 0b1) |
*/ |
brw_AND(&func, t1, X, brw_imm_uw(0xfffe)); /* X & ~0b1 */ |
if (!s_is_zero) { |
brw_AND(&func, t2, S, brw_imm_uw(1)); /* S & 0b1 */ |
brw_OR(&func, t1, t1, t2); /* (X & ~0b1) | (S & 0b1) */ |
} |
brw_SHL(&func, t1, t1, brw_imm_uw(1)); /* (X & ~0b1) << 1 |
| (S & 0b1) << 1 */ |
brw_AND(&func, t2, X, brw_imm_uw(1)); /* X & 0b1 */ |
brw_OR(&func, Xp, t1, t2); |
brw_AND(&func, t1, Y, brw_imm_uw(0xfffe)); /* Y & ~0b1 */ |
brw_SHL(&func, t1, t1, brw_imm_uw(1)); /* (Y & ~0b1) << 1 */ |
if (!s_is_zero) { |
brw_AND(&func, t2, S, brw_imm_uw(2)); /* S & 0b10 */ |
brw_OR(&func, t1, t1, t2); /* (Y & ~0b1) << 1 | (S & 0b10) */ |
} |
brw_AND(&func, t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ |
brw_OR(&func, Yp, t1, t2); |
break; |
case 8: |
/* encode_msaa(8, IMS, X, Y, S) = (X', Y', 0) |
* where X' = (X & ~0b1) << 2 | (S & 0b100) | (S & 0b1) << 1 |
* | (X & 0b1) |
* Y' = (Y & ~0b1) << 1 | (S & 0b10) | (Y & 0b1) |
*/ |
brw_AND(&func, t1, X, brw_imm_uw(0xfffe)); /* X & ~0b1 */ |
brw_SHL(&func, t1, t1, brw_imm_uw(2)); /* (X & ~0b1) << 2 */ |
if (!s_is_zero) { |
brw_AND(&func, t2, S, brw_imm_uw(4)); /* S & 0b100 */ |
brw_OR(&func, t1, t1, t2); /* (X & ~0b1) << 2 | (S & 0b100) */ |
brw_AND(&func, t2, S, brw_imm_uw(1)); /* S & 0b1 */ |
brw_SHL(&func, t2, t2, brw_imm_uw(1)); /* (S & 0b1) << 1 */ |
brw_OR(&func, t1, t1, t2); /* (X & ~0b1) << 2 | (S & 0b100) |
| (S & 0b1) << 1 */ |
} |
brw_AND(&func, t2, X, brw_imm_uw(1)); /* X & 0b1 */ |
brw_OR(&func, Xp, t1, t2); |
brw_AND(&func, t1, Y, brw_imm_uw(0xfffe)); /* Y & ~0b1 */ |
brw_SHL(&func, t1, t1, brw_imm_uw(1)); /* (Y & ~0b1) << 1 */ |
if (!s_is_zero) { |
brw_AND(&func, t2, S, brw_imm_uw(2)); /* S & 0b10 */ |
brw_OR(&func, t1, t1, t2); /* (Y & ~0b1) << 1 | (S & 0b10) */ |
} |
brw_AND(&func, t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ |
brw_OR(&func, Yp, t1, t2); |
break; |
} |
SWAP_XY_AND_XPYP(); |
s_is_zero = true; |
break; |
} |
brw_set_compression_control(&func, BRW_COMPRESSION_NONE); |
} |
/** |
* Emit code to compensate for the difference between MSAA and non-MSAA |
* surfaces. |
* |
* This code modifies the X and Y coordinates according to the formula: |
* |
* (X', Y', S) = decode_msaa(num_samples, IMS, X, Y, S) |
* |
* (See brw_blorp_blit_program). |
*/ |
void |
brw_blorp_blit_program::decode_msaa(unsigned num_samples, |
intel_msaa_layout layout) |
{ |
brw_set_compression_control(&func, BRW_COMPRESSION_COMPRESSED); |
switch (layout) { |
case INTEL_MSAA_LAYOUT_NONE: |
/* No translation necessary, and S should already be zero. */ |
assert(s_is_zero); |
break; |
case INTEL_MSAA_LAYOUT_CMS: |
/* We can't compensate for compressed layout since at this point in the |
* program we don't have access to the MCS buffer. |
*/ |
assert(!"Bad layout in encode_msaa"); |
break; |
case INTEL_MSAA_LAYOUT_UMS: |
/* No translation necessary. */ |
break; |
case INTEL_MSAA_LAYOUT_IMS: |
assert(s_is_zero); |
switch (num_samples) { |
case 4: |
/* decode_msaa(4, IMS, X, Y, 0) = (X', Y', S) |
* where X' = (X & ~0b11) >> 1 | (X & 0b1) |
* Y' = (Y & ~0b11) >> 1 | (Y & 0b1) |
* S = (Y & 0b10) | (X & 0b10) >> 1 |
*/ |
brw_AND(&func, t1, X, brw_imm_uw(0xfffc)); /* X & ~0b11 */ |
brw_SHR(&func, t1, t1, brw_imm_uw(1)); /* (X & ~0b11) >> 1 */ |
brw_AND(&func, t2, X, brw_imm_uw(1)); /* X & 0b1 */ |
brw_OR(&func, Xp, t1, t2); |
brw_AND(&func, t1, Y, brw_imm_uw(0xfffc)); /* Y & ~0b11 */ |
brw_SHR(&func, t1, t1, brw_imm_uw(1)); /* (Y & ~0b11) >> 1 */ |
brw_AND(&func, t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ |
brw_OR(&func, Yp, t1, t2); |
brw_AND(&func, t1, Y, brw_imm_uw(2)); /* Y & 0b10 */ |
brw_AND(&func, t2, X, brw_imm_uw(2)); /* X & 0b10 */ |
brw_SHR(&func, t2, t2, brw_imm_uw(1)); /* (X & 0b10) >> 1 */ |
brw_OR(&func, S, t1, t2); |
break; |
case 8: |
/* decode_msaa(8, IMS, X, Y, 0) = (X', Y', S) |
* where X' = (X & ~0b111) >> 2 | (X & 0b1) |
* Y' = (Y & ~0b11) >> 1 | (Y & 0b1) |
* S = (X & 0b100) | (Y & 0b10) | (X & 0b10) >> 1 |
*/ |
brw_AND(&func, t1, X, brw_imm_uw(0xfff8)); /* X & ~0b111 */ |
brw_SHR(&func, t1, t1, brw_imm_uw(2)); /* (X & ~0b111) >> 2 */ |
brw_AND(&func, t2, X, brw_imm_uw(1)); /* X & 0b1 */ |
brw_OR(&func, Xp, t1, t2); |
brw_AND(&func, t1, Y, brw_imm_uw(0xfffc)); /* Y & ~0b11 */ |
brw_SHR(&func, t1, t1, brw_imm_uw(1)); /* (Y & ~0b11) >> 1 */ |
brw_AND(&func, t2, Y, brw_imm_uw(1)); /* Y & 0b1 */ |
brw_OR(&func, Yp, t1, t2); |
brw_AND(&func, t1, X, brw_imm_uw(4)); /* X & 0b100 */ |
brw_AND(&func, t2, Y, brw_imm_uw(2)); /* Y & 0b10 */ |
brw_OR(&func, t1, t1, t2); /* (X & 0b100) | (Y & 0b10) */ |
brw_AND(&func, t2, X, brw_imm_uw(2)); /* X & 0b10 */ |
brw_SHR(&func, t2, t2, brw_imm_uw(1)); /* (X & 0b10) >> 1 */ |
brw_OR(&func, S, t1, t2); |
break; |
} |
s_is_zero = false; |
SWAP_XY_AND_XPYP(); |
break; |
} |
brw_set_compression_control(&func, BRW_COMPRESSION_NONE); |
} |
/** |
* Emit code that kills pixels whose X and Y coordinates are outside the |
* boundary of the rectangle defined by the push constants (dst_x0, dst_y0, |
* dst_x1, dst_y1). |
*/ |
void |
brw_blorp_blit_program::kill_if_outside_dst_rect() |
{ |
struct brw_reg f0 = brw_flag_reg(0, 0); |
struct brw_reg g1 = retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW); |
struct brw_reg null32 = vec16(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD)); |
brw_CMP(&func, null32, BRW_CONDITIONAL_GE, X, dst_x0); |
brw_CMP(&func, null32, BRW_CONDITIONAL_GE, Y, dst_y0); |
brw_CMP(&func, null32, BRW_CONDITIONAL_L, X, dst_x1); |
brw_CMP(&func, null32, BRW_CONDITIONAL_L, Y, dst_y1); |
brw_set_predicate_control(&func, BRW_PREDICATE_NONE); |
brw_push_insn_state(&func); |
brw_set_mask_control(&func, BRW_MASK_DISABLE); |
brw_AND(&func, g1, f0, g1); |
brw_pop_insn_state(&func); |
} |
/** |
* Emit code to translate from destination (X, Y) coordinates to source (X, Y) |
* coordinates. |
*/ |
void |
brw_blorp_blit_program::translate_dst_to_src() |
{ |
struct brw_reg X_f = retype(X, BRW_REGISTER_TYPE_F); |
struct brw_reg Y_f = retype(Y, BRW_REGISTER_TYPE_F); |
struct brw_reg Xp_f = retype(Xp, BRW_REGISTER_TYPE_F); |
struct brw_reg Yp_f = retype(Yp, BRW_REGISTER_TYPE_F); |
brw_set_compression_control(&func, BRW_COMPRESSION_COMPRESSED); |
/* Move the UD coordinates to float registers. */ |
brw_MOV(&func, Xp_f, X); |
brw_MOV(&func, Yp_f, Y); |
/* Scale and offset */ |
brw_MUL(&func, X_f, Xp_f, x_transform.multiplier); |
brw_MUL(&func, Y_f, Yp_f, y_transform.multiplier); |
brw_ADD(&func, X_f, X_f, x_transform.offset); |
brw_ADD(&func, Y_f, Y_f, y_transform.offset); |
if (key->blit_scaled && key->blend) { |
/* Translate coordinates to lay out the samples in a rectangular grid |
* roughly corresponding to sample locations. |
*/ |
brw_MUL(&func, X_f, X_f, brw_imm_f(key->x_scale)); |
brw_MUL(&func, Y_f, Y_f, brw_imm_f(key->y_scale)); |
/* Adjust coordinates so that integers represent pixel centers rather |
* than pixel edges. |
*/ |
brw_ADD(&func, X_f, X_f, brw_imm_f(-0.5)); |
brw_ADD(&func, Y_f, Y_f, brw_imm_f(-0.5)); |
/* Clamp the X, Y texture coordinates to properly handle the sampling of |
* texels on texture edges. |
*/ |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_L, |
X_f, brw_imm_f(0.0)); |
brw_MOV(&func, X_f, brw_imm_f(0.0)); |
brw_set_predicate_control(&func, BRW_PREDICATE_NONE); |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_GE, |
X_f, sample_grid_x1); |
brw_MOV(&func, X_f, sample_grid_x1); |
brw_set_predicate_control(&func, BRW_PREDICATE_NONE); |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_L, |
Y_f, brw_imm_f(0.0)); |
brw_MOV(&func, Y_f, brw_imm_f(0.0)); |
brw_set_predicate_control(&func, BRW_PREDICATE_NONE); |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_GE, |
Y_f, sample_grid_y1); |
brw_MOV(&func, Y_f, sample_grid_y1); |
brw_set_predicate_control(&func, BRW_PREDICATE_NONE); |
/* Store the fractional parts to be used as bilinear interpolation |
* coefficients. |
*/ |
brw_FRC(&func, x_frac, X_f); |
brw_FRC(&func, y_frac, Y_f); |
/* Round the float coordinates down to nearest integer */ |
brw_RNDD(&func, Xp_f, X_f); |
brw_RNDD(&func, Yp_f, Y_f); |
brw_MUL(&func, X_f, Xp_f, brw_imm_f(1 / key->x_scale)); |
brw_MUL(&func, Y_f, Yp_f, brw_imm_f(1 / key->y_scale)); |
} else { |
/* Round the float coordinates down to nearest integer by moving to |
* UD registers. |
*/ |
brw_MOV(&func, Xp, X_f); |
brw_MOV(&func, Yp, Y_f); |
} |
SWAP_XY_AND_XPYP(); |
brw_set_compression_control(&func, BRW_COMPRESSION_NONE); |
} |
/** |
* Emit code to transform the X and Y coordinates as needed for blending |
* together the different samples in an MSAA texture. |
*/ |
void |
brw_blorp_blit_program::single_to_blend() |
{ |
/* When looking up samples in an MSAA texture using the SAMPLE message, |
* Gen6 requires the texture coordinates to be odd integers (so that they |
* correspond to the center of a 2x2 block representing the four samples |
* that maxe up a pixel). So we need to multiply our X and Y coordinates |
* each by 2 and then add 1. |
*/ |
brw_set_compression_control(&func, BRW_COMPRESSION_COMPRESSED); |
brw_SHL(&func, t1, X, brw_imm_w(1)); |
brw_SHL(&func, t2, Y, brw_imm_w(1)); |
brw_ADD(&func, Xp, t1, brw_imm_w(1)); |
brw_ADD(&func, Yp, t2, brw_imm_w(1)); |
brw_set_compression_control(&func, BRW_COMPRESSION_NONE); |
SWAP_XY_AND_XPYP(); |
} |
/** |
* Count the number of trailing 1 bits in the given value. For example: |
* |
* count_trailing_one_bits(0) == 0 |
* count_trailing_one_bits(7) == 3 |
* count_trailing_one_bits(11) == 2 |
*/ |
inline int count_trailing_one_bits(unsigned value) |
{ |
#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ |
return __builtin_ctz(~value); |
#else |
return _mesa_bitcount(value & ~(value + 1)); |
#endif |
} |
void |
brw_blorp_blit_program::manual_blend_average(unsigned num_samples) |
{ |
if (key->tex_layout == INTEL_MSAA_LAYOUT_CMS) |
mcs_fetch(); |
/* We add together samples using a binary tree structure, e.g. for 4x MSAA: |
* |
* result = ((sample[0] + sample[1]) + (sample[2] + sample[3])) / 4 |
* |
* This ensures that when all samples have the same value, no numerical |
* precision is lost, since each addition operation always adds two equal |
* values, and summing two equal floating point values does not lose |
* precision. |
* |
* We perform this computation by treating the texture_data array as a |
* stack and performing the following operations: |
* |
* - push sample 0 onto stack |
* - push sample 1 onto stack |
* - add top two stack entries |
* - push sample 2 onto stack |
* - push sample 3 onto stack |
* - add top two stack entries |
* - add top two stack entries |
* - divide top stack entry by 4 |
* |
* Note that after pushing sample i onto the stack, the number of add |
* operations we do is equal to the number of trailing 1 bits in i. This |
* works provided the total number of samples is a power of two, which it |
* always is for i965. |
* |
* For integer formats, we replace the add operations with average |
* operations and skip the final division. |
*/ |
typedef struct brw_instruction *(*brw_op2_ptr)(struct brw_compile *, |
struct brw_reg, |
struct brw_reg, |
struct brw_reg); |
brw_op2_ptr combine_op = |
key->texture_data_type == BRW_REGISTER_TYPE_F ? brw_ADD : brw_AVG; |
unsigned stack_depth = 0; |
for (unsigned i = 0; i < num_samples; ++i) { |
assert(stack_depth == _mesa_bitcount(i)); /* Loop invariant */ |
/* Push sample i onto the stack */ |
assert(stack_depth < ARRAY_SIZE(texture_data)); |
if (i == 0) { |
s_is_zero = true; |
} else { |
s_is_zero = false; |
brw_MOV(&func, vec16(S), brw_imm_ud(i)); |
} |
texel_fetch(texture_data[stack_depth++]); |
if (i == 0 && key->tex_layout == INTEL_MSAA_LAYOUT_CMS) { |
/* The Ivy Bridge PRM, Vol4 Part1 p27 (Multisample Control Surface) |
* suggests an optimization: |
* |
* "A simple optimization with probable large return in |
* performance is to compare the MCS value to zero (indicating |
* all samples are on sample slice 0), and sample only from |
* sample slice 0 using ld2dss if MCS is zero." |
* |
* Note that in the case where the MCS value is zero, sampling from |
* sample slice 0 using ld2dss and sampling from sample 0 using |
* ld2dms are equivalent (since all samples are on sample slice 0). |
* Since we have already sampled from sample 0, all we need to do is |
* skip the remaining fetches and averaging if MCS is zero. |
*/ |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_NZ, |
mcs_data, brw_imm_ud(0)); |
brw_IF(&func, BRW_EXECUTE_16); |
} |
/* Do count_trailing_one_bits(i) times */ |
for (int j = count_trailing_one_bits(i); j-- > 0; ) { |
assert(stack_depth >= 2); |
--stack_depth; |
/* TODO: should use a smaller loop bound for non_RGBA formats */ |
for (int k = 0; k < 4; ++k) { |
combine_op(&func, offset(texture_data[stack_depth - 1], 2*k), |
offset(vec8(texture_data[stack_depth - 1]), 2*k), |
offset(vec8(texture_data[stack_depth]), 2*k)); |
} |
} |
} |
/* We should have just 1 sample on the stack now. */ |
assert(stack_depth == 1); |
if (key->texture_data_type == BRW_REGISTER_TYPE_F) { |
/* Scale the result down by a factor of num_samples */ |
/* TODO: should use a smaller loop bound for non-RGBA formats */ |
for (int j = 0; j < 4; ++j) { |
brw_MUL(&func, offset(texture_data[0], 2*j), |
offset(vec8(texture_data[0]), 2*j), |
brw_imm_f(1.0/num_samples)); |
} |
} |
if (key->tex_layout == INTEL_MSAA_LAYOUT_CMS) |
brw_ENDIF(&func); |
} |
void |
brw_blorp_blit_program::manual_blend_bilinear(unsigned num_samples) |
{ |
/* We do this computation by performing the following operations: |
* |
* In case of 4x, 8x MSAA: |
* - Compute the pixel coordinates and sample numbers (a, b, c, d) |
* which are later used for interpolation |
* - linearly interpolate samples a and b in X |
* - linearly interpolate samples c and d in X |
* - linearly interpolate the results of last two operations in Y |
* |
* result = lrp(lrp(a + b) + lrp(c + d)) |
*/ |
struct brw_reg Xp_f = retype(Xp, BRW_REGISTER_TYPE_F); |
struct brw_reg Yp_f = retype(Yp, BRW_REGISTER_TYPE_F); |
struct brw_reg t1_f = retype(t1, BRW_REGISTER_TYPE_F); |
struct brw_reg t2_f = retype(t2, BRW_REGISTER_TYPE_F); |
for (unsigned i = 0; i < 4; ++i) { |
assert(i < ARRAY_SIZE(texture_data)); |
s_is_zero = false; |
/* Compute pixel coordinates */ |
brw_ADD(&func, vec16(x_sample_coords), Xp_f, |
brw_imm_f((float)(i & 0x1) * (1.0 / key->x_scale))); |
brw_ADD(&func, vec16(y_sample_coords), Yp_f, |
brw_imm_f((float)((i >> 1) & 0x1) * (1.0 / key->y_scale))); |
brw_MOV(&func, vec16(X), x_sample_coords); |
brw_MOV(&func, vec16(Y), y_sample_coords); |
/* The MCS value we fetch has to match up with the pixel that we're |
* sampling from. Since we sample from different pixels in each |
* iteration of this "for" loop, the call to mcs_fetch() should be |
* here inside the loop after computing the pixel coordinates. |
*/ |
if (key->tex_layout == INTEL_MSAA_LAYOUT_CMS) |
mcs_fetch(); |
/* Compute sample index and map the sample index to a sample number. |
* Sample index layout shows the numbering of slots in a rectangular |
* grid of samples with in a pixel. Sample number layout shows the |
* rectangular grid of samples roughly corresponding to the real sample |
* locations with in a pixel. |
* In case of 4x MSAA, layout of sample indices matches the layout of |
* sample numbers: |
* --------- |
* | 0 | 1 | |
* --------- |
* | 2 | 3 | |
* --------- |
* |
* In case of 8x MSAA the two layouts don't match. |
* sample index layout : --------- sample number layout : --------- |
* | 0 | 1 | | 5 | 2 | |
* --------- --------- |
* | 2 | 3 | | 4 | 6 | |
* --------- --------- |
* | 4 | 5 | | 0 | 3 | |
* --------- --------- |
* | 6 | 7 | | 7 | 1 | |
* --------- --------- |
*/ |
brw_FRC(&func, vec16(t1_f), x_sample_coords); |
brw_FRC(&func, vec16(t2_f), y_sample_coords); |
brw_MUL(&func, vec16(t1_f), t1_f, brw_imm_f(key->x_scale)); |
brw_MUL(&func, vec16(t2_f), t2_f, brw_imm_f(key->x_scale * key->y_scale)); |
brw_ADD(&func, vec16(t1_f), t1_f, t2_f); |
brw_MOV(&func, vec16(S), t1_f); |
if (num_samples == 8) { |
/* Map the sample index to a sample number */ |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_L, |
S, brw_imm_d(4)); |
brw_IF(&func, BRW_EXECUTE_16); |
{ |
brw_MOV(&func, vec16(t2), brw_imm_d(5)); |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_EQ, |
S, brw_imm_d(1)); |
brw_MOV(&func, vec16(t2), brw_imm_d(2)); |
brw_set_predicate_control(&func, BRW_PREDICATE_NONE); |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_EQ, |
S, brw_imm_d(2)); |
brw_MOV(&func, vec16(t2), brw_imm_d(4)); |
brw_set_predicate_control(&func, BRW_PREDICATE_NONE); |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_EQ, |
S, brw_imm_d(3)); |
brw_MOV(&func, vec16(t2), brw_imm_d(6)); |
brw_set_predicate_control(&func, BRW_PREDICATE_NONE); |
} |
brw_ELSE(&func); |
{ |
brw_MOV(&func, vec16(t2), brw_imm_d(0)); |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_EQ, |
S, brw_imm_d(5)); |
brw_MOV(&func, vec16(t2), brw_imm_d(3)); |
brw_set_predicate_control(&func, BRW_PREDICATE_NONE); |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_EQ, |
S, brw_imm_d(6)); |
brw_MOV(&func, vec16(t2), brw_imm_d(7)); |
brw_set_predicate_control(&func, BRW_PREDICATE_NONE); |
brw_CMP(&func, vec16(brw_null_reg()), BRW_CONDITIONAL_EQ, |
S, brw_imm_d(7)); |
brw_MOV(&func, vec16(t2), brw_imm_d(1)); |
brw_set_predicate_control(&func, BRW_PREDICATE_NONE); |
} |
brw_ENDIF(&func); |
brw_MOV(&func, vec16(S), t2); |
} |
texel_fetch(texture_data[i]); |
} |
#define SAMPLE(x, y) offset(texture_data[x], y) |
brw_set_access_mode(&func, BRW_ALIGN_16); |
for (int index = 3; index > 0; ) { |
/* Since we're doing SIMD16, 4 color channels fits in to 8 registers. |
* Counter value of 8 in 'for' loop below is used to interpolate all |
* the color components. |
*/ |
for (int k = 0; k < 8; ++k) |
brw_LRP(&func, |
vec8(SAMPLE(index - 1, k)), |
offset(x_frac, k & 1), |
SAMPLE(index, k), |
SAMPLE(index - 1, k)); |
index -= 2; |
} |
for (int k = 0; k < 8; ++k) |
brw_LRP(&func, |
vec8(SAMPLE(0, k)), |
offset(y_frac, k & 1), |
vec8(SAMPLE(2, k)), |
vec8(SAMPLE(0, k))); |
brw_set_access_mode(&func, BRW_ALIGN_1); |
#undef SAMPLE |
} |
/** |
* Emit code to look up a value in the texture using the SAMPLE message (which |
* does blending of MSAA surfaces). |
*/ |
void |
brw_blorp_blit_program::sample(struct brw_reg dst) |
{ |
static const sampler_message_arg args[2] = { |
SAMPLER_MESSAGE_ARG_U_FLOAT, |
SAMPLER_MESSAGE_ARG_V_FLOAT |
}; |
texture_lookup(dst, GEN5_SAMPLER_MESSAGE_SAMPLE, args, |
ARRAY_SIZE(args)); |
} |
/** |
* Emit code to look up a value in the texture using the SAMPLE_LD message |
* (which does a simple texel fetch). |
*/ |
void |
brw_blorp_blit_program::texel_fetch(struct brw_reg dst) |
{ |
static const sampler_message_arg gen6_args[5] = { |
SAMPLER_MESSAGE_ARG_U_INT, |
SAMPLER_MESSAGE_ARG_V_INT, |
SAMPLER_MESSAGE_ARG_ZERO_INT, /* R */ |
SAMPLER_MESSAGE_ARG_ZERO_INT, /* LOD */ |
SAMPLER_MESSAGE_ARG_SI_INT |
}; |
static const sampler_message_arg gen7_ld_args[3] = { |
SAMPLER_MESSAGE_ARG_U_INT, |
SAMPLER_MESSAGE_ARG_ZERO_INT, /* LOD */ |
SAMPLER_MESSAGE_ARG_V_INT |
}; |
static const sampler_message_arg gen7_ld2dss_args[3] = { |
SAMPLER_MESSAGE_ARG_SI_INT, |
SAMPLER_MESSAGE_ARG_U_INT, |
SAMPLER_MESSAGE_ARG_V_INT |
}; |
static const sampler_message_arg gen7_ld2dms_args[4] = { |
SAMPLER_MESSAGE_ARG_SI_INT, |
SAMPLER_MESSAGE_ARG_MCS_INT, |
SAMPLER_MESSAGE_ARG_U_INT, |
SAMPLER_MESSAGE_ARG_V_INT |
}; |
switch (brw->gen) { |
case 6: |
texture_lookup(dst, GEN5_SAMPLER_MESSAGE_SAMPLE_LD, gen6_args, |
s_is_zero ? 2 : 5); |
break; |
case 7: |
switch (key->tex_layout) { |
case INTEL_MSAA_LAYOUT_IMS: |
/* From the Ivy Bridge PRM, Vol4 Part1 p72 (Multisampled Surface Storage |
* Format): |
* |
* If this field is MSFMT_DEPTH_STENCIL |
* [a.k.a. INTEL_MSAA_LAYOUT_IMS], the only sampling engine |
* messages allowed are "ld2dms", "resinfo", and "sampleinfo". |
* |
* So fall through to emit the same message as we use for |
* INTEL_MSAA_LAYOUT_CMS. |
*/ |
case INTEL_MSAA_LAYOUT_CMS: |
texture_lookup(dst, GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DMS, |
gen7_ld2dms_args, ARRAY_SIZE(gen7_ld2dms_args)); |
break; |
case INTEL_MSAA_LAYOUT_UMS: |
texture_lookup(dst, GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DSS, |
gen7_ld2dss_args, ARRAY_SIZE(gen7_ld2dss_args)); |
break; |
case INTEL_MSAA_LAYOUT_NONE: |
assert(s_is_zero); |
texture_lookup(dst, GEN5_SAMPLER_MESSAGE_SAMPLE_LD, gen7_ld_args, |
ARRAY_SIZE(gen7_ld_args)); |
break; |
} |
break; |
default: |
assert(!"Should not get here."); |
break; |
}; |
} |
void |
brw_blorp_blit_program::mcs_fetch() |
{ |
static const sampler_message_arg gen7_ld_mcs_args[2] = { |
SAMPLER_MESSAGE_ARG_U_INT, |
SAMPLER_MESSAGE_ARG_V_INT |
}; |
texture_lookup(vec16(mcs_data), GEN7_SAMPLER_MESSAGE_SAMPLE_LD_MCS, |
gen7_ld_mcs_args, ARRAY_SIZE(gen7_ld_mcs_args)); |
} |
void |
brw_blorp_blit_program::texture_lookup(struct brw_reg dst, |
GLuint msg_type, |
const sampler_message_arg *args, |
int num_args) |
{ |
struct brw_reg mrf = |
retype(vec16(brw_message_reg(base_mrf)), BRW_REGISTER_TYPE_UD); |
for (int arg = 0; arg < num_args; ++arg) { |
switch (args[arg]) { |
case SAMPLER_MESSAGE_ARG_U_FLOAT: |
brw_MOV(&func, retype(mrf, BRW_REGISTER_TYPE_F), X); |
break; |
case SAMPLER_MESSAGE_ARG_V_FLOAT: |
brw_MOV(&func, retype(mrf, BRW_REGISTER_TYPE_F), Y); |
break; |
case SAMPLER_MESSAGE_ARG_U_INT: |
brw_MOV(&func, mrf, X); |
break; |
case SAMPLER_MESSAGE_ARG_V_INT: |
brw_MOV(&func, mrf, Y); |
break; |
case SAMPLER_MESSAGE_ARG_SI_INT: |
/* Note: on Gen7, this code may be reached with s_is_zero==true |
* because in Gen7's ld2dss message, the sample index is the first |
* argument. When this happens, we need to move a 0 into the |
* appropriate message register. |
*/ |
if (s_is_zero) |
brw_MOV(&func, mrf, brw_imm_ud(0)); |
else |
brw_MOV(&func, mrf, S); |
break; |
case SAMPLER_MESSAGE_ARG_MCS_INT: |
switch (key->tex_layout) { |
case INTEL_MSAA_LAYOUT_CMS: |
brw_MOV(&func, mrf, mcs_data); |
break; |
case INTEL_MSAA_LAYOUT_IMS: |
/* When sampling from an IMS surface, MCS data is not relevant, |
* and the hardware ignores it. So don't bother populating it. |
*/ |
break; |
default: |
/* We shouldn't be trying to send MCS data with any other |
* layouts. |
*/ |
assert (!"Unsupported layout for MCS data"); |
break; |
} |
break; |
case SAMPLER_MESSAGE_ARG_ZERO_INT: |
brw_MOV(&func, mrf, brw_imm_ud(0)); |
break; |
} |
mrf.nr += 2; |
} |
brw_SAMPLE(&func, |
retype(dst, BRW_REGISTER_TYPE_F) /* dest */, |
base_mrf /* msg_reg_nr */, |
brw_message_reg(base_mrf) /* src0 */, |
BRW_BLORP_TEXTURE_BINDING_TABLE_INDEX, |
0 /* sampler */, |
msg_type, |
8 /* response_length. TODO: should be smaller for non-RGBA formats? */, |
mrf.nr - base_mrf /* msg_length */, |
0 /* header_present */, |
BRW_SAMPLER_SIMD_MODE_SIMD16, |
BRW_SAMPLER_RETURN_FORMAT_FLOAT32); |
} |
#undef X |
#undef Y |
#undef U |
#undef V |
#undef S |
#undef SWAP_XY_AND_XPYP |
void |
brw_blorp_blit_program::render_target_write() |
{ |
struct brw_reg mrf_rt_write = |
retype(vec16(brw_message_reg(base_mrf)), key->texture_data_type); |
int mrf_offset = 0; |
/* If we may have killed pixels, then we need to send R0 and R1 in a header |
* so that the render target knows which pixels we killed. |
*/ |
bool use_header = key->use_kill; |
if (use_header) { |
/* Copy R0/1 to MRF */ |
brw_MOV(&func, retype(mrf_rt_write, BRW_REGISTER_TYPE_UD), |
retype(R0, BRW_REGISTER_TYPE_UD)); |
mrf_offset += 2; |
} |
/* Copy texture data to MRFs */ |
for (int i = 0; i < 4; ++i) { |
/* E.g. mov(16) m2.0<1>:f r2.0<8;8,1>:f { Align1, H1 } */ |
brw_MOV(&func, offset(mrf_rt_write, mrf_offset), |
offset(vec8(texture_data[0]), 2*i)); |
mrf_offset += 2; |
} |
/* Now write to the render target and terminate the thread */ |
brw_fb_WRITE(&func, |
16 /* dispatch_width */, |
base_mrf /* msg_reg_nr */, |
mrf_rt_write /* src0 */, |
BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE, |
BRW_BLORP_RENDERBUFFER_BINDING_TABLE_INDEX, |
mrf_offset /* msg_length. TODO: Should be smaller for non-RGBA formats. */, |
0 /* response_length */, |
true /* eot */, |
use_header); |
} |
void |
brw_blorp_coord_transform_params::setup(GLfloat src0, GLfloat src1, |
GLfloat dst0, GLfloat dst1, |
bool mirror) |
{ |
float scale = (src1 - src0) / (dst1 - dst0); |
if (!mirror) { |
/* When not mirroring a coordinate (say, X), we need: |
* src_x - src_x0 = (dst_x - dst_x0 + 0.5) * scale |
* Therefore: |
* src_x = src_x0 + (dst_x - dst_x0 + 0.5) * scale |
* |
* blorp program uses "round toward zero" to convert the |
* transformed floating point coordinates to integer coordinates, |
* whereas the behaviour we actually want is "round to nearest", |
* so 0.5 provides the necessary correction. |
*/ |
multiplier = scale; |
offset = src0 + (-dst0 + 0.5) * scale; |
} else { |
/* When mirroring X we need: |
* src_x - src_x0 = dst_x1 - dst_x - 0.5 |
* Therefore: |
* src_x = src_x0 + (dst_x1 -dst_x - 0.5) * scale |
*/ |
multiplier = -scale; |
offset = src0 + (dst1 - 0.5) * scale; |
} |
} |
/** |
* Determine which MSAA layout the GPU pipeline should be configured for, |
* based on the chip generation, the number of samples, and the true layout of |
* the image in memory. |
*/ |
inline intel_msaa_layout |
compute_msaa_layout_for_pipeline(struct brw_context *brw, unsigned num_samples, |
intel_msaa_layout true_layout) |
{ |
if (num_samples <= 1) { |
/* When configuring the GPU for non-MSAA, we can still accommodate IMS |
* format buffers, by transforming coordinates appropriately. |
*/ |
assert(true_layout == INTEL_MSAA_LAYOUT_NONE || |
true_layout == INTEL_MSAA_LAYOUT_IMS); |
return INTEL_MSAA_LAYOUT_NONE; |
} else { |
assert(true_layout != INTEL_MSAA_LAYOUT_NONE); |
} |
/* Prior to Gen7, all MSAA surfaces use IMS layout. */ |
if (brw->gen == 6) { |
assert(true_layout == INTEL_MSAA_LAYOUT_IMS); |
} |
return true_layout; |
} |
brw_blorp_blit_params::brw_blorp_blit_params(struct brw_context *brw, |
struct intel_mipmap_tree *src_mt, |
unsigned src_level, unsigned src_layer, |
struct intel_mipmap_tree *dst_mt, |
unsigned dst_level, unsigned dst_layer, |
GLfloat src_x0, GLfloat src_y0, |
GLfloat src_x1, GLfloat src_y1, |
GLfloat dst_x0, GLfloat dst_y0, |
GLfloat dst_x1, GLfloat dst_y1, |
bool mirror_x, bool mirror_y) |
{ |
struct gl_context *ctx = &brw->ctx; |
const struct gl_framebuffer *read_fb = ctx->ReadBuffer; |
src.set(brw, src_mt, src_level, src_layer); |
dst.set(brw, dst_mt, dst_level, dst_layer); |
src.brw_surfaceformat = dst.brw_surfaceformat; |
use_wm_prog = true; |
memset(&wm_prog_key, 0, sizeof(wm_prog_key)); |
/* texture_data_type indicates the register type that should be used to |
* manipulate texture data. |
*/ |
switch (_mesa_get_format_datatype(src_mt->format)) { |
case GL_UNSIGNED_NORMALIZED: |
case GL_SIGNED_NORMALIZED: |
case GL_FLOAT: |
wm_prog_key.texture_data_type = BRW_REGISTER_TYPE_F; |
break; |
case GL_UNSIGNED_INT: |
if (src_mt->format == MESA_FORMAT_S8) { |
/* We process stencil as though it's an unsigned normalized color */ |
wm_prog_key.texture_data_type = BRW_REGISTER_TYPE_F; |
} else { |
wm_prog_key.texture_data_type = BRW_REGISTER_TYPE_UD; |
} |
break; |
case GL_INT: |
wm_prog_key.texture_data_type = BRW_REGISTER_TYPE_D; |
break; |
default: |
assert(!"Unrecognized blorp format"); |
break; |
} |
if (brw->gen > 6) { |
/* Gen7's rendering hardware only supports the IMS layout for depth and |
* stencil render targets. Blorp always maps its destination surface as |
* a color render target (even if it's actually a depth or stencil |
* buffer). So if the destination is IMS, we'll have to map it as a |
* single-sampled texture and interleave the samples ourselves. |
*/ |
if (dst_mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS) |
dst.num_samples = 0; |
} |
if (dst.map_stencil_as_y_tiled && dst.num_samples > 1) { |
/* If the destination surface is a W-tiled multisampled stencil buffer |
* that we're mapping as Y tiled, then we need to arrange for the WM |
* program to run once per sample rather than once per pixel, because |
* the memory layout of related samples doesn't match between W and Y |
* tiling. |
*/ |
wm_prog_key.persample_msaa_dispatch = true; |
} |
if (src.num_samples > 0 && dst.num_samples > 1) { |
/* We are blitting from a multisample buffer to a multisample buffer, so |
* we must preserve samples within a pixel. This means we have to |
* arrange for the WM program to run once per sample rather than once |
* per pixel. |
*/ |
wm_prog_key.persample_msaa_dispatch = true; |
} |
/* Scaled blitting or not. */ |
wm_prog_key.blit_scaled = |
((dst_x1 - dst_x0) == (src_x1 - src_x0) && |
(dst_y1 - dst_y0) == (src_y1 - src_y0)) ? false : true; |
/* Scaling factors used for bilinear filtering in multisample scaled |
* blits. |
*/ |
wm_prog_key.x_scale = 2.0; |
wm_prog_key.y_scale = src_mt->num_samples / 2.0; |
/* The render path must be configured to use the same number of samples as |
* the destination buffer. |
*/ |
num_samples = dst.num_samples; |
GLenum base_format = _mesa_get_format_base_format(src_mt->format); |
if (base_format != GL_DEPTH_COMPONENT && /* TODO: what about depth/stencil? */ |
base_format != GL_STENCIL_INDEX && |
src_mt->num_samples > 1 && dst_mt->num_samples <= 1) { |
/* We are downsampling a color buffer, so blend. */ |
wm_prog_key.blend = true; |
} |
/* src_samples and dst_samples are the true sample counts */ |
wm_prog_key.src_samples = src_mt->num_samples; |
wm_prog_key.dst_samples = dst_mt->num_samples; |
/* tex_samples and rt_samples are the sample counts that are set up in |
* SURFACE_STATE. |
*/ |
wm_prog_key.tex_samples = src.num_samples; |
wm_prog_key.rt_samples = dst.num_samples; |
/* tex_layout and rt_layout indicate the MSAA layout the GPU pipeline will |
* use to access the source and destination surfaces. |
*/ |
wm_prog_key.tex_layout = |
compute_msaa_layout_for_pipeline(brw, src.num_samples, src.msaa_layout); |
wm_prog_key.rt_layout = |
compute_msaa_layout_for_pipeline(brw, dst.num_samples, dst.msaa_layout); |
/* src_layout and dst_layout indicate the true MSAA layout used by src and |
* dst. |
*/ |
wm_prog_key.src_layout = src_mt->msaa_layout; |
wm_prog_key.dst_layout = dst_mt->msaa_layout; |
wm_prog_key.src_tiled_w = src.map_stencil_as_y_tiled; |
wm_prog_key.dst_tiled_w = dst.map_stencil_as_y_tiled; |
x0 = wm_push_consts.dst_x0 = dst_x0; |
y0 = wm_push_consts.dst_y0 = dst_y0; |
x1 = wm_push_consts.dst_x1 = dst_x1; |
y1 = wm_push_consts.dst_y1 = dst_y1; |
wm_push_consts.sample_grid_x1 = read_fb->Width * wm_prog_key.x_scale - 1.0; |
wm_push_consts.sample_grid_y1 = read_fb->Height * wm_prog_key.y_scale - 1.0; |
wm_push_consts.x_transform.setup(src_x0, src_x1, dst_x0, dst_x1, mirror_x); |
wm_push_consts.y_transform.setup(src_y0, src_y1, dst_y0, dst_y1, mirror_y); |
if (dst.num_samples <= 1 && dst_mt->num_samples > 1) { |
/* We must expand the rectangle we send through the rendering pipeline, |
* to account for the fact that we are mapping the destination region as |
* single-sampled when it is in fact multisampled. We must also align |
* it to a multiple of the multisampling pattern, because the |
* differences between multisampled and single-sampled surface formats |
* will mean that pixels are scrambled within the multisampling pattern. |
* TODO: what if this makes the coordinates too large? |
* |
* Note: this only works if the destination surface uses the IMS layout. |
* If it's UMS, then we have no choice but to set up the rendering |
* pipeline as multisampled. |
*/ |
assert(dst_mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS); |
switch (dst_mt->num_samples) { |
case 4: |
x0 = ROUND_DOWN_TO(x0 * 2, 4); |
y0 = ROUND_DOWN_TO(y0 * 2, 4); |
x1 = ALIGN(x1 * 2, 4); |
y1 = ALIGN(y1 * 2, 4); |
break; |
case 8: |
x0 = ROUND_DOWN_TO(x0 * 4, 8); |
y0 = ROUND_DOWN_TO(y0 * 2, 4); |
x1 = ALIGN(x1 * 4, 8); |
y1 = ALIGN(y1 * 2, 4); |
break; |
default: |
assert(!"Unrecognized sample count in brw_blorp_blit_params ctor"); |
break; |
} |
wm_prog_key.use_kill = true; |
} |
if (dst.map_stencil_as_y_tiled) { |
/* We must modify the rectangle we send through the rendering pipeline |
* (and the size and x/y offset of the destination surface), to account |
* for the fact that we are mapping it as Y-tiled when it is in fact |
* W-tiled. |
* |
* Both Y tiling and W tiling can be understood as organizations of |
* 32-byte sub-tiles; within each 32-byte sub-tile, the layout of pixels |
* is different, but the layout of the 32-byte sub-tiles within the 4k |
* tile is the same (8 sub-tiles across by 16 sub-tiles down, in |
* column-major order). In Y tiling, the sub-tiles are 16 bytes wide |
* and 2 rows high; in W tiling, they are 8 bytes wide and 4 rows high. |
* |
* Therefore, to account for the layout differences within the 32-byte |
* sub-tiles, we must expand the rectangle so the X coordinates of its |
* edges are multiples of 8 (the W sub-tile width), and its Y |
* coordinates of its edges are multiples of 4 (the W sub-tile height). |
* Then we need to scale the X and Y coordinates of the rectangle to |
* account for the differences in aspect ratio between the Y and W |
* sub-tiles. We need to modify the layer width and height similarly. |
* |
* A correction needs to be applied when MSAA is in use: since |
* INTEL_MSAA_LAYOUT_IMS uses an interleaving pattern whose height is 4, |
* we need to align the Y coordinates to multiples of 8, so that when |
* they are divided by two they are still multiples of 4. |
* |
* Note: Since the x/y offset of the surface will be applied using the |
* SURFACE_STATE command packet, it will be invisible to the swizzling |
* code in the shader; therefore it needs to be in a multiple of the |
* 32-byte sub-tile size. Fortunately it is, since the sub-tile is 8 |
* pixels wide and 4 pixels high (when viewed as a W-tiled stencil |
* buffer), and the miplevel alignment used for stencil buffers is 8 |
* pixels horizontally and either 4 or 8 pixels vertically (see |
* intel_horizontal_texture_alignment_unit() and |
* intel_vertical_texture_alignment_unit()). |
* |
* Note: Also, since the SURFACE_STATE command packet can only apply |
* offsets that are multiples of 4 pixels horizontally and 2 pixels |
* vertically, it is important that the offsets will be multiples of |
* these sizes after they are converted into Y-tiled coordinates. |
* Fortunately they will be, since we know from above that the offsets |
* are a multiple of the 32-byte sub-tile size, and in Y-tiled |
* coordinates the sub-tile is 16 pixels wide and 2 pixels high. |
* |
* TODO: what if this makes the coordinates (or the texture size) too |
* large? |
*/ |
const unsigned x_align = 8, y_align = dst.num_samples != 0 ? 8 : 4; |
x0 = ROUND_DOWN_TO(x0, x_align) * 2; |
y0 = ROUND_DOWN_TO(y0, y_align) / 2; |
x1 = ALIGN(x1, x_align) * 2; |
y1 = ALIGN(y1, y_align) / 2; |
dst.width = ALIGN(dst.width, x_align) * 2; |
dst.height = ALIGN(dst.height, y_align) / 2; |
dst.x_offset *= 2; |
dst.y_offset /= 2; |
wm_prog_key.use_kill = true; |
} |
if (src.map_stencil_as_y_tiled) { |
/* We must modify the size and x/y offset of the source surface to |
* account for the fact that we are mapping it as Y-tiled when it is in |
* fact W tiled. |
* |
* See the comments above concerning x/y offset alignment for the |
* destination surface. |
* |
* TODO: what if this makes the texture size too large? |
*/ |
const unsigned x_align = 8, y_align = src.num_samples != 0 ? 8 : 4; |
src.width = ALIGN(src.width, x_align) * 2; |
src.height = ALIGN(src.height, y_align) / 2; |
src.x_offset *= 2; |
src.y_offset /= 2; |
} |
} |
uint32_t |
brw_blorp_blit_params::get_wm_prog(struct brw_context *brw, |
brw_blorp_prog_data **prog_data) const |
{ |
uint32_t prog_offset = 0; |
if (!brw_search_cache(&brw->cache, BRW_BLORP_BLIT_PROG, |
&this->wm_prog_key, sizeof(this->wm_prog_key), |
&prog_offset, prog_data)) { |
brw_blorp_blit_program prog(brw, &this->wm_prog_key); |
GLuint program_size; |
const GLuint *program = prog.compile(brw, &program_size); |
brw_upload_cache(&brw->cache, BRW_BLORP_BLIT_PROG, |
&this->wm_prog_key, sizeof(this->wm_prog_key), |
program, program_size, |
&prog.prog_data, sizeof(prog.prog_data), |
&prog_offset, prog_data); |
} |
return prog_offset; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_blorp_clear.cpp |
---|
0,0 → 1,538 |
/* |
* Copyright © 2013 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. |
*/ |
extern "C" { |
#include "main/teximage.h" |
#include "main/blend.h" |
#include "main/fbobject.h" |
#include "main/renderbuffer.h" |
} |
#include "glsl/ralloc.h" |
#include "intel_fbo.h" |
#include "brw_blorp.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_state.h" |
#define FILE_DEBUG_FLAG DEBUG_BLORP |
struct brw_blorp_const_color_prog_key |
{ |
bool use_simd16_replicated_data; |
bool pad[3]; |
}; |
/** |
* Parameters for a blorp operation where the fragment shader outputs a |
* constant color. This is used for both fast color clears and color |
* resolves. |
*/ |
class brw_blorp_const_color_params : public brw_blorp_params |
{ |
public: |
virtual uint32_t get_wm_prog(struct brw_context *brw, |
brw_blorp_prog_data **prog_data) const; |
protected: |
brw_blorp_const_color_prog_key wm_prog_key; |
}; |
class brw_blorp_clear_params : public brw_blorp_const_color_params |
{ |
public: |
brw_blorp_clear_params(struct brw_context *brw, |
struct gl_framebuffer *fb, |
struct gl_renderbuffer *rb, |
GLubyte *color_mask, |
bool partial_clear); |
}; |
/** |
* Parameters for a blorp operation that performs a "render target resolve". |
* This is used to resolve pending fast clear pixels before a color buffer is |
* used for texturing, ReadPixels, or scanout. |
*/ |
class brw_blorp_rt_resolve_params : public brw_blorp_const_color_params |
{ |
public: |
brw_blorp_rt_resolve_params(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
}; |
class brw_blorp_const_color_program |
{ |
public: |
brw_blorp_const_color_program(struct brw_context *brw, |
const brw_blorp_const_color_prog_key *key); |
~brw_blorp_const_color_program(); |
const GLuint *compile(struct brw_context *brw, GLuint *program_size); |
brw_blorp_prog_data prog_data; |
private: |
void alloc_regs(); |
void *mem_ctx; |
struct brw_context *brw; |
const brw_blorp_const_color_prog_key *key; |
struct brw_compile func; |
/* Thread dispatch header */ |
struct brw_reg R0; |
/* Pixel X/Y coordinates (always in R1). */ |
struct brw_reg R1; |
/* Register with push constants (a single vec4) */ |
struct brw_reg clear_rgba; |
/* MRF used for render target writes */ |
GLuint base_mrf; |
}; |
brw_blorp_const_color_program::brw_blorp_const_color_program( |
struct brw_context *brw, |
const brw_blorp_const_color_prog_key *key) |
: mem_ctx(ralloc_context(NULL)), |
brw(brw), |
key(key), |
R0(), |
R1(), |
clear_rgba(), |
base_mrf(0) |
{ |
brw_init_compile(brw, &func, mem_ctx); |
} |
brw_blorp_const_color_program::~brw_blorp_const_color_program() |
{ |
ralloc_free(mem_ctx); |
} |
/** |
* Determine if fast color clear supports the given clear color. |
* |
* Fast color clear can only clear to color values of 1.0 or 0.0. At the |
* moment we only support floating point, unorm, and snorm buffers. |
*/ |
static bool |
is_color_fast_clear_compatible(struct brw_context *brw, |
gl_format format, |
const union gl_color_union *color) |
{ |
if (_mesa_is_format_integer_color(format)) |
return false; |
for (int i = 0; i < 4; i++) { |
if (color->f[i] != 0.0 && color->f[i] != 1.0) { |
perf_debug("Clear color unsupported by fast color clear. " |
"Falling back to slow clear.\n"); |
return false; |
} |
} |
return true; |
} |
/** |
* Convert the given color to a bitfield suitable for ORing into DWORD 7 of |
* SURFACE_STATE. |
*/ |
static uint32_t |
compute_fast_clear_color_bits(const union gl_color_union *color) |
{ |
uint32_t bits = 0; |
for (int i = 0; i < 4; i++) { |
if (color->f[i] != 0.0) |
bits |= 1 << (GEN7_SURFACE_CLEAR_COLOR_SHIFT + (3 - i)); |
} |
return bits; |
} |
brw_blorp_clear_params::brw_blorp_clear_params(struct brw_context *brw, |
struct gl_framebuffer *fb, |
struct gl_renderbuffer *rb, |
GLubyte *color_mask, |
bool partial_clear) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
dst.set(brw, irb->mt, irb->mt_level, irb->mt_layer); |
/* Override the surface format according to the context's sRGB rules. */ |
gl_format format = _mesa_get_render_format(ctx, irb->mt->format); |
dst.brw_surfaceformat = brw->render_target_format[format]; |
x0 = fb->_Xmin; |
x1 = fb->_Xmax; |
if (rb->Name != 0) { |
y0 = fb->_Ymin; |
y1 = fb->_Ymax; |
} else { |
y0 = rb->Height - fb->_Ymax; |
y1 = rb->Height - fb->_Ymin; |
} |
float *push_consts = (float *)&wm_push_consts; |
push_consts[0] = ctx->Color.ClearColor.f[0]; |
push_consts[1] = ctx->Color.ClearColor.f[1]; |
push_consts[2] = ctx->Color.ClearColor.f[2]; |
push_consts[3] = ctx->Color.ClearColor.f[3]; |
use_wm_prog = true; |
memset(&wm_prog_key, 0, sizeof(wm_prog_key)); |
wm_prog_key.use_simd16_replicated_data = true; |
/* From the SNB PRM (Vol4_Part1): |
* |
* "Replicated data (Message Type = 111) is only supported when |
* accessing tiled memory. Using this Message Type to access linear |
* (untiled) memory is UNDEFINED." |
*/ |
if (irb->mt->region->tiling == I915_TILING_NONE) |
wm_prog_key.use_simd16_replicated_data = false; |
/* Constant color writes ignore everyting in blend and color calculator |
* state. This is not documented. |
*/ |
for (int i = 0; i < 4; i++) { |
if (!color_mask[i]) { |
color_write_disable[i] = true; |
wm_prog_key.use_simd16_replicated_data = false; |
} |
} |
/* If we can do this as a fast color clear, do so. */ |
if (irb->mt->mcs_state != INTEL_MCS_STATE_NONE && !partial_clear && |
wm_prog_key.use_simd16_replicated_data && |
is_color_fast_clear_compatible(brw, format, &ctx->Color.ClearColor)) { |
memset(push_consts, 0xff, 4*sizeof(float)); |
fast_clear_op = GEN7_FAST_CLEAR_OP_FAST_CLEAR; |
/* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render |
* Target(s)", beneath the "Fast Color Clear" bullet (p327): |
* |
* Clear pass must have a clear rectangle that must follow alignment |
* rules in terms of pixels and lines as shown in the table |
* below. Further, the clear-rectangle height and width must be |
* multiple of the following dimensions. If the height and width of |
* the render target being cleared do not meet these requirements, |
* an MCS buffer can be created such that it follows the requirement |
* and covers the RT. |
* |
* The alignment size in the table that follows is related to the |
* alignment size returned by intel_get_non_msrt_mcs_alignment(), but |
* with X alignment multiplied by 16 and Y alignment multiplied by 32. |
*/ |
unsigned x_align, y_align; |
intel_get_non_msrt_mcs_alignment(brw, irb->mt, &x_align, &y_align); |
x_align *= 16; |
y_align *= 32; |
if (brw->is_haswell && brw->gt == 3) { |
/* From BSpec: 3D-Media-GPGPU Engine > 3D Pipeline > Pixel > Pixel |
* Backend > MCS Buffer for Render Target(s) [DevIVB+]: |
* [DevHSW:GT3]: Clear rectangle must be aligned to two times the |
* number of pixels in the table shown below... |
* x_align, y_align values computed above are the relevant entries |
* in the referred table. |
*/ |
x0 = ROUND_DOWN_TO(x0, 2 * x_align); |
y0 = ROUND_DOWN_TO(y0, 2 * y_align); |
x1 = ALIGN(x1, 2 * x_align); |
y1 = ALIGN(y1, 2 * y_align); |
} else { |
x0 = ROUND_DOWN_TO(x0, x_align); |
y0 = ROUND_DOWN_TO(y0, y_align); |
x1 = ALIGN(x1, x_align); |
y1 = ALIGN(y1, y_align); |
} |
/* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render |
* Target(s)", beneath the "Fast Color Clear" bullet (p327): |
* |
* In order to optimize the performance MCS buffer (when bound to 1X |
* RT) clear similarly to MCS buffer clear for MSRT case, clear rect |
* is required to be scaled by the following factors in the |
* horizontal and vertical directions: |
* |
* The X and Y scale down factors in the table that follows are each |
* equal to half the alignment value computed above. |
*/ |
unsigned x_scaledown = x_align / 2; |
unsigned y_scaledown = y_align / 2; |
x0 /= x_scaledown; |
y0 /= y_scaledown; |
x1 /= x_scaledown; |
y1 /= y_scaledown; |
} |
} |
brw_blorp_rt_resolve_params::brw_blorp_rt_resolve_params( |
struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
dst.set(brw, mt, 0 /* level */, 0 /* layer */); |
/* From the Ivy Bridge PRM, Vol2 Part1 11.9 "Render Target Resolve": |
* |
* A rectangle primitive must be scaled down by the following factors |
* with respect to render target being resolved. |
* |
* The scaledown factors in the table that follows are related to the |
* alignment size returned by intel_get_non_msrt_mcs_alignment(), but with |
* X and Y alignment each divided by 2. |
*/ |
unsigned x_align, y_align; |
intel_get_non_msrt_mcs_alignment(brw, mt, &x_align, &y_align); |
unsigned x_scaledown = x_align / 2; |
unsigned y_scaledown = y_align / 2; |
x0 = y0 = 0; |
x1 = ALIGN(mt->logical_width0, x_scaledown) / x_scaledown; |
y1 = ALIGN(mt->logical_height0, y_scaledown) / y_scaledown; |
fast_clear_op = GEN7_FAST_CLEAR_OP_RESOLVE; |
/* Note: there is no need to initialize push constants because it doesn't |
* matter what data gets dispatched to the render target. However, we must |
* ensure that the fragment shader delivers the data using the "replicated |
* color" message. |
*/ |
use_wm_prog = true; |
memset(&wm_prog_key, 0, sizeof(wm_prog_key)); |
wm_prog_key.use_simd16_replicated_data = true; |
} |
uint32_t |
brw_blorp_const_color_params::get_wm_prog(struct brw_context *brw, |
brw_blorp_prog_data **prog_data) |
const |
{ |
uint32_t prog_offset = 0; |
if (!brw_search_cache(&brw->cache, BRW_BLORP_CONST_COLOR_PROG, |
&this->wm_prog_key, sizeof(this->wm_prog_key), |
&prog_offset, prog_data)) { |
brw_blorp_const_color_program prog(brw, &this->wm_prog_key); |
GLuint program_size; |
const GLuint *program = prog.compile(brw, &program_size); |
brw_upload_cache(&brw->cache, BRW_BLORP_CONST_COLOR_PROG, |
&this->wm_prog_key, sizeof(this->wm_prog_key), |
program, program_size, |
&prog.prog_data, sizeof(prog.prog_data), |
&prog_offset, prog_data); |
} |
return prog_offset; |
} |
void |
brw_blorp_const_color_program::alloc_regs() |
{ |
int reg = 0; |
this->R0 = retype(brw_vec8_grf(reg++, 0), BRW_REGISTER_TYPE_UW); |
this->R1 = retype(brw_vec8_grf(reg++, 0), BRW_REGISTER_TYPE_UW); |
prog_data.first_curbe_grf = reg; |
clear_rgba = retype(brw_vec4_grf(reg++, 0), BRW_REGISTER_TYPE_F); |
reg += BRW_BLORP_NUM_PUSH_CONST_REGS; |
/* Make sure we didn't run out of registers */ |
assert(reg <= GEN7_MRF_HACK_START); |
this->base_mrf = 2; |
} |
const GLuint * |
brw_blorp_const_color_program::compile(struct brw_context *brw, |
GLuint *program_size) |
{ |
/* Set up prog_data */ |
memset(&prog_data, 0, sizeof(prog_data)); |
prog_data.persample_msaa_dispatch = false; |
alloc_regs(); |
brw_set_compression_control(&func, BRW_COMPRESSION_NONE); |
struct brw_reg mrf_rt_write = |
retype(vec16(brw_message_reg(base_mrf)), BRW_REGISTER_TYPE_F); |
uint32_t mlen, msg_type; |
if (key->use_simd16_replicated_data) { |
/* The message payload is a single register with the low 4 floats/ints |
* filled with the constant clear color. |
*/ |
brw_set_mask_control(&func, BRW_MASK_DISABLE); |
brw_MOV(&func, vec4(brw_message_reg(base_mrf)), clear_rgba); |
brw_set_mask_control(&func, BRW_MASK_ENABLE); |
msg_type = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED; |
mlen = 1; |
} else { |
for (int i = 0; i < 4; i++) { |
/* The message payload is pairs of registers for 16 pixels each of r, |
* g, b, and a. |
*/ |
brw_set_compression_control(&func, BRW_COMPRESSION_COMPRESSED); |
brw_MOV(&func, |
brw_message_reg(base_mrf + i * 2), |
brw_vec1_grf(clear_rgba.nr, i)); |
brw_set_compression_control(&func, BRW_COMPRESSION_NONE); |
} |
msg_type = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE; |
mlen = 8; |
} |
/* Now write to the render target and terminate the thread */ |
brw_fb_WRITE(&func, |
16 /* dispatch_width */, |
base_mrf /* msg_reg_nr */, |
mrf_rt_write /* src0 */, |
msg_type, |
BRW_BLORP_RENDERBUFFER_BINDING_TABLE_INDEX, |
mlen, |
0 /* response_length */, |
true /* eot */, |
false /* header present */); |
if (unlikely(INTEL_DEBUG & DEBUG_BLORP)) { |
printf("Native code for BLORP clear:\n"); |
brw_dump_compile(&func, stdout, 0, func.next_insn_offset); |
printf("\n"); |
} |
return brw_get_program(&func, program_size); |
} |
extern "C" { |
bool |
brw_blorp_clear_color(struct brw_context *brw, struct gl_framebuffer *fb, |
bool partial_clear) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* The constant color clear code doesn't work for multisampled surfaces, so |
* we need to support falling back to other clear mechanisms. |
* Unfortunately, our clear code is based on a bitmask that doesn't |
* distinguish individual color attachments, so we walk the attachments to |
* see if any require fallback, and fall back for all if any of them need |
* to. |
*/ |
for (unsigned buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) { |
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf]; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
if (irb && irb->mt->msaa_layout != INTEL_MSAA_LAYOUT_NONE) |
return false; |
} |
for (unsigned buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) { |
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[buf]; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
/* If this is an ES2 context or GL_ARB_ES2_compatibility is supported, |
* the framebuffer can be complete with some attachments missing. In |
* this case the _ColorDrawBuffers pointer will be NULL. |
*/ |
if (rb == NULL) |
continue; |
brw_blorp_clear_params params(brw, fb, rb, ctx->Color.ColorMask[buf], |
partial_clear); |
bool is_fast_clear = |
(params.fast_clear_op == GEN7_FAST_CLEAR_OP_FAST_CLEAR); |
if (is_fast_clear) { |
/* Record the clear color in the miptree so that it will be |
* programmed in SURFACE_STATE by later rendering and resolve |
* operations. |
*/ |
uint32_t new_color_value = |
compute_fast_clear_color_bits(&ctx->Color.ClearColor); |
if (irb->mt->fast_clear_color_value != new_color_value) { |
irb->mt->fast_clear_color_value = new_color_value; |
brw->state.dirty.brw |= BRW_NEW_SURFACES; |
} |
/* If the buffer is already in INTEL_MCS_STATE_CLEAR, the clear is |
* redundant and can be skipped. |
*/ |
if (irb->mt->mcs_state == INTEL_MCS_STATE_CLEAR) |
continue; |
/* If the MCS buffer hasn't been allocated yet, we need to allocate |
* it now. |
*/ |
if (!irb->mt->mcs_mt) { |
if (!intel_miptree_alloc_non_msrt_mcs(brw, irb->mt)) { |
/* MCS allocation failed--probably this will only happen in |
* out-of-memory conditions. But in any case, try to recover |
* by falling back to a non-blorp clear technique. |
*/ |
return false; |
} |
brw->state.dirty.brw |= BRW_NEW_SURFACES; |
} |
} |
DBG("%s to mt %p level %d layer %d\n", __FUNCTION__, |
irb->mt, irb->mt_level, irb->mt_layer); |
brw_blorp_exec(brw, ¶ms); |
if (is_fast_clear) { |
/* Now that the fast clear has occurred, put the buffer in |
* INTEL_MCS_STATE_CLEAR so that we won't waste time doing redundant |
* clears. |
*/ |
irb->mt->mcs_state = INTEL_MCS_STATE_CLEAR; |
} |
} |
return true; |
} |
void |
brw_blorp_resolve_color(struct brw_context *brw, struct intel_mipmap_tree *mt) |
{ |
DBG("%s to mt %p\n", __FUNCTION__, mt); |
brw_blorp_rt_resolve_params params(brw, mt); |
brw_blorp_exec(brw, ¶ms); |
mt->mcs_state = INTEL_MCS_STATE_RESOLVED; |
} |
} /* extern "C" */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_cc.c |
---|
0,0 → 1,259 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_util.h" |
#include "main/macros.h" |
#include "main/stencil.h" |
#include "intel_batchbuffer.h" |
static void |
brw_upload_cc_vp(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_cc_viewport *ccv; |
ccv = brw_state_batch(brw, AUB_TRACE_CC_VP_STATE, |
sizeof(*ccv), 32, &brw->cc.vp_offset); |
/* _NEW_TRANSFORM */ |
if (ctx->Transform.DepthClamp) { |
/* _NEW_VIEWPORT */ |
ccv->min_depth = MIN2(ctx->Viewport.Near, ctx->Viewport.Far); |
ccv->max_depth = MAX2(ctx->Viewport.Near, ctx->Viewport.Far); |
} else { |
ccv->min_depth = 0.0; |
ccv->max_depth = 1.0; |
} |
brw->state.dirty.cache |= CACHE_NEW_CC_VP; |
} |
const struct brw_tracked_state brw_cc_vp = { |
.dirty = { |
.mesa = _NEW_VIEWPORT | _NEW_TRANSFORM, |
.brw = BRW_NEW_BATCH, |
.cache = 0 |
}, |
.emit = brw_upload_cc_vp |
}; |
/** |
* Modify blend function to force destination alpha to 1.0 |
* |
* If \c function specifies a blend function that uses destination alpha, |
* replace it with a function that hard-wires destination alpha to 1.0. This |
* is used when rendering to xRGB targets. |
*/ |
GLenum |
brw_fix_xRGB_alpha(GLenum function) |
{ |
switch (function) { |
case GL_DST_ALPHA: |
return GL_ONE; |
case GL_ONE_MINUS_DST_ALPHA: |
case GL_SRC_ALPHA_SATURATE: |
return GL_ZERO; |
} |
return function; |
} |
/** |
* Creates the state cache entry for the given CC unit key. |
*/ |
static void upload_cc_unit(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_cc_unit_state *cc; |
cc = brw_state_batch(brw, AUB_TRACE_CC_STATE, |
sizeof(*cc), 64, &brw->cc.state_offset); |
memset(cc, 0, sizeof(*cc)); |
/* _NEW_STENCIL | _NEW_BUFFERS */ |
if (ctx->Stencil._Enabled) { |
const unsigned back = ctx->Stencil._BackFace; |
cc->cc0.stencil_enable = 1; |
cc->cc0.stencil_func = |
intel_translate_compare_func(ctx->Stencil.Function[0]); |
cc->cc0.stencil_fail_op = |
intel_translate_stencil_op(ctx->Stencil.FailFunc[0]); |
cc->cc0.stencil_pass_depth_fail_op = |
intel_translate_stencil_op(ctx->Stencil.ZFailFunc[0]); |
cc->cc0.stencil_pass_depth_pass_op = |
intel_translate_stencil_op(ctx->Stencil.ZPassFunc[0]); |
cc->cc1.stencil_ref = _mesa_get_stencil_ref(ctx, 0); |
cc->cc1.stencil_write_mask = ctx->Stencil.WriteMask[0]; |
cc->cc1.stencil_test_mask = ctx->Stencil.ValueMask[0]; |
if (ctx->Stencil._TestTwoSide) { |
cc->cc0.bf_stencil_enable = 1; |
cc->cc0.bf_stencil_func = |
intel_translate_compare_func(ctx->Stencil.Function[back]); |
cc->cc0.bf_stencil_fail_op = |
intel_translate_stencil_op(ctx->Stencil.FailFunc[back]); |
cc->cc0.bf_stencil_pass_depth_fail_op = |
intel_translate_stencil_op(ctx->Stencil.ZFailFunc[back]); |
cc->cc0.bf_stencil_pass_depth_pass_op = |
intel_translate_stencil_op(ctx->Stencil.ZPassFunc[back]); |
cc->cc1.bf_stencil_ref = _mesa_get_stencil_ref(ctx, back); |
cc->cc2.bf_stencil_write_mask = ctx->Stencil.WriteMask[back]; |
cc->cc2.bf_stencil_test_mask = ctx->Stencil.ValueMask[back]; |
} |
/* Not really sure about this: |
*/ |
if (ctx->Stencil.WriteMask[0] || |
(ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[back])) |
cc->cc0.stencil_write_enable = 1; |
} |
/* _NEW_COLOR */ |
if (ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY) { |
cc->cc2.logicop_enable = 1; |
cc->cc5.logicop_func = intel_translate_logic_op(ctx->Color.LogicOp); |
} else if (ctx->Color.BlendEnabled) { |
GLenum eqRGB = ctx->Color.Blend[0].EquationRGB; |
GLenum eqA = ctx->Color.Blend[0].EquationA; |
GLenum srcRGB = ctx->Color.Blend[0].SrcRGB; |
GLenum dstRGB = ctx->Color.Blend[0].DstRGB; |
GLenum srcA = ctx->Color.Blend[0].SrcA; |
GLenum dstA = ctx->Color.Blend[0].DstA; |
/* If the renderbuffer is XRGB, we have to frob the blend function to |
* force the destination alpha to 1.0. This means replacing GL_DST_ALPHA |
* with GL_ONE and GL_ONE_MINUS_DST_ALPHA with GL_ZERO. |
*/ |
if (ctx->DrawBuffer->Visual.alphaBits == 0) { |
srcRGB = brw_fix_xRGB_alpha(srcRGB); |
srcA = brw_fix_xRGB_alpha(srcA); |
dstRGB = brw_fix_xRGB_alpha(dstRGB); |
dstA = brw_fix_xRGB_alpha(dstA); |
} |
if (eqRGB == GL_MIN || eqRGB == GL_MAX) { |
srcRGB = dstRGB = GL_ONE; |
} |
if (eqA == GL_MIN || eqA == GL_MAX) { |
srcA = dstA = GL_ONE; |
} |
cc->cc6.dest_blend_factor = brw_translate_blend_factor(dstRGB); |
cc->cc6.src_blend_factor = brw_translate_blend_factor(srcRGB); |
cc->cc6.blend_function = brw_translate_blend_equation(eqRGB); |
cc->cc5.ia_dest_blend_factor = brw_translate_blend_factor(dstA); |
cc->cc5.ia_src_blend_factor = brw_translate_blend_factor(srcA); |
cc->cc5.ia_blend_function = brw_translate_blend_equation(eqA); |
cc->cc3.blend_enable = 1; |
cc->cc3.ia_blend_enable = (srcA != srcRGB || |
dstA != dstRGB || |
eqA != eqRGB); |
} |
if (ctx->Color.AlphaEnabled) { |
cc->cc3.alpha_test = 1; |
cc->cc3.alpha_test_func = |
intel_translate_compare_func(ctx->Color.AlphaFunc); |
cc->cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8; |
UNCLAMPED_FLOAT_TO_UBYTE(cc->cc7.alpha_ref.ub[0], ctx->Color.AlphaRef); |
} |
if (ctx->Color.DitherFlag) { |
cc->cc5.dither_enable = 1; |
cc->cc6.y_dither_offset = 0; |
cc->cc6.x_dither_offset = 0; |
} |
/* _NEW_DEPTH */ |
if (ctx->Depth.Test) { |
cc->cc2.depth_test = 1; |
cc->cc2.depth_test_function = |
intel_translate_compare_func(ctx->Depth.Func); |
cc->cc2.depth_write_enable = ctx->Depth.Mask; |
} |
if (brw->stats_wm || unlikely(INTEL_DEBUG & DEBUG_STATS)) |
cc->cc5.statistics_enable = 1; |
/* CACHE_NEW_CC_VP */ |
cc->cc4.cc_viewport_state_offset = (brw->batch.bo->offset + |
brw->cc.vp_offset) >> 5; /* reloc */ |
brw->state.dirty.cache |= CACHE_NEW_CC_UNIT; |
/* Emit CC viewport relocation */ |
drm_intel_bo_emit_reloc(brw->batch.bo, |
(brw->cc.state_offset + |
offsetof(struct brw_cc_unit_state, cc4)), |
brw->batch.bo, brw->cc.vp_offset, |
I915_GEM_DOMAIN_INSTRUCTION, 0); |
} |
const struct brw_tracked_state brw_cc_unit = { |
.dirty = { |
.mesa = _NEW_STENCIL | _NEW_COLOR | _NEW_DEPTH | _NEW_BUFFERS, |
.brw = BRW_NEW_BATCH | BRW_NEW_STATS_WM, |
.cache = CACHE_NEW_CC_VP |
}, |
.emit = upload_cc_unit, |
}; |
static void upload_blend_constant_color(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_BLEND_CONSTANT_COLOR << 16 | (5-2)); |
OUT_BATCH_F(ctx->Color.BlendColorUnclamped[0]); |
OUT_BATCH_F(ctx->Color.BlendColorUnclamped[1]); |
OUT_BATCH_F(ctx->Color.BlendColorUnclamped[2]); |
OUT_BATCH_F(ctx->Color.BlendColorUnclamped[3]); |
CACHED_BATCH(); |
} |
const struct brw_tracked_state brw_blend_constant_color = { |
.dirty = { |
.mesa = _NEW_COLOR, |
.brw = BRW_NEW_CONTEXT, |
.cache = 0 |
}, |
.emit = upload_blend_constant_color |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_cfg.cpp |
---|
0,0 → 1,261 |
/* |
* 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_fs.h" |
#include "brw_cfg.h" |
/** @file brw_cfg_t.cpp |
* |
* Walks the shader instructions generated and creates a set of basic |
* blocks with successor/predecessor edges connecting them. |
*/ |
static bblock_t * |
pop_stack(exec_list *list) |
{ |
bblock_link *link = (bblock_link *)list->get_tail(); |
bblock_t *block = link->block; |
link->remove(); |
return block; |
} |
bblock_t::bblock_t() |
{ |
start = NULL; |
end = NULL; |
parents.make_empty(); |
children.make_empty(); |
} |
void |
bblock_t::add_successor(void *mem_ctx, bblock_t *successor) |
{ |
successor->parents.push_tail(this->make_list(mem_ctx)); |
children.push_tail(successor->make_list(mem_ctx)); |
} |
bblock_link * |
bblock_t::make_list(void *mem_ctx) |
{ |
return new(mem_ctx) bblock_link(this); |
} |
cfg_t::cfg_t(backend_visitor *v) |
{ |
create(v->mem_ctx, &v->instructions); |
} |
cfg_t::cfg_t(void *mem_ctx, exec_list *instructions) |
{ |
create(mem_ctx, instructions); |
} |
void |
cfg_t::create(void *parent_mem_ctx, exec_list *instructions) |
{ |
mem_ctx = ralloc_context(parent_mem_ctx); |
block_list.make_empty(); |
num_blocks = 0; |
ip = 0; |
cur = NULL; |
bblock_t *entry = new_block(); |
bblock_t *cur_if = NULL, *cur_else = NULL, *cur_endif = NULL; |
bblock_t *cur_do = NULL, *cur_while = NULL; |
exec_list if_stack, else_stack, endif_stack, do_stack, while_stack; |
bblock_t *next; |
set_next_block(entry); |
entry->start = (backend_instruction *) instructions->get_head(); |
foreach_list(node, instructions) { |
backend_instruction *inst = (backend_instruction *)node; |
cur->end = inst; |
/* set_next_block wants the post-incremented ip */ |
ip++; |
switch (inst->opcode) { |
case BRW_OPCODE_IF: |
/* Push our information onto a stack so we can recover from |
* nested ifs. |
*/ |
if_stack.push_tail(cur_if->make_list(mem_ctx)); |
else_stack.push_tail(cur_else->make_list(mem_ctx)); |
endif_stack.push_tail(cur_endif->make_list(mem_ctx)); |
cur_if = cur; |
cur_else = NULL; |
/* Set up the block just after the endif. Don't know when exactly |
* it will start, yet. |
*/ |
cur_endif = new_block(); |
/* Set up our immediately following block, full of "then" |
* instructions. |
*/ |
next = new_block(); |
next->start = (backend_instruction *)inst->next; |
cur_if->add_successor(mem_ctx, next); |
set_next_block(next); |
break; |
case BRW_OPCODE_ELSE: |
cur->add_successor(mem_ctx, cur_endif); |
next = new_block(); |
next->start = (backend_instruction *)inst->next; |
cur_if->add_successor(mem_ctx, next); |
cur_else = next; |
set_next_block(next); |
break; |
case BRW_OPCODE_ENDIF: |
cur_endif->start = (backend_instruction *)inst->next; |
cur->add_successor(mem_ctx, cur_endif); |
set_next_block(cur_endif); |
if (!cur_else) |
cur_if->add_successor(mem_ctx, cur_endif); |
/* Pop the stack so we're in the previous if/else/endif */ |
cur_if = pop_stack(&if_stack); |
cur_else = pop_stack(&else_stack); |
cur_endif = pop_stack(&endif_stack); |
break; |
case BRW_OPCODE_DO: |
/* Push our information onto a stack so we can recover from |
* nested loops. |
*/ |
do_stack.push_tail(cur_do->make_list(mem_ctx)); |
while_stack.push_tail(cur_while->make_list(mem_ctx)); |
/* Set up the block just after the while. Don't know when exactly |
* it will start, yet. |
*/ |
cur_while = new_block(); |
/* Set up our immediately following block, full of "then" |
* instructions. |
*/ |
next = new_block(); |
next->start = (backend_instruction *)inst->next; |
cur->add_successor(mem_ctx, next); |
cur_do = next; |
set_next_block(next); |
break; |
case BRW_OPCODE_CONTINUE: |
cur->add_successor(mem_ctx, cur_do); |
next = new_block(); |
next->start = (backend_instruction *)inst->next; |
if (inst->predicate) |
cur->add_successor(mem_ctx, next); |
set_next_block(next); |
break; |
case BRW_OPCODE_BREAK: |
cur->add_successor(mem_ctx, cur_while); |
next = new_block(); |
next->start = (backend_instruction *)inst->next; |
if (inst->predicate) |
cur->add_successor(mem_ctx, next); |
set_next_block(next); |
break; |
case BRW_OPCODE_WHILE: |
cur_while->start = (backend_instruction *)inst->next; |
cur->add_successor(mem_ctx, cur_do); |
set_next_block(cur_while); |
/* Pop the stack so we're in the previous loop */ |
cur_do = pop_stack(&do_stack); |
cur_while = pop_stack(&while_stack); |
break; |
default: |
break; |
} |
} |
cur->end_ip = ip; |
make_block_array(); |
} |
cfg_t::~cfg_t() |
{ |
ralloc_free(mem_ctx); |
} |
bblock_t * |
cfg_t::new_block() |
{ |
bblock_t *block = new(mem_ctx) bblock_t(); |
return block; |
} |
void |
cfg_t::set_next_block(bblock_t *block) |
{ |
if (cur) { |
assert(cur->end->next == block->start); |
cur->end_ip = ip - 1; |
} |
block->start_ip = ip; |
block->block_num = num_blocks++; |
block_list.push_tail(block->make_list(mem_ctx)); |
cur = block; |
} |
void |
cfg_t::make_block_array() |
{ |
blocks = ralloc_array(mem_ctx, bblock_t *, num_blocks); |
int i = 0; |
foreach_list(block_node, &block_list) { |
bblock_link *link = (bblock_link *)block_node; |
blocks[i++] = link->block; |
} |
assert(i == num_blocks); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_cfg.h |
---|
0,0 → 1,105 |
/* |
* 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_fs.h" |
class bblock_link : public exec_node { |
public: |
bblock_link(bblock_t *block) |
: block(block) |
{ |
} |
bblock_t *block; |
}; |
class bblock_t { |
public: |
static void* operator new(size_t size, void *ctx) |
{ |
void *node; |
node = rzalloc_size(ctx, size); |
assert(node != NULL); |
return node; |
} |
bblock_link *make_list(void *mem_ctx); |
bblock_t(); |
void add_successor(void *mem_ctx, bblock_t *successor); |
backend_instruction *start; |
backend_instruction *end; |
int start_ip; |
int end_ip; |
exec_list parents; |
exec_list children; |
int block_num; |
}; |
class cfg_t { |
public: |
static void* operator new(size_t size, void *ctx) |
{ |
void *node; |
node = rzalloc_size(ctx, size); |
assert(node != NULL); |
return node; |
} |
cfg_t(backend_visitor *v); |
cfg_t(void *mem_ctx, exec_list *instructions); |
~cfg_t(); |
void create(void *mem_ctx, exec_list *instructions); |
bblock_t *new_block(); |
void set_next_block(bblock_t *block); |
void make_block_array(); |
/** @{ |
* |
* Used while generating the block list. |
*/ |
bblock_t *cur; |
int ip; |
/** @} */ |
void *mem_ctx; |
/** Ordered list (by ip) of basic blocks */ |
exec_list block_list; |
bblock_t **blocks; |
int num_blocks; |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_clear.c |
---|
0,0 → 1,268 |
/************************************************************************** |
* |
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. |
* Copyright 2009, 2012 Intel Corporation. |
* 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 "main/glheader.h" |
#include "main/mtypes.h" |
#include "main/condrender.h" |
#include "swrast/swrast.h" |
#include "drivers/common/meta.h" |
#include "intel_batchbuffer.h" |
#include "intel_blit.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "brw_context.h" |
#include "brw_blorp.h" |
#define FILE_DEBUG_FLAG DEBUG_BLIT |
static const char *buffer_names[] = { |
[BUFFER_FRONT_LEFT] = "front", |
[BUFFER_BACK_LEFT] = "back", |
[BUFFER_FRONT_RIGHT] = "front right", |
[BUFFER_BACK_RIGHT] = "back right", |
[BUFFER_DEPTH] = "depth", |
[BUFFER_STENCIL] = "stencil", |
[BUFFER_ACCUM] = "accum", |
[BUFFER_AUX0] = "aux0", |
[BUFFER_COLOR0] = "color0", |
[BUFFER_COLOR1] = "color1", |
[BUFFER_COLOR2] = "color2", |
[BUFFER_COLOR3] = "color3", |
[BUFFER_COLOR4] = "color4", |
[BUFFER_COLOR5] = "color5", |
[BUFFER_COLOR6] = "color6", |
[BUFFER_COLOR7] = "color7", |
}; |
static void |
debug_mask(const char *name, GLbitfield mask) |
{ |
GLuint i; |
if (unlikely(INTEL_DEBUG & DEBUG_BLIT)) { |
DBG("%s clear:", name); |
for (i = 0; i < BUFFER_COUNT; i++) { |
if (mask & (1 << i)) |
DBG(" %s", buffer_names[i]); |
} |
DBG("\n"); |
} |
} |
/** |
* Returns true if the scissor is a noop (cuts out nothing). |
*/ |
static bool |
noop_scissor(struct gl_context *ctx, struct gl_framebuffer *fb) |
{ |
return ctx->Scissor.X <= 0 && |
ctx->Scissor.Y <= 0 && |
ctx->Scissor.Width >= fb->Width && |
ctx->Scissor.Height >= fb->Height; |
} |
/** |
* Implements fast depth clears on gen6+. |
* |
* Fast clears basically work by setting a flag in each of the subspans |
* represented in the HiZ buffer that says "When you need the depth values for |
* this subspan, it's the hardware's current clear value." Then later rendering |
* can just use the static clear value instead of referencing memory. |
* |
* The tricky part of the implementation is that you have to have the clear |
* value that was used on the depth buffer in place for all further rendering, |
* at least until a resolve to the real depth buffer happens. |
*/ |
static bool |
brw_fast_clear_depth(struct gl_context *ctx) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct intel_renderbuffer *depth_irb = |
intel_get_renderbuffer(fb, BUFFER_DEPTH); |
struct intel_mipmap_tree *mt = depth_irb->mt; |
if (brw->gen < 6) |
return false; |
if (!intel_renderbuffer_has_hiz(depth_irb)) |
return false; |
/* We only handle full buffer clears -- otherwise you'd have to track whether |
* a previous clear had happened at a different clear value and resolve it |
* first. |
*/ |
if (ctx->Scissor.Enabled && !noop_scissor(ctx, fb)) { |
perf_debug("Failed to fast clear depth due to scissor being enabled. " |
"Possible 5%% performance win if avoided.\n"); |
return false; |
} |
uint32_t depth_clear_value; |
switch (mt->format) { |
case MESA_FORMAT_Z32_FLOAT_X24S8: |
case MESA_FORMAT_S8_Z24: |
/* From the Sandy Bridge PRM, volume 2 part 1, page 314: |
* |
* "[DevSNB+]: Several cases exist where Depth Buffer Clear cannot be |
* enabled (the legacy method of clearing must be performed): |
* |
* - If the depth buffer format is D32_FLOAT_S8X24_UINT or |
* D24_UNORM_S8_UINT. |
*/ |
return false; |
case MESA_FORMAT_Z32_FLOAT: |
depth_clear_value = float_as_int(ctx->Depth.Clear); |
break; |
case MESA_FORMAT_Z16: |
/* From the Sandy Bridge PRM, volume 2 part 1, page 314: |
* |
* "[DevSNB+]: Several cases exist where Depth Buffer Clear cannot be |
* enabled (the legacy method of clearing must be performed): |
* |
* - DevSNB{W/A}]: When depth buffer format is D16_UNORM and the |
* width of the map (LOD0) is not multiple of 16, fast clear |
* optimization must be disabled. |
*/ |
if (brw->gen == 6 && (mt->level[depth_irb->mt_level].width % 16) != 0) |
return false; |
/* FALLTHROUGH */ |
default: |
depth_clear_value = fb->_DepthMax * ctx->Depth.Clear; |
break; |
} |
/* If we're clearing to a new clear value, then we need to resolve any clear |
* flags out of the HiZ buffer into the real depth buffer. |
*/ |
if (mt->depth_clear_value != depth_clear_value) { |
intel_miptree_all_slices_resolve_depth(brw, mt); |
mt->depth_clear_value = depth_clear_value; |
} |
/* From the Sandy Bridge PRM, volume 2 part 1, page 313: |
* |
* "If other rendering operations have preceded this clear, a |
* PIPE_CONTROL with write cache flush enabled and Z-inhibit disabled |
* must be issued before the rectangle primitive used for the depth |
* buffer clear operation. |
*/ |
intel_batchbuffer_emit_mi_flush(brw); |
intel_hiz_exec(brw, mt, depth_irb->mt_level, depth_irb->mt_layer, |
GEN6_HIZ_OP_DEPTH_CLEAR); |
if (brw->gen == 6) { |
/* From the Sandy Bridge PRM, volume 2 part 1, page 314: |
* |
* "DevSNB, DevSNB-B{W/A}]: Depth buffer clear pass must be followed |
* by a PIPE_CONTROL command with DEPTH_STALL bit set and Then |
* followed by Depth FLUSH' |
*/ |
intel_batchbuffer_emit_mi_flush(brw); |
} |
/* Now, the HiZ buffer contains data that needs to be resolved to the depth |
* buffer. |
*/ |
intel_renderbuffer_set_needs_depth_resolve(depth_irb); |
return true; |
} |
/** |
* Called by ctx->Driver.Clear. |
*/ |
static void |
brw_clear(struct gl_context *ctx, GLbitfield mask) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
bool partial_clear = ctx->Scissor.Enabled && !noop_scissor(ctx, fb); |
if (!_mesa_check_conditional_render(ctx)) |
return; |
if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT)) { |
brw->front_buffer_dirty = true; |
} |
intel_prepare_render(brw); |
brw_workaround_depthstencil_alignment(brw, partial_clear ? 0 : mask); |
if (mask & BUFFER_BIT_DEPTH) { |
if (brw_fast_clear_depth(ctx)) { |
DBG("fast clear: depth\n"); |
mask &= ~BUFFER_BIT_DEPTH; |
} |
} |
/* BLORP is currently only supported on Gen6+. */ |
if (brw->gen >= 6) { |
if (mask & BUFFER_BITS_COLOR) { |
if (brw_blorp_clear_color(brw, fb, partial_clear)) { |
debug_mask("blorp color", mask & BUFFER_BITS_COLOR); |
mask &= ~BUFFER_BITS_COLOR; |
} |
} |
} |
GLbitfield tri_mask = mask & (BUFFER_BITS_COLOR | |
BUFFER_BIT_STENCIL | |
BUFFER_BIT_DEPTH); |
if (tri_mask) { |
debug_mask("tri", tri_mask); |
mask &= ~tri_mask; |
if (ctx->API == API_OPENGLES) { |
_mesa_meta_Clear(&brw->ctx, tri_mask); |
} else { |
_mesa_meta_glsl_Clear(&brw->ctx, tri_mask); |
} |
} |
/* Any strange buffers get passed off to swrast */ |
if (mask) { |
debug_mask("swrast", mask); |
_swrast_Clear(ctx, mask); |
} |
} |
void |
intelInitClearFuncs(struct dd_function_table *functions) |
{ |
functions->Clear = brw_clear; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_clip.c |
---|
0,0 → 1,262 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "intel_batchbuffer.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_util.h" |
#include "brw_state.h" |
#include "brw_clip.h" |
#include "glsl/ralloc.h" |
#define FRONT_UNFILLED_BIT 0x1 |
#define BACK_UNFILLED_BIT 0x2 |
static void compile_clip_prog( struct brw_context *brw, |
struct brw_clip_prog_key *key ) |
{ |
struct brw_clip_compile c; |
const GLuint *program; |
void *mem_ctx; |
GLuint program_size; |
GLuint i; |
memset(&c, 0, sizeof(c)); |
mem_ctx = ralloc_context(NULL); |
/* Begin the compilation: |
*/ |
brw_init_compile(brw, &c.func, mem_ctx); |
c.func.single_program_flow = 1; |
c.key = *key; |
c.vue_map = brw->vue_map_geom_out; |
/* nr_regs is the number of registers filled by reading data from the VUE. |
* This program accesses the entire VUE, so nr_regs needs to be the size of |
* the VUE (measured in pairs, since two slots are stored in each |
* register). |
*/ |
c.nr_regs = (c.vue_map.num_slots + 1)/2; |
c.prog_data.clip_mode = c.key.clip_mode; /* XXX */ |
/* For some reason the thread is spawned with only 4 channels |
* unmasked. |
*/ |
brw_set_mask_control(&c.func, BRW_MASK_DISABLE); |
/* Would ideally have the option of producing a program which could |
* do all three: |
*/ |
switch (key->primitive) { |
case GL_TRIANGLES: |
if (key->do_unfilled) |
brw_emit_unfilled_clip( &c ); |
else |
brw_emit_tri_clip( &c ); |
break; |
case GL_LINES: |
brw_emit_line_clip( &c ); |
break; |
case GL_POINTS: |
brw_emit_point_clip( &c ); |
break; |
default: |
assert(0); |
return; |
} |
/* get the program |
*/ |
program = brw_get_program(&c.func, &program_size); |
if (unlikely(INTEL_DEBUG & DEBUG_CLIP)) { |
printf("clip:\n"); |
for (i = 0; i < program_size / sizeof(struct brw_instruction); i++) |
brw_disasm(stdout, &((struct brw_instruction *)program)[i], |
brw->gen); |
printf("\n"); |
} |
brw_upload_cache(&brw->cache, |
BRW_CLIP_PROG, |
&c.key, sizeof(c.key), |
program, program_size, |
&c.prog_data, sizeof(c.prog_data), |
&brw->clip.prog_offset, &brw->clip.prog_data); |
ralloc_free(mem_ctx); |
} |
/* Calculate interpolants for triangle and line rasterization. |
*/ |
static void |
brw_upload_clip_prog(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_clip_prog_key key; |
memset(&key, 0, sizeof(key)); |
/* Populate the key: |
*/ |
/* BRW_NEW_REDUCED_PRIMITIVE */ |
key.primitive = brw->reduced_primitive; |
/* BRW_NEW_VUE_MAP_GEOM_OUT */ |
key.attrs = brw->vue_map_geom_out.slots_valid; |
/* _NEW_LIGHT */ |
key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT); |
key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION); |
/* _NEW_TRANSFORM (also part of VUE map)*/ |
key.nr_userclip = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); |
if (brw->gen == 5) |
key.clip_mode = BRW_CLIPMODE_KERNEL_CLIP; |
else |
key.clip_mode = BRW_CLIPMODE_NORMAL; |
/* _NEW_POLYGON */ |
if (key.primitive == GL_TRIANGLES) { |
if (ctx->Polygon.CullFlag && |
ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) |
key.clip_mode = BRW_CLIPMODE_REJECT_ALL; |
else { |
GLuint fill_front = CLIP_CULL; |
GLuint fill_back = CLIP_CULL; |
GLuint offset_front = 0; |
GLuint offset_back = 0; |
if (!ctx->Polygon.CullFlag || |
ctx->Polygon.CullFaceMode != GL_FRONT) { |
switch (ctx->Polygon.FrontMode) { |
case GL_FILL: |
fill_front = CLIP_FILL; |
offset_front = 0; |
break; |
case GL_LINE: |
fill_front = CLIP_LINE; |
offset_front = ctx->Polygon.OffsetLine; |
break; |
case GL_POINT: |
fill_front = CLIP_POINT; |
offset_front = ctx->Polygon.OffsetPoint; |
break; |
} |
} |
if (!ctx->Polygon.CullFlag || |
ctx->Polygon.CullFaceMode != GL_BACK) { |
switch (ctx->Polygon.BackMode) { |
case GL_FILL: |
fill_back = CLIP_FILL; |
offset_back = 0; |
break; |
case GL_LINE: |
fill_back = CLIP_LINE; |
offset_back = ctx->Polygon.OffsetLine; |
break; |
case GL_POINT: |
fill_back = CLIP_POINT; |
offset_back = ctx->Polygon.OffsetPoint; |
break; |
} |
} |
if (ctx->Polygon.BackMode != GL_FILL || |
ctx->Polygon.FrontMode != GL_FILL) { |
key.do_unfilled = 1; |
/* Most cases the fixed function units will handle. Cases where |
* one or more polygon faces are unfilled will require help: |
*/ |
key.clip_mode = BRW_CLIPMODE_CLIP_NON_REJECTED; |
if (offset_back || offset_front) { |
/* _NEW_POLYGON, _NEW_BUFFERS */ |
key.offset_units = ctx->Polygon.OffsetUnits * ctx->DrawBuffer->_MRD * 2; |
key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD; |
} |
switch (ctx->Polygon.FrontFace) { |
case GL_CCW: |
key.fill_ccw = fill_front; |
key.fill_cw = fill_back; |
key.offset_ccw = offset_front; |
key.offset_cw = offset_back; |
if (ctx->Light.Model.TwoSide && |
key.fill_cw != CLIP_CULL) |
key.copy_bfc_cw = 1; |
break; |
case GL_CW: |
key.fill_cw = fill_front; |
key.fill_ccw = fill_back; |
key.offset_cw = offset_front; |
key.offset_ccw = offset_back; |
if (ctx->Light.Model.TwoSide && |
key.fill_ccw != CLIP_CULL) |
key.copy_bfc_ccw = 1; |
break; |
} |
} |
} |
} |
if (!brw_search_cache(&brw->cache, BRW_CLIP_PROG, |
&key, sizeof(key), |
&brw->clip.prog_offset, &brw->clip.prog_data)) { |
compile_clip_prog( brw, &key ); |
} |
} |
const struct brw_tracked_state brw_clip_prog = { |
.dirty = { |
.mesa = (_NEW_LIGHT | |
_NEW_TRANSFORM | |
_NEW_POLYGON | |
_NEW_BUFFERS), |
.brw = (BRW_NEW_REDUCED_PRIMITIVE | BRW_NEW_VUE_MAP_GEOM_OUT) |
}, |
.emit = brw_upload_clip_prog |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_clip.h |
---|
0,0 → 1,186 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 BRW_CLIP_H |
#define BRW_CLIP_H |
#include "brw_context.h" |
#include "brw_eu.h" |
#define MAX_VERTS (3+6+6) |
/* Note that if unfilled primitives are being emitted, we have to fix |
* up polygon offset and flatshading at this point: |
*/ |
struct brw_clip_prog_key { |
GLbitfield64 attrs; |
GLuint primitive:4; |
GLuint nr_userclip:4; |
GLuint do_flat_shading:1; |
GLuint pv_first:1; |
GLuint do_unfilled:1; |
GLuint fill_cw:2; /* includes cull information */ |
GLuint fill_ccw:2; /* includes cull information */ |
GLuint offset_cw:1; |
GLuint offset_ccw:1; |
GLuint copy_bfc_cw:1; |
GLuint copy_bfc_ccw:1; |
GLuint clip_mode:3; |
GLfloat offset_factor; |
GLfloat offset_units; |
}; |
#define CLIP_LINE 0 |
#define CLIP_POINT 1 |
#define CLIP_FILL 2 |
#define CLIP_CULL 3 |
#define PRIM_MASK (0x1f) |
struct brw_clip_compile { |
struct brw_compile func; |
struct brw_clip_prog_key key; |
struct brw_clip_prog_data prog_data; |
struct { |
struct brw_reg R0; |
struct brw_reg vertex[MAX_VERTS]; |
struct brw_reg t; |
struct brw_reg t0, t1; |
struct brw_reg dp0, dp1; |
struct brw_reg dpPrev; |
struct brw_reg dp; |
struct brw_reg loopcount; |
struct brw_reg nr_verts; |
struct brw_reg planemask; |
struct brw_reg inlist; |
struct brw_reg outlist; |
struct brw_reg freelist; |
struct brw_reg dir; |
struct brw_reg tmp0, tmp1; |
struct brw_reg offset; |
struct brw_reg fixed_planes; |
struct brw_reg plane_equation; |
struct brw_reg ff_sync; |
/* Bitmask indicating which coordinate attribute should be used for |
* comparison to each clipping plane. A 0 indicates that VARYING_SLOT_POS |
* should be used, because it's one of the fixed +/- x/y/z planes that |
* constitute the bounds of the view volume. A 1 indicates that |
* VARYING_SLOT_CLIP_VERTEX should be used (if available) since it's a user- |
* defined clipping plane. |
*/ |
struct brw_reg vertex_src_mask; |
} reg; |
/* Number of registers storing VUE data */ |
GLuint nr_regs; |
GLuint first_tmp; |
GLuint last_tmp; |
bool need_direction; |
struct brw_vue_map vue_map; |
}; |
/** |
* True if the given varying is one of the outputs of the vertex shader. |
*/ |
static inline bool brw_clip_have_varying(struct brw_clip_compile *c, |
GLuint varying) |
{ |
return (c->key.attrs & BITFIELD64_BIT(varying)) ? 1 : 0; |
} |
/* Points are only culled, so no need for a clip routine, however it |
* works out easier to have a dummy one. |
*/ |
void brw_emit_unfilled_clip( struct brw_clip_compile *c ); |
void brw_emit_tri_clip( struct brw_clip_compile *c ); |
void brw_emit_line_clip( struct brw_clip_compile *c ); |
void brw_emit_point_clip( struct brw_clip_compile *c ); |
/* brw_clip_tri.c, for use by the unfilled clip routine: |
*/ |
void brw_clip_tri_init_vertices( struct brw_clip_compile *c ); |
void brw_clip_tri_flat_shade( struct brw_clip_compile *c ); |
void brw_clip_tri( struct brw_clip_compile *c ); |
void brw_clip_tri_emit_polygon( struct brw_clip_compile *c ); |
void brw_clip_tri_alloc_regs( struct brw_clip_compile *c, |
GLuint nr_verts ); |
/* Utils: |
*/ |
void brw_clip_interp_vertex( struct brw_clip_compile *c, |
struct brw_indirect dest_ptr, |
struct brw_indirect v0_ptr, /* from */ |
struct brw_indirect v1_ptr, /* to */ |
struct brw_reg t0, |
bool force_edgeflag ); |
void brw_clip_init_planes( struct brw_clip_compile *c ); |
void brw_clip_emit_vue(struct brw_clip_compile *c, |
struct brw_indirect vert, |
bool allocate, |
bool eot, |
GLuint header); |
void brw_clip_kill_thread(struct brw_clip_compile *c); |
struct brw_reg brw_clip_plane_stride( struct brw_clip_compile *c ); |
struct brw_reg brw_clip_plane0_address( struct brw_clip_compile *c ); |
void brw_clip_copy_colors( struct brw_clip_compile *c, |
GLuint to, GLuint from ); |
void brw_clip_init_clipmask( struct brw_clip_compile *c ); |
struct brw_reg get_tmp( struct brw_clip_compile *c ); |
void brw_clip_project_position(struct brw_clip_compile *c, |
struct brw_reg pos ); |
void brw_clip_ff_sync(struct brw_clip_compile *c); |
void brw_clip_init_ff_sync(struct brw_clip_compile *c); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_clip_line.c |
---|
0,0 → 1,283 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "program/program.h" |
#include "intel_batchbuffer.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_clip.h" |
static void brw_clip_line_alloc_regs( struct brw_clip_compile *c ) |
{ |
struct brw_context *brw = c->func.brw; |
GLuint i = 0,j; |
/* Register usage is static, precompute here: |
*/ |
c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++; |
if (c->key.nr_userclip) { |
c->reg.fixed_planes = brw_vec4_grf(i, 0); |
i += (6 + c->key.nr_userclip + 1) / 2; |
c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2; |
} |
else |
c->prog_data.curb_read_length = 0; |
/* Payload vertices plus space for more generated vertices: |
*/ |
for (j = 0; j < 4; j++) { |
c->reg.vertex[j] = brw_vec4_grf(i, 0); |
i += c->nr_regs; |
} |
c->reg.t = brw_vec1_grf(i, 0); |
c->reg.t0 = brw_vec1_grf(i, 1); |
c->reg.t1 = brw_vec1_grf(i, 2); |
c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD); |
c->reg.plane_equation = brw_vec4_grf(i, 4); |
i++; |
c->reg.dp0 = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */ |
c->reg.dp1 = brw_vec1_grf(i, 4); |
i++; |
if (!c->key.nr_userclip) { |
c->reg.fixed_planes = brw_vec8_grf(i, 0); |
i++; |
} |
if (brw->gen == 5) { |
c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD); |
i++; |
} |
c->first_tmp = i; |
c->last_tmp = i; |
c->prog_data.urb_read_length = c->nr_regs; /* ? */ |
c->prog_data.total_grf = i; |
} |
/* Line clipping, more or less following the following algorithm: |
* |
* for (p=0;p<MAX_PLANES;p++) { |
* if (clipmask & (1 << p)) { |
* GLfloat dp0 = DOTPROD( vtx0, plane[p] ); |
* GLfloat dp1 = DOTPROD( vtx1, plane[p] ); |
* |
* if (IS_NEGATIVE(dp1)) { |
* GLfloat t = dp1 / (dp1 - dp0); |
* if (t > t1) t1 = t; |
* } else { |
* GLfloat t = dp0 / (dp0 - dp1); |
* if (t > t0) t0 = t; |
* } |
* |
* if (t0 + t1 >= 1.0) |
* return; |
* } |
* } |
* |
* interp( ctx, newvtx0, vtx0, vtx1, t0 ); |
* interp( ctx, newvtx1, vtx1, vtx0, t1 ); |
* |
*/ |
static void clip_and_emit_line( struct brw_clip_compile *c ) |
{ |
/* FIXME: use VARYING_SLOT_CLIP_VERTEX if available for user clip planes. */ |
struct brw_compile *p = &c->func; |
struct brw_context *brw = p->brw; |
struct brw_indirect vtx0 = brw_indirect(0, 0); |
struct brw_indirect vtx1 = brw_indirect(1, 0); |
struct brw_indirect newvtx0 = brw_indirect(2, 0); |
struct brw_indirect newvtx1 = brw_indirect(3, 0); |
struct brw_indirect plane_ptr = brw_indirect(4, 0); |
struct brw_reg v1_null_ud = retype(vec1(brw_null_reg()), BRW_REGISTER_TYPE_UD); |
GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); |
brw_MOV(p, get_addr_reg(vtx0), brw_address(c->reg.vertex[0])); |
brw_MOV(p, get_addr_reg(vtx1), brw_address(c->reg.vertex[1])); |
brw_MOV(p, get_addr_reg(newvtx0), brw_address(c->reg.vertex[2])); |
brw_MOV(p, get_addr_reg(newvtx1), brw_address(c->reg.vertex[3])); |
brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c)); |
/* Note: init t0, t1 together: |
*/ |
brw_MOV(p, vec2(c->reg.t0), brw_imm_f(0)); |
brw_clip_init_planes(c); |
brw_clip_init_clipmask(c); |
/* -ve rhw workaround */ |
if (brw->has_negative_rhw_bug) { |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2), |
brw_imm_ud(1<<20)); |
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(0x3f)); |
} |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_DO(p, BRW_EXECUTE_1); |
{ |
/* if (planemask & 1) |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_AND(p, v1_null_ud, c->reg.planemask, brw_imm_ud(1)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
if (c->key.nr_userclip) |
brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0)); |
else |
brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0)); |
/* dp = DP4(vtx->position, plane) |
*/ |
brw_DP4(p, vec4(c->reg.dp0), deref_4f(vtx0, hpos_offset), c->reg.plane_equation); |
/* if (IS_NEGATIVE(dp1)) |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_L); |
brw_DP4(p, vec4(c->reg.dp1), deref_4f(vtx1, hpos_offset), c->reg.plane_equation); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
/* |
* Both can be negative on GM965/G965 due to RHW workaround |
* if so, this object should be rejected. |
*/ |
if (brw->has_negative_rhw_bug) { |
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, c->reg.dp0, brw_imm_f(0.0)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_clip_kill_thread(c); |
} |
brw_ENDIF(p); |
} |
brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0)); |
brw_math_invert(p, c->reg.t, c->reg.t); |
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1); |
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 ); |
brw_MOV(p, c->reg.t1, c->reg.t); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
} |
brw_ELSE(p); |
{ |
/* Coming back in. We know that both cannot be negative |
* because the line would have been culled in that case. |
*/ |
/* If both are positive, do nothing */ |
/* Only on GM965/G965 */ |
if (brw->has_negative_rhw_bug) { |
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0)); |
brw_IF(p, BRW_EXECUTE_1); |
} |
{ |
brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1)); |
brw_math_invert(p, c->reg.t, c->reg.t); |
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0); |
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 ); |
brw_MOV(p, c->reg.t0, c->reg.t); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
} |
if (brw->has_negative_rhw_bug) { |
brw_ENDIF(p); |
} |
} |
brw_ENDIF(p); |
} |
brw_ENDIF(p); |
/* plane_ptr++; |
*/ |
brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c)); |
/* while (planemask>>=1) != 0 |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1)); |
} |
brw_WHILE(p); |
brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1); |
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, false); |
brw_clip_interp_vertex(c, newvtx1, vtx1, vtx0, c->reg.t1, false); |
brw_clip_emit_vue(c, newvtx0, 1, 0, |
(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_START); |
brw_clip_emit_vue(c, newvtx1, 0, 1, |
(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_END); |
} |
brw_ENDIF(p); |
brw_clip_kill_thread(c); |
} |
void brw_emit_line_clip( struct brw_clip_compile *c ) |
{ |
brw_clip_line_alloc_regs(c); |
brw_clip_init_ff_sync(c); |
if (c->key.do_flat_shading) { |
if (c->key.pv_first) |
brw_clip_copy_colors(c, 1, 0); |
else |
brw_clip_copy_colors(c, 0, 1); |
} |
clip_and_emit_line(c); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_clip_point.c |
---|
0,0 → 1,55 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "program/program.h" |
#include "intel_batchbuffer.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_clip.h" |
/* Point clipping, nothing to do? |
*/ |
void brw_emit_point_clip( struct brw_clip_compile *c ) |
{ |
/* Send an empty message to kill the thread: |
*/ |
brw_clip_tri_alloc_regs(c, 0); |
brw_clip_init_ff_sync(c); |
brw_clip_kill_thread(c); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_clip_state.c |
---|
0,0 → 1,168 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
static void |
upload_clip_vp(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_clipper_viewport *vp; |
vp = brw_state_batch(brw, AUB_TRACE_CLIP_VP_STATE, |
sizeof(*vp), 32, &brw->clip.vp_offset); |
const float maximum_post_clamp_delta = 4096; |
float gbx = maximum_post_clamp_delta / (float) ctx->Viewport.Width; |
float gby = maximum_post_clamp_delta / (float) ctx->Viewport.Height; |
vp->xmin = -gbx; |
vp->xmax = gbx; |
vp->ymin = -gby; |
vp->ymax = gby; |
} |
static void |
brw_upload_clip_unit(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_clip_unit_state *clip; |
/* _NEW_BUFFERS */ |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
upload_clip_vp(brw); |
clip = brw_state_batch(brw, AUB_TRACE_CLIP_STATE, |
sizeof(*clip), 32, &brw->clip.state_offset); |
memset(clip, 0, sizeof(*clip)); |
/* BRW_NEW_PROGRAM_CACHE | CACHE_NEW_CLIP_PROG */ |
clip->thread0.grf_reg_count = (ALIGN(brw->clip.prog_data->total_grf, 16) / |
16 - 1); |
clip->thread0.kernel_start_pointer = |
brw_program_reloc(brw, |
brw->clip.state_offset + |
offsetof(struct brw_clip_unit_state, thread0), |
brw->clip.prog_offset + |
(clip->thread0.grf_reg_count << 1)) >> 6; |
clip->thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754; |
clip->thread1.single_program_flow = 1; |
clip->thread3.urb_entry_read_length = brw->clip.prog_data->urb_read_length; |
clip->thread3.const_urb_entry_read_length = |
brw->clip.prog_data->curb_read_length; |
/* BRW_NEW_CURBE_OFFSETS */ |
clip->thread3.const_urb_entry_read_offset = brw->curbe.clip_start * 2; |
clip->thread3.dispatch_grf_start_reg = 1; |
clip->thread3.urb_entry_read_offset = 0; |
/* BRW_NEW_URB_FENCE */ |
clip->thread4.nr_urb_entries = brw->urb.nr_clip_entries; |
clip->thread4.urb_entry_allocation_size = brw->urb.vsize - 1; |
/* If we have enough clip URB entries to run two threads, do so. |
*/ |
if (brw->urb.nr_clip_entries >= 10) { |
/* Half of the URB entries go to each thread, and it has to be an |
* even number. |
*/ |
assert(brw->urb.nr_clip_entries % 2 == 0); |
/* Although up to 16 concurrent Clip threads are allowed on Ironlake, |
* only 2 threads can output VUEs at a time. |
*/ |
if (brw->gen == 5) |
clip->thread4.max_threads = 16 - 1; |
else |
clip->thread4.max_threads = 2 - 1; |
} else { |
assert(brw->urb.nr_clip_entries >= 5); |
clip->thread4.max_threads = 1 - 1; |
} |
if (unlikely(INTEL_DEBUG & DEBUG_STATS)) |
clip->thread4.stats_enable = 1; |
clip->clip5.userclip_enable_flags = 0x7f; |
clip->clip5.userclip_must_clip = 1; |
/* enable guardband clipping if we can */ |
if (ctx->Viewport.X == 0 && |
ctx->Viewport.Y == 0 && |
ctx->Viewport.Width == fb->Width && |
ctx->Viewport.Height == fb->Height) |
{ |
clip->clip5.guard_band_enable = 1; |
clip->clip6.clipper_viewport_state_ptr = |
(brw->batch.bo->offset + brw->clip.vp_offset) >> 5; |
/* emit clip viewport relocation */ |
drm_intel_bo_emit_reloc(brw->batch.bo, |
(brw->clip.state_offset + |
offsetof(struct brw_clip_unit_state, clip6)), |
brw->batch.bo, brw->clip.vp_offset, |
I915_GEM_DOMAIN_INSTRUCTION, 0); |
} |
/* _NEW_TRANSFORM */ |
if (!ctx->Transform.DepthClamp) |
clip->clip5.viewport_z_clip_enable = 1; |
clip->clip5.viewport_xy_clip_enable = 1; |
clip->clip5.vertex_position_space = BRW_CLIP_NDCSPACE; |
clip->clip5.api_mode = BRW_CLIP_API_OGL; |
clip->clip5.clip_mode = brw->clip.prog_data->clip_mode; |
if (brw->is_g4x) |
clip->clip5.negative_w_clip_test = 1; |
clip->viewport_xmin = -1; |
clip->viewport_xmax = 1; |
clip->viewport_ymin = -1; |
clip->viewport_ymax = 1; |
brw->state.dirty.cache |= CACHE_NEW_CLIP_UNIT; |
} |
const struct brw_tracked_state brw_clip_unit = { |
.dirty = { |
.mesa = _NEW_TRANSFORM | _NEW_BUFFERS | _NEW_VIEWPORT, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_PROGRAM_CACHE | |
BRW_NEW_CURBE_OFFSETS | |
BRW_NEW_URB_FENCE), |
.cache = CACHE_NEW_CLIP_PROG |
}, |
.emit = brw_upload_clip_unit, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_clip_tri.c |
---|
0,0 → 1,662 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "program/program.h" |
#include "intel_batchbuffer.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_clip.h" |
static void release_tmps( struct brw_clip_compile *c ) |
{ |
c->last_tmp = c->first_tmp; |
} |
void brw_clip_tri_alloc_regs( struct brw_clip_compile *c, |
GLuint nr_verts ) |
{ |
struct brw_context *brw = c->func.brw; |
GLuint i = 0,j; |
/* Register usage is static, precompute here: |
*/ |
c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++; |
if (c->key.nr_userclip) { |
c->reg.fixed_planes = brw_vec4_grf(i, 0); |
i += (6 + c->key.nr_userclip + 1) / 2; |
c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2; |
} |
else |
c->prog_data.curb_read_length = 0; |
/* Payload vertices plus space for more generated vertices: |
*/ |
for (j = 0; j < nr_verts; j++) { |
c->reg.vertex[j] = brw_vec4_grf(i, 0); |
i += c->nr_regs; |
} |
if (c->vue_map.num_slots % 2) { |
/* The VUE has an odd number of slots so the last register is only half |
* used. Fill the second half with zero. |
*/ |
for (j = 0; j < 3; j++) { |
GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots); |
brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0)); |
} |
} |
c->reg.t = brw_vec1_grf(i, 0); |
c->reg.loopcount = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_D); |
c->reg.nr_verts = retype(brw_vec1_grf(i, 2), BRW_REGISTER_TYPE_UD); |
c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD); |
c->reg.plane_equation = brw_vec4_grf(i, 4); |
i++; |
c->reg.dpPrev = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */ |
c->reg.dp = brw_vec1_grf(i, 4); |
i++; |
c->reg.inlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0); |
i++; |
c->reg.outlist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0); |
i++; |
c->reg.freelist = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0); |
i++; |
if (!c->key.nr_userclip) { |
c->reg.fixed_planes = brw_vec8_grf(i, 0); |
i++; |
} |
if (c->key.do_unfilled) { |
c->reg.dir = brw_vec4_grf(i, 0); |
c->reg.offset = brw_vec4_grf(i, 4); |
i++; |
c->reg.tmp0 = brw_vec4_grf(i, 0); |
c->reg.tmp1 = brw_vec4_grf(i, 4); |
i++; |
} |
c->reg.vertex_src_mask = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD); |
i++; |
if (brw->gen == 5) { |
c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD); |
i++; |
} |
c->first_tmp = i; |
c->last_tmp = i; |
c->prog_data.urb_read_length = c->nr_regs; /* ? */ |
c->prog_data.total_grf = i; |
} |
void brw_clip_tri_init_vertices( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */ |
/* Initial list of indices for incoming vertexes: |
*/ |
brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK)); |
brw_CMP(p, |
vec1(brw_null_reg()), |
BRW_CONDITIONAL_EQ, |
tmp0, |
brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE)); |
/* XXX: Is there an easier way to do this? Need to reverse every |
* second tristrip element: Can ignore sometimes? |
*/ |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[1]) ); |
brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[0]) ); |
if (c->need_direction) |
brw_MOV(p, c->reg.dir, brw_imm_f(-1)); |
} |
brw_ELSE(p); |
{ |
brw_MOV(p, get_element(c->reg.inlist, 0), brw_address(c->reg.vertex[0]) ); |
brw_MOV(p, get_element(c->reg.inlist, 1), brw_address(c->reg.vertex[1]) ); |
if (c->need_direction) |
brw_MOV(p, c->reg.dir, brw_imm_f(1)); |
} |
brw_ENDIF(p); |
brw_MOV(p, get_element(c->reg.inlist, 2), brw_address(c->reg.vertex[2]) ); |
brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0)); |
brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3)); |
} |
void brw_clip_tri_flat_shade( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */ |
brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK)); |
brw_CMP(p, |
vec1(brw_null_reg()), |
BRW_CONDITIONAL_EQ, |
tmp0, |
brw_imm_ud(_3DPRIM_POLYGON)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_clip_copy_colors(c, 1, 0); |
brw_clip_copy_colors(c, 2, 0); |
} |
brw_ELSE(p); |
{ |
if (c->key.pv_first) { |
brw_CMP(p, |
vec1(brw_null_reg()), |
BRW_CONDITIONAL_EQ, |
tmp0, |
brw_imm_ud(_3DPRIM_TRIFAN)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_clip_copy_colors(c, 0, 1); |
brw_clip_copy_colors(c, 2, 1); |
} |
brw_ELSE(p); |
{ |
brw_clip_copy_colors(c, 1, 0); |
brw_clip_copy_colors(c, 2, 0); |
} |
brw_ENDIF(p); |
} |
else { |
brw_clip_copy_colors(c, 0, 2); |
brw_clip_copy_colors(c, 1, 2); |
} |
} |
brw_ENDIF(p); |
} |
static inline void |
load_vertex_pos(struct brw_clip_compile *c, struct brw_indirect vtx, |
struct brw_reg dst, |
GLuint hpos_offset, GLuint clip_offset) |
{ |
struct brw_compile *p = &c->func; |
/* |
* Roughly: |
* dst = (vertex_src_mask & 1) ? src.hpos : src.clipvertex; |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_AND(p, vec1(brw_null_reg()), c->reg.vertex_src_mask, brw_imm_ud(1)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_MOV(p, dst, deref_4f(vtx, clip_offset)); |
} |
brw_ELSE(p); |
{ |
brw_MOV(p, dst, deref_4f(vtx, hpos_offset)); |
} |
brw_ENDIF(p); |
} |
/* Use mesa's clipping algorithms, translated to GEN4 assembly. |
*/ |
void brw_clip_tri( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_indirect vtx = brw_indirect(0, 0); |
struct brw_indirect vtxPrev = brw_indirect(1, 0); |
struct brw_indirect vtxOut = brw_indirect(2, 0); |
struct brw_indirect plane_ptr = brw_indirect(3, 0); |
struct brw_indirect inlist_ptr = brw_indirect(4, 0); |
struct brw_indirect outlist_ptr = brw_indirect(5, 0); |
struct brw_indirect freelist_ptr = brw_indirect(6, 0); |
GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); |
GLuint clipvert_offset = brw_clip_have_varying(c, VARYING_SLOT_CLIP_VERTEX) |
? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_VERTEX) |
: hpos_offset; |
brw_MOV(p, get_addr_reg(vtxPrev), brw_address(c->reg.vertex[2]) ); |
brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c)); |
brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist)); |
brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist)); |
brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) ); |
/* Set the initial vertex source mask: The first 6 planes are the bounds |
* of the view volume; the next 6 planes are the user clipping planes. |
*/ |
brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0xfc0)); |
brw_DO(p, BRW_EXECUTE_1); |
{ |
/* if (planemask & 1) |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
/* vtxOut = freelist_ptr++ |
*/ |
brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(freelist_ptr) ); |
brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE)); |
if (c->key.nr_userclip) |
brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0)); |
else |
brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0)); |
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); |
brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0)); |
brw_DO(p, BRW_EXECUTE_1); |
{ |
/* vtx = *input_ptr; |
*/ |
brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0)); |
load_vertex_pos(c, vtxPrev, vec4(c->reg.dpPrev), hpos_offset, clipvert_offset); |
/* IS_NEGATIVE(prev) */ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_L); |
brw_DP4(p, vec4(c->reg.dpPrev), vec4(c->reg.dpPrev), c->reg.plane_equation); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
load_vertex_pos(c, vtx, vec4(c->reg.dp), hpos_offset, clipvert_offset); |
/* IS_POSITIVE(next) |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_GE); |
brw_DP4(p, vec4(c->reg.dp), vec4(c->reg.dp), c->reg.plane_equation); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
/* Coming back in. |
*/ |
brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp)); |
brw_math_invert(p, c->reg.t, c->reg.t); |
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev); |
/* If (vtxOut == 0) vtxOut = vtxPrev |
*/ |
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) ); |
brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev) ); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, false); |
/* *outlist_ptr++ = vtxOut; |
* nr_verts++; |
* vtxOut = 0; |
*/ |
brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut)); |
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short))); |
brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1)); |
brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) ); |
} |
brw_ENDIF(p); |
} |
brw_ELSE(p); |
{ |
/* *outlist_ptr++ = vtxPrev; |
* nr_verts++; |
*/ |
brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev)); |
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short))); |
brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1)); |
load_vertex_pos(c, vtx, vec4(c->reg.dp), hpos_offset, clipvert_offset); |
/* IS_NEGATIVE(next) |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_L); |
brw_DP4(p, vec4(c->reg.dp), vec4(c->reg.dp), c->reg.plane_equation); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
/* Going out of bounds. Avoid division by zero as we |
* know dp != dpPrev from DIFFERENT_SIGNS, above. |
*/ |
brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev)); |
brw_math_invert(p, c->reg.t, c->reg.t); |
brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp); |
/* If (vtxOut == 0) vtxOut = vtx |
*/ |
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) ); |
brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx) ); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, true); |
/* *outlist_ptr++ = vtxOut; |
* nr_verts++; |
* vtxOut = 0; |
*/ |
brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut)); |
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short))); |
brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1)); |
brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) ); |
} |
brw_ENDIF(p); |
} |
brw_ENDIF(p); |
/* vtxPrev = vtx; |
* inlist_ptr++; |
*/ |
brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx)); |
brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short))); |
/* while (--loopcount != 0) |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); |
} |
brw_WHILE(p); |
/* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1] |
* inlist = outlist |
* inlist_ptr = &inlist[0] |
* outlist_ptr = &outlist[0] |
*/ |
brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2)); |
brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0)); |
brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0)); |
brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist)); |
brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist)); |
} |
brw_ENDIF(p); |
/* plane_ptr++; |
*/ |
brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c)); |
/* nr_verts >= 3 |
*/ |
brw_CMP(p, |
vec1(brw_null_reg()), |
BRW_CONDITIONAL_GE, |
c->reg.nr_verts, |
brw_imm_ud(3)); |
/* && (planemask>>=1) != 0 |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1)); |
brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1)); |
} |
brw_WHILE(p); |
} |
void brw_clip_tri_emit_polygon(struct brw_clip_compile *c) |
{ |
struct brw_compile *p = &c->func; |
/* for (loopcount = nr_verts-2; loopcount > 0; loopcount--) |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_G); |
brw_ADD(p, |
c->reg.loopcount, |
c->reg.nr_verts, |
brw_imm_d(-2)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
struct brw_indirect v0 = brw_indirect(0, 0); |
struct brw_indirect vptr = brw_indirect(1, 0); |
brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist)); |
brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0)); |
brw_clip_emit_vue(c, v0, 1, 0, |
((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_START)); |
brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2)); |
brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0)); |
brw_DO(p, BRW_EXECUTE_1); |
{ |
brw_clip_emit_vue(c, v0, 1, 0, |
(_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)); |
brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2)); |
brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0)); |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); |
} |
brw_WHILE(p); |
brw_clip_emit_vue(c, v0, 0, 1, |
((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_END)); |
} |
brw_ENDIF(p); |
} |
static void do_clip_tri( struct brw_clip_compile *c ) |
{ |
brw_clip_init_planes(c); |
brw_clip_tri(c); |
} |
static void maybe_do_clip_tri( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
do_clip_tri(c); |
} |
brw_ENDIF(p); |
} |
static void brw_clip_test( struct brw_clip_compile *c ) |
{ |
struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); |
struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); |
struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); |
struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); |
struct brw_reg v0 = get_tmp(c); |
struct brw_reg v1 = get_tmp(c); |
struct brw_reg v2 = get_tmp(c); |
struct brw_indirect vt0 = brw_indirect(0, 0); |
struct brw_indirect vt1 = brw_indirect(1, 0); |
struct brw_indirect vt2 = brw_indirect(2, 0); |
struct brw_compile *p = &c->func; |
struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */ |
GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_POS); |
brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0])); |
brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1])); |
brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2])); |
brw_MOV(p, v0, deref_4f(vt0, hpos_offset)); |
brw_MOV(p, v1, deref_4f(vt1, hpos_offset)); |
brw_MOV(p, v2, deref_4f(vt2, hpos_offset)); |
brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f)); |
/* test nearz, xmin, ymin plane */ |
/* clip.xyz < -clip.w */ |
brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3))); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3))); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3))); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
/* All vertices are outside of a plane, rejected */ |
brw_AND(p, t, t1, t2); |
brw_AND(p, t, t, t3); |
brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1)); |
brw_OR(p, tmp0, tmp0, get_element(t, 2)); |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_clip_kill_thread(c); |
} |
brw_ENDIF(p); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
/* some vertices are inside a plane, some are outside,need to clip */ |
brw_XOR(p, t, t1, t2); |
brw_XOR(p, t1, t2, t3); |
brw_OR(p, t, t, t1); |
brw_AND(p, t, t, brw_imm_ud(0x1)); |
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, |
get_element(t, 0), brw_imm_ud(0)); |
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5))); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, |
get_element(t, 1), brw_imm_ud(0)); |
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3))); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, |
get_element(t, 2), brw_imm_ud(0)); |
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1))); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
/* test farz, xmax, ymax plane */ |
/* clip.xyz > clip.w */ |
brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3)); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3)); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3)); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
/* All vertices are outside of a plane, rejected */ |
brw_AND(p, t, t1, t2); |
brw_AND(p, t, t, t3); |
brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1)); |
brw_OR(p, tmp0, tmp0, get_element(t, 2)); |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_clip_kill_thread(c); |
} |
brw_ENDIF(p); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
/* some vertices are inside a plane, some are outside,need to clip */ |
brw_XOR(p, t, t1, t2); |
brw_XOR(p, t1, t2, t3); |
brw_OR(p, t, t, t1); |
brw_AND(p, t, t, brw_imm_ud(0x1)); |
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, |
get_element(t, 0), brw_imm_ud(0)); |
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4))); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, |
get_element(t, 1), brw_imm_ud(0)); |
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2))); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ, |
get_element(t, 2), brw_imm_ud(0)); |
brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0))); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
release_tmps(c); |
} |
void brw_emit_tri_clip( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_context *brw = p->brw; |
brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6); |
brw_clip_tri_init_vertices(c); |
brw_clip_init_clipmask(c); |
brw_clip_init_ff_sync(c); |
/* if -ve rhw workaround bit is set, |
do cliptest */ |
if (brw->has_negative_rhw_bug) { |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2), |
brw_imm_ud(1<<20)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_clip_test(c); |
} |
brw_ENDIF(p); |
} |
/* Can't push into do_clip_tri because with polygon (or quad) |
* flatshading, need to apply the flatshade here because we don't |
* respect the PV when converting to trifan for emit: |
*/ |
if (c->key.do_flat_shading) |
brw_clip_tri_flat_shade(c); |
if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) || |
(c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP)) |
do_clip_tri(c); |
else |
maybe_do_clip_tri(c); |
brw_clip_tri_emit_polygon(c); |
/* Send an empty message to kill the thread: |
*/ |
brw_clip_kill_thread(c); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_clip_unfilled.c |
---|
0,0 → 1,522 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "program/program.h" |
#include "intel_batchbuffer.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_clip.h" |
/* This is performed against the original triangles, so no indirection |
* required: |
BZZZT! |
*/ |
static void compute_tri_direction( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_reg e = c->reg.tmp0; |
struct brw_reg f = c->reg.tmp1; |
GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); |
struct brw_reg v0 = byte_offset(c->reg.vertex[0], hpos_offset); |
struct brw_reg v1 = byte_offset(c->reg.vertex[1], hpos_offset); |
struct brw_reg v2 = byte_offset(c->reg.vertex[2], hpos_offset); |
struct brw_reg v0n = get_tmp(c); |
struct brw_reg v1n = get_tmp(c); |
struct brw_reg v2n = get_tmp(c); |
/* Convert to NDC. |
* NOTE: We can't modify the original vertex coordinates, |
* as it may impact further operations. |
* So, we have to keep normalized coordinates in temp registers. |
* |
* TBD-KC |
* Try to optimize unnecessary MOV's. |
*/ |
brw_MOV(p, v0n, v0); |
brw_MOV(p, v1n, v1); |
brw_MOV(p, v2n, v2); |
brw_clip_project_position(c, v0n); |
brw_clip_project_position(c, v1n); |
brw_clip_project_position(c, v2n); |
/* Calculate the vectors of two edges of the triangle: |
*/ |
brw_ADD(p, e, v0n, negate(v2n)); |
brw_ADD(p, f, v1n, negate(v2n)); |
/* Take their crossproduct: |
*/ |
brw_set_access_mode(p, BRW_ALIGN_16); |
brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, 1,2,0,3), brw_swizzle(f,2,0,1,3)); |
brw_MAC(p, vec4(e), negate(brw_swizzle(e, 2,0,1,3)), brw_swizzle(f,1,2,0,3)); |
brw_set_access_mode(p, BRW_ALIGN_1); |
brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e)); |
} |
static void cull_direction( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
GLuint conditional; |
assert (!(c->key.fill_ccw == CLIP_CULL && |
c->key.fill_cw == CLIP_CULL)); |
if (c->key.fill_ccw == CLIP_CULL) |
conditional = BRW_CONDITIONAL_GE; |
else |
conditional = BRW_CONDITIONAL_L; |
brw_CMP(p, |
vec1(brw_null_reg()), |
conditional, |
get_element(c->reg.dir, 2), |
brw_imm_f(0)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_clip_kill_thread(c); |
} |
brw_ENDIF(p); |
} |
static void copy_bfc( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
GLuint conditional; |
/* Do we have any colors to copy? |
*/ |
if (!(brw_clip_have_varying(c, VARYING_SLOT_COL0) && |
brw_clip_have_varying(c, VARYING_SLOT_BFC0)) && |
!(brw_clip_have_varying(c, VARYING_SLOT_COL1) && |
brw_clip_have_varying(c, VARYING_SLOT_BFC1))) |
return; |
/* In some wierd degnerate cases we can end up testing the |
* direction twice, once for culling and once for bfc copying. Oh |
* well, that's what you get for setting wierd GL state. |
*/ |
if (c->key.copy_bfc_ccw) |
conditional = BRW_CONDITIONAL_GE; |
else |
conditional = BRW_CONDITIONAL_L; |
brw_CMP(p, |
vec1(brw_null_reg()), |
conditional, |
get_element(c->reg.dir, 2), |
brw_imm_f(0)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
GLuint i; |
for (i = 0; i < 3; i++) { |
if (brw_clip_have_varying(c, VARYING_SLOT_COL0) && |
brw_clip_have_varying(c, VARYING_SLOT_BFC0)) |
brw_MOV(p, |
byte_offset(c->reg.vertex[i], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_COL0)), |
byte_offset(c->reg.vertex[i], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_BFC0))); |
if (brw_clip_have_varying(c, VARYING_SLOT_COL1) && |
brw_clip_have_varying(c, VARYING_SLOT_BFC1)) |
brw_MOV(p, |
byte_offset(c->reg.vertex[i], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_COL1)), |
byte_offset(c->reg.vertex[i], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_BFC1))); |
} |
} |
brw_ENDIF(p); |
} |
/* |
GLfloat iz = 1.0 / dir.z; |
GLfloat ac = dir.x * iz; |
GLfloat bc = dir.y * iz; |
offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE; |
offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor; |
offset *= MRD; |
*/ |
static void compute_offset( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_reg off = c->reg.offset; |
struct brw_reg dir = c->reg.dir; |
brw_math_invert(p, get_element(off, 2), get_element(dir, 2)); |
brw_MUL(p, vec2(off), dir, get_element(off, 2)); |
brw_CMP(p, |
vec1(brw_null_reg()), |
BRW_CONDITIONAL_GE, |
brw_abs(get_element(off, 0)), |
brw_abs(get_element(off, 1))); |
brw_SEL(p, vec1(off), brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1))); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_MUL(p, vec1(off), off, brw_imm_f(c->key.offset_factor)); |
brw_ADD(p, vec1(off), off, brw_imm_f(c->key.offset_units)); |
} |
static void merge_edgeflags( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0); |
brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK)); |
brw_CMP(p, |
vec1(brw_null_reg()), |
BRW_CONDITIONAL_EQ, |
tmp0, |
brw_imm_ud(_3DPRIM_POLYGON)); |
/* Get away with using reg.vertex because we know that this is not |
* a _3DPRIM_TRISTRIP_REVERSE: |
*/ |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_EQ); |
brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8)); |
brw_MOV(p, byte_offset(c->reg.vertex[0], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_EDGE)), |
brw_imm_f(0)); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_set_conditionalmod(p, BRW_CONDITIONAL_EQ); |
brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9)); |
brw_MOV(p, byte_offset(c->reg.vertex[2], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_EDGE)), |
brw_imm_f(0)); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
} |
brw_ENDIF(p); |
} |
static void apply_one_offset( struct brw_clip_compile *c, |
struct brw_indirect vert ) |
{ |
struct brw_compile *p = &c->func; |
GLuint ndc_offset = brw_varying_to_offset(&c->vue_map, |
BRW_VARYING_SLOT_NDC); |
struct brw_reg z = deref_1f(vert, ndc_offset + |
2 * type_sz(BRW_REGISTER_TYPE_F)); |
brw_ADD(p, z, z, vec1(c->reg.offset)); |
} |
/*********************************************************************** |
* Output clipped polygon as an unfilled primitive: |
*/ |
static void emit_lines(struct brw_clip_compile *c, |
bool do_offset) |
{ |
struct brw_compile *p = &c->func; |
struct brw_indirect v0 = brw_indirect(0, 0); |
struct brw_indirect v1 = brw_indirect(1, 0); |
struct brw_indirect v0ptr = brw_indirect(2, 0); |
struct brw_indirect v1ptr = brw_indirect(3, 0); |
/* Need a seperate loop for offset: |
*/ |
if (do_offset) { |
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); |
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist)); |
brw_DO(p, BRW_EXECUTE_1); |
{ |
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0)); |
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2)); |
apply_one_offset(c, v0); |
brw_set_conditionalmod(p, BRW_CONDITIONAL_G); |
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); |
} |
brw_WHILE(p); |
} |
/* v1ptr = &inlist[nr_verts] |
* *v1ptr = v0 |
*/ |
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); |
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist)); |
brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW)); |
brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW)); |
brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0)); |
brw_DO(p, BRW_EXECUTE_1); |
{ |
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0)); |
brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2)); |
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2)); |
/* draw edge if edgeflag != 0 */ |
brw_CMP(p, |
vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, |
deref_1f(v0, brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_EDGE)), |
brw_imm_f(0)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_clip_emit_vue(c, v0, 1, 0, |
(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_START); |
brw_clip_emit_vue(c, v1, 1, 0, |
(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_END); |
} |
brw_ENDIF(p); |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); |
} |
brw_WHILE(p); |
} |
static void emit_points(struct brw_clip_compile *c, |
bool do_offset ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_indirect v0 = brw_indirect(0, 0); |
struct brw_indirect v0ptr = brw_indirect(2, 0); |
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts); |
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist)); |
brw_DO(p, BRW_EXECUTE_1); |
{ |
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0)); |
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2)); |
/* draw if edgeflag != 0 |
*/ |
brw_CMP(p, |
vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, |
deref_1f(v0, brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_EDGE)), |
brw_imm_f(0)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
if (do_offset) |
apply_one_offset(c, v0); |
brw_clip_emit_vue(c, v0, 1, 0, |
(_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_START | URB_WRITE_PRIM_END); |
} |
brw_ENDIF(p); |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1)); |
} |
brw_WHILE(p); |
} |
static void emit_primitives( struct brw_clip_compile *c, |
GLuint mode, |
bool do_offset ) |
{ |
switch (mode) { |
case CLIP_FILL: |
brw_clip_tri_emit_polygon(c); |
break; |
case CLIP_LINE: |
emit_lines(c, do_offset); |
break; |
case CLIP_POINT: |
emit_points(c, do_offset); |
break; |
case CLIP_CULL: |
assert(0); |
break; |
} |
} |
static void emit_unfilled_primitives( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
/* Direction culling has already been done. |
*/ |
if (c->key.fill_ccw != c->key.fill_cw && |
c->key.fill_ccw != CLIP_CULL && |
c->key.fill_cw != CLIP_CULL) |
{ |
brw_CMP(p, |
vec1(brw_null_reg()), |
BRW_CONDITIONAL_GE, |
get_element(c->reg.dir, 2), |
brw_imm_f(0)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw); |
} |
brw_ELSE(p); |
{ |
emit_primitives(c, c->key.fill_cw, c->key.offset_cw); |
} |
brw_ENDIF(p); |
} |
else if (c->key.fill_cw != CLIP_CULL) { |
emit_primitives(c, c->key.fill_cw, c->key.offset_cw); |
} |
else if (c->key.fill_ccw != CLIP_CULL) { |
emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw); |
} |
} |
static void check_nr_verts( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_clip_kill_thread(c); |
} |
brw_ENDIF(p); |
} |
void brw_emit_unfilled_clip( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) || |
(c->key.fill_ccw != c->key.fill_cw) || |
c->key.fill_ccw == CLIP_CULL || |
c->key.fill_cw == CLIP_CULL || |
c->key.copy_bfc_cw || |
c->key.copy_bfc_ccw); |
brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6); |
brw_clip_tri_init_vertices(c); |
brw_clip_init_ff_sync(c); |
assert(brw_clip_have_varying(c, VARYING_SLOT_EDGE)); |
if (c->key.fill_ccw == CLIP_CULL && |
c->key.fill_cw == CLIP_CULL) { |
brw_clip_kill_thread(c); |
return; |
} |
merge_edgeflags(c); |
/* Need to use the inlist indirection here: |
*/ |
if (c->need_direction) |
compute_tri_direction(c); |
if (c->key.fill_ccw == CLIP_CULL || |
c->key.fill_cw == CLIP_CULL) |
cull_direction(c); |
if (c->key.offset_ccw || |
c->key.offset_cw) |
compute_offset(c); |
if (c->key.copy_bfc_ccw || |
c->key.copy_bfc_cw) |
copy_bfc(c); |
/* Need to do this whether we clip or not: |
*/ |
if (c->key.do_flat_shading) |
brw_clip_tri_flat_shade(c); |
brw_clip_init_clipmask(c); |
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_clip_init_planes(c); |
brw_clip_tri(c); |
check_nr_verts(c); |
} |
brw_ENDIF(p); |
emit_unfilled_primitives(c); |
brw_clip_kill_thread(c); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_clip_util.c |
---|
0,0 → 1,396 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "program/program.h" |
#include "intel_batchbuffer.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_clip.h" |
struct brw_reg get_tmp( struct brw_clip_compile *c ) |
{ |
struct brw_reg tmp = brw_vec4_grf(c->last_tmp, 0); |
if (++c->last_tmp > c->prog_data.total_grf) |
c->prog_data.total_grf = c->last_tmp; |
return tmp; |
} |
static void release_tmp( struct brw_clip_compile *c, struct brw_reg tmp ) |
{ |
if (tmp.nr == c->last_tmp-1) |
c->last_tmp--; |
} |
static struct brw_reg make_plane_ud(GLuint x, GLuint y, GLuint z, GLuint w) |
{ |
return brw_imm_ud((w<<24) | (z<<16) | (y<<8) | x); |
} |
void brw_clip_init_planes( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
if (!c->key.nr_userclip) { |
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 0), make_plane_ud( 0, 0, 0xff, 1)); |
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 1), make_plane_ud( 0, 0, 1, 1)); |
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 2), make_plane_ud( 0, 0xff, 0, 1)); |
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 3), make_plane_ud( 0, 1, 0, 1)); |
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 4), make_plane_ud(0xff, 0, 0, 1)); |
brw_MOV(p, get_element_ud(c->reg.fixed_planes, 5), make_plane_ud( 1, 0, 0, 1)); |
} |
} |
#define W 3 |
/* Project 'pos' to screen space (or back again), overwrite with results: |
*/ |
void brw_clip_project_position(struct brw_clip_compile *c, struct brw_reg pos ) |
{ |
struct brw_compile *p = &c->func; |
/* calc rhw |
*/ |
brw_math_invert(p, get_element(pos, W), get_element(pos, W)); |
/* value.xyz *= value.rhw |
*/ |
brw_set_access_mode(p, BRW_ALIGN_16); |
brw_MUL(p, brw_writemask(pos, WRITEMASK_XYZ), pos, brw_swizzle1(pos, W)); |
brw_set_access_mode(p, BRW_ALIGN_1); |
} |
static void brw_clip_project_vertex( struct brw_clip_compile *c, |
struct brw_indirect vert_addr ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_reg tmp = get_tmp(c); |
GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); |
GLuint ndc_offset = brw_varying_to_offset(&c->vue_map, |
BRW_VARYING_SLOT_NDC); |
/* Fixup position. Extract from the original vertex and re-project |
* to screen space: |
*/ |
brw_MOV(p, tmp, deref_4f(vert_addr, hpos_offset)); |
brw_clip_project_position(c, tmp); |
brw_MOV(p, deref_4f(vert_addr, ndc_offset), tmp); |
release_tmp(c, tmp); |
} |
/* Interpolate between two vertices and put the result into a0.0. |
* Increment a0.0 accordingly. |
*/ |
void brw_clip_interp_vertex( struct brw_clip_compile *c, |
struct brw_indirect dest_ptr, |
struct brw_indirect v0_ptr, /* from */ |
struct brw_indirect v1_ptr, /* to */ |
struct brw_reg t0, |
bool force_edgeflag) |
{ |
struct brw_compile *p = &c->func; |
struct brw_reg tmp = get_tmp(c); |
GLuint slot; |
/* Just copy the vertex header: |
*/ |
/* |
* After CLIP stage, only first 256 bits of the VUE are read |
* back on Ironlake, so needn't change it |
*/ |
brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1); |
/* Iterate over each attribute (could be done in pairs?) |
*/ |
for (slot = 0; slot < c->vue_map.num_slots; slot++) { |
int varying = c->vue_map.slot_to_varying[slot]; |
GLuint delta = brw_vue_slot_to_offset(slot); |
if (varying == VARYING_SLOT_EDGE) { |
if (force_edgeflag) |
brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1)); |
else |
brw_MOV(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta)); |
} else if (varying == VARYING_SLOT_PSIZ || |
varying == VARYING_SLOT_CLIP_DIST0 || |
varying == VARYING_SLOT_CLIP_DIST1) { |
/* PSIZ doesn't need interpolation because it isn't used by the |
* fragment shader. CLIP_DIST0 and CLIP_DIST1 don't need |
* intepolation because on pre-GEN6, these are just placeholder VUE |
* slots that don't perform any action. |
*/ |
} else if (varying < VARYING_SLOT_MAX) { |
/* This is a true vertex result (and not a special value for the VUE |
* header), so interpolate: |
* |
* New = attr0 + t*attr1 - t*attr0 |
*/ |
brw_MUL(p, |
vec4(brw_null_reg()), |
deref_4f(v1_ptr, delta), |
t0); |
brw_MAC(p, |
tmp, |
negate(deref_4f(v0_ptr, delta)), |
t0); |
brw_ADD(p, |
deref_4f(dest_ptr, delta), |
deref_4f(v0_ptr, delta), |
tmp); |
} |
} |
if (c->vue_map.num_slots % 2) { |
GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots); |
brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0)); |
} |
release_tmp(c, tmp); |
/* Recreate the projected (NDC) coordinate in the new vertex |
* header: |
*/ |
brw_clip_project_vertex(c, dest_ptr ); |
} |
void brw_clip_emit_vue(struct brw_clip_compile *c, |
struct brw_indirect vert, |
bool allocate, |
bool eot, |
GLuint header) |
{ |
struct brw_compile *p = &c->func; |
brw_clip_ff_sync(c); |
assert(!(allocate && eot)); |
/* Copy the vertex from vertn into m1..mN+1: |
*/ |
brw_copy_from_indirect(p, brw_message_reg(1), vert, c->nr_regs); |
/* Overwrite PrimType and PrimStart in the message header, for |
* each vertex in turn: |
*/ |
brw_MOV(p, get_element_ud(c->reg.R0, 2), brw_imm_ud(header)); |
/* Send each vertex as a seperate write to the urb. This |
* is different to the concept in brw_sf_emit.c, where |
* subsequent writes are used to build up a single urb |
* entry. Each of these writes instantiates a seperate |
* urb entry - (I think... what about 'allocate'?) |
*/ |
brw_urb_WRITE(p, |
allocate ? c->reg.R0 : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), |
0, |
c->reg.R0, |
allocate, |
1, /* used */ |
c->nr_regs + 1, /* msg length */ |
allocate ? 1 : 0, /* response_length */ |
eot, /* eot */ |
1, /* writes_complete */ |
0, /* urb offset */ |
BRW_URB_SWIZZLE_NONE); |
} |
void brw_clip_kill_thread(struct brw_clip_compile *c) |
{ |
struct brw_compile *p = &c->func; |
brw_clip_ff_sync(c); |
/* Send an empty message to kill the thread and release any |
* allocated urb entry: |
*/ |
brw_urb_WRITE(p, |
retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), |
0, |
c->reg.R0, |
0, /* allocate */ |
0, /* used */ |
1, /* msg len */ |
0, /* response len */ |
1, /* eot */ |
1, /* writes complete */ |
0, |
BRW_URB_SWIZZLE_NONE); |
} |
struct brw_reg brw_clip_plane0_address( struct brw_clip_compile *c ) |
{ |
return brw_address(c->reg.fixed_planes); |
} |
struct brw_reg brw_clip_plane_stride( struct brw_clip_compile *c ) |
{ |
if (c->key.nr_userclip) { |
return brw_imm_uw(16); |
} |
else { |
return brw_imm_uw(4); |
} |
} |
/* If flatshading, distribute color from provoking vertex prior to |
* clipping. |
*/ |
void brw_clip_copy_colors( struct brw_clip_compile *c, |
GLuint to, GLuint from ) |
{ |
struct brw_compile *p = &c->func; |
if (brw_clip_have_varying(c, VARYING_SLOT_COL0)) |
brw_MOV(p, |
byte_offset(c->reg.vertex[to], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_COL0)), |
byte_offset(c->reg.vertex[from], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_COL0))); |
if (brw_clip_have_varying(c, VARYING_SLOT_COL1)) |
brw_MOV(p, |
byte_offset(c->reg.vertex[to], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_COL1)), |
byte_offset(c->reg.vertex[from], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_COL1))); |
if (brw_clip_have_varying(c, VARYING_SLOT_BFC0)) |
brw_MOV(p, |
byte_offset(c->reg.vertex[to], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_BFC0)), |
byte_offset(c->reg.vertex[from], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_BFC0))); |
if (brw_clip_have_varying(c, VARYING_SLOT_BFC1)) |
brw_MOV(p, |
byte_offset(c->reg.vertex[to], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_BFC1)), |
byte_offset(c->reg.vertex[from], |
brw_varying_to_offset(&c->vue_map, |
VARYING_SLOT_BFC1))); |
} |
void brw_clip_init_clipmask( struct brw_clip_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_reg incoming = get_element_ud(c->reg.R0, 2); |
/* Shift so that lowest outcode bit is rightmost: |
*/ |
brw_SHR(p, c->reg.planemask, incoming, brw_imm_ud(26)); |
if (c->key.nr_userclip) { |
struct brw_reg tmp = retype(vec1(get_tmp(c)), BRW_REGISTER_TYPE_UD); |
/* Rearrange userclip outcodes so that they come directly after |
* the fixed plane bits. |
*/ |
brw_AND(p, tmp, incoming, brw_imm_ud(0x3f<<14)); |
brw_SHR(p, tmp, tmp, brw_imm_ud(8)); |
brw_OR(p, c->reg.planemask, c->reg.planemask, tmp); |
release_tmp(c, tmp); |
} |
} |
void brw_clip_ff_sync(struct brw_clip_compile *c) |
{ |
struct brw_compile *p = &c->func; |
struct brw_context *brw = p->brw; |
if (brw->gen == 5) { |
brw_set_conditionalmod(p, BRW_CONDITIONAL_Z); |
brw_AND(p, brw_null_reg(), c->reg.ff_sync, brw_imm_ud(0x1)); |
brw_IF(p, BRW_EXECUTE_1); |
{ |
brw_OR(p, c->reg.ff_sync, c->reg.ff_sync, brw_imm_ud(0x1)); |
brw_ff_sync(p, |
c->reg.R0, |
0, |
c->reg.R0, |
1, /* allocate */ |
1, /* response length */ |
0 /* eot */); |
} |
brw_ENDIF(p); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
} |
} |
void brw_clip_init_ff_sync(struct brw_clip_compile *c) |
{ |
struct brw_context *brw = c->func.brw; |
if (brw->gen == 5) { |
struct brw_compile *p = &c->func; |
brw_MOV(p, c->reg.ff_sync, brw_imm_ud(0)); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_context.c |
---|
0,0 → 1,480 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/api_exec.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "main/points.h" |
#include "main/simple_list.h" |
#include "main/version.h" |
#include "main/vtxfmt.h" |
#include "vbo/vbo_context.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
#include "brw_draw.h" |
#include "brw_state.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_tex.h" |
#include "intel_tex_obj.h" |
#include "tnl/t_pipeline.h" |
#include "glsl/ralloc.h" |
/*************************************** |
* Mesa's Driver Functions |
***************************************/ |
static size_t |
brw_query_samples_for_format(struct gl_context *ctx, GLenum target, |
GLenum internalFormat, int samples[16]) |
{ |
struct brw_context *brw = brw_context(ctx); |
(void) target; |
switch (brw->gen) { |
case 7: |
samples[0] = 8; |
samples[1] = 4; |
return 2; |
case 6: |
samples[0] = 4; |
return 1; |
default: |
samples[0] = 1; |
return 1; |
} |
} |
static void brwInitDriverFunctions(struct intel_screen *screen, |
struct dd_function_table *functions) |
{ |
intelInitDriverFunctions( functions ); |
brwInitFragProgFuncs( functions ); |
brw_init_common_queryobj_functions(functions); |
if (screen->gen >= 6) |
gen6_init_queryobj_functions(functions); |
else |
gen4_init_queryobj_functions(functions); |
functions->QuerySamplesForFormat = brw_query_samples_for_format; |
if (screen->gen >= 7) { |
functions->BeginTransformFeedback = gen7_begin_transform_feedback; |
functions->EndTransformFeedback = gen7_end_transform_feedback; |
} else { |
functions->BeginTransformFeedback = brw_begin_transform_feedback; |
functions->EndTransformFeedback = brw_end_transform_feedback; |
} |
if (screen->gen >= 6) |
functions->GetSamplePosition = gen6_get_sample_position; |
} |
static void |
brw_initialize_context_constants(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
ctx->Const.QueryCounterBits.Timestamp = 36; |
ctx->Const.StripTextureBorder = true; |
ctx->Const.MaxDualSourceDrawBuffers = 1; |
ctx->Const.MaxDrawBuffers = BRW_MAX_DRAW_BUFFERS; |
ctx->Const.FragmentProgram.MaxTextureImageUnits = BRW_MAX_TEX_UNIT; |
ctx->Const.MaxTextureCoordUnits = 8; /* Mesa limit */ |
ctx->Const.MaxTextureUnits = |
MIN2(ctx->Const.MaxTextureCoordUnits, |
ctx->Const.FragmentProgram.MaxTextureImageUnits); |
ctx->Const.VertexProgram.MaxTextureImageUnits = BRW_MAX_TEX_UNIT; |
ctx->Const.MaxCombinedTextureImageUnits = |
ctx->Const.VertexProgram.MaxTextureImageUnits + |
ctx->Const.FragmentProgram.MaxTextureImageUnits; |
ctx->Const.MaxTextureLevels = 14; /* 8192 */ |
if (ctx->Const.MaxTextureLevels > MAX_TEXTURE_LEVELS) |
ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS; |
ctx->Const.Max3DTextureLevels = 9; |
ctx->Const.MaxCubeTextureLevels = 12; |
if (brw->gen >= 7) |
ctx->Const.MaxArrayTextureLayers = 2048; |
else |
ctx->Const.MaxArrayTextureLayers = 512; |
ctx->Const.MaxTextureRectSize = 1 << 12; |
ctx->Const.MaxTextureMaxAnisotropy = 16.0; |
ctx->Const.MaxRenderbufferSize = 8192; |
/* Hardware only supports a limited number of transform feedback buffers. |
* So we need to override the Mesa default (which is based only on software |
* limits). |
*/ |
ctx->Const.MaxTransformFeedbackBuffers = BRW_MAX_SOL_BUFFERS; |
/* On Gen6, in the worst case, we use up one binding table entry per |
* transform feedback component (see comments above the definition of |
* BRW_MAX_SOL_BINDINGS, in brw_context.h), so we need to advertise a value |
* for MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS equal to |
* BRW_MAX_SOL_BINDINGS. |
* |
* In "separate components" mode, we need to divide this value by |
* BRW_MAX_SOL_BUFFERS, so that the total number of binding table entries |
* used up by all buffers will not exceed BRW_MAX_SOL_BINDINGS. |
*/ |
ctx->Const.MaxTransformFeedbackInterleavedComponents = BRW_MAX_SOL_BINDINGS; |
ctx->Const.MaxTransformFeedbackSeparateComponents = |
BRW_MAX_SOL_BINDINGS / BRW_MAX_SOL_BUFFERS; |
if (brw->gen == 6) { |
ctx->Const.MaxSamples = 4; |
ctx->Const.MaxColorTextureSamples = 4; |
ctx->Const.MaxDepthTextureSamples = 4; |
ctx->Const.MaxIntegerSamples = 4; |
} else if (brw->gen >= 7) { |
ctx->Const.MaxSamples = 8; |
ctx->Const.MaxColorTextureSamples = 8; |
ctx->Const.MaxDepthTextureSamples = 8; |
ctx->Const.MaxIntegerSamples = 8; |
} |
ctx->Const.MinLineWidth = 1.0; |
ctx->Const.MinLineWidthAA = 1.0; |
ctx->Const.MaxLineWidth = 5.0; |
ctx->Const.MaxLineWidthAA = 5.0; |
ctx->Const.LineWidthGranularity = 0.5; |
ctx->Const.MinPointSize = 1.0; |
ctx->Const.MinPointSizeAA = 1.0; |
ctx->Const.MaxPointSize = 255.0; |
ctx->Const.MaxPointSizeAA = 255.0; |
ctx->Const.PointSizeGranularity = 1.0; |
if (brw->gen >= 6) |
ctx->Const.MaxClipPlanes = 8; |
ctx->Const.VertexProgram.MaxNativeInstructions = 16 * 1024; |
ctx->Const.VertexProgram.MaxAluInstructions = 0; |
ctx->Const.VertexProgram.MaxTexInstructions = 0; |
ctx->Const.VertexProgram.MaxTexIndirections = 0; |
ctx->Const.VertexProgram.MaxNativeAluInstructions = 0; |
ctx->Const.VertexProgram.MaxNativeTexInstructions = 0; |
ctx->Const.VertexProgram.MaxNativeTexIndirections = 0; |
ctx->Const.VertexProgram.MaxNativeAttribs = 16; |
ctx->Const.VertexProgram.MaxNativeTemps = 256; |
ctx->Const.VertexProgram.MaxNativeAddressRegs = 1; |
ctx->Const.VertexProgram.MaxNativeParameters = 1024; |
ctx->Const.VertexProgram.MaxEnvParams = |
MIN2(ctx->Const.VertexProgram.MaxNativeParameters, |
ctx->Const.VertexProgram.MaxEnvParams); |
ctx->Const.FragmentProgram.MaxNativeInstructions = 1024; |
ctx->Const.FragmentProgram.MaxNativeAluInstructions = 1024; |
ctx->Const.FragmentProgram.MaxNativeTexInstructions = 1024; |
ctx->Const.FragmentProgram.MaxNativeTexIndirections = 1024; |
ctx->Const.FragmentProgram.MaxNativeAttribs = 12; |
ctx->Const.FragmentProgram.MaxNativeTemps = 256; |
ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; |
ctx->Const.FragmentProgram.MaxNativeParameters = 1024; |
ctx->Const.FragmentProgram.MaxEnvParams = |
MIN2(ctx->Const.FragmentProgram.MaxNativeParameters, |
ctx->Const.FragmentProgram.MaxEnvParams); |
/* Fragment shaders use real, 32-bit twos-complement integers for all |
* integer types. |
*/ |
ctx->Const.FragmentProgram.LowInt.RangeMin = 31; |
ctx->Const.FragmentProgram.LowInt.RangeMax = 30; |
ctx->Const.FragmentProgram.LowInt.Precision = 0; |
ctx->Const.FragmentProgram.HighInt = ctx->Const.FragmentProgram.LowInt; |
ctx->Const.FragmentProgram.MediumInt = ctx->Const.FragmentProgram.LowInt; |
/* Gen6 converts quads to polygon in beginning of 3D pipeline, |
* but we're not sure how it's actually done for vertex order, |
* that affect provoking vertex decision. Always use last vertex |
* convention for quad primitive which works as expected for now. |
*/ |
if (brw->gen >= 6) |
ctx->Const.QuadsFollowProvokingVertexConvention = false; |
ctx->Const.NativeIntegers = true; |
ctx->Const.UniformBooleanTrue = 1; |
ctx->Const.UniformBufferOffsetAlignment = 16; |
ctx->Const.ForceGLSLExtensionsWarn = |
driQueryOptionb(&brw->optionCache, "force_glsl_extensions_warn"); |
ctx->Const.DisableGLSLLineContinuations = |
driQueryOptionb(&brw->optionCache, "disable_glsl_line_continuations"); |
/* We want the GLSL compiler to emit code that uses condition codes */ |
for (int i = 0; i <= MESA_SHADER_FRAGMENT; i++) { |
ctx->ShaderCompilerOptions[i].MaxIfDepth = brw->gen < 6 ? 16 : UINT_MAX; |
ctx->ShaderCompilerOptions[i].EmitCondCodes = true; |
ctx->ShaderCompilerOptions[i].EmitNoNoise = true; |
ctx->ShaderCompilerOptions[i].EmitNoMainReturn = true; |
ctx->ShaderCompilerOptions[i].EmitNoIndirectInput = true; |
ctx->ShaderCompilerOptions[i].EmitNoIndirectOutput = true; |
ctx->ShaderCompilerOptions[i].EmitNoIndirectUniform = |
(i == MESA_SHADER_FRAGMENT); |
ctx->ShaderCompilerOptions[i].EmitNoIndirectTemp = |
(i == MESA_SHADER_FRAGMENT); |
ctx->ShaderCompilerOptions[i].LowerClipDistance = true; |
} |
ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].PreferDP4 = true; |
} |
bool |
brwCreateContext(int api, |
const struct gl_config *mesaVis, |
__DRIcontext *driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
uint32_t flags, |
unsigned *error, |
void *sharedContextPrivate) |
{ |
__DRIscreen *sPriv = driContextPriv->driScreenPriv; |
struct intel_screen *screen = sPriv->driverPrivate; |
struct dd_function_table functions; |
struct brw_context *brw = rzalloc(NULL, struct brw_context); |
if (!brw) { |
printf("%s: failed to alloc context\n", __FUNCTION__); |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
return false; |
} |
/* brwInitVtbl needs to know the chipset generation so that it can set the |
* right pointers. |
*/ |
brw->gen = screen->gen; |
brwInitVtbl( brw ); |
brwInitDriverFunctions(screen, &functions); |
struct gl_context *ctx = &brw->ctx; |
if (!intelInitContext( brw, api, major_version, minor_version, |
mesaVis, driContextPriv, |
sharedContextPrivate, &functions, |
error)) { |
ralloc_free(brw); |
return false; |
} |
brw_initialize_context_constants(brw); |
/* Reinitialize the context point state. It depends on ctx->Const values. */ |
_mesa_init_point(ctx); |
if (brw->gen >= 6) { |
/* Create a new hardware context. Using a hardware context means that |
* our GPU state will be saved/restored on context switch, allowing us |
* to assume that the GPU is in the same state we left it in. |
* |
* This is required for transform feedback buffer offsets, query objects, |
* and also allows us to reduce how much state we have to emit. |
*/ |
brw->hw_ctx = drm_intel_gem_context_create(brw->bufmgr); |
if (!brw->hw_ctx) { |
fprintf(stderr, "Gen6+ requires Kernel 3.6 or later.\n"); |
ralloc_free(brw); |
return false; |
} |
} |
brw_init_surface_formats(brw); |
/* Initialize swrast, tnl driver tables: */ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
if (tnl) |
tnl->Driver.RunPipeline = _tnl_run_pipeline; |
ctx->DriverFlags.NewTransformFeedback = BRW_NEW_TRANSFORM_FEEDBACK; |
ctx->DriverFlags.NewRasterizerDiscard = BRW_NEW_RASTERIZER_DISCARD; |
ctx->DriverFlags.NewUniformBuffer = BRW_NEW_UNIFORM_BUFFER; |
if (brw->is_g4x || brw->gen >= 5) { |
brw->CMD_VF_STATISTICS = GM45_3DSTATE_VF_STATISTICS; |
brw->CMD_PIPELINE_SELECT = CMD_PIPELINE_SELECT_GM45; |
brw->has_surface_tile_offset = true; |
if (brw->gen < 6) |
brw->has_compr4 = true; |
brw->has_aa_line_parameters = true; |
brw->has_pln = true; |
} else { |
brw->CMD_VF_STATISTICS = GEN4_3DSTATE_VF_STATISTICS; |
brw->CMD_PIPELINE_SELECT = CMD_PIPELINE_SELECT_965; |
} |
/* WM maximum threads is number of EUs times number of threads per EU. */ |
assert(brw->gen <= 7); |
if (brw->is_haswell) { |
if (brw->gt == 1) { |
brw->max_wm_threads = 102; |
brw->max_vs_threads = 70; |
brw->urb.size = 128; |
brw->urb.max_vs_entries = 640; |
brw->urb.max_gs_entries = 256; |
} else if (brw->gt == 2) { |
brw->max_wm_threads = 204; |
brw->max_vs_threads = 280; |
brw->urb.size = 256; |
brw->urb.max_vs_entries = 1664; |
brw->urb.max_gs_entries = 640; |
} else if (brw->gt == 3) { |
brw->max_wm_threads = 408; |
brw->max_vs_threads = 280; |
brw->urb.size = 512; |
brw->urb.max_vs_entries = 1664; |
brw->urb.max_gs_entries = 640; |
} |
} else if (brw->gen == 7) { |
if (brw->gt == 1) { |
brw->max_wm_threads = 48; |
brw->max_vs_threads = 36; |
brw->max_gs_threads = 36; |
brw->urb.size = 128; |
brw->urb.max_vs_entries = 512; |
brw->urb.max_gs_entries = 192; |
} else if (brw->gt == 2) { |
brw->max_wm_threads = 172; |
brw->max_vs_threads = 128; |
brw->max_gs_threads = 128; |
brw->urb.size = 256; |
brw->urb.max_vs_entries = 704; |
brw->urb.max_gs_entries = 320; |
} else { |
assert(!"Unknown gen7 device."); |
} |
} else if (brw->gen == 6) { |
if (brw->gt == 2) { |
brw->max_wm_threads = 80; |
brw->max_vs_threads = 60; |
brw->max_gs_threads = 60; |
brw->urb.size = 64; /* volume 5c.5 section 5.1 */ |
brw->urb.max_vs_entries = 256; /* volume 2a (see 3DSTATE_URB) */ |
brw->urb.max_gs_entries = 256; |
} else { |
brw->max_wm_threads = 40; |
brw->max_vs_threads = 24; |
brw->max_gs_threads = 21; /* conservative; 24 if rendering disabled */ |
brw->urb.size = 32; /* volume 5c.5 section 5.1 */ |
brw->urb.max_vs_entries = 256; /* volume 2a (see 3DSTATE_URB) */ |
brw->urb.max_gs_entries = 256; |
} |
brw->urb.gen6_gs_previously_active = false; |
} else if (brw->gen == 5) { |
brw->urb.size = 1024; |
brw->max_vs_threads = 72; |
brw->max_gs_threads = 32; |
brw->max_wm_threads = 12 * 6; |
} else if (brw->is_g4x) { |
brw->urb.size = 384; |
brw->max_vs_threads = 32; |
brw->max_gs_threads = 2; |
brw->max_wm_threads = 10 * 5; |
} else if (brw->gen < 6) { |
brw->urb.size = 256; |
brw->max_vs_threads = 16; |
brw->max_gs_threads = 2; |
brw->max_wm_threads = 8 * 4; |
brw->has_negative_rhw_bug = true; |
} |
if (brw->gen <= 7) { |
brw->needs_unlit_centroid_workaround = true; |
} |
brw->prim_restart.in_progress = false; |
brw->prim_restart.enable_cut_index = false; |
brw_init_state( brw ); |
brw->curbe.last_buf = calloc(1, 4096); |
brw->curbe.next_buf = calloc(1, 4096); |
brw->state.dirty.mesa = ~0; |
brw->state.dirty.brw = ~0; |
brw->emit_state_always = 0; |
brw->batch.need_workaround_flush = true; |
ctx->VertexProgram._MaintainTnlProgram = true; |
ctx->FragmentProgram._MaintainTexEnvProgram = true; |
brw_draw_init( brw ); |
brw->precompile = driQueryOptionb(&brw->optionCache, "shader_precompile"); |
ctx->Const.ContextFlags = 0; |
if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) |
ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; |
if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) { |
ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; |
/* Turn on some extra GL_ARB_debug_output generation. */ |
brw->perf_debug = true; |
} |
brw_fs_alloc_reg_sets(brw); |
if (INTEL_DEBUG & DEBUG_SHADER_TIME) |
brw_init_shader_time(brw); |
_mesa_compute_version(ctx); |
_mesa_initialize_dispatch_tables(ctx); |
_mesa_initialize_vbo_vtxfmt(ctx); |
return true; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_context.h |
---|
0,0 → 1,1506 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 BRWCONTEXT_INC |
#define BRWCONTEXT_INC |
#include "intel_context.h" |
#include "brw_structs.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
/* Glossary: |
* |
* URB - uniform resource buffer. A mid-sized buffer which is |
* partitioned between the fixed function units and used for passing |
* values (vertices, primitives, constants) between them. |
* |
* CURBE - constant URB entry. An urb region (entry) used to hold |
* constant values which the fixed function units can be instructed to |
* preload into the GRF when spawning a thread. |
* |
* VUE - vertex URB entry. An urb entry holding a vertex and usually |
* a vertex header. The header contains control information and |
* things like primitive type, Begin/end flags and clip codes. |
* |
* PUE - primitive URB entry. An urb entry produced by the setup (SF) |
* unit holding rasterization and interpolation parameters. |
* |
* GRF - general register file. One of several register files |
* addressable by programmed threads. The inputs (r0, payload, curbe, |
* urb) of the thread are preloaded to this area before the thread is |
* spawned. The registers are individually 8 dwords wide and suitable |
* for general usage. Registers holding thread input values are not |
* special and may be overwritten. |
* |
* MRF - message register file. Threads communicate (and terminate) |
* by sending messages. Message parameters are placed in contiguous |
* MRF registers. All program output is via these messages. URB |
* entries are populated by sending a message to the shared URB |
* function containing the new data, together with a control word, |
* often an unmodified copy of R0. |
* |
* R0 - GRF register 0. Typically holds control information used when |
* sending messages to other threads. |
* |
* EU or GEN4 EU: The name of the programmable subsystem of the |
* i965 hardware. Threads are executed by the EU, the registers |
* described above are part of the EU architecture. |
* |
* Fixed function units: |
* |
* CS - Command streamer. Notional first unit, little software |
* interaction. Holds the URB entries used for constant data, ie the |
* CURBEs. |
* |
* VF/VS - Vertex Fetch / Vertex Shader. The fixed function part of |
* this unit is responsible for pulling vertices out of vertex buffers |
* in vram and injecting them into the processing pipe as VUEs. If |
* enabled, it first passes them to a VS thread which is a good place |
* for the driver to implement any active vertex shader. |
* |
* GS - Geometry Shader. This corresponds to a new DX10 concept. If |
* enabled, incoming strips etc are passed to GS threads in individual |
* line/triangle/point units. The GS thread may perform arbitary |
* computation and emit whatever primtives with whatever vertices it |
* chooses. This makes GS an excellent place to implement GL's |
* unfilled polygon modes, though of course it is capable of much |
* more. Additionally, GS is used to translate away primitives not |
* handled by latter units, including Quads and Lineloops. |
* |
* CS - Clipper. Mesa's clipping algorithms are imported to run on |
* this unit. The fixed function part performs cliptesting against |
* the 6 fixed clipplanes and makes descisions on whether or not the |
* incoming primitive needs to be passed to a thread for clipping. |
* User clip planes are handled via cooperation with the VS thread. |
* |
* SF - Strips Fans or Setup: Triangles are prepared for |
* rasterization. Interpolation coefficients are calculated. |
* Flatshading and two-side lighting usually performed here. |
* |
* WM - Windower. Interpolation of vertex attributes performed here. |
* Fragment shader implemented here. SIMD aspects of EU taken full |
* advantage of, as pixels are processed in blocks of 16. |
* |
* CC - Color Calculator. No EU threads associated with this unit. |
* Handles blending and (presumably) depth and stencil testing. |
*/ |
#define BRW_MAX_CURBE (32*16) |
struct brw_context; |
struct brw_instruction; |
struct brw_vs_prog_key; |
struct brw_wm_prog_key; |
struct brw_wm_prog_data; |
enum brw_state_id { |
BRW_STATE_URB_FENCE, |
BRW_STATE_FRAGMENT_PROGRAM, |
BRW_STATE_VERTEX_PROGRAM, |
BRW_STATE_CURBE_OFFSETS, |
BRW_STATE_REDUCED_PRIMITIVE, |
BRW_STATE_PRIMITIVE, |
BRW_STATE_CONTEXT, |
BRW_STATE_PSP, |
BRW_STATE_SURFACES, |
BRW_STATE_VS_BINDING_TABLE, |
BRW_STATE_GS_BINDING_TABLE, |
BRW_STATE_PS_BINDING_TABLE, |
BRW_STATE_INDICES, |
BRW_STATE_VERTICES, |
BRW_STATE_BATCH, |
BRW_STATE_INDEX_BUFFER, |
BRW_STATE_VS_CONSTBUF, |
BRW_STATE_PROGRAM_CACHE, |
BRW_STATE_STATE_BASE_ADDRESS, |
BRW_STATE_VUE_MAP_GEOM_OUT, |
BRW_STATE_TRANSFORM_FEEDBACK, |
BRW_STATE_RASTERIZER_DISCARD, |
BRW_STATE_STATS_WM, |
BRW_STATE_UNIFORM_BUFFER, |
BRW_STATE_META_IN_PROGRESS, |
}; |
#define BRW_NEW_URB_FENCE (1 << BRW_STATE_URB_FENCE) |
#define BRW_NEW_FRAGMENT_PROGRAM (1 << BRW_STATE_FRAGMENT_PROGRAM) |
#define BRW_NEW_VERTEX_PROGRAM (1 << BRW_STATE_VERTEX_PROGRAM) |
#define BRW_NEW_CURBE_OFFSETS (1 << BRW_STATE_CURBE_OFFSETS) |
#define BRW_NEW_REDUCED_PRIMITIVE (1 << BRW_STATE_REDUCED_PRIMITIVE) |
#define BRW_NEW_PRIMITIVE (1 << BRW_STATE_PRIMITIVE) |
#define BRW_NEW_CONTEXT (1 << BRW_STATE_CONTEXT) |
#define BRW_NEW_PSP (1 << BRW_STATE_PSP) |
#define BRW_NEW_SURFACES (1 << BRW_STATE_SURFACES) |
#define BRW_NEW_VS_BINDING_TABLE (1 << BRW_STATE_VS_BINDING_TABLE) |
#define BRW_NEW_GS_BINDING_TABLE (1 << BRW_STATE_GS_BINDING_TABLE) |
#define BRW_NEW_PS_BINDING_TABLE (1 << BRW_STATE_PS_BINDING_TABLE) |
#define BRW_NEW_INDICES (1 << BRW_STATE_INDICES) |
#define BRW_NEW_VERTICES (1 << BRW_STATE_VERTICES) |
/** |
* Used for any batch entry with a relocated pointer that will be used |
* by any 3D rendering. |
*/ |
#define BRW_NEW_BATCH (1 << BRW_STATE_BATCH) |
/** \see brw.state.depth_region */ |
#define BRW_NEW_INDEX_BUFFER (1 << BRW_STATE_INDEX_BUFFER) |
#define BRW_NEW_VS_CONSTBUF (1 << BRW_STATE_VS_CONSTBUF) |
#define BRW_NEW_PROGRAM_CACHE (1 << BRW_STATE_PROGRAM_CACHE) |
#define BRW_NEW_STATE_BASE_ADDRESS (1 << BRW_STATE_STATE_BASE_ADDRESS) |
#define BRW_NEW_VUE_MAP_GEOM_OUT (1 << BRW_STATE_VUE_MAP_GEOM_OUT) |
#define BRW_NEW_TRANSFORM_FEEDBACK (1 << BRW_STATE_TRANSFORM_FEEDBACK) |
#define BRW_NEW_RASTERIZER_DISCARD (1 << BRW_STATE_RASTERIZER_DISCARD) |
#define BRW_NEW_STATS_WM (1 << BRW_STATE_STATS_WM) |
#define BRW_NEW_UNIFORM_BUFFER (1 << BRW_STATE_UNIFORM_BUFFER) |
#define BRW_NEW_META_IN_PROGRESS (1 << BRW_STATE_META_IN_PROGRESS) |
struct brw_state_flags { |
/** State update flags signalled by mesa internals */ |
GLuint mesa; |
/** |
* State update flags signalled as the result of brw_tracked_state updates |
*/ |
GLuint brw; |
/** State update flags signalled by brw_state_cache.c searches */ |
GLuint cache; |
}; |
#define AUB_TRACE_TYPE_MASK 0x0000ff00 |
#define AUB_TRACE_TYPE_NOTYPE (0 << 8) |
#define AUB_TRACE_TYPE_BATCH (1 << 8) |
#define AUB_TRACE_TYPE_VERTEX_BUFFER (5 << 8) |
#define AUB_TRACE_TYPE_2D_MAP (6 << 8) |
#define AUB_TRACE_TYPE_CUBE_MAP (7 << 8) |
#define AUB_TRACE_TYPE_VOLUME_MAP (9 << 8) |
#define AUB_TRACE_TYPE_1D_MAP (10 << 8) |
#define AUB_TRACE_TYPE_CONSTANT_BUFFER (11 << 8) |
#define AUB_TRACE_TYPE_CONSTANT_URB (12 << 8) |
#define AUB_TRACE_TYPE_INDEX_BUFFER (13 << 8) |
#define AUB_TRACE_TYPE_GENERAL (14 << 8) |
#define AUB_TRACE_TYPE_SURFACE (15 << 8) |
/** |
* state_struct_type enum values are encoded with the top 16 bits representing |
* the type to be delivered to the .aub file, and the bottom 16 bits |
* representing the subtype. This macro performs the encoding. |
*/ |
#define ENCODE_SS_TYPE(type, subtype) (((type) << 16) | (subtype)) |
enum state_struct_type { |
AUB_TRACE_VS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 1), |
AUB_TRACE_GS_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 2), |
AUB_TRACE_CLIP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 3), |
AUB_TRACE_SF_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 4), |
AUB_TRACE_WM_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 5), |
AUB_TRACE_CC_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 6), |
AUB_TRACE_CLIP_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 7), |
AUB_TRACE_SF_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 8), |
AUB_TRACE_CC_VP_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x9), |
AUB_TRACE_SAMPLER_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xa), |
AUB_TRACE_KERNEL_INSTRUCTIONS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xb), |
AUB_TRACE_SCRATCH_SPACE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xc), |
AUB_TRACE_SAMPLER_DEFAULT_COLOR = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0xd), |
AUB_TRACE_SCISSOR_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x15), |
AUB_TRACE_BLEND_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x16), |
AUB_TRACE_DEPTH_STENCIL_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_GENERAL, 0x17), |
AUB_TRACE_VERTEX_BUFFER = ENCODE_SS_TYPE(AUB_TRACE_TYPE_VERTEX_BUFFER, 0), |
AUB_TRACE_BINDING_TABLE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x100), |
AUB_TRACE_SURFACE_STATE = ENCODE_SS_TYPE(AUB_TRACE_TYPE_SURFACE, 0x200), |
AUB_TRACE_VS_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 0), |
AUB_TRACE_WM_CONSTANTS = ENCODE_SS_TYPE(AUB_TRACE_TYPE_CONSTANT_BUFFER, 1), |
}; |
/** |
* Decode a state_struct_type value to determine the type that should be |
* stored in the .aub file. |
*/ |
static inline uint32_t AUB_TRACE_TYPE(enum state_struct_type ss_type) |
{ |
return (ss_type & 0xFFFF0000) >> 16; |
} |
/** |
* Decode a state_struct_type value to determine the subtype that should be |
* stored in the .aub file. |
*/ |
static inline uint32_t AUB_TRACE_SUBTYPE(enum state_struct_type ss_type) |
{ |
return ss_type & 0xFFFF; |
} |
/** Subclass of Mesa vertex program */ |
struct brw_vertex_program { |
struct gl_vertex_program program; |
GLuint id; |
}; |
/** Subclass of Mesa fragment program */ |
struct brw_fragment_program { |
struct gl_fragment_program program; |
GLuint id; /**< serial no. to identify frag progs, never re-used */ |
}; |
struct brw_shader { |
struct gl_shader base; |
bool compiled_once; |
/** Shader IR transformed for native compile, at link time. */ |
struct exec_list *ir; |
}; |
/* Data about a particular attempt to compile a program. Note that |
* there can be many of these, each in a different GL state |
* corresponding to a different brw_wm_prog_key struct, with different |
* compiled programs. |
* |
* Note: brw_wm_prog_data_compare() must be updated when adding fields to this |
* struct! |
*/ |
struct brw_wm_prog_data { |
GLuint curb_read_length; |
GLuint urb_read_length; |
GLuint first_curbe_grf; |
GLuint first_curbe_grf_16; |
GLuint reg_blocks; |
GLuint reg_blocks_16; |
GLuint total_scratch; |
GLuint nr_params; /**< number of float params/constants */ |
GLuint nr_pull_params; |
bool dual_src_blend; |
int dispatch_width; |
uint32_t prog_offset_16; |
/** |
* Mask of which interpolation modes are required by the fragment shader. |
* Used in hardware setup on gen6+. |
*/ |
uint32_t barycentric_interp_modes; |
/* Pointers to tracked values (only valid once |
* _mesa_load_state_parameters has been called at runtime). |
* |
* These must be the last fields of the struct (see |
* brw_wm_prog_data_compare()). |
*/ |
const float **param; |
const float **pull_param; |
}; |
/** |
* Enum representing the i965-specific vertex results that don't correspond |
* exactly to any element of gl_varying_slot. The values of this enum are |
* assigned such that they don't conflict with gl_varying_slot. |
*/ |
typedef enum |
{ |
BRW_VARYING_SLOT_NDC = VARYING_SLOT_MAX, |
BRW_VARYING_SLOT_PAD, |
/** |
* Technically this is not a varying but just a placeholder that |
* compile_sf_prog() inserts into its VUE map to cause the gl_PointCoord |
* builtin variable to be compiled correctly. see compile_sf_prog() for |
* more info. |
*/ |
BRW_VARYING_SLOT_PNTC, |
BRW_VARYING_SLOT_COUNT |
} brw_varying_slot; |
/** |
* Data structure recording the relationship between the gl_varying_slot enum |
* and "slots" within the vertex URB entry (VUE). A "slot" is defined as a |
* single octaword within the VUE (128 bits). |
* |
* Note that each BRW register contains 256 bits (2 octawords), so when |
* accessing the VUE in URB_NOSWIZZLE mode, each register corresponds to two |
* consecutive VUE slots. When accessing the VUE in URB_INTERLEAVED mode (as |
* in a vertex shader), each register corresponds to a single VUE slot, since |
* it contains data for two separate vertices. |
*/ |
struct brw_vue_map { |
/** |
* Bitfield representing all varying slots that are (a) stored in this VUE |
* map, and (b) actually written by the shader. Does not include any of |
* the additional varying slots defined in brw_varying_slot. |
*/ |
GLbitfield64 slots_valid; |
/** |
* Map from gl_varying_slot value to VUE slot. For gl_varying_slots that are |
* not stored in a slot (because they are not written, or because |
* additional processing is applied before storing them in the VUE), the |
* value is -1. |
*/ |
signed char varying_to_slot[BRW_VARYING_SLOT_COUNT]; |
/** |
* Map from VUE slot to gl_varying_slot value. For slots that do not |
* directly correspond to a gl_varying_slot, the value comes from |
* brw_varying_slot. |
* |
* For slots that are not in use, the value is BRW_VARYING_SLOT_COUNT (this |
* simplifies code that uses the value stored in slot_to_varying to |
* create a bit mask). |
*/ |
signed char slot_to_varying[BRW_VARYING_SLOT_COUNT]; |
/** |
* Total number of VUE slots in use |
*/ |
int num_slots; |
}; |
/** |
* Convert a VUE slot number into a byte offset within the VUE. |
*/ |
static inline GLuint brw_vue_slot_to_offset(GLuint slot) |
{ |
return 16*slot; |
} |
/** |
* Convert a vertex output (brw_varying_slot) into a byte offset within the |
* VUE. |
*/ |
static inline GLuint brw_varying_to_offset(struct brw_vue_map *vue_map, |
GLuint varying) |
{ |
return brw_vue_slot_to_offset(vue_map->varying_to_slot[varying]); |
} |
void brw_compute_vue_map(struct brw_context *brw, struct brw_vue_map *vue_map, |
GLbitfield64 slots_valid, bool userclip_active); |
struct brw_sf_prog_data { |
GLuint urb_read_length; |
GLuint total_grf; |
/* Each vertex may have upto 12 attributes, 4 components each, |
* except WPOS which requires only 2. (11*4 + 2) == 44 ==> 11 |
* rows. |
* |
* Actually we use 4 for each, so call it 12 rows. |
*/ |
GLuint urb_entry_size; |
}; |
struct brw_clip_prog_data { |
GLuint curb_read_length; /* user planes? */ |
GLuint clip_mode; |
GLuint urb_read_length; |
GLuint total_grf; |
}; |
struct brw_gs_prog_data { |
GLuint urb_read_length; |
GLuint total_grf; |
/** |
* Gen6 transform feedback: Amount by which the streaming vertex buffer |
* indices should be incremented each time the GS is invoked. |
*/ |
unsigned svbi_postincrement_value; |
}; |
/* Note: brw_vec4_prog_data_compare() must be updated when adding fields to |
* this struct! |
*/ |
struct brw_vec4_prog_data { |
struct brw_vue_map vue_map; |
GLuint curb_read_length; |
GLuint urb_read_length; |
GLuint total_grf; |
GLuint nr_params; /**< number of float params/constants */ |
GLuint nr_pull_params; /**< number of dwords referenced by pull_param[] */ |
GLuint total_scratch; |
/* Used for calculating urb partitions. In the VS, this is the size of the |
* URB entry used for both input and output to the thread. In the GS, this |
* is the size of the URB entry used for output. |
*/ |
GLuint urb_entry_size; |
int num_surfaces; |
/* These pointers must appear last. See brw_vec4_prog_data_compare(). */ |
const float **param; |
const float **pull_param; |
}; |
/* Note: brw_vs_prog_data_compare() must be updated when adding fields to this |
* struct! |
*/ |
struct brw_vs_prog_data { |
struct brw_vec4_prog_data base; |
GLbitfield64 inputs_read; |
bool uses_vertexid; |
}; |
/** Number of texture sampler units */ |
#define BRW_MAX_TEX_UNIT 16 |
/** Max number of render targets in a shader */ |
#define BRW_MAX_DRAW_BUFFERS 8 |
/** |
* Max number of binding table entries used for stream output. |
* |
* From the OpenGL 3.0 spec, table 6.44 (Transform Feedback State), the |
* minimum value of MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is 64. |
* |
* On Gen6, the size of transform feedback data is limited not by the number |
* of components but by the number of binding table entries we set aside. We |
* use one binding table entry for a float, one entry for a vector, and one |
* entry per matrix column. Since the only way we can communicate our |
* transform feedback capabilities to the client is via |
* MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, we need to plan for the |
* worst case, in which all the varyings are floats, so we use up one binding |
* table entry per component. Therefore we need to set aside at least 64 |
* binding table entries for use by transform feedback. |
* |
* Note: since we don't currently pack varyings, it is currently impossible |
* for the client to actually use up all of these binding table entries--if |
* all of their varyings were floats, they would run out of varying slots and |
* fail to link. But that's a bug, so it seems prudent to go ahead and |
* allocate the number of binding table entries we will need once the bug is |
* fixed. |
*/ |
#define BRW_MAX_SOL_BINDINGS 64 |
/** Maximum number of actual buffers used for stream output */ |
#define BRW_MAX_SOL_BUFFERS 4 |
#define BRW_MAX_WM_UBOS 12 |
#define BRW_MAX_VS_UBOS 12 |
/** |
* Helpers to create Surface Binding Table indexes for draw buffers, |
* textures, and constant buffers. |
* |
* Shader threads access surfaces via numeric handles, rather than directly |
* using pointers. The binding table maps these numeric handles to the |
* address of the actual buffer. |
* |
* For example, a shader might ask to sample from "surface 7." In this case, |
* bind[7] would contain a pointer to a texture. |
* |
* Currently, our WM binding tables are (arbitrarily) programmed as follows: |
* |
* +-------------------------------+ |
* | 0 | Draw buffer 0 | |
* | . | . | |
* | : | : | |
* | 7 | Draw buffer 7 | |
* |-----|-------------------------| |
* | 8 | WM Pull Constant Buffer | |
* |-----|-------------------------| |
* | 9 | Texture 0 | |
* | . | . | |
* | : | : | |
* | 24 | Texture 15 | |
* |-----|-------------------------| |
* | 25 | UBO 0 | |
* | . | . | |
* | : | : | |
* | 36 | UBO 11 | |
* +-------------------------------+ |
* |
* Our VS binding tables are programmed as follows: |
* |
* +-----+-------------------------+ |
* | 0 | VS Pull Constant Buffer | |
* +-----+-------------------------+ |
* | 1 | Texture 0 | |
* | . | . | |
* | : | : | |
* | 16 | Texture 15 | |
* +-----+-------------------------+ |
* | 17 | UBO 0 | |
* | . | . | |
* | : | : | |
* | 28 | UBO 11 | |
* +-------------------------------+ |
* |
* Our (gen6) GS binding tables are programmed as follows: |
* |
* +-----+-------------------------+ |
* | 0 | SOL Binding 0 | |
* | . | . | |
* | : | : | |
* | 63 | SOL Binding 63 | |
* +-----+-------------------------+ |
* |
* Note that nothing actually uses the SURF_INDEX_DRAW macro, so it has to be |
* the identity function or things will break. We do want to keep draw buffers |
* first so we can use headerless render target writes for RT 0. |
*/ |
#define SURF_INDEX_DRAW(d) (d) |
#define SURF_INDEX_FRAG_CONST_BUFFER (BRW_MAX_DRAW_BUFFERS + 1) |
#define SURF_INDEX_TEXTURE(t) (BRW_MAX_DRAW_BUFFERS + 2 + (t)) |
#define SURF_INDEX_WM_UBO(u) (SURF_INDEX_TEXTURE(BRW_MAX_TEX_UNIT) + u) |
#define SURF_INDEX_WM_SHADER_TIME (SURF_INDEX_WM_UBO(12)) |
/** Maximum size of the binding table. */ |
#define BRW_MAX_WM_SURFACES (SURF_INDEX_WM_SHADER_TIME + 1) |
#define SURF_INDEX_VERT_CONST_BUFFER (0) |
#define SURF_INDEX_VS_TEXTURE(t) (SURF_INDEX_VERT_CONST_BUFFER + 1 + (t)) |
#define SURF_INDEX_VS_UBO(u) (SURF_INDEX_VS_TEXTURE(BRW_MAX_TEX_UNIT) + u) |
#define SURF_INDEX_VS_SHADER_TIME (SURF_INDEX_VS_UBO(12)) |
#define BRW_MAX_VS_SURFACES (SURF_INDEX_VS_SHADER_TIME + 1) |
#define SURF_INDEX_SOL_BINDING(t) ((t)) |
#define BRW_MAX_GS_SURFACES SURF_INDEX_SOL_BINDING(BRW_MAX_SOL_BINDINGS) |
/** |
* Stride in bytes between shader_time entries. |
* |
* We separate entries by a cacheline to reduce traffic between EUs writing to |
* different entries. |
*/ |
#define SHADER_TIME_STRIDE 64 |
enum brw_cache_id { |
BRW_CC_VP, |
BRW_CC_UNIT, |
BRW_WM_PROG, |
BRW_BLORP_BLIT_PROG, |
BRW_BLORP_CONST_COLOR_PROG, |
BRW_SAMPLER, |
BRW_WM_UNIT, |
BRW_SF_PROG, |
BRW_SF_VP, |
BRW_SF_UNIT, /* scissor state on gen6 */ |
BRW_VS_UNIT, |
BRW_VS_PROG, |
BRW_GS_UNIT, |
BRW_GS_PROG, |
BRW_CLIP_VP, |
BRW_CLIP_UNIT, |
BRW_CLIP_PROG, |
BRW_MAX_CACHE |
}; |
struct brw_cache_item { |
/** |
* Effectively part of the key, cache_id identifies what kind of state |
* buffer is involved, and also which brw->state.dirty.cache flag should |
* be set when this cache item is chosen. |
*/ |
enum brw_cache_id cache_id; |
/** 32-bit hash of the key data */ |
GLuint hash; |
GLuint key_size; /* for variable-sized keys */ |
GLuint aux_size; |
const void *key; |
uint32_t offset; |
uint32_t size; |
struct brw_cache_item *next; |
}; |
typedef bool (*cache_aux_compare_func)(const void *a, const void *b, |
int aux_size, const void *key); |
typedef void (*cache_aux_free_func)(const void *aux); |
struct brw_cache { |
struct brw_context *brw; |
struct brw_cache_item **items; |
drm_intel_bo *bo; |
GLuint size, n_items; |
uint32_t next_offset; |
bool bo_used_by_gpu; |
/** |
* Optional functions used in determining whether the prog_data for a new |
* cache item matches an existing cache item (in case there's relevant data |
* outside of the prog_data). If NULL, a plain memcmp is done. |
*/ |
cache_aux_compare_func aux_compare[BRW_MAX_CACHE]; |
/** Optional functions for freeing other pointers attached to a prog_data. */ |
cache_aux_free_func aux_free[BRW_MAX_CACHE]; |
}; |
/* Considered adding a member to this struct to document which flags |
* an update might raise so that ordering of the state atoms can be |
* checked or derived at runtime. Dropped the idea in favor of having |
* a debug mode where the state is monitored for flags which are |
* raised that have already been tested against. |
*/ |
struct brw_tracked_state { |
struct brw_state_flags dirty; |
void (*emit)( struct brw_context *brw ); |
}; |
enum shader_time_shader_type { |
ST_NONE, |
ST_VS, |
ST_VS_WRITTEN, |
ST_VS_RESET, |
ST_FS8, |
ST_FS8_WRITTEN, |
ST_FS8_RESET, |
ST_FS16, |
ST_FS16_WRITTEN, |
ST_FS16_RESET, |
}; |
/* Flags for brw->state.cache. |
*/ |
#define CACHE_NEW_CC_VP (1<<BRW_CC_VP) |
#define CACHE_NEW_CC_UNIT (1<<BRW_CC_UNIT) |
#define CACHE_NEW_WM_PROG (1<<BRW_WM_PROG) |
#define CACHE_NEW_SAMPLER (1<<BRW_SAMPLER) |
#define CACHE_NEW_WM_UNIT (1<<BRW_WM_UNIT) |
#define CACHE_NEW_SF_PROG (1<<BRW_SF_PROG) |
#define CACHE_NEW_SF_VP (1<<BRW_SF_VP) |
#define CACHE_NEW_SF_UNIT (1<<BRW_SF_UNIT) |
#define CACHE_NEW_VS_UNIT (1<<BRW_VS_UNIT) |
#define CACHE_NEW_VS_PROG (1<<BRW_VS_PROG) |
#define CACHE_NEW_GS_UNIT (1<<BRW_GS_UNIT) |
#define CACHE_NEW_GS_PROG (1<<BRW_GS_PROG) |
#define CACHE_NEW_CLIP_VP (1<<BRW_CLIP_VP) |
#define CACHE_NEW_CLIP_UNIT (1<<BRW_CLIP_UNIT) |
#define CACHE_NEW_CLIP_PROG (1<<BRW_CLIP_PROG) |
struct brw_cached_batch_item { |
struct header *header; |
GLuint sz; |
struct brw_cached_batch_item *next; |
}; |
/* Protect against a future where VERT_ATTRIB_MAX > 32. Wouldn't life |
* be easier if C allowed arrays of packed elements? |
*/ |
#define ATTRIB_BIT_DWORDS ((VERT_ATTRIB_MAX+31)/32) |
struct brw_vertex_buffer { |
/** Buffer object containing the uploaded vertex data */ |
drm_intel_bo *bo; |
uint32_t offset; |
/** Byte stride between elements in the uploaded array */ |
GLuint stride; |
GLuint step_rate; |
}; |
struct brw_vertex_element { |
const struct gl_client_array *glarray; |
int buffer; |
/** The corresponding Mesa vertex attribute */ |
gl_vert_attrib attrib; |
/** Offset of the first element within the buffer object */ |
unsigned int offset; |
}; |
struct brw_query_object { |
struct gl_query_object Base; |
/** Last query BO associated with this query. */ |
drm_intel_bo *bo; |
/** Last index in bo with query data for this object. */ |
int last_index; |
}; |
/** |
* brw_context is derived from gl_context. |
*/ |
struct brw_context |
{ |
struct gl_context ctx; /**< base class, must be first field */ |
struct |
{ |
void (*destroy) (struct brw_context * brw); |
void (*finish_batch) (struct brw_context * brw); |
void (*new_batch) (struct brw_context * brw); |
void (*update_texture_surface)(struct gl_context *ctx, |
unsigned unit, |
uint32_t *binding_table, |
unsigned surf_index); |
void (*update_renderbuffer_surface)(struct brw_context *brw, |
struct gl_renderbuffer *rb, |
bool layered, |
unsigned unit); |
void (*update_null_renderbuffer_surface)(struct brw_context *brw, |
unsigned unit); |
void (*create_constant_surface)(struct brw_context *brw, |
drm_intel_bo *bo, |
uint32_t offset, |
uint32_t size, |
uint32_t *out_offset, |
bool dword_pitch); |
/** |
* Send the appropriate state packets to configure depth, stencil, and |
* HiZ buffers (i965+ only) |
*/ |
void (*emit_depth_stencil_hiz)(struct brw_context *brw, |
struct intel_mipmap_tree *depth_mt, |
uint32_t depth_offset, |
uint32_t depthbuffer_format, |
uint32_t depth_surface_type, |
struct intel_mipmap_tree *stencil_mt, |
bool hiz, bool separate_stencil, |
uint32_t width, uint32_t height, |
uint32_t tile_x, uint32_t tile_y); |
} vtbl; |
dri_bufmgr *bufmgr; |
drm_intel_context *hw_ctx; |
struct intel_batchbuffer batch; |
bool no_batch_wrap; |
struct { |
drm_intel_bo *bo; |
GLuint offset; |
uint32_t buffer_len; |
uint32_t buffer_offset; |
char buffer[4096]; |
} upload; |
/** |
* Set if rendering has occured to the drawable's front buffer. |
* |
* This is used in the DRI2 case to detect that glFlush should also copy |
* the contents of the fake front buffer to the real front buffer. |
*/ |
bool front_buffer_dirty; |
/** |
* Track whether front-buffer rendering is currently enabled |
* |
* A separate flag is used to track this in order to support MRT more |
* easily. |
*/ |
bool is_front_buffer_rendering; |
/** |
* Track whether front-buffer is the current read target. |
* |
* This is closely associated with is_front_buffer_rendering, but may |
* be set separately. The DRI2 fake front buffer must be referenced |
* either way. |
*/ |
bool is_front_buffer_reading; |
/** Framerate throttling: @{ */ |
drm_intel_bo *first_post_swapbuffers_batch; |
bool need_throttle; |
/** @} */ |
GLuint stats_wm; |
/** |
* drirc options: |
* @{ |
*/ |
bool no_rast; |
bool always_flush_batch; |
bool always_flush_cache; |
bool disable_throttling; |
bool precompile; |
driOptionCache optionCache; |
/** @} */ |
GLuint primitive; /**< Hardware primitive, such as _3DPRIM_TRILIST. */ |
GLenum reduced_primitive; |
/** |
* Set if we're either a debug context or the INTEL_DEBUG=perf environment |
* variable is set, this is the flag indicating to do expensive work that |
* might lead to a perf_debug() call. |
*/ |
bool perf_debug; |
uint32_t max_gtt_map_object_size; |
bool emit_state_always; |
int gen; |
int gt; |
bool is_g4x; |
bool is_baytrail; |
bool is_haswell; |
bool has_hiz; |
bool has_separate_stencil; |
bool must_use_separate_stencil; |
bool has_llc; |
bool has_swizzling; |
bool has_surface_tile_offset; |
bool has_compr4; |
bool has_negative_rhw_bug; |
bool has_aa_line_parameters; |
bool has_pln; |
/** |
* Some versions of Gen hardware don't do centroid interpolation correctly |
* on unlit pixels, causing incorrect values for derivatives near triangle |
* edges. Enabling this flag causes the fragment shader to use |
* non-centroid interpolation for unlit pixels, at the expense of two extra |
* fragment shader instructions. |
*/ |
bool needs_unlit_centroid_workaround; |
GLuint NewGLState; |
struct { |
struct brw_state_flags dirty; |
} state; |
struct brw_cache cache; |
struct brw_cached_batch_item *cached_batch_items; |
/* Whether a meta-operation is in progress. */ |
bool meta_in_progress; |
struct { |
struct brw_vertex_element inputs[VERT_ATTRIB_MAX]; |
struct brw_vertex_buffer buffers[VERT_ATTRIB_MAX]; |
struct brw_vertex_element *enabled[VERT_ATTRIB_MAX]; |
GLuint nr_enabled; |
GLuint nr_buffers; |
/* Summary of size and varying of active arrays, so we can check |
* for changes to this state: |
*/ |
unsigned int min_index, max_index; |
/* Offset from start of vertex buffer so we can avoid redefining |
* the same VB packed over and over again. |
*/ |
unsigned int start_vertex_bias; |
} vb; |
struct { |
/** |
* Index buffer for this draw_prims call. |
* |
* Updates are signaled by BRW_NEW_INDICES. |
*/ |
const struct _mesa_index_buffer *ib; |
/* Updates are signaled by BRW_NEW_INDEX_BUFFER. */ |
drm_intel_bo *bo; |
GLuint type; |
/* Offset to index buffer index to use in CMD_3D_PRIM so that we can |
* avoid re-uploading the IB packet over and over if we're actually |
* referencing the same index buffer. |
*/ |
unsigned int start_vertex_offset; |
} ib; |
/* Active vertex program: |
*/ |
const struct gl_vertex_program *vertex_program; |
const struct gl_fragment_program *fragment_program; |
/* hw-dependent 3DSTATE_VF_STATISTICS opcode */ |
uint32_t CMD_VF_STATISTICS; |
/* hw-dependent 3DSTATE_PIPELINE_SELECT opcode */ |
uint32_t CMD_PIPELINE_SELECT; |
/** |
* Platform specific constants containing the maximum number of threads |
* for each pipeline stage. |
*/ |
int max_vs_threads; |
int max_gs_threads; |
int max_wm_threads; |
/* BRW_NEW_URB_ALLOCATIONS: |
*/ |
struct { |
GLuint vsize; /* vertex size plus header in urb registers */ |
GLuint csize; /* constant buffer size in urb registers */ |
GLuint sfsize; /* setup data size in urb registers */ |
bool constrained; |
GLuint max_vs_entries; /* Maximum number of VS entries */ |
GLuint max_gs_entries; /* Maximum number of GS entries */ |
GLuint nr_vs_entries; |
GLuint nr_gs_entries; |
GLuint nr_clip_entries; |
GLuint nr_sf_entries; |
GLuint nr_cs_entries; |
GLuint vs_start; |
GLuint gs_start; |
GLuint clip_start; |
GLuint sf_start; |
GLuint cs_start; |
GLuint size; /* Hardware URB size, in KB. */ |
/* gen6: True if the most recently sent _3DSTATE_URB message allocated |
* URB space for the GS. |
*/ |
bool gen6_gs_previously_active; |
} urb; |
/* BRW_NEW_CURBE_OFFSETS: |
*/ |
struct { |
GLuint wm_start; /**< pos of first wm const in CURBE buffer */ |
GLuint wm_size; /**< number of float[4] consts, multiple of 16 */ |
GLuint clip_start; |
GLuint clip_size; |
GLuint vs_start; |
GLuint vs_size; |
GLuint total_size; |
drm_intel_bo *curbe_bo; |
/** Offset within curbe_bo of space for current curbe entry */ |
GLuint curbe_offset; |
/** Offset within curbe_bo of space for next curbe entry */ |
GLuint curbe_next_offset; |
/** |
* Copy of the last set of CURBEs uploaded. Frequently we'll end up |
* in brw_curbe.c with the same set of constant data to be uploaded, |
* so we'd rather not upload new constants in that case (it can cause |
* a pipeline bubble since only up to 4 can be pipelined at a time). |
*/ |
GLfloat *last_buf; |
/** |
* Allocation for where to calculate the next set of CURBEs. |
* It's a hot enough path that malloc/free of that data matters. |
*/ |
GLfloat *next_buf; |
GLuint last_bufsz; |
} curbe; |
/** SAMPLER_STATE count and offset */ |
struct { |
GLuint count; |
uint32_t offset; |
} sampler; |
/** |
* Layout of vertex data exiting the geometry portion of the pipleine. |
* This comes from the geometry shader if one exists, otherwise from the |
* vertex shader. |
* |
* BRW_NEW_VUE_MAP_GEOM_OUT is flagged when the VUE map changes. |
*/ |
struct brw_vue_map vue_map_geom_out; |
struct { |
struct brw_vs_prog_data *prog_data; |
drm_intel_bo *scratch_bo; |
drm_intel_bo *const_bo; |
/** Offset in the program cache to the VS program */ |
uint32_t prog_offset; |
uint32_t state_offset; |
uint32_t push_const_offset; /* Offset in the batchbuffer */ |
int push_const_size; /* in 256-bit register increments */ |
/** @{ register allocator */ |
struct ra_regs *regs; |
/** |
* Array of the ra classes for the unaligned contiguous register |
* block sizes used. |
*/ |
int *classes; |
/** |
* Mapping for register-allocated objects in *regs to the first |
* GRF for that object. |
*/ |
uint8_t *ra_reg_to_grf; |
/** @} */ |
uint32_t bind_bo_offset; |
uint32_t surf_offset[BRW_MAX_VS_SURFACES]; |
} vs; |
struct { |
struct brw_gs_prog_data *prog_data; |
bool prog_active; |
/** Offset in the program cache to the CLIP program pre-gen6 */ |
uint32_t prog_offset; |
uint32_t state_offset; |
uint32_t bind_bo_offset; |
uint32_t surf_offset[BRW_MAX_GS_SURFACES]; |
} gs; |
struct { |
struct brw_clip_prog_data *prog_data; |
/** Offset in the program cache to the CLIP program pre-gen6 */ |
uint32_t prog_offset; |
/* Offset in the batch to the CLIP state on pre-gen6. */ |
uint32_t state_offset; |
/* As of gen6, this is the offset in the batch to the CLIP VP, |
* instead of vp_bo. |
*/ |
uint32_t vp_offset; |
} clip; |
struct { |
struct brw_sf_prog_data *prog_data; |
/** Offset in the program cache to the CLIP program pre-gen6 */ |
uint32_t prog_offset; |
uint32_t state_offset; |
uint32_t vp_offset; |
} sf; |
struct { |
struct brw_wm_prog_data *prog_data; |
/** offsets in the batch to sampler default colors (texture border color) |
*/ |
uint32_t sdc_offset[BRW_MAX_TEX_UNIT]; |
GLuint render_surf; |
drm_intel_bo *scratch_bo; |
/** |
* Buffer object used in place of multisampled null render targets on |
* Gen6. See brw_update_null_renderbuffer_surface(). |
*/ |
drm_intel_bo *multisampled_null_render_target_bo; |
/** Offset in the program cache to the WM program */ |
uint32_t prog_offset; |
uint32_t state_offset; /* offset in batchbuffer to pre-gen6 WM state */ |
drm_intel_bo *const_bo; /* pull constant buffer. */ |
/** |
* This is offset in the batch to the push constants on gen6. |
* |
* Pre-gen6, push constants live in the CURBE. |
*/ |
uint32_t push_const_offset; |
/** Binding table of pointers to surf_bo entries */ |
uint32_t bind_bo_offset; |
uint32_t surf_offset[BRW_MAX_WM_SURFACES]; |
struct { |
struct ra_regs *regs; |
/** Array of the ra classes for the unaligned contiguous |
* register block sizes used. |
*/ |
int *classes; |
/** |
* Mapping for register-allocated objects in *regs to the first |
* GRF for that object. |
*/ |
uint8_t *ra_reg_to_grf; |
/** |
* ra class for the aligned pairs we use for PLN, which doesn't |
* appear in *classes. |
*/ |
int aligned_pairs_class; |
} reg_sets[2]; |
} wm; |
struct { |
uint32_t state_offset; |
uint32_t blend_state_offset; |
uint32_t depth_stencil_state_offset; |
uint32_t vp_offset; |
} cc; |
struct { |
struct brw_query_object *obj; |
bool begin_emitted; |
} query; |
int num_atoms; |
const struct brw_tracked_state **atoms; |
/* If (INTEL_DEBUG & DEBUG_BATCH) */ |
struct { |
uint32_t offset; |
uint32_t size; |
enum state_struct_type type; |
} *state_batch_list; |
int state_batch_count; |
uint32_t render_target_format[MESA_FORMAT_COUNT]; |
bool format_supported_as_render_target[MESA_FORMAT_COUNT]; |
/* PrimitiveRestart */ |
struct { |
bool in_progress; |
bool enable_cut_index; |
} prim_restart; |
/** Computed depth/stencil/hiz state from the current attached |
* renderbuffers, valid only during the drawing state upload loop after |
* brw_workaround_depthstencil_alignment(). |
*/ |
struct { |
struct intel_mipmap_tree *depth_mt; |
struct intel_mipmap_tree *stencil_mt; |
/* Inter-tile (page-aligned) byte offsets. */ |
uint32_t depth_offset, hiz_offset, stencil_offset; |
/* Intra-tile x,y offsets for drawing to depth/stencil/hiz */ |
uint32_t tile_x, tile_y; |
} depthstencil; |
uint32_t num_instances; |
int basevertex; |
struct { |
drm_intel_bo *bo; |
struct gl_shader_program **shader_programs; |
struct gl_program **programs; |
enum shader_time_shader_type *types; |
uint64_t *cumulative; |
int num_entries; |
int max_entries; |
double report_time; |
} shader_time; |
__DRIcontext *driContext; |
struct intel_screen *intelScreen; |
void (*saved_viewport)(struct gl_context *ctx, |
GLint x, GLint y, GLsizei width, GLsizei height); |
}; |
/*====================================================================== |
* brw_vtbl.c |
*/ |
void brwInitVtbl( struct brw_context *brw ); |
/*====================================================================== |
* brw_context.c |
*/ |
bool brwCreateContext(int api, |
const struct gl_config *mesaVis, |
__DRIcontext *driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
uint32_t flags, |
unsigned *error, |
void *sharedContextPrivate); |
/*====================================================================== |
* brw_misc_state.c |
*/ |
void brw_get_depthstencil_tile_masks(struct intel_mipmap_tree *depth_mt, |
uint32_t depth_level, |
uint32_t depth_layer, |
struct intel_mipmap_tree *stencil_mt, |
uint32_t *out_tile_mask_x, |
uint32_t *out_tile_mask_y); |
void brw_workaround_depthstencil_alignment(struct brw_context *brw, |
GLbitfield clear_mask); |
/*====================================================================== |
* brw_queryobj.c |
*/ |
void brw_init_common_queryobj_functions(struct dd_function_table *functions); |
void gen4_init_queryobj_functions(struct dd_function_table *functions); |
void brw_emit_query_begin(struct brw_context *brw); |
void brw_emit_query_end(struct brw_context *brw); |
/** gen6_queryobj.c */ |
void gen6_init_queryobj_functions(struct dd_function_table *functions); |
/*====================================================================== |
* brw_state_dump.c |
*/ |
void brw_debug_batch(struct brw_context *brw); |
void brw_annotate_aub(struct brw_context *brw); |
/*====================================================================== |
* brw_tex.c |
*/ |
void brw_validate_textures( struct brw_context *brw ); |
/*====================================================================== |
* brw_program.c |
*/ |
void brwInitFragProgFuncs( struct dd_function_table *functions ); |
int brw_get_scratch_size(int size); |
void brw_get_scratch_bo(struct brw_context *brw, |
drm_intel_bo **scratch_bo, int size); |
void brw_init_shader_time(struct brw_context *brw); |
int brw_get_shader_time_index(struct brw_context *brw, |
struct gl_shader_program *shader_prog, |
struct gl_program *prog, |
enum shader_time_shader_type type); |
void brw_collect_and_report_shader_time(struct brw_context *brw); |
void brw_destroy_shader_time(struct brw_context *brw); |
/* brw_urb.c |
*/ |
void brw_upload_urb_fence(struct brw_context *brw); |
/* brw_curbe.c |
*/ |
void brw_upload_cs_urb_state(struct brw_context *brw); |
/* brw_fs_reg_allocate.cpp |
*/ |
void brw_fs_alloc_reg_sets(struct brw_context *brw); |
/* brw_disasm.c */ |
int brw_disasm (FILE *file, struct brw_instruction *inst, int gen); |
/* brw_vs.c */ |
gl_clip_plane *brw_select_clip_planes(struct gl_context *ctx); |
/* brw_wm_surface_state.c */ |
void brw_init_surface_formats(struct brw_context *brw); |
void |
brw_update_sol_surface(struct brw_context *brw, |
struct gl_buffer_object *buffer_obj, |
uint32_t *out_offset, unsigned num_vector_components, |
unsigned stride_dwords, unsigned offset_dwords); |
void brw_upload_ubo_surfaces(struct brw_context *brw, |
struct gl_shader *shader, |
uint32_t *surf_offsets); |
/* brw_surface_formats.c */ |
bool brw_is_hiz_depth_format(struct brw_context *ctx, gl_format format); |
bool brw_render_target_supported(struct brw_context *brw, |
struct gl_renderbuffer *rb); |
/* gen6_sol.c */ |
void |
brw_begin_transform_feedback(struct gl_context *ctx, GLenum mode, |
struct gl_transform_feedback_object *obj); |
void |
brw_end_transform_feedback(struct gl_context *ctx, |
struct gl_transform_feedback_object *obj); |
/* gen7_sol_state.c */ |
void |
gen7_begin_transform_feedback(struct gl_context *ctx, GLenum mode, |
struct gl_transform_feedback_object *obj); |
void |
gen7_end_transform_feedback(struct gl_context *ctx, |
struct gl_transform_feedback_object *obj); |
/* brw_blorp_blit.cpp */ |
GLbitfield |
brw_blorp_framebuffer(struct brw_context *brw, |
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, |
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, |
GLbitfield mask, GLenum filter); |
bool |
brw_blorp_copytexsubimage(struct brw_context *brw, |
struct gl_renderbuffer *src_rb, |
struct gl_texture_image *dst_image, |
int slice, |
int srcX0, int srcY0, |
int dstX0, int dstY0, |
int width, int height); |
/* gen6_multisample_state.c */ |
void |
gen6_emit_3dstate_multisample(struct brw_context *brw, |
unsigned num_samples); |
void |
gen6_emit_3dstate_sample_mask(struct brw_context *brw, |
unsigned num_samples, float coverage, |
bool coverage_invert, unsigned sample_mask); |
void |
gen6_get_sample_position(struct gl_context *ctx, |
struct gl_framebuffer *fb, |
GLuint index, |
GLfloat *result); |
/* gen7_urb.c */ |
void |
gen7_allocate_push_constants(struct brw_context *brw); |
void |
gen7_emit_urb_state(struct brw_context *brw, GLuint nr_vs_entries, |
GLuint vs_size, GLuint vs_start); |
/*====================================================================== |
* Inline conversion functions. These are better-typed than the |
* macros used previously: |
*/ |
static INLINE struct brw_context * |
brw_context( struct gl_context *ctx ) |
{ |
return (struct brw_context *)ctx; |
} |
static INLINE struct brw_vertex_program * |
brw_vertex_program(struct gl_vertex_program *p) |
{ |
return (struct brw_vertex_program *) p; |
} |
static INLINE const struct brw_vertex_program * |
brw_vertex_program_const(const struct gl_vertex_program *p) |
{ |
return (const struct brw_vertex_program *) p; |
} |
static INLINE struct brw_fragment_program * |
brw_fragment_program(struct gl_fragment_program *p) |
{ |
return (struct brw_fragment_program *) p; |
} |
static INLINE const struct brw_fragment_program * |
brw_fragment_program_const(const struct gl_fragment_program *p) |
{ |
return (const struct brw_fragment_program *) p; |
} |
/** |
* Pre-gen6, the register file of the EUs was shared between threads, |
* and each thread used some subset allocated on a 16-register block |
* granularity. The unit states wanted these block counts. |
*/ |
static inline int |
brw_register_blocks(int reg_count) |
{ |
return ALIGN(reg_count, 16) / 16 - 1; |
} |
static inline uint32_t |
brw_program_reloc(struct brw_context *brw, uint32_t state_offset, |
uint32_t prog_offset) |
{ |
if (brw->gen >= 5) { |
/* Using state base address. */ |
return prog_offset; |
} |
drm_intel_bo_emit_reloc(brw->batch.bo, |
state_offset, |
brw->cache.bo, |
prog_offset, |
I915_GEM_DOMAIN_INSTRUCTION, 0); |
return brw->cache.bo->offset + prog_offset; |
} |
bool brw_do_cubemap_normalize(struct exec_list *instructions); |
bool brw_lower_texture_gradients(struct brw_context *brw, |
struct exec_list *instructions); |
struct opcode_desc { |
char *name; |
int nsrc; |
int ndst; |
}; |
extern const struct opcode_desc opcode_descs[128]; |
void |
brw_emit_depthbuffer(struct brw_context *brw); |
void |
brw_emit_depth_stencil_hiz(struct brw_context *brw, |
struct intel_mipmap_tree *depth_mt, |
uint32_t depth_offset, uint32_t depthbuffer_format, |
uint32_t depth_surface_type, |
struct intel_mipmap_tree *stencil_mt, |
bool hiz, bool separate_stencil, |
uint32_t width, uint32_t height, |
uint32_t tile_x, uint32_t tile_y); |
void |
gen7_emit_depth_stencil_hiz(struct brw_context *brw, |
struct intel_mipmap_tree *depth_mt, |
uint32_t depth_offset, uint32_t depthbuffer_format, |
uint32_t depth_surface_type, |
struct intel_mipmap_tree *stencil_mt, |
bool hiz, bool separate_stencil, |
uint32_t width, uint32_t height, |
uint32_t tile_x, uint32_t tile_y); |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_cubemap_normalize.cpp |
---|
0,0 → 1,121 |
/* |
* Copyright © 2010 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. |
*/ |
/** |
* \file brw_cubemap_normalize.cpp |
* |
* IR lower pass to perform the normalization of the cubemap coordinates to |
* have the largest magnitude component be -1.0 or 1.0. |
* |
* \author Eric Anholt <eric@anholt.net> |
*/ |
#include "glsl/glsl_types.h" |
#include "glsl/ir.h" |
#include "program/prog_instruction.h" /* For WRITEMASK_* */ |
class brw_cubemap_normalize_visitor : public ir_hierarchical_visitor { |
public: |
brw_cubemap_normalize_visitor() |
{ |
progress = false; |
} |
ir_visitor_status visit_leave(ir_texture *ir); |
bool progress; |
}; |
ir_visitor_status |
brw_cubemap_normalize_visitor::visit_leave(ir_texture *ir) |
{ |
if (ir->sampler->type->sampler_dimensionality != GLSL_SAMPLER_DIM_CUBE) |
return visit_continue; |
if (ir->op == ir_txs) |
return visit_continue; |
void *mem_ctx = ralloc_parent(ir); |
ir_variable *var = new(mem_ctx) ir_variable(ir->coordinate->type, |
"coordinate", ir_var_auto); |
base_ir->insert_before(var); |
ir_dereference *deref = new(mem_ctx) ir_dereference_variable(var); |
ir_assignment *assign = new(mem_ctx) ir_assignment(deref, ir->coordinate, |
NULL); |
base_ir->insert_before(assign); |
deref = new(mem_ctx) ir_dereference_variable(var); |
ir_rvalue *swiz0 = new(mem_ctx) ir_swizzle(deref, 0, 0, 0, 0, 1); |
deref = new(mem_ctx) ir_dereference_variable(var); |
ir_rvalue *swiz1 = new(mem_ctx) ir_swizzle(deref, 1, 0, 0, 0, 1); |
deref = new(mem_ctx) ir_dereference_variable(var); |
ir_rvalue *swiz2 = new(mem_ctx) ir_swizzle(deref, 2, 0, 0, 0, 1); |
swiz0 = new(mem_ctx) ir_expression(ir_unop_abs, swiz0->type, swiz0, NULL); |
swiz1 = new(mem_ctx) ir_expression(ir_unop_abs, swiz1->type, swiz1, NULL); |
swiz2 = new(mem_ctx) ir_expression(ir_unop_abs, swiz2->type, swiz2, NULL); |
ir_expression *expr; |
expr = new(mem_ctx) ir_expression(ir_binop_max, |
glsl_type::float_type, |
swiz0, swiz1); |
expr = new(mem_ctx) ir_expression(ir_binop_max, |
glsl_type::float_type, |
expr, swiz2); |
expr = new(mem_ctx) ir_expression(ir_unop_rcp, |
glsl_type::float_type, |
expr, NULL); |
/* coordinate.xyz *= expr */ |
assign = new(mem_ctx) ir_assignment( |
new(mem_ctx) ir_dereference_variable(var), |
new(mem_ctx) ir_swizzle( |
new(mem_ctx) ir_expression(ir_binop_mul, |
ir->coordinate->type, |
new(mem_ctx) ir_dereference_variable(var), |
expr), |
0, 1, 2, 0, 3)); |
assign->write_mask = WRITEMASK_XYZ; |
base_ir->insert_before(assign); |
ir->coordinate = new(mem_ctx) ir_dereference_variable(var); |
progress = true; |
return visit_continue; |
} |
extern "C" { |
bool |
brw_do_cubemap_normalize(exec_list *instructions) |
{ |
brw_cubemap_normalize_visitor v; |
visit_list_elements(&v, instructions); |
return v.progress; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_curbe.c |
---|
0,0 → 1,339 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "program/prog_parameter.h" |
#include "program/prog_print.h" |
#include "program/prog_statevars.h" |
#include "intel_batchbuffer.h" |
#include "intel_regions.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
#include "brw_state.h" |
#include "brw_util.h" |
/** |
* Partition the CURBE between the various users of constant values: |
* Note that vertex and fragment shaders can now fetch constants out |
* of constant buffers. We no longer allocatea block of the GRF for |
* constants. That greatly reduces the demand for space in the CURBE. |
* Some of the comments within are dated... |
*/ |
static void calculate_curbe_offsets( struct brw_context *brw ) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* CACHE_NEW_WM_PROG */ |
const GLuint nr_fp_regs = (brw->wm.prog_data->nr_params + 15) / 16; |
/* BRW_NEW_VERTEX_PROGRAM */ |
const GLuint nr_vp_regs = (brw->vs.prog_data->base.nr_params + 15) / 16; |
GLuint nr_clip_regs = 0; |
GLuint total_regs; |
/* _NEW_TRANSFORM */ |
if (ctx->Transform.ClipPlanesEnabled) { |
GLuint nr_planes = 6 + _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); |
nr_clip_regs = (nr_planes * 4 + 15) / 16; |
} |
total_regs = nr_fp_regs + nr_vp_regs + nr_clip_regs; |
/* This can happen - what to do? Probably rather than falling |
* back, the best thing to do is emit programs which code the |
* constants as immediate values. Could do this either as a static |
* cap on WM and VS, or adaptively. |
* |
* Unfortunately, this is currently dependent on the results of the |
* program generation process (in the case of wm), so this would |
* introduce the need to re-generate programs in the event of a |
* curbe allocation failure. |
*/ |
/* Max size is 32 - just large enough to |
* hold the 128 parameters allowed by |
* the fragment and vertex program |
* api's. It's not clear what happens |
* when both VP and FP want to use 128 |
* parameters, though. |
*/ |
assert(total_regs <= 32); |
/* Lazy resize: |
*/ |
if (nr_fp_regs > brw->curbe.wm_size || |
nr_vp_regs > brw->curbe.vs_size || |
nr_clip_regs != brw->curbe.clip_size || |
(total_regs < brw->curbe.total_size / 4 && |
brw->curbe.total_size > 16)) { |
GLuint reg = 0; |
/* Calculate a new layout: |
*/ |
reg = 0; |
brw->curbe.wm_start = reg; |
brw->curbe.wm_size = nr_fp_regs; reg += nr_fp_regs; |
brw->curbe.clip_start = reg; |
brw->curbe.clip_size = nr_clip_regs; reg += nr_clip_regs; |
brw->curbe.vs_start = reg; |
brw->curbe.vs_size = nr_vp_regs; reg += nr_vp_regs; |
brw->curbe.total_size = reg; |
if (0) |
printf("curbe wm %d+%d clip %d+%d vs %d+%d\n", |
brw->curbe.wm_start, |
brw->curbe.wm_size, |
brw->curbe.clip_start, |
brw->curbe.clip_size, |
brw->curbe.vs_start, |
brw->curbe.vs_size ); |
brw->state.dirty.brw |= BRW_NEW_CURBE_OFFSETS; |
} |
} |
const struct brw_tracked_state brw_curbe_offsets = { |
.dirty = { |
.mesa = _NEW_TRANSFORM, |
.brw = BRW_NEW_VERTEX_PROGRAM | BRW_NEW_CONTEXT, |
.cache = CACHE_NEW_WM_PROG |
}, |
.emit = calculate_curbe_offsets |
}; |
/* Define the number of curbes within CS's urb allocation. Multiple |
* urb entries -> multiple curbes. These will be used by |
* fixed-function hardware in a double-buffering scheme to avoid a |
* pipeline stall each time the contents of the curbe is changed. |
*/ |
void brw_upload_cs_urb_state(struct brw_context *brw) |
{ |
BEGIN_BATCH(2); |
/* It appears that this is the state packet for the CS unit, ie. the |
* urb entries detailed here are housed in the CS range from the |
* URB_FENCE command. |
*/ |
OUT_BATCH(CMD_CS_URB_STATE << 16 | (2-2)); |
/* BRW_NEW_URB_FENCE */ |
if (brw->urb.csize == 0) { |
OUT_BATCH(0); |
} else { |
/* BRW_NEW_URB_FENCE */ |
assert(brw->urb.nr_cs_entries); |
OUT_BATCH((brw->urb.csize - 1) << 4 | brw->urb.nr_cs_entries); |
} |
CACHED_BATCH(); |
} |
static GLfloat fixed_plane[6][4] = { |
{ 0, 0, -1, 1 }, |
{ 0, 0, 1, 1 }, |
{ 0, -1, 0, 1 }, |
{ 0, 1, 0, 1 }, |
{-1, 0, 0, 1 }, |
{ 1, 0, 0, 1 } |
}; |
/* Upload a new set of constants. Too much variability to go into the |
* cache mechanism, but maybe would benefit from a comparison against |
* the current uploaded set of constants. |
*/ |
static void |
brw_upload_constant_buffer(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
const GLuint sz = brw->curbe.total_size; |
const GLuint bufsz = sz * 16 * sizeof(GLfloat); |
GLfloat *buf; |
GLuint i; |
gl_clip_plane *clip_planes; |
if (sz == 0) { |
brw->curbe.last_bufsz = 0; |
goto emit; |
} |
buf = brw->curbe.next_buf; |
/* fragment shader constants */ |
if (brw->curbe.wm_size) { |
GLuint offset = brw->curbe.wm_start * 16; |
/* copy float constants */ |
for (i = 0; i < brw->wm.prog_data->nr_params; i++) { |
buf[offset + i] = *brw->wm.prog_data->param[i]; |
} |
} |
/* clipper constants */ |
if (brw->curbe.clip_size) { |
GLuint offset = brw->curbe.clip_start * 16; |
GLuint j; |
/* If any planes are going this way, send them all this way: |
*/ |
for (i = 0; i < 6; i++) { |
buf[offset + i * 4 + 0] = fixed_plane[i][0]; |
buf[offset + i * 4 + 1] = fixed_plane[i][1]; |
buf[offset + i * 4 + 2] = fixed_plane[i][2]; |
buf[offset + i * 4 + 3] = fixed_plane[i][3]; |
} |
/* Clip planes: _NEW_TRANSFORM plus _NEW_PROJECTION to get to |
* clip-space: |
*/ |
clip_planes = brw_select_clip_planes(ctx); |
for (j = 0; j < MAX_CLIP_PLANES; j++) { |
if (ctx->Transform.ClipPlanesEnabled & (1<<j)) { |
buf[offset + i * 4 + 0] = clip_planes[j][0]; |
buf[offset + i * 4 + 1] = clip_planes[j][1]; |
buf[offset + i * 4 + 2] = clip_planes[j][2]; |
buf[offset + i * 4 + 3] = clip_planes[j][3]; |
i++; |
} |
} |
} |
/* vertex shader constants */ |
if (brw->curbe.vs_size) { |
GLuint offset = brw->curbe.vs_start * 16; |
for (i = 0; i < brw->vs.prog_data->base.nr_params; i++) { |
buf[offset + i] = *brw->vs.prog_data->base.param[i]; |
} |
} |
if (0) { |
for (i = 0; i < sz*16; i+=4) |
printf("curbe %d.%d: %f %f %f %f\n", i/8, i&4, |
buf[i+0], buf[i+1], buf[i+2], buf[i+3]); |
printf("last_buf %p buf %p sz %d/%d cmp %d\n", |
brw->curbe.last_buf, buf, |
bufsz, brw->curbe.last_bufsz, |
brw->curbe.last_buf ? memcmp(buf, brw->curbe.last_buf, bufsz) : -1); |
} |
if (brw->curbe.curbe_bo != NULL && |
bufsz == brw->curbe.last_bufsz && |
memcmp(buf, brw->curbe.last_buf, bufsz) == 0) { |
/* constants have not changed */ |
} else { |
/* Update the record of what our last set of constants was. We |
* don't just flip the pointers because we don't fill in the |
* data in the padding between the entries. |
*/ |
memcpy(brw->curbe.last_buf, buf, bufsz); |
brw->curbe.last_bufsz = bufsz; |
if (brw->curbe.curbe_bo != NULL && |
brw->curbe.curbe_next_offset + bufsz > brw->curbe.curbe_bo->size) |
{ |
drm_intel_gem_bo_unmap_gtt(brw->curbe.curbe_bo); |
drm_intel_bo_unreference(brw->curbe.curbe_bo); |
brw->curbe.curbe_bo = NULL; |
} |
if (brw->curbe.curbe_bo == NULL) { |
/* Allocate a single page for CURBE entries for this batchbuffer. |
* They're generally around 64b. |
*/ |
brw->curbe.curbe_bo = drm_intel_bo_alloc(brw->bufmgr, "CURBE", |
4096, 1 << 6); |
brw->curbe.curbe_next_offset = 0; |
drm_intel_gem_bo_map_gtt(brw->curbe.curbe_bo); |
assert(bufsz < 4096); |
} |
brw->curbe.curbe_offset = brw->curbe.curbe_next_offset; |
brw->curbe.curbe_next_offset += bufsz; |
brw->curbe.curbe_next_offset = ALIGN(brw->curbe.curbe_next_offset, 64); |
/* Copy data to the buffer: |
*/ |
memcpy(brw->curbe.curbe_bo->virtual + brw->curbe.curbe_offset, |
buf, |
bufsz); |
} |
/* Because this provokes an action (ie copy the constants into the |
* URB), it shouldn't be shortcircuited if identical to the |
* previous time - because eg. the urb destination may have |
* changed, or the urb contents different to last time. |
* |
* Note that the data referred to is actually copied internally, |
* not just used in place according to passed pointer. |
* |
* It appears that the CS unit takes care of using each available |
* URB entry (Const URB Entry == CURBE) in turn, and issuing |
* flushes as necessary when doublebuffering of CURBEs isn't |
* possible. |
*/ |
emit: |
BEGIN_BATCH(2); |
if (brw->curbe.total_size == 0) { |
OUT_BATCH((CMD_CONST_BUFFER << 16) | (2 - 2)); |
OUT_BATCH(0); |
} else { |
OUT_BATCH((CMD_CONST_BUFFER << 16) | (1 << 8) | (2 - 2)); |
OUT_RELOC(brw->curbe.curbe_bo, |
I915_GEM_DOMAIN_INSTRUCTION, 0, |
(brw->curbe.total_size - 1) + brw->curbe.curbe_offset); |
} |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state brw_constant_buffer = { |
.dirty = { |
.mesa = _NEW_PROGRAM_CONSTANTS, |
.brw = (BRW_NEW_FRAGMENT_PROGRAM | |
BRW_NEW_VERTEX_PROGRAM | |
BRW_NEW_URB_FENCE | /* Implicit - hardware requires this, not used above */ |
BRW_NEW_PSP | /* Implicit - hardware requires this, not used above */ |
BRW_NEW_CURBE_OFFSETS | |
BRW_NEW_BATCH), |
.cache = (CACHE_NEW_WM_PROG) |
}, |
.emit = brw_upload_constant_buffer, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_defines.h |
---|
0,0 → 1,1761 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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> |
*/ |
#define INTEL_MASK(high, low) (((1<<((high)-(low)+1))-1)<<(low)) |
#define SET_FIELD(value, field) (((value) << field ## _SHIFT) & field ## _MASK) |
#define GET_FIELD(word, field) (((word) & field ## _MASK) >> field ## _SHIFT) |
#ifndef BRW_DEFINES_H |
#define BRW_DEFINES_H |
/* 3D state: |
*/ |
#define PIPE_CONTROL_NOWRITE 0x00 |
#define PIPE_CONTROL_WRITEIMMEDIATE 0x01 |
#define PIPE_CONTROL_WRITEDEPTH 0x02 |
#define PIPE_CONTROL_WRITETIMESTAMP 0x03 |
#define PIPE_CONTROL_GTTWRITE_PROCESS_LOCAL 0x00 |
#define PIPE_CONTROL_GTTWRITE_GLOBAL 0x01 |
#define CMD_3D_PRIM 0x7b00 /* 3DPRIMITIVE */ |
/* DW0 */ |
# define GEN4_3DPRIM_TOPOLOGY_TYPE_SHIFT 10 |
# define GEN4_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL (0 << 15) |
# define GEN4_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM (1 << 15) |
/* DW1 */ |
# define GEN7_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL (0 << 8) |
# define GEN7_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM (1 << 8) |
#define _3DPRIM_POINTLIST 0x01 |
#define _3DPRIM_LINELIST 0x02 |
#define _3DPRIM_LINESTRIP 0x03 |
#define _3DPRIM_TRILIST 0x04 |
#define _3DPRIM_TRISTRIP 0x05 |
#define _3DPRIM_TRIFAN 0x06 |
#define _3DPRIM_QUADLIST 0x07 |
#define _3DPRIM_QUADSTRIP 0x08 |
#define _3DPRIM_LINELIST_ADJ 0x09 |
#define _3DPRIM_LINESTRIP_ADJ 0x0A |
#define _3DPRIM_TRILIST_ADJ 0x0B |
#define _3DPRIM_TRISTRIP_ADJ 0x0C |
#define _3DPRIM_TRISTRIP_REVERSE 0x0D |
#define _3DPRIM_POLYGON 0x0E |
#define _3DPRIM_RECTLIST 0x0F |
#define _3DPRIM_LINELOOP 0x10 |
#define _3DPRIM_POINTLIST_BF 0x11 |
#define _3DPRIM_LINESTRIP_CONT 0x12 |
#define _3DPRIM_LINESTRIP_BF 0x13 |
#define _3DPRIM_LINESTRIP_CONT_BF 0x14 |
#define _3DPRIM_TRIFAN_NOSTIPPLE 0x15 |
#define BRW_ANISORATIO_2 0 |
#define BRW_ANISORATIO_4 1 |
#define BRW_ANISORATIO_6 2 |
#define BRW_ANISORATIO_8 3 |
#define BRW_ANISORATIO_10 4 |
#define BRW_ANISORATIO_12 5 |
#define BRW_ANISORATIO_14 6 |
#define BRW_ANISORATIO_16 7 |
#define BRW_BLENDFACTOR_ONE 0x1 |
#define BRW_BLENDFACTOR_SRC_COLOR 0x2 |
#define BRW_BLENDFACTOR_SRC_ALPHA 0x3 |
#define BRW_BLENDFACTOR_DST_ALPHA 0x4 |
#define BRW_BLENDFACTOR_DST_COLOR 0x5 |
#define BRW_BLENDFACTOR_SRC_ALPHA_SATURATE 0x6 |
#define BRW_BLENDFACTOR_CONST_COLOR 0x7 |
#define BRW_BLENDFACTOR_CONST_ALPHA 0x8 |
#define BRW_BLENDFACTOR_SRC1_COLOR 0x9 |
#define BRW_BLENDFACTOR_SRC1_ALPHA 0x0A |
#define BRW_BLENDFACTOR_ZERO 0x11 |
#define BRW_BLENDFACTOR_INV_SRC_COLOR 0x12 |
#define BRW_BLENDFACTOR_INV_SRC_ALPHA 0x13 |
#define BRW_BLENDFACTOR_INV_DST_ALPHA 0x14 |
#define BRW_BLENDFACTOR_INV_DST_COLOR 0x15 |
#define BRW_BLENDFACTOR_INV_CONST_COLOR 0x17 |
#define BRW_BLENDFACTOR_INV_CONST_ALPHA 0x18 |
#define BRW_BLENDFACTOR_INV_SRC1_COLOR 0x19 |
#define BRW_BLENDFACTOR_INV_SRC1_ALPHA 0x1A |
#define BRW_BLENDFUNCTION_ADD 0 |
#define BRW_BLENDFUNCTION_SUBTRACT 1 |
#define BRW_BLENDFUNCTION_REVERSE_SUBTRACT 2 |
#define BRW_BLENDFUNCTION_MIN 3 |
#define BRW_BLENDFUNCTION_MAX 4 |
#define BRW_ALPHATEST_FORMAT_UNORM8 0 |
#define BRW_ALPHATEST_FORMAT_FLOAT32 1 |
#define BRW_CHROMAKEY_KILL_ON_ANY_MATCH 0 |
#define BRW_CHROMAKEY_REPLACE_BLACK 1 |
#define BRW_CLIP_API_OGL 0 |
#define BRW_CLIP_API_DX 1 |
#define BRW_CLIPMODE_NORMAL 0 |
#define BRW_CLIPMODE_CLIP_ALL 1 |
#define BRW_CLIPMODE_CLIP_NON_REJECTED 2 |
#define BRW_CLIPMODE_REJECT_ALL 3 |
#define BRW_CLIPMODE_ACCEPT_ALL 4 |
#define BRW_CLIPMODE_KERNEL_CLIP 5 |
#define BRW_CLIP_NDCSPACE 0 |
#define BRW_CLIP_SCREENSPACE 1 |
#define BRW_COMPAREFUNCTION_ALWAYS 0 |
#define BRW_COMPAREFUNCTION_NEVER 1 |
#define BRW_COMPAREFUNCTION_LESS 2 |
#define BRW_COMPAREFUNCTION_EQUAL 3 |
#define BRW_COMPAREFUNCTION_LEQUAL 4 |
#define BRW_COMPAREFUNCTION_GREATER 5 |
#define BRW_COMPAREFUNCTION_NOTEQUAL 6 |
#define BRW_COMPAREFUNCTION_GEQUAL 7 |
#define BRW_COVERAGE_PIXELS_HALF 0 |
#define BRW_COVERAGE_PIXELS_1 1 |
#define BRW_COVERAGE_PIXELS_2 2 |
#define BRW_COVERAGE_PIXELS_4 3 |
#define BRW_CULLMODE_BOTH 0 |
#define BRW_CULLMODE_NONE 1 |
#define BRW_CULLMODE_FRONT 2 |
#define BRW_CULLMODE_BACK 3 |
#define BRW_DEFAULTCOLOR_R8G8B8A8_UNORM 0 |
#define BRW_DEFAULTCOLOR_R32G32B32A32_FLOAT 1 |
#define BRW_DEPTHFORMAT_D32_FLOAT_S8X24_UINT 0 |
#define BRW_DEPTHFORMAT_D32_FLOAT 1 |
#define BRW_DEPTHFORMAT_D24_UNORM_S8_UINT 2 |
#define BRW_DEPTHFORMAT_D24_UNORM_X8_UINT 3 /* GEN5 */ |
#define BRW_DEPTHFORMAT_D16_UNORM 5 |
#define BRW_FLOATING_POINT_IEEE_754 0 |
#define BRW_FLOATING_POINT_NON_IEEE_754 1 |
#define BRW_FRONTWINDING_CW 0 |
#define BRW_FRONTWINDING_CCW 1 |
#define BRW_SPRITE_POINT_ENABLE 16 |
#define BRW_CUT_INDEX_ENABLE (1 << 10) |
#define BRW_INDEX_BYTE 0 |
#define BRW_INDEX_WORD 1 |
#define BRW_INDEX_DWORD 2 |
#define BRW_LOGICOPFUNCTION_CLEAR 0 |
#define BRW_LOGICOPFUNCTION_NOR 1 |
#define BRW_LOGICOPFUNCTION_AND_INVERTED 2 |
#define BRW_LOGICOPFUNCTION_COPY_INVERTED 3 |
#define BRW_LOGICOPFUNCTION_AND_REVERSE 4 |
#define BRW_LOGICOPFUNCTION_INVERT 5 |
#define BRW_LOGICOPFUNCTION_XOR 6 |
#define BRW_LOGICOPFUNCTION_NAND 7 |
#define BRW_LOGICOPFUNCTION_AND 8 |
#define BRW_LOGICOPFUNCTION_EQUIV 9 |
#define BRW_LOGICOPFUNCTION_NOOP 10 |
#define BRW_LOGICOPFUNCTION_OR_INVERTED 11 |
#define BRW_LOGICOPFUNCTION_COPY 12 |
#define BRW_LOGICOPFUNCTION_OR_REVERSE 13 |
#define BRW_LOGICOPFUNCTION_OR 14 |
#define BRW_LOGICOPFUNCTION_SET 15 |
#define BRW_MAPFILTER_NEAREST 0x0 |
#define BRW_MAPFILTER_LINEAR 0x1 |
#define BRW_MAPFILTER_ANISOTROPIC 0x2 |
#define BRW_MIPFILTER_NONE 0 |
#define BRW_MIPFILTER_NEAREST 1 |
#define BRW_MIPFILTER_LINEAR 3 |
#define BRW_ADDRESS_ROUNDING_ENABLE_U_MAG 0x20 |
#define BRW_ADDRESS_ROUNDING_ENABLE_U_MIN 0x10 |
#define BRW_ADDRESS_ROUNDING_ENABLE_V_MAG 0x08 |
#define BRW_ADDRESS_ROUNDING_ENABLE_V_MIN 0x04 |
#define BRW_ADDRESS_ROUNDING_ENABLE_R_MAG 0x02 |
#define BRW_ADDRESS_ROUNDING_ENABLE_R_MIN 0x01 |
#define BRW_POLYGON_FRONT_FACING 0 |
#define BRW_POLYGON_BACK_FACING 1 |
#define BRW_PREFILTER_ALWAYS 0x0 |
#define BRW_PREFILTER_NEVER 0x1 |
#define BRW_PREFILTER_LESS 0x2 |
#define BRW_PREFILTER_EQUAL 0x3 |
#define BRW_PREFILTER_LEQUAL 0x4 |
#define BRW_PREFILTER_GREATER 0x5 |
#define BRW_PREFILTER_NOTEQUAL 0x6 |
#define BRW_PREFILTER_GEQUAL 0x7 |
#define BRW_PROVOKING_VERTEX_0 0 |
#define BRW_PROVOKING_VERTEX_1 1 |
#define BRW_PROVOKING_VERTEX_2 2 |
#define BRW_RASTRULE_UPPER_LEFT 0 |
#define BRW_RASTRULE_UPPER_RIGHT 1 |
/* These are listed as "Reserved, but not seen as useful" |
* in Intel documentation (page 212, "Point Rasterization Rule", |
* section 7.4 "SF Pipeline State Summary", of document |
* "Intel® 965 Express Chipset Family and Intel® G35 Express |
* Chipset Graphics Controller Programmer's Reference Manual, |
* Volume 2: 3D/Media", Revision 1.0b as of January 2008, |
* available at |
* http://intellinuxgraphics.org/documentation.html |
* at the time of this writing). |
* |
* These appear to be supported on at least some |
* i965-family devices, and the BRW_RASTRULE_LOWER_RIGHT |
* is useful when using OpenGL to render to a FBO |
* (which has the pixel coordinate Y orientation inverted |
* with respect to the normal OpenGL pixel coordinate system). |
*/ |
#define BRW_RASTRULE_LOWER_LEFT 2 |
#define BRW_RASTRULE_LOWER_RIGHT 3 |
#define BRW_RENDERTARGET_CLAMPRANGE_UNORM 0 |
#define BRW_RENDERTARGET_CLAMPRANGE_SNORM 1 |
#define BRW_RENDERTARGET_CLAMPRANGE_FORMAT 2 |
#define BRW_STENCILOP_KEEP 0 |
#define BRW_STENCILOP_ZERO 1 |
#define BRW_STENCILOP_REPLACE 2 |
#define BRW_STENCILOP_INCRSAT 3 |
#define BRW_STENCILOP_DECRSAT 4 |
#define BRW_STENCILOP_INCR 5 |
#define BRW_STENCILOP_DECR 6 |
#define BRW_STENCILOP_INVERT 7 |
/* Surface state DW0 */ |
#define BRW_SURFACE_RC_READ_WRITE (1 << 8) |
#define BRW_SURFACE_MIPLAYOUT_SHIFT 10 |
#define BRW_SURFACE_MIPMAPLAYOUT_BELOW 0 |
#define BRW_SURFACE_MIPMAPLAYOUT_RIGHT 1 |
#define BRW_SURFACE_CUBEFACE_ENABLES 0x3f |
#define BRW_SURFACE_BLEND_ENABLED (1 << 13) |
#define BRW_SURFACE_WRITEDISABLE_B_SHIFT 14 |
#define BRW_SURFACE_WRITEDISABLE_G_SHIFT 15 |
#define BRW_SURFACE_WRITEDISABLE_R_SHIFT 16 |
#define BRW_SURFACE_WRITEDISABLE_A_SHIFT 17 |
#define BRW_SURFACEFORMAT_R32G32B32A32_FLOAT 0x000 |
#define BRW_SURFACEFORMAT_R32G32B32A32_SINT 0x001 |
#define BRW_SURFACEFORMAT_R32G32B32A32_UINT 0x002 |
#define BRW_SURFACEFORMAT_R32G32B32A32_UNORM 0x003 |
#define BRW_SURFACEFORMAT_R32G32B32A32_SNORM 0x004 |
#define BRW_SURFACEFORMAT_R64G64_FLOAT 0x005 |
#define BRW_SURFACEFORMAT_R32G32B32X32_FLOAT 0x006 |
#define BRW_SURFACEFORMAT_R32G32B32A32_SSCALED 0x007 |
#define BRW_SURFACEFORMAT_R32G32B32A32_USCALED 0x008 |
#define BRW_SURFACEFORMAT_R32G32B32A32_SFIXED 0x020 |
#define BRW_SURFACEFORMAT_R64G64_PASSTHRU 0x021 |
#define BRW_SURFACEFORMAT_R32G32B32_FLOAT 0x040 |
#define BRW_SURFACEFORMAT_R32G32B32_SINT 0x041 |
#define BRW_SURFACEFORMAT_R32G32B32_UINT 0x042 |
#define BRW_SURFACEFORMAT_R32G32B32_UNORM 0x043 |
#define BRW_SURFACEFORMAT_R32G32B32_SNORM 0x044 |
#define BRW_SURFACEFORMAT_R32G32B32_SSCALED 0x045 |
#define BRW_SURFACEFORMAT_R32G32B32_USCALED 0x046 |
#define BRW_SURFACEFORMAT_R32G32B32_SFIXED 0x050 |
#define BRW_SURFACEFORMAT_R16G16B16A16_UNORM 0x080 |
#define BRW_SURFACEFORMAT_R16G16B16A16_SNORM 0x081 |
#define BRW_SURFACEFORMAT_R16G16B16A16_SINT 0x082 |
#define BRW_SURFACEFORMAT_R16G16B16A16_UINT 0x083 |
#define BRW_SURFACEFORMAT_R16G16B16A16_FLOAT 0x084 |
#define BRW_SURFACEFORMAT_R32G32_FLOAT 0x085 |
#define BRW_SURFACEFORMAT_R32G32_SINT 0x086 |
#define BRW_SURFACEFORMAT_R32G32_UINT 0x087 |
#define BRW_SURFACEFORMAT_R32_FLOAT_X8X24_TYPELESS 0x088 |
#define BRW_SURFACEFORMAT_X32_TYPELESS_G8X24_UINT 0x089 |
#define BRW_SURFACEFORMAT_L32A32_FLOAT 0x08A |
#define BRW_SURFACEFORMAT_R32G32_UNORM 0x08B |
#define BRW_SURFACEFORMAT_R32G32_SNORM 0x08C |
#define BRW_SURFACEFORMAT_R64_FLOAT 0x08D |
#define BRW_SURFACEFORMAT_R16G16B16X16_UNORM 0x08E |
#define BRW_SURFACEFORMAT_R16G16B16X16_FLOAT 0x08F |
#define BRW_SURFACEFORMAT_A32X32_FLOAT 0x090 |
#define BRW_SURFACEFORMAT_L32X32_FLOAT 0x091 |
#define BRW_SURFACEFORMAT_I32X32_FLOAT 0x092 |
#define BRW_SURFACEFORMAT_R16G16B16A16_SSCALED 0x093 |
#define BRW_SURFACEFORMAT_R16G16B16A16_USCALED 0x094 |
#define BRW_SURFACEFORMAT_R32G32_SSCALED 0x095 |
#define BRW_SURFACEFORMAT_R32G32_USCALED 0x096 |
#define BRW_SURFACEFORMAT_R32G32_SFIXED 0x0A0 |
#define BRW_SURFACEFORMAT_R64_PASSTHRU 0x0A1 |
#define BRW_SURFACEFORMAT_B8G8R8A8_UNORM 0x0C0 |
#define BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB 0x0C1 |
#define BRW_SURFACEFORMAT_R10G10B10A2_UNORM 0x0C2 |
#define BRW_SURFACEFORMAT_R10G10B10A2_UNORM_SRGB 0x0C3 |
#define BRW_SURFACEFORMAT_R10G10B10A2_UINT 0x0C4 |
#define BRW_SURFACEFORMAT_R10G10B10_SNORM_A2_UNORM 0x0C5 |
#define BRW_SURFACEFORMAT_R8G8B8A8_UNORM 0x0C7 |
#define BRW_SURFACEFORMAT_R8G8B8A8_UNORM_SRGB 0x0C8 |
#define BRW_SURFACEFORMAT_R8G8B8A8_SNORM 0x0C9 |
#define BRW_SURFACEFORMAT_R8G8B8A8_SINT 0x0CA |
#define BRW_SURFACEFORMAT_R8G8B8A8_UINT 0x0CB |
#define BRW_SURFACEFORMAT_R16G16_UNORM 0x0CC |
#define BRW_SURFACEFORMAT_R16G16_SNORM 0x0CD |
#define BRW_SURFACEFORMAT_R16G16_SINT 0x0CE |
#define BRW_SURFACEFORMAT_R16G16_UINT 0x0CF |
#define BRW_SURFACEFORMAT_R16G16_FLOAT 0x0D0 |
#define BRW_SURFACEFORMAT_B10G10R10A2_UNORM 0x0D1 |
#define BRW_SURFACEFORMAT_B10G10R10A2_UNORM_SRGB 0x0D2 |
#define BRW_SURFACEFORMAT_R11G11B10_FLOAT 0x0D3 |
#define BRW_SURFACEFORMAT_R32_SINT 0x0D6 |
#define BRW_SURFACEFORMAT_R32_UINT 0x0D7 |
#define BRW_SURFACEFORMAT_R32_FLOAT 0x0D8 |
#define BRW_SURFACEFORMAT_R24_UNORM_X8_TYPELESS 0x0D9 |
#define BRW_SURFACEFORMAT_X24_TYPELESS_G8_UINT 0x0DA |
#define BRW_SURFACEFORMAT_L16A16_UNORM 0x0DF |
#define BRW_SURFACEFORMAT_I24X8_UNORM 0x0E0 |
#define BRW_SURFACEFORMAT_L24X8_UNORM 0x0E1 |
#define BRW_SURFACEFORMAT_A24X8_UNORM 0x0E2 |
#define BRW_SURFACEFORMAT_I32_FLOAT 0x0E3 |
#define BRW_SURFACEFORMAT_L32_FLOAT 0x0E4 |
#define BRW_SURFACEFORMAT_A32_FLOAT 0x0E5 |
#define BRW_SURFACEFORMAT_B8G8R8X8_UNORM 0x0E9 |
#define BRW_SURFACEFORMAT_B8G8R8X8_UNORM_SRGB 0x0EA |
#define BRW_SURFACEFORMAT_R8G8B8X8_UNORM 0x0EB |
#define BRW_SURFACEFORMAT_R8G8B8X8_UNORM_SRGB 0x0EC |
#define BRW_SURFACEFORMAT_R9G9B9E5_SHAREDEXP 0x0ED |
#define BRW_SURFACEFORMAT_B10G10R10X2_UNORM 0x0EE |
#define BRW_SURFACEFORMAT_L16A16_FLOAT 0x0F0 |
#define BRW_SURFACEFORMAT_R32_UNORM 0x0F1 |
#define BRW_SURFACEFORMAT_R32_SNORM 0x0F2 |
#define BRW_SURFACEFORMAT_R10G10B10X2_USCALED 0x0F3 |
#define BRW_SURFACEFORMAT_R8G8B8A8_SSCALED 0x0F4 |
#define BRW_SURFACEFORMAT_R8G8B8A8_USCALED 0x0F5 |
#define BRW_SURFACEFORMAT_R16G16_SSCALED 0x0F6 |
#define BRW_SURFACEFORMAT_R16G16_USCALED 0x0F7 |
#define BRW_SURFACEFORMAT_R32_SSCALED 0x0F8 |
#define BRW_SURFACEFORMAT_R32_USCALED 0x0F9 |
#define BRW_SURFACEFORMAT_B5G6R5_UNORM 0x100 |
#define BRW_SURFACEFORMAT_B5G6R5_UNORM_SRGB 0x101 |
#define BRW_SURFACEFORMAT_B5G5R5A1_UNORM 0x102 |
#define BRW_SURFACEFORMAT_B5G5R5A1_UNORM_SRGB 0x103 |
#define BRW_SURFACEFORMAT_B4G4R4A4_UNORM 0x104 |
#define BRW_SURFACEFORMAT_B4G4R4A4_UNORM_SRGB 0x105 |
#define BRW_SURFACEFORMAT_R8G8_UNORM 0x106 |
#define BRW_SURFACEFORMAT_R8G8_SNORM 0x107 |
#define BRW_SURFACEFORMAT_R8G8_SINT 0x108 |
#define BRW_SURFACEFORMAT_R8G8_UINT 0x109 |
#define BRW_SURFACEFORMAT_R16_UNORM 0x10A |
#define BRW_SURFACEFORMAT_R16_SNORM 0x10B |
#define BRW_SURFACEFORMAT_R16_SINT 0x10C |
#define BRW_SURFACEFORMAT_R16_UINT 0x10D |
#define BRW_SURFACEFORMAT_R16_FLOAT 0x10E |
#define BRW_SURFACEFORMAT_A8P8_UNORM_PALETTE0 0x10F |
#define BRW_SURFACEFORMAT_A8P8_UNORM_PALETTE1 0x110 |
#define BRW_SURFACEFORMAT_I16_UNORM 0x111 |
#define BRW_SURFACEFORMAT_L16_UNORM 0x112 |
#define BRW_SURFACEFORMAT_A16_UNORM 0x113 |
#define BRW_SURFACEFORMAT_L8A8_UNORM 0x114 |
#define BRW_SURFACEFORMAT_I16_FLOAT 0x115 |
#define BRW_SURFACEFORMAT_L16_FLOAT 0x116 |
#define BRW_SURFACEFORMAT_A16_FLOAT 0x117 |
#define BRW_SURFACEFORMAT_L8A8_UNORM_SRGB 0x118 |
#define BRW_SURFACEFORMAT_R5G5_SNORM_B6_UNORM 0x119 |
#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM 0x11A |
#define BRW_SURFACEFORMAT_B5G5R5X1_UNORM_SRGB 0x11B |
#define BRW_SURFACEFORMAT_R8G8_SSCALED 0x11C |
#define BRW_SURFACEFORMAT_R8G8_USCALED 0x11D |
#define BRW_SURFACEFORMAT_R16_SSCALED 0x11E |
#define BRW_SURFACEFORMAT_R16_USCALED 0x11F |
#define BRW_SURFACEFORMAT_P8A8_UNORM_PALETTE0 0x122 |
#define BRW_SURFACEFORMAT_P8A8_UNORM_PALETTE1 0x123 |
#define BRW_SURFACEFORMAT_A1B5G5R5_UNORM 0x124 |
#define BRW_SURFACEFORMAT_A4B4G4R4_UNORM 0x125 |
#define BRW_SURFACEFORMAT_L8A8_UINT 0x126 |
#define BRW_SURFACEFORMAT_L8A8_SINT 0x127 |
#define BRW_SURFACEFORMAT_R8_UNORM 0x140 |
#define BRW_SURFACEFORMAT_R8_SNORM 0x141 |
#define BRW_SURFACEFORMAT_R8_SINT 0x142 |
#define BRW_SURFACEFORMAT_R8_UINT 0x143 |
#define BRW_SURFACEFORMAT_A8_UNORM 0x144 |
#define BRW_SURFACEFORMAT_I8_UNORM 0x145 |
#define BRW_SURFACEFORMAT_L8_UNORM 0x146 |
#define BRW_SURFACEFORMAT_P4A4_UNORM 0x147 |
#define BRW_SURFACEFORMAT_A4P4_UNORM 0x148 |
#define BRW_SURFACEFORMAT_R8_SSCALED 0x149 |
#define BRW_SURFACEFORMAT_R8_USCALED 0x14A |
#define BRW_SURFACEFORMAT_P8_UNORM_PALETTE0 0x14B |
#define BRW_SURFACEFORMAT_L8_UNORM_SRGB 0x14C |
#define BRW_SURFACEFORMAT_P8_UNORM_PALETTE1 0x14D |
#define BRW_SURFACEFORMAT_P4A4_UNORM_PALETTE1 0x14E |
#define BRW_SURFACEFORMAT_A4P4_UNORM_PALETTE1 0x14F |
#define BRW_SURFACEFORMAT_Y8_SNORM 0x150 |
#define BRW_SURFACEFORMAT_L8_UINT 0x152 |
#define BRW_SURFACEFORMAT_L8_SINT 0x153 |
#define BRW_SURFACEFORMAT_I8_UINT 0x154 |
#define BRW_SURFACEFORMAT_I8_SINT 0x155 |
#define BRW_SURFACEFORMAT_DXT1_RGB_SRGB 0x180 |
#define BRW_SURFACEFORMAT_R1_UINT 0x181 |
#define BRW_SURFACEFORMAT_YCRCB_NORMAL 0x182 |
#define BRW_SURFACEFORMAT_YCRCB_SWAPUVY 0x183 |
#define BRW_SURFACEFORMAT_P2_UNORM_PALETTE0 0x184 |
#define BRW_SURFACEFORMAT_P2_UNORM_PALETTE1 0x185 |
#define BRW_SURFACEFORMAT_BC1_UNORM 0x186 |
#define BRW_SURFACEFORMAT_BC2_UNORM 0x187 |
#define BRW_SURFACEFORMAT_BC3_UNORM 0x188 |
#define BRW_SURFACEFORMAT_BC4_UNORM 0x189 |
#define BRW_SURFACEFORMAT_BC5_UNORM 0x18A |
#define BRW_SURFACEFORMAT_BC1_UNORM_SRGB 0x18B |
#define BRW_SURFACEFORMAT_BC2_UNORM_SRGB 0x18C |
#define BRW_SURFACEFORMAT_BC3_UNORM_SRGB 0x18D |
#define BRW_SURFACEFORMAT_MONO8 0x18E |
#define BRW_SURFACEFORMAT_YCRCB_SWAPUV 0x18F |
#define BRW_SURFACEFORMAT_YCRCB_SWAPY 0x190 |
#define BRW_SURFACEFORMAT_DXT1_RGB 0x191 |
#define BRW_SURFACEFORMAT_FXT1 0x192 |
#define BRW_SURFACEFORMAT_R8G8B8_UNORM 0x193 |
#define BRW_SURFACEFORMAT_R8G8B8_SNORM 0x194 |
#define BRW_SURFACEFORMAT_R8G8B8_SSCALED 0x195 |
#define BRW_SURFACEFORMAT_R8G8B8_USCALED 0x196 |
#define BRW_SURFACEFORMAT_R64G64B64A64_FLOAT 0x197 |
#define BRW_SURFACEFORMAT_R64G64B64_FLOAT 0x198 |
#define BRW_SURFACEFORMAT_BC4_SNORM 0x199 |
#define BRW_SURFACEFORMAT_BC5_SNORM 0x19A |
#define BRW_SURFACEFORMAT_R16G16B16_FLOAT 0x19B |
#define BRW_SURFACEFORMAT_R16G16B16_UNORM 0x19C |
#define BRW_SURFACEFORMAT_R16G16B16_SNORM 0x19D |
#define BRW_SURFACEFORMAT_R16G16B16_SSCALED 0x19E |
#define BRW_SURFACEFORMAT_R16G16B16_USCALED 0x19F |
#define BRW_SURFACEFORMAT_BC6H_SF16 0x1A1 |
#define BRW_SURFACEFORMAT_BC7_UNORM 0x1A2 |
#define BRW_SURFACEFORMAT_BC7_UNORM_SRGB 0x1A3 |
#define BRW_SURFACEFORMAT_BC6H_UF16 0x1A4 |
#define BRW_SURFACEFORMAT_PLANAR_420_8 0x1A5 |
#define BRW_SURFACEFORMAT_R8G8B8_UNORM_SRGB 0x1A8 |
#define BRW_SURFACEFORMAT_ETC1_RGB8 0x1A9 |
#define BRW_SURFACEFORMAT_ETC2_RGB8 0x1AA |
#define BRW_SURFACEFORMAT_EAC_R11 0x1AB |
#define BRW_SURFACEFORMAT_EAC_RG11 0x1AC |
#define BRW_SURFACEFORMAT_EAC_SIGNED_R11 0x1AD |
#define BRW_SURFACEFORMAT_EAC_SIGNED_RG11 0x1AE |
#define BRW_SURFACEFORMAT_ETC2_SRGB8 0x1AF |
#define BRW_SURFACEFORMAT_R16G16B16_UINT 0x1B0 |
#define BRW_SURFACEFORMAT_R16G16B16_SINT 0x1B1 |
#define BRW_SURFACEFORMAT_R32_SFIXED 0x1B2 |
#define BRW_SURFACEFORMAT_R10G10B10A2_SNORM 0x1B3 |
#define BRW_SURFACEFORMAT_R10G10B10A2_USCALED 0x1B4 |
#define BRW_SURFACEFORMAT_R10G10B10A2_SSCALED 0x1B5 |
#define BRW_SURFACEFORMAT_R10G10B10A2_SINT 0x1B6 |
#define BRW_SURFACEFORMAT_B10G10R10A2_SNORM 0x1B7 |
#define BRW_SURFACEFORMAT_B10G10R10A2_USCALED 0x1B8 |
#define BRW_SURFACEFORMAT_B10G10R10A2_SSCALED 0x1B9 |
#define BRW_SURFACEFORMAT_B10G10R10A2_UINT 0x1BA |
#define BRW_SURFACEFORMAT_B10G10R10A2_SINT 0x1BB |
#define BRW_SURFACEFORMAT_R64G64B64A64_PASSTHRU 0x1BC |
#define BRW_SURFACEFORMAT_R64G64B64_PASSTHRU 0x1BD |
#define BRW_SURFACEFORMAT_ETC2_RGB8_PTA 0x1C0 |
#define BRW_SURFACEFORMAT_ETC2_SRGB8_PTA 0x1C1 |
#define BRW_SURFACEFORMAT_ETC2_EAC_RGBA8 0x1C2 |
#define BRW_SURFACEFORMAT_ETC2_EAC_SRGB8_A8 0x1C3 |
#define BRW_SURFACEFORMAT_R8G8B8_UINT 0x1C8 |
#define BRW_SURFACEFORMAT_R8G8B8_SINT 0x1C9 |
#define BRW_SURFACEFORMAT_RAW 0x1FF |
#define BRW_SURFACE_FORMAT_SHIFT 18 |
#define BRW_SURFACE_FORMAT_MASK INTEL_MASK(26, 18) |
#define BRW_SURFACERETURNFORMAT_FLOAT32 0 |
#define BRW_SURFACERETURNFORMAT_S1 1 |
#define BRW_SURFACE_TYPE_SHIFT 29 |
#define BRW_SURFACE_TYPE_MASK INTEL_MASK(31, 29) |
#define BRW_SURFACE_1D 0 |
#define BRW_SURFACE_2D 1 |
#define BRW_SURFACE_3D 2 |
#define BRW_SURFACE_CUBE 3 |
#define BRW_SURFACE_BUFFER 4 |
#define BRW_SURFACE_NULL 7 |
#define GEN7_SURFACE_IS_ARRAY (1 << 28) |
#define GEN7_SURFACE_VALIGN_2 (0 << 16) |
#define GEN7_SURFACE_VALIGN_4 (1 << 16) |
#define GEN7_SURFACE_HALIGN_4 (0 << 15) |
#define GEN7_SURFACE_HALIGN_8 (1 << 15) |
#define GEN7_SURFACE_TILING_NONE (0 << 13) |
#define GEN7_SURFACE_TILING_X (2 << 13) |
#define GEN7_SURFACE_TILING_Y (3 << 13) |
#define GEN7_SURFACE_ARYSPC_FULL (0 << 10) |
#define GEN7_SURFACE_ARYSPC_LOD0 (1 << 10) |
/* Surface state DW2 */ |
#define BRW_SURFACE_HEIGHT_SHIFT 19 |
#define BRW_SURFACE_HEIGHT_MASK INTEL_MASK(31, 19) |
#define BRW_SURFACE_WIDTH_SHIFT 6 |
#define BRW_SURFACE_WIDTH_MASK INTEL_MASK(18, 6) |
#define BRW_SURFACE_LOD_SHIFT 2 |
#define BRW_SURFACE_LOD_MASK INTEL_MASK(5, 2) |
#define GEN7_SURFACE_HEIGHT_SHIFT 16 |
#define GEN7_SURFACE_HEIGHT_MASK INTEL_MASK(29, 16) |
#define GEN7_SURFACE_WIDTH_SHIFT 0 |
#define GEN7_SURFACE_WIDTH_MASK INTEL_MASK(13, 0) |
/* Surface state DW3 */ |
#define BRW_SURFACE_DEPTH_SHIFT 21 |
#define BRW_SURFACE_DEPTH_MASK INTEL_MASK(31, 21) |
#define BRW_SURFACE_PITCH_SHIFT 3 |
#define BRW_SURFACE_PITCH_MASK INTEL_MASK(19, 3) |
#define BRW_SURFACE_TILED (1 << 1) |
#define BRW_SURFACE_TILED_Y (1 << 0) |
/* Surface state DW4 */ |
#define BRW_SURFACE_MIN_LOD_SHIFT 28 |
#define BRW_SURFACE_MIN_LOD_MASK INTEL_MASK(31, 28) |
#define BRW_SURFACE_MULTISAMPLECOUNT_1 (0 << 4) |
#define BRW_SURFACE_MULTISAMPLECOUNT_4 (2 << 4) |
#define GEN7_SURFACE_MULTISAMPLECOUNT_1 (0 << 3) |
#define GEN7_SURFACE_MULTISAMPLECOUNT_4 (2 << 3) |
#define GEN7_SURFACE_MULTISAMPLECOUNT_8 (3 << 3) |
#define GEN7_SURFACE_MSFMT_MSS (0 << 6) |
#define GEN7_SURFACE_MSFMT_DEPTH_STENCIL (1 << 6) |
#define GEN7_SURFACE_MIN_ARRAY_ELEMENT_SHIFT 18 |
#define GEN7_SURFACE_RENDER_TARGET_VIEW_EXTENT_SHIFT 7 |
/* Surface state DW5 */ |
#define BRW_SURFACE_X_OFFSET_SHIFT 25 |
#define BRW_SURFACE_X_OFFSET_MASK INTEL_MASK(31, 25) |
#define BRW_SURFACE_VERTICAL_ALIGN_ENABLE (1 << 24) |
#define BRW_SURFACE_Y_OFFSET_SHIFT 20 |
#define BRW_SURFACE_Y_OFFSET_MASK INTEL_MASK(23, 20) |
#define GEN7_SURFACE_MIN_LOD_SHIFT 4 |
#define GEN7_SURFACE_MIN_LOD_MASK INTEL_MASK(7, 4) |
#define GEN7_SURFACE_MOCS_SHIFT 16 |
#define GEN7_SURFACE_MOCS_MASK INTEL_MASK(19, 16) |
/* Surface state DW6 */ |
#define GEN7_SURFACE_MCS_ENABLE (1 << 0) |
#define GEN7_SURFACE_MCS_PITCH_SHIFT 3 |
#define GEN7_SURFACE_MCS_PITCH_MASK INTEL_MASK(11, 3) |
/* Surface state DW7 */ |
#define GEN7_SURFACE_CLEAR_COLOR_SHIFT 28 |
#define GEN7_SURFACE_SCS_R_SHIFT 25 |
#define GEN7_SURFACE_SCS_R_MASK INTEL_MASK(27, 25) |
#define GEN7_SURFACE_SCS_G_SHIFT 22 |
#define GEN7_SURFACE_SCS_G_MASK INTEL_MASK(24, 22) |
#define GEN7_SURFACE_SCS_B_SHIFT 19 |
#define GEN7_SURFACE_SCS_B_MASK INTEL_MASK(21, 19) |
#define GEN7_SURFACE_SCS_A_SHIFT 16 |
#define GEN7_SURFACE_SCS_A_MASK INTEL_MASK(18, 16) |
/* The actual swizzle values/what channel to use */ |
#define HSW_SCS_ZERO 0 |
#define HSW_SCS_ONE 1 |
#define HSW_SCS_RED 4 |
#define HSW_SCS_GREEN 5 |
#define HSW_SCS_BLUE 6 |
#define HSW_SCS_ALPHA 7 |
#define BRW_TEXCOORDMODE_WRAP 0 |
#define BRW_TEXCOORDMODE_MIRROR 1 |
#define BRW_TEXCOORDMODE_CLAMP 2 |
#define BRW_TEXCOORDMODE_CUBE 3 |
#define BRW_TEXCOORDMODE_CLAMP_BORDER 4 |
#define BRW_TEXCOORDMODE_MIRROR_ONCE 5 |
#define BRW_THREAD_PRIORITY_NORMAL 0 |
#define BRW_THREAD_PRIORITY_HIGH 1 |
#define BRW_TILEWALK_XMAJOR 0 |
#define BRW_TILEWALK_YMAJOR 1 |
#define BRW_VERTEX_SUBPIXEL_PRECISION_8BITS 0 |
#define BRW_VERTEX_SUBPIXEL_PRECISION_4BITS 1 |
/* Execution Unit (EU) defines |
*/ |
#define BRW_ALIGN_1 0 |
#define BRW_ALIGN_16 1 |
#define BRW_ADDRESS_DIRECT 0 |
#define BRW_ADDRESS_REGISTER_INDIRECT_REGISTER 1 |
#define BRW_CHANNEL_X 0 |
#define BRW_CHANNEL_Y 1 |
#define BRW_CHANNEL_Z 2 |
#define BRW_CHANNEL_W 3 |
enum brw_compression { |
BRW_COMPRESSION_NONE = 0, |
BRW_COMPRESSION_2NDHALF = 1, |
BRW_COMPRESSION_COMPRESSED = 2, |
}; |
#define GEN6_COMPRESSION_1Q 0 |
#define GEN6_COMPRESSION_2Q 1 |
#define GEN6_COMPRESSION_3Q 2 |
#define GEN6_COMPRESSION_4Q 3 |
#define GEN6_COMPRESSION_1H 0 |
#define GEN6_COMPRESSION_2H 2 |
#define BRW_CONDITIONAL_NONE 0 |
#define BRW_CONDITIONAL_Z 1 |
#define BRW_CONDITIONAL_NZ 2 |
#define BRW_CONDITIONAL_EQ 1 /* Z */ |
#define BRW_CONDITIONAL_NEQ 2 /* NZ */ |
#define BRW_CONDITIONAL_G 3 |
#define BRW_CONDITIONAL_GE 4 |
#define BRW_CONDITIONAL_L 5 |
#define BRW_CONDITIONAL_LE 6 |
#define BRW_CONDITIONAL_R 7 |
#define BRW_CONDITIONAL_O 8 |
#define BRW_CONDITIONAL_U 9 |
#define BRW_DEBUG_NONE 0 |
#define BRW_DEBUG_BREAKPOINT 1 |
#define BRW_DEPENDENCY_NORMAL 0 |
#define BRW_DEPENDENCY_NOTCLEARED 1 |
#define BRW_DEPENDENCY_NOTCHECKED 2 |
#define BRW_DEPENDENCY_DISABLE 3 |
#define BRW_EXECUTE_1 0 |
#define BRW_EXECUTE_2 1 |
#define BRW_EXECUTE_4 2 |
#define BRW_EXECUTE_8 3 |
#define BRW_EXECUTE_16 4 |
#define BRW_EXECUTE_32 5 |
#define BRW_HORIZONTAL_STRIDE_0 0 |
#define BRW_HORIZONTAL_STRIDE_1 1 |
#define BRW_HORIZONTAL_STRIDE_2 2 |
#define BRW_HORIZONTAL_STRIDE_4 3 |
#define BRW_INSTRUCTION_NORMAL 0 |
#define BRW_INSTRUCTION_SATURATE 1 |
#define BRW_MASK_ENABLE 0 |
#define BRW_MASK_DISABLE 1 |
/** @{ |
* |
* Gen6 has replaced "mask enable/disable" with WECtrl, which is |
* effectively the same but much simpler to think about. Now, there |
* are two contributors ANDed together to whether channels are |
* executed: The predication on the instruction, and the channel write |
* enable. |
*/ |
/** |
* This is the default value. It means that a channel's write enable is set |
* if the per-channel IP is pointing at this instruction. |
*/ |
#define BRW_WE_NORMAL 0 |
/** |
* This is used like BRW_MASK_DISABLE, and causes all channels to have |
* their write enable set. Note that predication still contributes to |
* whether the channel actually gets written. |
*/ |
#define BRW_WE_ALL 1 |
/** @} */ |
enum opcode { |
/* These are the actual hardware opcodes. */ |
BRW_OPCODE_MOV = 1, |
BRW_OPCODE_SEL = 2, |
BRW_OPCODE_NOT = 4, |
BRW_OPCODE_AND = 5, |
BRW_OPCODE_OR = 6, |
BRW_OPCODE_XOR = 7, |
BRW_OPCODE_SHR = 8, |
BRW_OPCODE_SHL = 9, |
BRW_OPCODE_RSR = 10, |
BRW_OPCODE_RSL = 11, |
BRW_OPCODE_ASR = 12, |
BRW_OPCODE_CMP = 16, |
BRW_OPCODE_CMPN = 17, |
BRW_OPCODE_F32TO16 = 19, |
BRW_OPCODE_F16TO32 = 20, |
BRW_OPCODE_BFREV = 23, |
BRW_OPCODE_BFE = 24, |
BRW_OPCODE_BFI1 = 25, |
BRW_OPCODE_BFI2 = 26, |
BRW_OPCODE_JMPI = 32, |
BRW_OPCODE_IF = 34, |
BRW_OPCODE_IFF = 35, |
BRW_OPCODE_ELSE = 36, |
BRW_OPCODE_ENDIF = 37, |
BRW_OPCODE_DO = 38, |
BRW_OPCODE_WHILE = 39, |
BRW_OPCODE_BREAK = 40, |
BRW_OPCODE_CONTINUE = 41, |
BRW_OPCODE_HALT = 42, |
BRW_OPCODE_MSAVE = 44, |
BRW_OPCODE_MRESTORE = 45, |
BRW_OPCODE_PUSH = 46, |
BRW_OPCODE_POP = 47, |
BRW_OPCODE_WAIT = 48, |
BRW_OPCODE_SEND = 49, |
BRW_OPCODE_SENDC = 50, |
BRW_OPCODE_MATH = 56, |
BRW_OPCODE_ADD = 64, |
BRW_OPCODE_MUL = 65, |
BRW_OPCODE_AVG = 66, |
BRW_OPCODE_FRC = 67, |
BRW_OPCODE_RNDU = 68, |
BRW_OPCODE_RNDD = 69, |
BRW_OPCODE_RNDE = 70, |
BRW_OPCODE_RNDZ = 71, |
BRW_OPCODE_MAC = 72, |
BRW_OPCODE_MACH = 73, |
BRW_OPCODE_LZD = 74, |
BRW_OPCODE_FBH = 75, |
BRW_OPCODE_FBL = 76, |
BRW_OPCODE_CBIT = 77, |
BRW_OPCODE_SAD2 = 80, |
BRW_OPCODE_SADA2 = 81, |
BRW_OPCODE_DP4 = 84, |
BRW_OPCODE_DPH = 85, |
BRW_OPCODE_DP3 = 86, |
BRW_OPCODE_DP2 = 87, |
BRW_OPCODE_DPA2 = 88, |
BRW_OPCODE_LINE = 89, |
BRW_OPCODE_PLN = 90, |
BRW_OPCODE_MAD = 91, |
BRW_OPCODE_LRP = 92, |
BRW_OPCODE_NOP = 126, |
/* These are compiler backend opcodes that get translated into other |
* instructions. |
*/ |
FS_OPCODE_FB_WRITE = 128, |
SHADER_OPCODE_RCP, |
SHADER_OPCODE_RSQ, |
SHADER_OPCODE_SQRT, |
SHADER_OPCODE_EXP2, |
SHADER_OPCODE_LOG2, |
SHADER_OPCODE_POW, |
SHADER_OPCODE_INT_QUOTIENT, |
SHADER_OPCODE_INT_REMAINDER, |
SHADER_OPCODE_SIN, |
SHADER_OPCODE_COS, |
SHADER_OPCODE_TEX, |
SHADER_OPCODE_TXD, |
SHADER_OPCODE_TXF, |
SHADER_OPCODE_TXL, |
SHADER_OPCODE_TXS, |
FS_OPCODE_TXB, |
SHADER_OPCODE_TXF_MS, |
SHADER_OPCODE_LOD, |
SHADER_OPCODE_SHADER_TIME_ADD, |
FS_OPCODE_DDX, |
FS_OPCODE_DDY, |
FS_OPCODE_PIXEL_X, |
FS_OPCODE_PIXEL_Y, |
FS_OPCODE_CINTERP, |
FS_OPCODE_LINTERP, |
FS_OPCODE_SPILL, |
FS_OPCODE_UNSPILL, |
FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD, |
FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD_GEN7, |
FS_OPCODE_VARYING_PULL_CONSTANT_LOAD, |
FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7, |
FS_OPCODE_MOV_DISPATCH_TO_FLAGS, |
FS_OPCODE_DISCARD_JUMP, |
FS_OPCODE_SET_SIMD4X2_OFFSET, |
FS_OPCODE_PACK_HALF_2x16_SPLIT, |
FS_OPCODE_UNPACK_HALF_2x16_SPLIT_X, |
FS_OPCODE_UNPACK_HALF_2x16_SPLIT_Y, |
FS_OPCODE_PLACEHOLDER_HALT, |
VS_OPCODE_URB_WRITE, |
VS_OPCODE_SCRATCH_READ, |
VS_OPCODE_SCRATCH_WRITE, |
VS_OPCODE_PULL_CONSTANT_LOAD, |
VS_OPCODE_PULL_CONSTANT_LOAD_GEN7, |
}; |
#define BRW_PREDICATE_NONE 0 |
#define BRW_PREDICATE_NORMAL 1 |
#define BRW_PREDICATE_ALIGN1_ANYV 2 |
#define BRW_PREDICATE_ALIGN1_ALLV 3 |
#define BRW_PREDICATE_ALIGN1_ANY2H 4 |
#define BRW_PREDICATE_ALIGN1_ALL2H 5 |
#define BRW_PREDICATE_ALIGN1_ANY4H 6 |
#define BRW_PREDICATE_ALIGN1_ALL4H 7 |
#define BRW_PREDICATE_ALIGN1_ANY8H 8 |
#define BRW_PREDICATE_ALIGN1_ALL8H 9 |
#define BRW_PREDICATE_ALIGN1_ANY16H 10 |
#define BRW_PREDICATE_ALIGN1_ALL16H 11 |
#define BRW_PREDICATE_ALIGN16_REPLICATE_X 2 |
#define BRW_PREDICATE_ALIGN16_REPLICATE_Y 3 |
#define BRW_PREDICATE_ALIGN16_REPLICATE_Z 4 |
#define BRW_PREDICATE_ALIGN16_REPLICATE_W 5 |
#define BRW_PREDICATE_ALIGN16_ANY4H 6 |
#define BRW_PREDICATE_ALIGN16_ALL4H 7 |
#define BRW_ARCHITECTURE_REGISTER_FILE 0 |
#define BRW_GENERAL_REGISTER_FILE 1 |
#define BRW_MESSAGE_REGISTER_FILE 2 |
#define BRW_IMMEDIATE_VALUE 3 |
#define BRW_REGISTER_TYPE_UD 0 |
#define BRW_REGISTER_TYPE_D 1 |
#define BRW_REGISTER_TYPE_UW 2 |
#define BRW_REGISTER_TYPE_W 3 |
#define BRW_REGISTER_TYPE_UB 4 |
#define BRW_REGISTER_TYPE_B 5 |
#define BRW_REGISTER_TYPE_VF 5 /* packed float vector, immediates only? */ |
#define BRW_REGISTER_TYPE_HF 6 |
#define BRW_REGISTER_TYPE_V 6 /* packed int vector, immediates only, uword dest only */ |
#define BRW_REGISTER_TYPE_F 7 |
/* SNB adds 3-src instructions (MAD and LRP) that only operate on floats, so |
* the types were implied. IVB adds BFE and BFI2 that operate on doublewords |
* and unsigned doublewords, so a new field is also available in the da3src |
* struct (part of struct brw_instruction.bits1 in brw_structs.h) to select |
* dst and shared-src types. The values are different from BRW_REGISTER_TYPE_*. |
*/ |
#define BRW_3SRC_TYPE_F 0 |
#define BRW_3SRC_TYPE_D 1 |
#define BRW_3SRC_TYPE_UD 2 |
#define BRW_3SRC_TYPE_DF 3 |
#define BRW_ARF_NULL 0x00 |
#define BRW_ARF_ADDRESS 0x10 |
#define BRW_ARF_ACCUMULATOR 0x20 |
#define BRW_ARF_FLAG 0x30 |
#define BRW_ARF_MASK 0x40 |
#define BRW_ARF_MASK_STACK 0x50 |
#define BRW_ARF_MASK_STACK_DEPTH 0x60 |
#define BRW_ARF_STATE 0x70 |
#define BRW_ARF_CONTROL 0x80 |
#define BRW_ARF_NOTIFICATION_COUNT 0x90 |
#define BRW_ARF_IP 0xA0 |
#define BRW_ARF_TDR 0xB0 |
#define BRW_ARF_TIMESTAMP 0xC0 |
#define BRW_MRF_COMPR4 (1 << 7) |
#define BRW_AMASK 0 |
#define BRW_IMASK 1 |
#define BRW_LMASK 2 |
#define BRW_CMASK 3 |
#define BRW_THREAD_NORMAL 0 |
#define BRW_THREAD_ATOMIC 1 |
#define BRW_THREAD_SWITCH 2 |
#define BRW_VERTICAL_STRIDE_0 0 |
#define BRW_VERTICAL_STRIDE_1 1 |
#define BRW_VERTICAL_STRIDE_2 2 |
#define BRW_VERTICAL_STRIDE_4 3 |
#define BRW_VERTICAL_STRIDE_8 4 |
#define BRW_VERTICAL_STRIDE_16 5 |
#define BRW_VERTICAL_STRIDE_32 6 |
#define BRW_VERTICAL_STRIDE_64 7 |
#define BRW_VERTICAL_STRIDE_128 8 |
#define BRW_VERTICAL_STRIDE_256 9 |
#define BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL 0xF |
#define BRW_WIDTH_1 0 |
#define BRW_WIDTH_2 1 |
#define BRW_WIDTH_4 2 |
#define BRW_WIDTH_8 3 |
#define BRW_WIDTH_16 4 |
#define BRW_STATELESS_BUFFER_BOUNDARY_1K 0 |
#define BRW_STATELESS_BUFFER_BOUNDARY_2K 1 |
#define BRW_STATELESS_BUFFER_BOUNDARY_4K 2 |
#define BRW_STATELESS_BUFFER_BOUNDARY_8K 3 |
#define BRW_STATELESS_BUFFER_BOUNDARY_16K 4 |
#define BRW_STATELESS_BUFFER_BOUNDARY_32K 5 |
#define BRW_STATELESS_BUFFER_BOUNDARY_64K 6 |
#define BRW_STATELESS_BUFFER_BOUNDARY_128K 7 |
#define BRW_STATELESS_BUFFER_BOUNDARY_256K 8 |
#define BRW_STATELESS_BUFFER_BOUNDARY_512K 9 |
#define BRW_STATELESS_BUFFER_BOUNDARY_1M 10 |
#define BRW_STATELESS_BUFFER_BOUNDARY_2M 11 |
#define BRW_POLYGON_FACING_FRONT 0 |
#define BRW_POLYGON_FACING_BACK 1 |
/** |
* Message target: Shared Function ID for where to SEND a message. |
* |
* These are enumerated in the ISA reference under "send - Send Message". |
* In particular, see the following tables: |
* - G45 PRM, Volume 4, Table 14-15 "Message Descriptor Definition" |
* - Sandybridge PRM, Volume 4 Part 2, Table 8-16 "Extended Message Descriptor" |
* - Ivybridge PRM, Volume 1 Part 1, section 3.2.7 "GPE Function IDs" |
*/ |
enum brw_message_target { |
BRW_SFID_NULL = 0, |
BRW_SFID_MATH = 1, /* Only valid on Gen4-5 */ |
BRW_SFID_SAMPLER = 2, |
BRW_SFID_MESSAGE_GATEWAY = 3, |
BRW_SFID_DATAPORT_READ = 4, |
BRW_SFID_DATAPORT_WRITE = 5, |
BRW_SFID_URB = 6, |
BRW_SFID_THREAD_SPAWNER = 7, |
GEN6_SFID_DATAPORT_SAMPLER_CACHE = 4, |
GEN6_SFID_DATAPORT_RENDER_CACHE = 5, |
GEN6_SFID_DATAPORT_CONSTANT_CACHE = 9, |
GEN7_SFID_DATAPORT_DATA_CACHE = 10, |
HSW_SFID_DATAPORT_DATA_CACHE_1 = 12, |
}; |
#define GEN7_MESSAGE_TARGET_DP_DATA_CACHE 10 |
#define BRW_SAMPLER_RETURN_FORMAT_FLOAT32 0 |
#define BRW_SAMPLER_RETURN_FORMAT_UINT32 2 |
#define BRW_SAMPLER_RETURN_FORMAT_SINT32 3 |
#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE 0 |
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE 0 |
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS 0 |
#define BRW_SAMPLER_MESSAGE_SIMD8_KILLPIX 1 |
#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD 1 |
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD 1 |
#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_GRADIENTS 2 |
#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_GRADIENTS 2 |
#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_COMPARE 0 |
#define BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_COMPARE 2 |
#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_BIAS_COMPARE 0 |
#define BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD_COMPARE 1 |
#define BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_LOD_COMPARE 1 |
#define BRW_SAMPLER_MESSAGE_SIMD4X2_RESINFO 2 |
#define BRW_SAMPLER_MESSAGE_SIMD16_RESINFO 2 |
#define BRW_SAMPLER_MESSAGE_SIMD4X2_LD 3 |
#define BRW_SAMPLER_MESSAGE_SIMD8_LD 3 |
#define BRW_SAMPLER_MESSAGE_SIMD16_LD 3 |
#define GEN5_SAMPLER_MESSAGE_SAMPLE 0 |
#define GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS 1 |
#define GEN5_SAMPLER_MESSAGE_SAMPLE_LOD 2 |
#define GEN5_SAMPLER_MESSAGE_SAMPLE_COMPARE 3 |
#define GEN5_SAMPLER_MESSAGE_SAMPLE_DERIVS 4 |
#define GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS_COMPARE 5 |
#define GEN5_SAMPLER_MESSAGE_SAMPLE_LOD_COMPARE 6 |
#define GEN5_SAMPLER_MESSAGE_SAMPLE_LD 7 |
#define GEN5_SAMPLER_MESSAGE_LOD 9 |
#define GEN5_SAMPLER_MESSAGE_SAMPLE_RESINFO 10 |
#define HSW_SAMPLER_MESSAGE_SAMPLE_DERIV_COMPARE 20 |
#define GEN7_SAMPLER_MESSAGE_SAMPLE_LD_MCS 29 |
#define GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DMS 30 |
#define GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DSS 31 |
/* for GEN5 only */ |
#define BRW_SAMPLER_SIMD_MODE_SIMD4X2 0 |
#define BRW_SAMPLER_SIMD_MODE_SIMD8 1 |
#define BRW_SAMPLER_SIMD_MODE_SIMD16 2 |
#define BRW_SAMPLER_SIMD_MODE_SIMD32_64 3 |
#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDLOW 0 |
#define BRW_DATAPORT_OWORD_BLOCK_1_OWORDHIGH 1 |
#define BRW_DATAPORT_OWORD_BLOCK_2_OWORDS 2 |
#define BRW_DATAPORT_OWORD_BLOCK_4_OWORDS 3 |
#define BRW_DATAPORT_OWORD_BLOCK_8_OWORDS 4 |
#define BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD 0 |
#define BRW_DATAPORT_OWORD_DUAL_BLOCK_4OWORDS 2 |
#define BRW_DATAPORT_DWORD_SCATTERED_BLOCK_8DWORDS 2 |
#define BRW_DATAPORT_DWORD_SCATTERED_BLOCK_16DWORDS 3 |
/* This one stays the same across generations. */ |
#define BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ 0 |
/* GEN4 */ |
#define BRW_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ 1 |
#define BRW_DATAPORT_READ_MESSAGE_MEDIA_BLOCK_READ 2 |
#define BRW_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ 3 |
/* G45, GEN5 */ |
#define G45_DATAPORT_READ_MESSAGE_RENDER_UNORM_READ 1 |
#define G45_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ 2 |
#define G45_DATAPORT_READ_MESSAGE_AVC_LOOP_FILTER_READ 3 |
#define G45_DATAPORT_READ_MESSAGE_MEDIA_BLOCK_READ 4 |
#define G45_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ 6 |
/* GEN6 */ |
#define GEN6_DATAPORT_READ_MESSAGE_RENDER_UNORM_READ 1 |
#define GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ 2 |
#define GEN6_DATAPORT_READ_MESSAGE_MEDIA_BLOCK_READ 4 |
#define GEN6_DATAPORT_READ_MESSAGE_OWORD_UNALIGN_BLOCK_READ 5 |
#define GEN6_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ 6 |
#define BRW_DATAPORT_READ_TARGET_DATA_CACHE 0 |
#define BRW_DATAPORT_READ_TARGET_RENDER_CACHE 1 |
#define BRW_DATAPORT_READ_TARGET_SAMPLER_CACHE 2 |
#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE 0 |
#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE_REPLICATED 1 |
#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01 2 |
#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN23 3 |
#define BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01 4 |
#define BRW_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE 0 |
#define BRW_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE 1 |
#define BRW_DATAPORT_WRITE_MESSAGE_MEDIA_BLOCK_WRITE 2 |
#define BRW_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE 3 |
#define BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE 4 |
#define BRW_DATAPORT_WRITE_MESSAGE_STREAMED_VERTEX_BUFFER_WRITE 5 |
#define BRW_DATAPORT_WRITE_MESSAGE_FLUSH_RENDER_CACHE 7 |
/* GEN6 */ |
#define GEN6_DATAPORT_WRITE_MESSAGE_DWORD_ATOMIC_WRITE 7 |
#define GEN6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE 8 |
#define GEN6_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE 9 |
#define GEN6_DATAPORT_WRITE_MESSAGE_MEDIA_BLOCK_WRITE 10 |
#define GEN6_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE 11 |
#define GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE 12 |
#define GEN6_DATAPORT_WRITE_MESSAGE_STREAMED_VB_WRITE 13 |
#define GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_UNORM_WRITE 14 |
/* GEN7 */ |
#define GEN7_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE 10 |
#define GEN7_DATAPORT_DC_OWORD_BLOCK_READ 0 |
#define GEN7_DATAPORT_DC_UNALIGNED_OWORD_BLOCK_READ 1 |
#define GEN7_DATAPORT_DC_OWORD_DUAL_BLOCK_READ 2 |
#define GEN7_DATAPORT_DC_DWORD_SCATTERED_READ 3 |
#define GEN7_DATAPORT_DC_BYTE_SCATTERED_READ 4 |
#define GEN7_DATAPORT_DC_UNTYPED_SURFACE_READ 5 |
#define GEN7_DATAPORT_DC_UNTYPED_ATOMIC_OP 6 |
#define GEN7_DATAPORT_DC_MEMORY_FENCE 7 |
#define GEN7_DATAPORT_DC_OWORD_BLOCK_WRITE 8 |
#define GEN7_DATAPORT_DC_OWORD_DUAL_BLOCK_WRITE 10 |
#define GEN7_DATAPORT_DC_DWORD_SCATTERED_WRITE 11 |
#define GEN7_DATAPORT_DC_BYTE_SCATTERED_WRITE 12 |
#define GEN7_DATAPORT_DC_UNTYPED_SURFACE_WRITE 13 |
/* HSW */ |
#define HSW_DATAPORT_DC_PORT0_OWORD_BLOCK_READ 0 |
#define HSW_DATAPORT_DC_PORT0_UNALIGNED_OWORD_BLOCK_READ 1 |
#define HSW_DATAPORT_DC_PORT0_OWORD_DUAL_BLOCK_READ 2 |
#define HSW_DATAPORT_DC_PORT0_DWORD_SCATTERED_READ 3 |
#define HSW_DATAPORT_DC_PORT0_BYTE_SCATTERED_READ 4 |
#define HSW_DATAPORT_DC_PORT0_MEMORY_FENCE 7 |
#define HSW_DATAPORT_DC_PORT0_OWORD_BLOCK_WRITE 8 |
#define HSW_DATAPORT_DC_PORT0_OWORD_DUAL_BLOCK_WRITE 10 |
#define HSW_DATAPORT_DC_PORT0_DWORD_SCATTERED_WRITE 11 |
#define HSW_DATAPORT_DC_PORT0_BYTE_SCATTERED_WRITE 12 |
#define HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_READ 1 |
#define HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP 2 |
#define HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP_SIMD4X2 3 |
#define HSW_DATAPORT_DC_PORT1_MEDIA_BLOCK_READ 4 |
#define HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_READ 5 |
#define HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP 6 |
#define HSW_DATAPORT_DC_PORT1_TYPED_ATOMIC_OP_SIMD4X2 7 |
#define HSW_DATAPORT_DC_PORT1_UNTYPED_SURFACE_WRITE 9 |
#define HSW_DATAPORT_DC_PORT1_MEDIA_BLOCK_WRITE 10 |
#define HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP 11 |
#define HSW_DATAPORT_DC_PORT1_ATOMIC_COUNTER_OP_SIMD4X2 12 |
#define HSW_DATAPORT_DC_PORT1_TYPED_SURFACE_WRITE 13 |
/* dataport atomic operations. */ |
#define BRW_AOP_AND 1 |
#define BRW_AOP_OR 2 |
#define BRW_AOP_XOR 3 |
#define BRW_AOP_MOV 4 |
#define BRW_AOP_INC 5 |
#define BRW_AOP_DEC 6 |
#define BRW_AOP_ADD 7 |
#define BRW_AOP_SUB 8 |
#define BRW_AOP_REVSUB 9 |
#define BRW_AOP_IMAX 10 |
#define BRW_AOP_IMIN 11 |
#define BRW_AOP_UMAX 12 |
#define BRW_AOP_UMIN 13 |
#define BRW_AOP_CMPWR 14 |
#define BRW_AOP_PREDEC 15 |
#define BRW_MATH_FUNCTION_INV 1 |
#define BRW_MATH_FUNCTION_LOG 2 |
#define BRW_MATH_FUNCTION_EXP 3 |
#define BRW_MATH_FUNCTION_SQRT 4 |
#define BRW_MATH_FUNCTION_RSQ 5 |
#define BRW_MATH_FUNCTION_SIN 6 |
#define BRW_MATH_FUNCTION_COS 7 |
#define BRW_MATH_FUNCTION_SINCOS 8 /* gen4, gen5 */ |
#define BRW_MATH_FUNCTION_FDIV 9 /* gen6+ */ |
#define BRW_MATH_FUNCTION_POW 10 |
#define BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER 11 |
#define BRW_MATH_FUNCTION_INT_DIV_QUOTIENT 12 |
#define BRW_MATH_FUNCTION_INT_DIV_REMAINDER 13 |
#define BRW_MATH_INTEGER_UNSIGNED 0 |
#define BRW_MATH_INTEGER_SIGNED 1 |
#define BRW_MATH_PRECISION_FULL 0 |
#define BRW_MATH_PRECISION_PARTIAL 1 |
#define BRW_MATH_SATURATE_NONE 0 |
#define BRW_MATH_SATURATE_SATURATE 1 |
#define BRW_MATH_DATA_VECTOR 0 |
#define BRW_MATH_DATA_SCALAR 1 |
#define BRW_URB_OPCODE_WRITE 0 |
#define BRW_URB_SWIZZLE_NONE 0 |
#define BRW_URB_SWIZZLE_INTERLEAVE 1 |
#define BRW_URB_SWIZZLE_TRANSPOSE 2 |
#define BRW_SCRATCH_SPACE_SIZE_1K 0 |
#define BRW_SCRATCH_SPACE_SIZE_2K 1 |
#define BRW_SCRATCH_SPACE_SIZE_4K 2 |
#define BRW_SCRATCH_SPACE_SIZE_8K 3 |
#define BRW_SCRATCH_SPACE_SIZE_16K 4 |
#define BRW_SCRATCH_SPACE_SIZE_32K 5 |
#define BRW_SCRATCH_SPACE_SIZE_64K 6 |
#define BRW_SCRATCH_SPACE_SIZE_128K 7 |
#define BRW_SCRATCH_SPACE_SIZE_256K 8 |
#define BRW_SCRATCH_SPACE_SIZE_512K 9 |
#define BRW_SCRATCH_SPACE_SIZE_1M 10 |
#define BRW_SCRATCH_SPACE_SIZE_2M 11 |
#define CMD_URB_FENCE 0x6000 |
#define CMD_CS_URB_STATE 0x6001 |
#define CMD_CONST_BUFFER 0x6002 |
#define CMD_STATE_BASE_ADDRESS 0x6101 |
#define CMD_STATE_SIP 0x6102 |
#define CMD_PIPELINE_SELECT_965 0x6104 |
#define CMD_PIPELINE_SELECT_GM45 0x6904 |
#define _3DSTATE_PIPELINED_POINTERS 0x7800 |
#define _3DSTATE_BINDING_TABLE_POINTERS 0x7801 |
# define GEN6_BINDING_TABLE_MODIFY_VS (1 << 8) |
# define GEN6_BINDING_TABLE_MODIFY_GS (1 << 9) |
# define GEN6_BINDING_TABLE_MODIFY_PS (1 << 12) |
#define _3DSTATE_BINDING_TABLE_POINTERS_VS 0x7826 /* GEN7+ */ |
#define _3DSTATE_BINDING_TABLE_POINTERS_HS 0x7827 /* GEN7+ */ |
#define _3DSTATE_BINDING_TABLE_POINTERS_DS 0x7828 /* GEN7+ */ |
#define _3DSTATE_BINDING_TABLE_POINTERS_GS 0x7829 /* GEN7+ */ |
#define _3DSTATE_BINDING_TABLE_POINTERS_PS 0x782A /* GEN7+ */ |
#define _3DSTATE_SAMPLER_STATE_POINTERS 0x7802 /* GEN6+ */ |
# define PS_SAMPLER_STATE_CHANGE (1 << 12) |
# define GS_SAMPLER_STATE_CHANGE (1 << 9) |
# define VS_SAMPLER_STATE_CHANGE (1 << 8) |
/* DW1: VS */ |
/* DW2: GS */ |
/* DW3: PS */ |
#define _3DSTATE_SAMPLER_STATE_POINTERS_VS 0x782B /* GEN7+ */ |
#define _3DSTATE_SAMPLER_STATE_POINTERS_GS 0x782E /* GEN7+ */ |
#define _3DSTATE_SAMPLER_STATE_POINTERS_PS 0x782F /* GEN7+ */ |
#define _3DSTATE_VERTEX_BUFFERS 0x7808 |
# define BRW_VB0_INDEX_SHIFT 27 |
# define GEN6_VB0_INDEX_SHIFT 26 |
# define BRW_VB0_ACCESS_VERTEXDATA (0 << 26) |
# define BRW_VB0_ACCESS_INSTANCEDATA (1 << 26) |
# define GEN6_VB0_ACCESS_VERTEXDATA (0 << 20) |
# define GEN6_VB0_ACCESS_INSTANCEDATA (1 << 20) |
# define GEN7_VB0_ADDRESS_MODIFYENABLE (1 << 14) |
# define BRW_VB0_PITCH_SHIFT 0 |
#define _3DSTATE_VERTEX_ELEMENTS 0x7809 |
# define BRW_VE0_INDEX_SHIFT 27 |
# define GEN6_VE0_INDEX_SHIFT 26 |
# define BRW_VE0_FORMAT_SHIFT 16 |
# define BRW_VE0_VALID (1 << 26) |
# define GEN6_VE0_VALID (1 << 25) |
# define GEN6_VE0_EDGE_FLAG_ENABLE (1 << 15) |
# define BRW_VE0_SRC_OFFSET_SHIFT 0 |
# define BRW_VE1_COMPONENT_NOSTORE 0 |
# define BRW_VE1_COMPONENT_STORE_SRC 1 |
# define BRW_VE1_COMPONENT_STORE_0 2 |
# define BRW_VE1_COMPONENT_STORE_1_FLT 3 |
# define BRW_VE1_COMPONENT_STORE_1_INT 4 |
# define BRW_VE1_COMPONENT_STORE_VID 5 |
# define BRW_VE1_COMPONENT_STORE_IID 6 |
# define BRW_VE1_COMPONENT_STORE_PID 7 |
# define BRW_VE1_COMPONENT_0_SHIFT 28 |
# define BRW_VE1_COMPONENT_1_SHIFT 24 |
# define BRW_VE1_COMPONENT_2_SHIFT 20 |
# define BRW_VE1_COMPONENT_3_SHIFT 16 |
# define BRW_VE1_DST_OFFSET_SHIFT 0 |
#define CMD_INDEX_BUFFER 0x780a |
#define GEN4_3DSTATE_VF_STATISTICS 0x780b |
#define GM45_3DSTATE_VF_STATISTICS 0x680b |
#define _3DSTATE_CC_STATE_POINTERS 0x780e /* GEN6+ */ |
#define _3DSTATE_BLEND_STATE_POINTERS 0x7824 /* GEN7+ */ |
#define _3DSTATE_DEPTH_STENCIL_STATE_POINTERS 0x7825 /* GEN7+ */ |
#define _3DSTATE_URB 0x7805 /* GEN6 */ |
# define GEN6_URB_VS_SIZE_SHIFT 16 |
# define GEN6_URB_VS_ENTRIES_SHIFT 0 |
# define GEN6_URB_GS_ENTRIES_SHIFT 8 |
# define GEN6_URB_GS_SIZE_SHIFT 0 |
#define _3DSTATE_VF 0x780c /* GEN7.5+ */ |
#define HSW_CUT_INDEX_ENABLE (1 << 8) |
#define _3DSTATE_URB_VS 0x7830 /* GEN7+ */ |
#define _3DSTATE_URB_HS 0x7831 /* GEN7+ */ |
#define _3DSTATE_URB_DS 0x7832 /* GEN7+ */ |
#define _3DSTATE_URB_GS 0x7833 /* GEN7+ */ |
# define GEN7_URB_ENTRY_SIZE_SHIFT 16 |
# define GEN7_URB_STARTING_ADDRESS_SHIFT 25 |
#define _3DSTATE_PUSH_CONSTANT_ALLOC_VS 0x7912 /* GEN7+ */ |
#define _3DSTATE_PUSH_CONSTANT_ALLOC_PS 0x7916 /* GEN7+ */ |
# define GEN7_PUSH_CONSTANT_BUFFER_OFFSET_SHIFT 16 |
#define _3DSTATE_VIEWPORT_STATE_POINTERS 0x780d /* GEN6+ */ |
# define GEN6_CC_VIEWPORT_MODIFY (1 << 12) |
# define GEN6_SF_VIEWPORT_MODIFY (1 << 11) |
# define GEN6_CLIP_VIEWPORT_MODIFY (1 << 10) |
#define _3DSTATE_VIEWPORT_STATE_POINTERS_CC 0x7823 /* GEN7+ */ |
#define _3DSTATE_VIEWPORT_STATE_POINTERS_SF_CL 0x7821 /* GEN7+ */ |
#define _3DSTATE_SCISSOR_STATE_POINTERS 0x780f /* GEN6+ */ |
#define _3DSTATE_VS 0x7810 /* GEN6+ */ |
/* DW2 */ |
# define GEN6_VS_SPF_MODE (1 << 31) |
# define GEN6_VS_VECTOR_MASK_ENABLE (1 << 30) |
# define GEN6_VS_SAMPLER_COUNT_SHIFT 27 |
# define GEN6_VS_BINDING_TABLE_ENTRY_COUNT_SHIFT 18 |
# define GEN6_VS_FLOATING_POINT_MODE_IEEE_754 (0 << 16) |
# define GEN6_VS_FLOATING_POINT_MODE_ALT (1 << 16) |
/* DW4 */ |
# define GEN6_VS_DISPATCH_START_GRF_SHIFT 20 |
# define GEN6_VS_URB_READ_LENGTH_SHIFT 11 |
# define GEN6_VS_URB_ENTRY_READ_OFFSET_SHIFT 4 |
/* DW5 */ |
# define GEN6_VS_MAX_THREADS_SHIFT 25 |
# define HSW_VS_MAX_THREADS_SHIFT 23 |
# define GEN6_VS_STATISTICS_ENABLE (1 << 10) |
# define GEN6_VS_CACHE_DISABLE (1 << 1) |
# define GEN6_VS_ENABLE (1 << 0) |
#define _3DSTATE_GS 0x7811 /* GEN6+ */ |
/* DW2 */ |
# define GEN6_GS_SPF_MODE (1 << 31) |
# define GEN6_GS_VECTOR_MASK_ENABLE (1 << 30) |
# define GEN6_GS_SAMPLER_COUNT_SHIFT 27 |
# define GEN6_GS_BINDING_TABLE_ENTRY_COUNT_SHIFT 18 |
# define GEN6_GS_FLOATING_POINT_MODE_IEEE_754 (0 << 16) |
# define GEN6_GS_FLOATING_POINT_MODE_ALT (1 << 16) |
/* DW4 */ |
# define GEN6_GS_URB_READ_LENGTH_SHIFT 11 |
# define GEN7_GS_INCLUDE_VERTEX_HANDLES (1 << 10) |
# define GEN6_GS_URB_ENTRY_READ_OFFSET_SHIFT 4 |
# define GEN6_GS_DISPATCH_START_GRF_SHIFT 0 |
/* DW5 */ |
# define GEN6_GS_MAX_THREADS_SHIFT 25 |
# define GEN6_GS_STATISTICS_ENABLE (1 << 10) |
# define GEN6_GS_SO_STATISTICS_ENABLE (1 << 9) |
# define GEN6_GS_RENDERING_ENABLE (1 << 8) |
# define GEN7_GS_ENABLE (1 << 0) |
/* DW6 */ |
# define GEN6_GS_REORDER (1 << 30) |
# define GEN6_GS_DISCARD_ADJACENCY (1 << 29) |
# define GEN6_GS_SVBI_PAYLOAD_ENABLE (1 << 28) |
# define GEN6_GS_SVBI_POSTINCREMENT_ENABLE (1 << 27) |
# define GEN6_GS_SVBI_POSTINCREMENT_VALUE_SHIFT 16 |
# define GEN6_GS_SVBI_POSTINCREMENT_VALUE_MASK INTEL_MASK(25, 16) |
# define GEN6_GS_ENABLE (1 << 15) |
# define BRW_GS_EDGE_INDICATOR_0 (1 << 8) |
# define BRW_GS_EDGE_INDICATOR_1 (1 << 9) |
#define _3DSTATE_HS 0x781B /* GEN7+ */ |
#define _3DSTATE_TE 0x781C /* GEN7+ */ |
#define _3DSTATE_DS 0x781D /* GEN7+ */ |
#define _3DSTATE_CLIP 0x7812 /* GEN6+ */ |
/* DW1 */ |
# define GEN7_CLIP_WINDING_CW (0 << 20) |
# define GEN7_CLIP_WINDING_CCW (1 << 20) |
# define GEN7_CLIP_VERTEX_SUBPIXEL_PRECISION_8 (0 << 19) |
# define GEN7_CLIP_VERTEX_SUBPIXEL_PRECISION_4 (1 << 19) |
# define GEN7_CLIP_EARLY_CULL (1 << 18) |
# define GEN7_CLIP_CULLMODE_BOTH (0 << 16) |
# define GEN7_CLIP_CULLMODE_NONE (1 << 16) |
# define GEN7_CLIP_CULLMODE_FRONT (2 << 16) |
# define GEN7_CLIP_CULLMODE_BACK (3 << 16) |
# define GEN6_CLIP_STATISTICS_ENABLE (1 << 10) |
/** |
* Just does cheap culling based on the clip distance. Bits must be |
* disjoint with USER_CLIP_CLIP_DISTANCE bits. |
*/ |
# define GEN6_USER_CLIP_CULL_DISTANCES_SHIFT 0 |
/* DW2 */ |
# define GEN6_CLIP_ENABLE (1 << 31) |
# define GEN6_CLIP_API_OGL (0 << 30) |
# define GEN6_CLIP_API_D3D (1 << 30) |
# define GEN6_CLIP_XY_TEST (1 << 28) |
# define GEN6_CLIP_Z_TEST (1 << 27) |
# define GEN6_CLIP_GB_TEST (1 << 26) |
/** 8-bit field of which user clip distances to clip aganist. */ |
# define GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT 16 |
# define GEN6_CLIP_MODE_NORMAL (0 << 13) |
# define GEN6_CLIP_MODE_REJECT_ALL (3 << 13) |
# define GEN6_CLIP_MODE_ACCEPT_ALL (4 << 13) |
# define GEN6_CLIP_PERSPECTIVE_DIVIDE_DISABLE (1 << 9) |
# define GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE (1 << 8) |
# define GEN6_CLIP_TRI_PROVOKE_SHIFT 4 |
# define GEN6_CLIP_LINE_PROVOKE_SHIFT 2 |
# define GEN6_CLIP_TRIFAN_PROVOKE_SHIFT 0 |
/* DW3 */ |
# define GEN6_CLIP_MIN_POINT_WIDTH_SHIFT 17 |
# define GEN6_CLIP_MAX_POINT_WIDTH_SHIFT 6 |
# define GEN6_CLIP_FORCE_ZERO_RTAINDEX (1 << 5) |
#define _3DSTATE_SF 0x7813 /* GEN6+ */ |
/* DW1 (for gen6) */ |
# define GEN6_SF_NUM_OUTPUTS_SHIFT 22 |
# define GEN6_SF_SWIZZLE_ENABLE (1 << 21) |
# define GEN6_SF_POINT_SPRITE_UPPERLEFT (0 << 20) |
# define GEN6_SF_POINT_SPRITE_LOWERLEFT (1 << 20) |
# define GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT 11 |
# define GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT 4 |
/* DW2 */ |
# define GEN6_SF_LEGACY_GLOBAL_DEPTH_BIAS (1 << 11) |
# define GEN6_SF_STATISTICS_ENABLE (1 << 10) |
# define GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID (1 << 9) |
# define GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME (1 << 8) |
# define GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT (1 << 7) |
# define GEN6_SF_FRONT_SOLID (0 << 5) |
# define GEN6_SF_FRONT_WIREFRAME (1 << 5) |
# define GEN6_SF_FRONT_POINT (2 << 5) |
# define GEN6_SF_BACK_SOLID (0 << 3) |
# define GEN6_SF_BACK_WIREFRAME (1 << 3) |
# define GEN6_SF_BACK_POINT (2 << 3) |
# define GEN6_SF_VIEWPORT_TRANSFORM_ENABLE (1 << 1) |
# define GEN6_SF_WINDING_CCW (1 << 0) |
/* DW3 */ |
# define GEN6_SF_LINE_AA_ENABLE (1 << 31) |
# define GEN6_SF_CULL_BOTH (0 << 29) |
# define GEN6_SF_CULL_NONE (1 << 29) |
# define GEN6_SF_CULL_FRONT (2 << 29) |
# define GEN6_SF_CULL_BACK (3 << 29) |
# define GEN6_SF_LINE_WIDTH_SHIFT 18 /* U3.7 */ |
# define GEN6_SF_LINE_END_CAP_WIDTH_0_5 (0 << 16) |
# define GEN6_SF_LINE_END_CAP_WIDTH_1_0 (1 << 16) |
# define GEN6_SF_LINE_END_CAP_WIDTH_2_0 (2 << 16) |
# define GEN6_SF_LINE_END_CAP_WIDTH_4_0 (3 << 16) |
# define GEN6_SF_SCISSOR_ENABLE (1 << 11) |
# define GEN6_SF_MSRAST_OFF_PIXEL (0 << 8) |
# define GEN6_SF_MSRAST_OFF_PATTERN (1 << 8) |
# define GEN6_SF_MSRAST_ON_PIXEL (2 << 8) |
# define GEN6_SF_MSRAST_ON_PATTERN (3 << 8) |
/* DW4 */ |
# define GEN6_SF_TRI_PROVOKE_SHIFT 29 |
# define GEN6_SF_LINE_PROVOKE_SHIFT 27 |
# define GEN6_SF_TRIFAN_PROVOKE_SHIFT 25 |
# define GEN6_SF_LINE_AA_MODE_MANHATTAN (0 << 14) |
# define GEN6_SF_LINE_AA_MODE_TRUE (1 << 14) |
# define GEN6_SF_VERTEX_SUBPIXEL_8BITS (0 << 12) |
# define GEN6_SF_VERTEX_SUBPIXEL_4BITS (1 << 12) |
# define GEN6_SF_USE_STATE_POINT_WIDTH (1 << 11) |
# define GEN6_SF_POINT_WIDTH_SHIFT 0 /* U8.3 */ |
/* DW5: depth offset constant */ |
/* DW6: depth offset scale */ |
/* DW7: depth offset clamp */ |
/* DW8 */ |
# define ATTRIBUTE_1_OVERRIDE_W (1 << 31) |
# define ATTRIBUTE_1_OVERRIDE_Z (1 << 30) |
# define ATTRIBUTE_1_OVERRIDE_Y (1 << 29) |
# define ATTRIBUTE_1_OVERRIDE_X (1 << 28) |
# define ATTRIBUTE_1_CONST_SOURCE_SHIFT 25 |
# define ATTRIBUTE_1_SWIZZLE_SHIFT 22 |
# define ATTRIBUTE_1_SOURCE_SHIFT 16 |
# define ATTRIBUTE_0_OVERRIDE_W (1 << 15) |
# define ATTRIBUTE_0_OVERRIDE_Z (1 << 14) |
# define ATTRIBUTE_0_OVERRIDE_Y (1 << 13) |
# define ATTRIBUTE_0_OVERRIDE_X (1 << 12) |
# define ATTRIBUTE_0_CONST_SOURCE_SHIFT 9 |
# define ATTRIBUTE_0_SWIZZLE_SHIFT 6 |
# define ATTRIBUTE_0_SOURCE_SHIFT 0 |
# define ATTRIBUTE_SWIZZLE_INPUTATTR 0 |
# define ATTRIBUTE_SWIZZLE_INPUTATTR_FACING 1 |
# define ATTRIBUTE_SWIZZLE_INPUTATTR_W 2 |
# define ATTRIBUTE_SWIZZLE_INPUTATTR_FACING_W 3 |
# define ATTRIBUTE_SWIZZLE_SHIFT 6 |
/* DW16: Point sprite texture coordinate enables */ |
/* DW17: Constant interpolation enables */ |
/* DW18: attr 0-7 wrap shortest enables */ |
/* DW19: attr 8-16 wrap shortest enables */ |
/* On GEN7, many fields of 3DSTATE_SF were split out into a new command: |
* 3DSTATE_SBE. The remaining fields live in different DWords, but retain |
* the same bit-offset. The only new field: |
*/ |
/* GEN7/DW1: */ |
# define GEN7_SF_DEPTH_BUFFER_SURFACE_FORMAT_SHIFT 12 |
/* GEN7/DW2: */ |
# define HSW_SF_LINE_STIPPLE_ENABLE 14 |
#define _3DSTATE_SBE 0x781F /* GEN7+ */ |
/* DW1 */ |
# define GEN7_SBE_SWIZZLE_CONTROL_MODE (1 << 28) |
# define GEN7_SBE_NUM_OUTPUTS_SHIFT 22 |
# define GEN7_SBE_SWIZZLE_ENABLE (1 << 21) |
# define GEN7_SBE_POINT_SPRITE_LOWERLEFT (1 << 20) |
# define GEN7_SBE_URB_ENTRY_READ_LENGTH_SHIFT 11 |
# define GEN7_SBE_URB_ENTRY_READ_OFFSET_SHIFT 4 |
/* DW2-9: Attribute setup (same as DW8-15 of gen6 _3DSTATE_SF) */ |
/* DW10: Point sprite texture coordinate enables */ |
/* DW11: Constant interpolation enables */ |
/* DW12: attr 0-7 wrap shortest enables */ |
/* DW13: attr 8-16 wrap shortest enables */ |
enum brw_wm_barycentric_interp_mode { |
BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC = 0, |
BRW_WM_PERSPECTIVE_CENTROID_BARYCENTRIC = 1, |
BRW_WM_PERSPECTIVE_SAMPLE_BARYCENTRIC = 2, |
BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC = 3, |
BRW_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC = 4, |
BRW_WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC = 5, |
BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT = 6 |
}; |
#define BRW_WM_NONPERSPECTIVE_BARYCENTRIC_BITS \ |
((1 << BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC) | \ |
(1 << BRW_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC) | \ |
(1 << BRW_WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC)) |
#define _3DSTATE_WM 0x7814 /* GEN6+ */ |
/* DW1: kernel pointer */ |
/* DW2 */ |
# define GEN6_WM_SPF_MODE (1 << 31) |
# define GEN6_WM_VECTOR_MASK_ENABLE (1 << 30) |
# define GEN6_WM_SAMPLER_COUNT_SHIFT 27 |
# define GEN6_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT 18 |
# define GEN6_WM_FLOATING_POINT_MODE_IEEE_754 (0 << 16) |
# define GEN6_WM_FLOATING_POINT_MODE_ALT (1 << 16) |
/* DW3: scratch space */ |
/* DW4 */ |
# define GEN6_WM_STATISTICS_ENABLE (1 << 31) |
# define GEN6_WM_DEPTH_CLEAR (1 << 30) |
# define GEN6_WM_DEPTH_RESOLVE (1 << 28) |
# define GEN6_WM_HIERARCHICAL_DEPTH_RESOLVE (1 << 27) |
# define GEN6_WM_DISPATCH_START_GRF_SHIFT_0 16 |
# define GEN6_WM_DISPATCH_START_GRF_SHIFT_1 8 |
# define GEN6_WM_DISPATCH_START_GRF_SHIFT_2 0 |
/* DW5 */ |
# define GEN6_WM_MAX_THREADS_SHIFT 25 |
# define GEN6_WM_KILL_ENABLE (1 << 22) |
# define GEN6_WM_COMPUTED_DEPTH (1 << 21) |
# define GEN6_WM_USES_SOURCE_DEPTH (1 << 20) |
# define GEN6_WM_DISPATCH_ENABLE (1 << 19) |
# define GEN6_WM_LINE_END_CAP_AA_WIDTH_0_5 (0 << 16) |
# define GEN6_WM_LINE_END_CAP_AA_WIDTH_1_0 (1 << 16) |
# define GEN6_WM_LINE_END_CAP_AA_WIDTH_2_0 (2 << 16) |
# define GEN6_WM_LINE_END_CAP_AA_WIDTH_4_0 (3 << 16) |
# define GEN6_WM_LINE_AA_WIDTH_0_5 (0 << 14) |
# define GEN6_WM_LINE_AA_WIDTH_1_0 (1 << 14) |
# define GEN6_WM_LINE_AA_WIDTH_2_0 (2 << 14) |
# define GEN6_WM_LINE_AA_WIDTH_4_0 (3 << 14) |
# define GEN6_WM_POLYGON_STIPPLE_ENABLE (1 << 13) |
# define GEN6_WM_LINE_STIPPLE_ENABLE (1 << 11) |
# define GEN6_WM_OMASK_TO_RENDER_TARGET (1 << 9) |
# define GEN6_WM_USES_SOURCE_W (1 << 8) |
# define GEN6_WM_DUAL_SOURCE_BLEND_ENABLE (1 << 7) |
# define GEN6_WM_32_DISPATCH_ENABLE (1 << 2) |
# define GEN6_WM_16_DISPATCH_ENABLE (1 << 1) |
# define GEN6_WM_8_DISPATCH_ENABLE (1 << 0) |
/* DW6 */ |
# define GEN6_WM_NUM_SF_OUTPUTS_SHIFT 20 |
# define GEN6_WM_POSOFFSET_NONE (0 << 18) |
# define GEN6_WM_POSOFFSET_CENTROID (2 << 18) |
# define GEN6_WM_POSOFFSET_SAMPLE (3 << 18) |
# define GEN6_WM_POSITION_ZW_PIXEL (0 << 16) |
# define GEN6_WM_POSITION_ZW_CENTROID (2 << 16) |
# define GEN6_WM_POSITION_ZW_SAMPLE (3 << 16) |
# define GEN6_WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC (1 << 15) |
# define GEN6_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC (1 << 14) |
# define GEN6_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC (1 << 13) |
# define GEN6_WM_PERSPECTIVE_SAMPLE_BARYCENTRIC (1 << 12) |
# define GEN6_WM_PERSPECTIVE_CENTROID_BARYCENTRIC (1 << 11) |
# define GEN6_WM_PERSPECTIVE_PIXEL_BARYCENTRIC (1 << 10) |
# define GEN6_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT 10 |
# define GEN6_WM_POINT_RASTRULE_UPPER_RIGHT (1 << 9) |
# define GEN6_WM_MSRAST_OFF_PIXEL (0 << 1) |
# define GEN6_WM_MSRAST_OFF_PATTERN (1 << 1) |
# define GEN6_WM_MSRAST_ON_PIXEL (2 << 1) |
# define GEN6_WM_MSRAST_ON_PATTERN (3 << 1) |
# define GEN6_WM_MSDISPMODE_PERSAMPLE (0 << 0) |
# define GEN6_WM_MSDISPMODE_PERPIXEL (1 << 0) |
/* DW7: kernel 1 pointer */ |
/* DW8: kernel 2 pointer */ |
#define _3DSTATE_CONSTANT_VS 0x7815 /* GEN6+ */ |
#define _3DSTATE_CONSTANT_GS 0x7816 /* GEN6+ */ |
#define _3DSTATE_CONSTANT_PS 0x7817 /* GEN6+ */ |
# define GEN6_CONSTANT_BUFFER_3_ENABLE (1 << 15) |
# define GEN6_CONSTANT_BUFFER_2_ENABLE (1 << 14) |
# define GEN6_CONSTANT_BUFFER_1_ENABLE (1 << 13) |
# define GEN6_CONSTANT_BUFFER_0_ENABLE (1 << 12) |
#define _3DSTATE_CONSTANT_HS 0x7819 /* GEN7+ */ |
#define _3DSTATE_CONSTANT_DS 0x781A /* GEN7+ */ |
#define _3DSTATE_STREAMOUT 0x781e /* GEN7+ */ |
/* DW1 */ |
# define SO_FUNCTION_ENABLE (1 << 31) |
# define SO_RENDERING_DISABLE (1 << 30) |
/* This selects which incoming rendering stream goes down the pipeline. The |
* rendering stream is 0 if not defined by special cases in the GS state. |
*/ |
# define SO_RENDER_STREAM_SELECT_SHIFT 27 |
# define SO_RENDER_STREAM_SELECT_MASK INTEL_MASK(28, 27) |
/* Controls reordering of TRISTRIP_* elements in stream output (not rendering). |
*/ |
# define SO_REORDER_TRAILING (1 << 26) |
/* Controls SO_NUM_PRIMS_WRITTEN_* and SO_PRIM_STORAGE_* */ |
# define SO_STATISTICS_ENABLE (1 << 25) |
# define SO_BUFFER_ENABLE(n) (1 << (8 + (n))) |
/* DW2 */ |
# define SO_STREAM_3_VERTEX_READ_OFFSET_SHIFT 29 |
# define SO_STREAM_3_VERTEX_READ_OFFSET_MASK INTEL_MASK(29, 29) |
# define SO_STREAM_3_VERTEX_READ_LENGTH_SHIFT 24 |
# define SO_STREAM_3_VERTEX_READ_LENGTH_MASK INTEL_MASK(28, 24) |
# define SO_STREAM_2_VERTEX_READ_OFFSET_SHIFT 21 |
# define SO_STREAM_2_VERTEX_READ_OFFSET_MASK INTEL_MASK(21, 21) |
# define SO_STREAM_2_VERTEX_READ_LENGTH_SHIFT 16 |
# define SO_STREAM_2_VERTEX_READ_LENGTH_MASK INTEL_MASK(20, 16) |
# define SO_STREAM_1_VERTEX_READ_OFFSET_SHIFT 13 |
# define SO_STREAM_1_VERTEX_READ_OFFSET_MASK INTEL_MASK(13, 13) |
# define SO_STREAM_1_VERTEX_READ_LENGTH_SHIFT 8 |
# define SO_STREAM_1_VERTEX_READ_LENGTH_MASK INTEL_MASK(12, 8) |
# define SO_STREAM_0_VERTEX_READ_OFFSET_SHIFT 5 |
# define SO_STREAM_0_VERTEX_READ_OFFSET_MASK INTEL_MASK(5, 5) |
# define SO_STREAM_0_VERTEX_READ_LENGTH_SHIFT 0 |
# define SO_STREAM_0_VERTEX_READ_LENGTH_MASK INTEL_MASK(4, 0) |
/* 3DSTATE_WM for Gen7 */ |
/* DW1 */ |
# define GEN7_WM_STATISTICS_ENABLE (1 << 31) |
# define GEN7_WM_DEPTH_CLEAR (1 << 30) |
# define GEN7_WM_DISPATCH_ENABLE (1 << 29) |
# define GEN7_WM_DEPTH_RESOLVE (1 << 28) |
# define GEN7_WM_HIERARCHICAL_DEPTH_RESOLVE (1 << 27) |
# define GEN7_WM_KILL_ENABLE (1 << 25) |
# define GEN7_WM_PSCDEPTH_OFF (0 << 23) |
# define GEN7_WM_PSCDEPTH_ON (1 << 23) |
# define GEN7_WM_PSCDEPTH_ON_GE (2 << 23) |
# define GEN7_WM_PSCDEPTH_ON_LE (3 << 23) |
# define GEN7_WM_USES_SOURCE_DEPTH (1 << 20) |
# define GEN7_WM_USES_SOURCE_W (1 << 19) |
# define GEN7_WM_POSITION_ZW_PIXEL (0 << 17) |
# define GEN7_WM_POSITION_ZW_CENTROID (2 << 17) |
# define GEN7_WM_POSITION_ZW_SAMPLE (3 << 17) |
# define GEN7_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT 11 |
# define GEN7_WM_USES_INPUT_COVERAGE_MASK (1 << 10) |
# define GEN7_WM_LINE_END_CAP_AA_WIDTH_0_5 (0 << 8) |
# define GEN7_WM_LINE_END_CAP_AA_WIDTH_1_0 (1 << 8) |
# define GEN7_WM_LINE_END_CAP_AA_WIDTH_2_0 (2 << 8) |
# define GEN7_WM_LINE_END_CAP_AA_WIDTH_4_0 (3 << 8) |
# define GEN7_WM_LINE_AA_WIDTH_0_5 (0 << 6) |
# define GEN7_WM_LINE_AA_WIDTH_1_0 (1 << 6) |
# define GEN7_WM_LINE_AA_WIDTH_2_0 (2 << 6) |
# define GEN7_WM_LINE_AA_WIDTH_4_0 (3 << 6) |
# define GEN7_WM_POLYGON_STIPPLE_ENABLE (1 << 4) |
# define GEN7_WM_LINE_STIPPLE_ENABLE (1 << 3) |
# define GEN7_WM_POINT_RASTRULE_UPPER_RIGHT (1 << 2) |
# define GEN7_WM_MSRAST_OFF_PIXEL (0 << 0) |
# define GEN7_WM_MSRAST_OFF_PATTERN (1 << 0) |
# define GEN7_WM_MSRAST_ON_PIXEL (2 << 0) |
# define GEN7_WM_MSRAST_ON_PATTERN (3 << 0) |
/* DW2 */ |
# define GEN7_WM_MSDISPMODE_PERSAMPLE (0 << 31) |
# define GEN7_WM_MSDISPMODE_PERPIXEL (1 << 31) |
#define _3DSTATE_PS 0x7820 /* GEN7+ */ |
/* DW1: kernel pointer */ |
/* DW2 */ |
# define GEN7_PS_SPF_MODE (1 << 31) |
# define GEN7_PS_VECTOR_MASK_ENABLE (1 << 30) |
# define GEN7_PS_SAMPLER_COUNT_SHIFT 27 |
# define GEN7_PS_BINDING_TABLE_ENTRY_COUNT_SHIFT 18 |
# define GEN7_PS_FLOATING_POINT_MODE_IEEE_754 (0 << 16) |
# define GEN7_PS_FLOATING_POINT_MODE_ALT (1 << 16) |
/* DW3: scratch space */ |
/* DW4 */ |
# define IVB_PS_MAX_THREADS_SHIFT 24 |
# define HSW_PS_MAX_THREADS_SHIFT 23 |
# define HSW_PS_SAMPLE_MASK_SHIFT 12 |
# define HSW_PS_SAMPLE_MASK_MASK INTEL_MASK(19, 12) |
# define GEN7_PS_PUSH_CONSTANT_ENABLE (1 << 11) |
# define GEN7_PS_ATTRIBUTE_ENABLE (1 << 10) |
# define GEN7_PS_OMASK_TO_RENDER_TARGET (1 << 9) |
# define GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE (1 << 8) |
# define GEN7_PS_DUAL_SOURCE_BLEND_ENABLE (1 << 7) |
# define GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE (1 << 6) |
# define GEN7_PS_POSOFFSET_NONE (0 << 3) |
# define GEN7_PS_POSOFFSET_CENTROID (2 << 3) |
# define GEN7_PS_POSOFFSET_SAMPLE (3 << 3) |
# define GEN7_PS_32_DISPATCH_ENABLE (1 << 2) |
# define GEN7_PS_16_DISPATCH_ENABLE (1 << 1) |
# define GEN7_PS_8_DISPATCH_ENABLE (1 << 0) |
/* DW5 */ |
# define GEN7_PS_DISPATCH_START_GRF_SHIFT_0 16 |
# define GEN7_PS_DISPATCH_START_GRF_SHIFT_1 8 |
# define GEN7_PS_DISPATCH_START_GRF_SHIFT_2 0 |
/* DW6: kernel 1 pointer */ |
/* DW7: kernel 2 pointer */ |
#define _3DSTATE_SAMPLE_MASK 0x7818 /* GEN6+ */ |
#define _3DSTATE_DRAWING_RECTANGLE 0x7900 |
#define _3DSTATE_BLEND_CONSTANT_COLOR 0x7901 |
#define _3DSTATE_CHROMA_KEY 0x7904 |
#define _3DSTATE_DEPTH_BUFFER 0x7905 /* GEN4-6 */ |
#define _3DSTATE_POLY_STIPPLE_OFFSET 0x7906 |
#define _3DSTATE_POLY_STIPPLE_PATTERN 0x7907 |
#define _3DSTATE_LINE_STIPPLE_PATTERN 0x7908 |
#define _3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP 0x7909 |
#define _3DSTATE_AA_LINE_PARAMETERS 0x790a /* G45+ */ |
#define _3DSTATE_GS_SVB_INDEX 0x790b /* CTG+ */ |
/* DW1 */ |
# define SVB_INDEX_SHIFT 29 |
# define SVB_LOAD_INTERNAL_VERTEX_COUNT (1 << 0) /* SNB+ */ |
/* DW2: SVB index */ |
/* DW3: SVB maximum index */ |
#define _3DSTATE_MULTISAMPLE 0x790d /* GEN6+ */ |
/* DW1 */ |
# define MS_PIXEL_LOCATION_CENTER (0 << 4) |
# define MS_PIXEL_LOCATION_UPPER_LEFT (1 << 4) |
# define MS_NUMSAMPLES_1 (0 << 1) |
# define MS_NUMSAMPLES_4 (2 << 1) |
# define MS_NUMSAMPLES_8 (3 << 1) |
#define _3DSTATE_STENCIL_BUFFER 0x790e /* ILK, SNB */ |
#define _3DSTATE_HIER_DEPTH_BUFFER 0x790f /* ILK, SNB */ |
#define GEN7_3DSTATE_CLEAR_PARAMS 0x7804 |
#define GEN7_3DSTATE_DEPTH_BUFFER 0x7805 |
#define GEN7_3DSTATE_STENCIL_BUFFER 0x7806 |
# define HSW_STENCIL_ENABLED (1 << 31) |
#define GEN7_3DSTATE_HIER_DEPTH_BUFFER 0x7807 |
#define _3DSTATE_CLEAR_PARAMS 0x7910 /* ILK, SNB */ |
# define GEN5_DEPTH_CLEAR_VALID (1 << 15) |
/* DW1: depth clear value */ |
/* DW2 */ |
# define GEN7_DEPTH_CLEAR_VALID (1 << 0) |
#define _3DSTATE_SO_DECL_LIST 0x7917 /* GEN7+ */ |
/* DW1 */ |
# define SO_STREAM_TO_BUFFER_SELECTS_3_SHIFT 12 |
# define SO_STREAM_TO_BUFFER_SELECTS_3_MASK INTEL_MASK(15, 12) |
# define SO_STREAM_TO_BUFFER_SELECTS_2_SHIFT 8 |
# define SO_STREAM_TO_BUFFER_SELECTS_2_MASK INTEL_MASK(11, 8) |
# define SO_STREAM_TO_BUFFER_SELECTS_1_SHIFT 4 |
# define SO_STREAM_TO_BUFFER_SELECTS_1_MASK INTEL_MASK(7, 4) |
# define SO_STREAM_TO_BUFFER_SELECTS_0_SHIFT 0 |
# define SO_STREAM_TO_BUFFER_SELECTS_0_MASK INTEL_MASK(3, 0) |
/* DW2 */ |
# define SO_NUM_ENTRIES_3_SHIFT 24 |
# define SO_NUM_ENTRIES_3_MASK INTEL_MASK(31, 24) |
# define SO_NUM_ENTRIES_2_SHIFT 16 |
# define SO_NUM_ENTRIES_2_MASK INTEL_MASK(23, 16) |
# define SO_NUM_ENTRIES_1_SHIFT 8 |
# define SO_NUM_ENTRIES_1_MASK INTEL_MASK(15, 8) |
# define SO_NUM_ENTRIES_0_SHIFT 0 |
# define SO_NUM_ENTRIES_0_MASK INTEL_MASK(7, 0) |
/* SO_DECL DW0 */ |
# define SO_DECL_OUTPUT_BUFFER_SLOT_SHIFT 12 |
# define SO_DECL_OUTPUT_BUFFER_SLOT_MASK INTEL_MASK(13, 12) |
# define SO_DECL_HOLE_FLAG (1 << 11) |
# define SO_DECL_REGISTER_INDEX_SHIFT 4 |
# define SO_DECL_REGISTER_INDEX_MASK INTEL_MASK(9, 4) |
# define SO_DECL_COMPONENT_MASK_SHIFT 0 |
# define SO_DECL_COMPONENT_MASK_MASK INTEL_MASK(3, 0) |
#define _3DSTATE_SO_BUFFER 0x7918 /* GEN7+ */ |
/* DW1 */ |
# define SO_BUFFER_INDEX_SHIFT 29 |
# define SO_BUFFER_INDEX_MASK INTEL_MASK(30, 29) |
# define SO_BUFFER_PITCH_SHIFT 0 |
# define SO_BUFFER_PITCH_MASK INTEL_MASK(11, 0) |
/* DW2: start address */ |
/* DW3: end address. */ |
#define CMD_PIPE_CONTROL 0x7a00 |
#define CMD_MI_FLUSH 0x0200 |
/* Bitfields for the URB_WRITE message, DW2 of message header: */ |
#define URB_WRITE_PRIM_END 0x1 |
#define URB_WRITE_PRIM_START 0x2 |
#define URB_WRITE_PRIM_TYPE_SHIFT 2 |
/* Maximum number of entries that can be addressed using a binding table |
* pointer of type SURFTYPE_BUFFER |
*/ |
#define BRW_MAX_NUM_BUFFER_ENTRIES (1 << 27) |
/* Memory Object Control State: |
* Specifying zero for L3 means "uncached in L3", at least on Haswell |
* and Baytrail, since there are no PTE flags for setting L3 cacheability. |
* On Ivybridge, the PTEs do have a cache-in-L3 bit, so setting MOCS to 0 |
* may still respect that. |
*/ |
#define GEN7_MOCS_L3 1 |
/* Ivybridge only: cache in LLC. |
* Specifying zero here means to use the PTE values set by the kernel; |
* non-zero overrides the PTE values. |
*/ |
#define IVB_MOCS_LLC (1 << 1) |
/* Baytrail only: snoop in CPU cache */ |
#define BYT_MOCS_SNOOP (1 << 1) |
/* Haswell only: LLC/eLLC controls (write-back or uncached). |
* Specifying zero here means to use the PTE values set by the kernel, |
* which is useful since it offers additional control (write-through |
* cacheing and age). Non-zero overrides the PTE values. |
*/ |
#define HSW_MOCS_UC_LLC_UC_ELLC (1 << 1) |
#define HSW_MOCS_WB_LLC_WB_ELLC (2 << 1) |
#define HSW_MOCS_UC_LLC_WB_ELLC (3 << 1) |
#include "intel_chipset.h" |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_disasm.c |
---|
0,0 → 1,1379 |
/* |
* Copyright © 2008 Keith Packard |
* |
* Permission to use, copy, modify, distribute, and sell this software and its |
* documentation for any purpose is hereby granted without fee, provided that |
* the above copyright notice appear in all copies and that both that copyright |
* notice and this permission notice appear in supporting documentation, and |
* that the name of the copyright holders not be used in advertising or |
* publicity pertaining to distribution of the software without specific, |
* written prior permission. The copyright holders make no representations |
* about the suitability of this software for any purpose. It is provided "as |
* is" without express or implied warranty. |
* |
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
* OF THIS SOFTWARE. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <getopt.h> |
#include <unistd.h> |
#include <stdarg.h> |
#include "main/mtypes.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
const struct opcode_desc opcode_descs[128] = { |
[BRW_OPCODE_MOV] = { .name = "mov", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_FRC] = { .name = "frc", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_RNDU] = { .name = "rndu", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_RNDD] = { .name = "rndd", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_RNDE] = { .name = "rnde", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_RNDZ] = { .name = "rndz", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_NOT] = { .name = "not", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_LZD] = { .name = "lzd", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_F32TO16] = { .name = "f32to16", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_F16TO32] = { .name = "f16to32", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_BFREV] = { .name = "bfrev", .nsrc = 1, .ndst = 1}, |
[BRW_OPCODE_FBH] = { .name = "fbh", .nsrc = 1, .ndst = 1}, |
[BRW_OPCODE_FBL] = { .name = "fbl", .nsrc = 1, .ndst = 1}, |
[BRW_OPCODE_CBIT] = { .name = "cbit", .nsrc = 1, .ndst = 1}, |
[BRW_OPCODE_MUL] = { .name = "mul", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_MAC] = { .name = "mac", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_MACH] = { .name = "mach", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_LINE] = { .name = "line", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_PLN] = { .name = "pln", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_MAD] = { .name = "mad", .nsrc = 3, .ndst = 1 }, |
[BRW_OPCODE_LRP] = { .name = "lrp", .nsrc = 3, .ndst = 1 }, |
[BRW_OPCODE_SAD2] = { .name = "sad2", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_SADA2] = { .name = "sada2", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_DP4] = { .name = "dp4", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_DPH] = { .name = "dph", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_DP3] = { .name = "dp3", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_DP2] = { .name = "dp2", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_MATH] = { .name = "math", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_AVG] = { .name = "avg", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_ADD] = { .name = "add", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_SEL] = { .name = "sel", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_AND] = { .name = "and", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_OR] = { .name = "or", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_XOR] = { .name = "xor", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_SHR] = { .name = "shr", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_SHL] = { .name = "shl", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_ASR] = { .name = "asr", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_CMP] = { .name = "cmp", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_CMPN] = { .name = "cmpn", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_BFE] = { .name = "bfe", .nsrc = 3, .ndst = 1}, |
[BRW_OPCODE_BFI1] = { .name = "bfe1", .nsrc = 2, .ndst = 1}, |
[BRW_OPCODE_BFI2] = { .name = "bfe2", .nsrc = 3, .ndst = 1}, |
[BRW_OPCODE_SEND] = { .name = "send", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_SENDC] = { .name = "sendc", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_NOP] = { .name = "nop", .nsrc = 0, .ndst = 0 }, |
[BRW_OPCODE_JMPI] = { .name = "jmpi", .nsrc = 0, .ndst = 0 }, |
[BRW_OPCODE_IF] = { .name = "if", .nsrc = 2, .ndst = 0 }, |
[BRW_OPCODE_IFF] = { .name = "iff", .nsrc = 2, .ndst = 1 }, |
[BRW_OPCODE_WHILE] = { .name = "while", .nsrc = 2, .ndst = 0 }, |
[BRW_OPCODE_ELSE] = { .name = "else", .nsrc = 2, .ndst = 0 }, |
[BRW_OPCODE_BREAK] = { .name = "break", .nsrc = 2, .ndst = 0 }, |
[BRW_OPCODE_CONTINUE] = { .name = "cont", .nsrc = 1, .ndst = 0 }, |
[BRW_OPCODE_HALT] = { .name = "halt", .nsrc = 1, .ndst = 0 }, |
[BRW_OPCODE_MSAVE] = { .name = "msave", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_PUSH] = { .name = "push", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_MRESTORE] = { .name = "mrest", .nsrc = 1, .ndst = 1 }, |
[BRW_OPCODE_POP] = { .name = "pop", .nsrc = 2, .ndst = 0 }, |
[BRW_OPCODE_WAIT] = { .name = "wait", .nsrc = 1, .ndst = 0 }, |
[BRW_OPCODE_DO] = { .name = "do", .nsrc = 0, .ndst = 0 }, |
[BRW_OPCODE_ENDIF] = { .name = "endif", .nsrc = 2, .ndst = 0 }, |
}; |
static const struct opcode_desc *opcode = opcode_descs; |
static const char * const conditional_modifier[16] = { |
[BRW_CONDITIONAL_NONE] = "", |
[BRW_CONDITIONAL_Z] = ".e", |
[BRW_CONDITIONAL_NZ] = ".ne", |
[BRW_CONDITIONAL_G] = ".g", |
[BRW_CONDITIONAL_GE] = ".ge", |
[BRW_CONDITIONAL_L] = ".l", |
[BRW_CONDITIONAL_LE] = ".le", |
[BRW_CONDITIONAL_R] = ".r", |
[BRW_CONDITIONAL_O] = ".o", |
[BRW_CONDITIONAL_U] = ".u", |
}; |
static const char * const negate[2] = { |
[0] = "", |
[1] = "-", |
}; |
static const char * const _abs[2] = { |
[0] = "", |
[1] = "(abs)", |
}; |
static const char * const vert_stride[16] = { |
[0] = "0", |
[1] = "1", |
[2] = "2", |
[3] = "4", |
[4] = "8", |
[5] = "16", |
[6] = "32", |
[15] = "VxH", |
}; |
static const char * const width[8] = { |
[0] = "1", |
[1] = "2", |
[2] = "4", |
[3] = "8", |
[4] = "16", |
}; |
static const char * const horiz_stride[4] = { |
[0] = "0", |
[1] = "1", |
[2] = "2", |
[3] = "4" |
}; |
static const char * const chan_sel[4] = { |
[0] = "x", |
[1] = "y", |
[2] = "z", |
[3] = "w", |
}; |
static const char * const debug_ctrl[2] = { |
[0] = "", |
[1] = ".breakpoint" |
}; |
static const char * const saturate[2] = { |
[0] = "", |
[1] = ".sat" |
}; |
static const char * const accwr[2] = { |
[0] = "", |
[1] = "AccWrEnable" |
}; |
static const char * const wectrl[2] = { |
[0] = "WE_normal", |
[1] = "WE_all" |
}; |
static const char * const exec_size[8] = { |
[0] = "1", |
[1] = "2", |
[2] = "4", |
[3] = "8", |
[4] = "16", |
[5] = "32" |
}; |
static const char * const pred_inv[2] = { |
[0] = "+", |
[1] = "-" |
}; |
static const char * const pred_ctrl_align16[16] = { |
[1] = "", |
[2] = ".x", |
[3] = ".y", |
[4] = ".z", |
[5] = ".w", |
[6] = ".any4h", |
[7] = ".all4h", |
}; |
static const char * const pred_ctrl_align1[16] = { |
[1] = "", |
[2] = ".anyv", |
[3] = ".allv", |
[4] = ".any2h", |
[5] = ".all2h", |
[6] = ".any4h", |
[7] = ".all4h", |
[8] = ".any8h", |
[9] = ".all8h", |
[10] = ".any16h", |
[11] = ".all16h", |
}; |
static const char * const thread_ctrl[4] = { |
[0] = "", |
[2] = "switch" |
}; |
static const char * const compr_ctrl[4] = { |
[0] = "", |
[1] = "sechalf", |
[2] = "compr", |
[3] = "compr4", |
}; |
static const char * const dep_ctrl[4] = { |
[0] = "", |
[1] = "NoDDClr", |
[2] = "NoDDChk", |
[3] = "NoDDClr,NoDDChk", |
}; |
static const char * const mask_ctrl[4] = { |
[0] = "", |
[1] = "nomask", |
}; |
static const char * const access_mode[2] = { |
[0] = "align1", |
[1] = "align16", |
}; |
static const char * const reg_encoding[8] = { |
[0] = "UD", |
[1] = "D", |
[2] = "UW", |
[3] = "W", |
[4] = "UB", |
[5] = "B", |
[7] = "F" |
}; |
const int reg_type_size[8] = { |
[0] = 4, |
[1] = 4, |
[2] = 2, |
[3] = 2, |
[4] = 1, |
[5] = 1, |
[7] = 4 |
}; |
static const char * const reg_file[4] = { |
[0] = "A", |
[1] = "g", |
[2] = "m", |
[3] = "imm", |
}; |
static const char * const writemask[16] = { |
[0x0] = ".", |
[0x1] = ".x", |
[0x2] = ".y", |
[0x3] = ".xy", |
[0x4] = ".z", |
[0x5] = ".xz", |
[0x6] = ".yz", |
[0x7] = ".xyz", |
[0x8] = ".w", |
[0x9] = ".xw", |
[0xa] = ".yw", |
[0xb] = ".xyw", |
[0xc] = ".zw", |
[0xd] = ".xzw", |
[0xe] = ".yzw", |
[0xf] = "", |
}; |
static const char * const end_of_thread[2] = { |
[0] = "", |
[1] = "EOT" |
}; |
static const char * const target_function[16] = { |
[BRW_SFID_NULL] = "null", |
[BRW_SFID_MATH] = "math", |
[BRW_SFID_SAMPLER] = "sampler", |
[BRW_SFID_MESSAGE_GATEWAY] = "gateway", |
[BRW_SFID_DATAPORT_READ] = "read", |
[BRW_SFID_DATAPORT_WRITE] = "write", |
[BRW_SFID_URB] = "urb", |
[BRW_SFID_THREAD_SPAWNER] = "thread_spawner" |
}; |
static const char * const target_function_gen6[16] = { |
[BRW_SFID_NULL] = "null", |
[BRW_SFID_MATH] = "math", |
[BRW_SFID_SAMPLER] = "sampler", |
[BRW_SFID_MESSAGE_GATEWAY] = "gateway", |
[BRW_SFID_URB] = "urb", |
[BRW_SFID_THREAD_SPAWNER] = "thread_spawner", |
[GEN6_SFID_DATAPORT_SAMPLER_CACHE] = "sampler", |
[GEN6_SFID_DATAPORT_RENDER_CACHE] = "render", |
[GEN6_SFID_DATAPORT_CONSTANT_CACHE] = "const", |
[GEN7_SFID_DATAPORT_DATA_CACHE] = "data" |
}; |
static const char * const dp_rc_msg_type_gen6[16] = { |
[BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ] = "OWORD block read", |
[GEN6_DATAPORT_READ_MESSAGE_RENDER_UNORM_READ] = "RT UNORM read", |
[GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ] = "OWORD dual block read", |
[GEN6_DATAPORT_READ_MESSAGE_MEDIA_BLOCK_READ] = "media block read", |
[GEN6_DATAPORT_READ_MESSAGE_OWORD_UNALIGN_BLOCK_READ] = "OWORD unaligned block read", |
[GEN6_DATAPORT_READ_MESSAGE_DWORD_SCATTERED_READ] = "DWORD scattered read", |
[GEN6_DATAPORT_WRITE_MESSAGE_DWORD_ATOMIC_WRITE] = "DWORD atomic write", |
[GEN6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE] = "OWORD block write", |
[GEN6_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE] = "OWORD dual block write", |
[GEN6_DATAPORT_WRITE_MESSAGE_MEDIA_BLOCK_WRITE] = "media block write", |
[GEN6_DATAPORT_WRITE_MESSAGE_DWORD_SCATTERED_WRITE] = "DWORD scattered write", |
[GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE] = "RT write", |
[GEN6_DATAPORT_WRITE_MESSAGE_STREAMED_VB_WRITE] = "streamed VB write", |
[GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_UNORM_WRITE] = "RT UNORMc write", |
}; |
static const char * const math_function[16] = { |
[BRW_MATH_FUNCTION_INV] = "inv", |
[BRW_MATH_FUNCTION_LOG] = "log", |
[BRW_MATH_FUNCTION_EXP] = "exp", |
[BRW_MATH_FUNCTION_SQRT] = "sqrt", |
[BRW_MATH_FUNCTION_RSQ] = "rsq", |
[BRW_MATH_FUNCTION_SIN] = "sin", |
[BRW_MATH_FUNCTION_COS] = "cos", |
[BRW_MATH_FUNCTION_SINCOS] = "sincos", |
[BRW_MATH_FUNCTION_FDIV] = "fdiv", |
[BRW_MATH_FUNCTION_POW] = "pow", |
[BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER] = "intdivmod", |
[BRW_MATH_FUNCTION_INT_DIV_QUOTIENT] = "intdiv", |
[BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intmod", |
}; |
static const char * const math_saturate[2] = { |
[0] = "", |
[1] = "sat" |
}; |
static const char * const math_signed[2] = { |
[0] = "", |
[1] = "signed" |
}; |
static const char * const math_scalar[2] = { |
[0] = "", |
[1] = "scalar" |
}; |
static const char * const math_precision[2] = { |
[0] = "", |
[1] = "partial_precision" |
}; |
static const char * const urb_opcode[2] = { |
[0] = "urb_write", |
[1] = "ff_sync", |
}; |
static const char * const urb_swizzle[4] = { |
[BRW_URB_SWIZZLE_NONE] = "", |
[BRW_URB_SWIZZLE_INTERLEAVE] = "interleave", |
[BRW_URB_SWIZZLE_TRANSPOSE] = "transpose", |
}; |
static const char * const urb_allocate[2] = { |
[0] = "", |
[1] = "allocate" |
}; |
static const char * const urb_used[2] = { |
[0] = "", |
[1] = "used" |
}; |
static const char * const urb_complete[2] = { |
[0] = "", |
[1] = "complete" |
}; |
static const char * const sampler_target_format[4] = { |
[0] = "F", |
[2] = "UD", |
[3] = "D" |
}; |
static int column; |
static int string (FILE *file, const char *string) |
{ |
fputs (string, file); |
column += strlen (string); |
return 0; |
} |
static int format (FILE *f, const char *format, ...) |
{ |
char buf[1024]; |
va_list args; |
va_start (args, format); |
vsnprintf (buf, sizeof (buf) - 1, format, args); |
va_end (args); |
string (f, buf); |
return 0; |
} |
static int newline (FILE *f) |
{ |
putc ('\n', f); |
column = 0; |
return 0; |
} |
static int pad (FILE *f, int c) |
{ |
do |
string (f, " "); |
while (column < c); |
return 0; |
} |
static int control (FILE *file, const char *name, const char * const ctrl[], |
GLuint id, int *space) |
{ |
if (!ctrl[id]) { |
fprintf (file, "*** invalid %s value %d ", |
name, id); |
return 1; |
} |
if (ctrl[id][0]) |
{ |
if (space && *space) |
string (file, " "); |
string (file, ctrl[id]); |
if (space) |
*space = 1; |
} |
return 0; |
} |
static int print_opcode (FILE *file, int id) |
{ |
if (!opcode[id].name) { |
format (file, "*** invalid opcode value %d ", id); |
return 1; |
} |
string (file, opcode[id].name); |
return 0; |
} |
static int three_source_type_to_reg_type(int three_source_type) |
{ |
switch (three_source_type) { |
case BRW_3SRC_TYPE_F: |
return BRW_REGISTER_TYPE_F; |
case BRW_3SRC_TYPE_D: |
return BRW_REGISTER_TYPE_D; |
case BRW_3SRC_TYPE_UD: |
return BRW_REGISTER_TYPE_UD; |
} |
return -1; |
} |
static int reg (FILE *file, GLuint _reg_file, GLuint _reg_nr) |
{ |
int err = 0; |
/* Clear the Compr4 instruction compression bit. */ |
if (_reg_file == BRW_MESSAGE_REGISTER_FILE) |
_reg_nr &= ~(1 << 7); |
if (_reg_file == BRW_ARCHITECTURE_REGISTER_FILE) { |
switch (_reg_nr & 0xf0) { |
case BRW_ARF_NULL: |
string (file, "null"); |
return -1; |
case BRW_ARF_ADDRESS: |
format (file, "a%d", _reg_nr & 0x0f); |
break; |
case BRW_ARF_ACCUMULATOR: |
format (file, "acc%d", _reg_nr & 0x0f); |
break; |
case BRW_ARF_FLAG: |
format (file, "f%d", _reg_nr & 0x0f); |
break; |
case BRW_ARF_MASK: |
format (file, "mask%d", _reg_nr & 0x0f); |
break; |
case BRW_ARF_MASK_STACK: |
format (file, "msd%d", _reg_nr & 0x0f); |
break; |
case BRW_ARF_STATE: |
format (file, "sr%d", _reg_nr & 0x0f); |
break; |
case BRW_ARF_CONTROL: |
format (file, "cr%d", _reg_nr & 0x0f); |
break; |
case BRW_ARF_NOTIFICATION_COUNT: |
format (file, "n%d", _reg_nr & 0x0f); |
break; |
case BRW_ARF_IP: |
string (file, "ip"); |
return -1; |
break; |
default: |
format (file, "ARF%d", _reg_nr); |
break; |
} |
} else { |
err |= control (file, "src reg file", reg_file, _reg_file, NULL); |
format (file, "%d", _reg_nr); |
} |
return err; |
} |
static int dest (FILE *file, struct brw_instruction *inst) |
{ |
int err = 0; |
if (inst->header.access_mode == BRW_ALIGN_1) |
{ |
if (inst->bits1.da1.dest_address_mode == BRW_ADDRESS_DIRECT) |
{ |
err |= reg (file, inst->bits1.da1.dest_reg_file, inst->bits1.da1.dest_reg_nr); |
if (err == -1) |
return 0; |
if (inst->bits1.da1.dest_subreg_nr) |
format (file, ".%d", inst->bits1.da1.dest_subreg_nr / |
reg_type_size[inst->bits1.da1.dest_reg_type]); |
string (file, "<"); |
err |= control (file, "horiz stride", horiz_stride, inst->bits1.da1.dest_horiz_stride, NULL); |
string (file, ">"); |
err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da1.dest_reg_type, NULL); |
} |
else |
{ |
string (file, "g[a0"); |
if (inst->bits1.ia1.dest_subreg_nr) |
format (file, ".%d", inst->bits1.ia1.dest_subreg_nr / |
reg_type_size[inst->bits1.ia1.dest_reg_type]); |
if (inst->bits1.ia1.dest_indirect_offset) |
format (file, " %d", inst->bits1.ia1.dest_indirect_offset); |
string (file, "]<"); |
err |= control (file, "horiz stride", horiz_stride, inst->bits1.ia1.dest_horiz_stride, NULL); |
string (file, ">"); |
err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.ia1.dest_reg_type, NULL); |
} |
} |
else |
{ |
if (inst->bits1.da16.dest_address_mode == BRW_ADDRESS_DIRECT) |
{ |
err |= reg (file, inst->bits1.da16.dest_reg_file, inst->bits1.da16.dest_reg_nr); |
if (err == -1) |
return 0; |
if (inst->bits1.da16.dest_subreg_nr) |
format (file, ".%d", inst->bits1.da16.dest_subreg_nr / |
reg_type_size[inst->bits1.da16.dest_reg_type]); |
string (file, "<1>"); |
err |= control (file, "writemask", writemask, inst->bits1.da16.dest_writemask, NULL); |
err |= control (file, "dest reg encoding", reg_encoding, inst->bits1.da16.dest_reg_type, NULL); |
} |
else |
{ |
err = 1; |
string (file, "Indirect align16 address mode not supported"); |
} |
} |
return 0; |
} |
static int dest_3src (FILE *file, struct brw_instruction *inst) |
{ |
int err = 0; |
uint32_t reg_file; |
if (inst->bits1.da3src.dest_reg_file) |
reg_file = BRW_MESSAGE_REGISTER_FILE; |
else |
reg_file = BRW_GENERAL_REGISTER_FILE; |
err |= reg (file, reg_file, inst->bits1.da3src.dest_reg_nr); |
if (err == -1) |
return 0; |
if (inst->bits1.da3src.dest_subreg_nr) |
format (file, ".%d", inst->bits1.da3src.dest_subreg_nr); |
string (file, "<1>"); |
err |= control (file, "writemask", writemask, inst->bits1.da3src.dest_writemask, NULL); |
err |= control (file, "dest reg encoding", reg_encoding, |
three_source_type_to_reg_type(inst->bits1.da3src.dst_type), |
NULL); |
return 0; |
} |
static int src_align1_region (FILE *file, |
GLuint _vert_stride, GLuint _width, GLuint _horiz_stride) |
{ |
int err = 0; |
string (file, "<"); |
err |= control (file, "vert stride", vert_stride, _vert_stride, NULL); |
string (file, ","); |
err |= control (file, "width", width, _width, NULL); |
string (file, ","); |
err |= control (file, "horiz_stride", horiz_stride, _horiz_stride, NULL); |
string (file, ">"); |
return err; |
} |
static int src_da1 (FILE *file, GLuint type, GLuint _reg_file, |
GLuint _vert_stride, GLuint _width, GLuint _horiz_stride, |
GLuint reg_num, GLuint sub_reg_num, GLuint __abs, GLuint _negate) |
{ |
int err = 0; |
err |= control (file, "negate", negate, _negate, NULL); |
err |= control (file, "abs", _abs, __abs, NULL); |
err |= reg (file, _reg_file, reg_num); |
if (err == -1) |
return 0; |
if (sub_reg_num) |
format (file, ".%d", sub_reg_num / reg_type_size[type]); /* use formal style like spec */ |
src_align1_region (file, _vert_stride, _width, _horiz_stride); |
err |= control (file, "src reg encoding", reg_encoding, type, NULL); |
return err; |
} |
static int src_ia1 (FILE *file, |
GLuint type, |
GLuint _reg_file, |
GLint _addr_imm, |
GLuint _addr_subreg_nr, |
GLuint _negate, |
GLuint __abs, |
GLuint _addr_mode, |
GLuint _horiz_stride, |
GLuint _width, |
GLuint _vert_stride) |
{ |
int err = 0; |
err |= control (file, "negate", negate, _negate, NULL); |
err |= control (file, "abs", _abs, __abs, NULL); |
string (file, "g[a0"); |
if (_addr_subreg_nr) |
format (file, ".%d", _addr_subreg_nr); |
if (_addr_imm) |
format (file, " %d", _addr_imm); |
string (file, "]"); |
src_align1_region (file, _vert_stride, _width, _horiz_stride); |
err |= control (file, "src reg encoding", reg_encoding, type, NULL); |
return err; |
} |
static int src_da16 (FILE *file, |
GLuint _reg_type, |
GLuint _reg_file, |
GLuint _vert_stride, |
GLuint _reg_nr, |
GLuint _subreg_nr, |
GLuint __abs, |
GLuint _negate, |
GLuint swz_x, |
GLuint swz_y, |
GLuint swz_z, |
GLuint swz_w) |
{ |
int err = 0; |
err |= control (file, "negate", negate, _negate, NULL); |
err |= control (file, "abs", _abs, __abs, NULL); |
err |= reg (file, _reg_file, _reg_nr); |
if (err == -1) |
return 0; |
if (_subreg_nr) |
/* bit4 for subreg number byte addressing. Make this same meaning as |
in da1 case, so output looks consistent. */ |
format (file, ".%d", 16 / reg_type_size[_reg_type]); |
string (file, "<"); |
err |= control (file, "vert stride", vert_stride, _vert_stride, NULL); |
string (file, ",4,1>"); |
/* |
* Three kinds of swizzle display: |
* identity - nothing printed |
* 1->all - print the single channel |
* 1->1 - print the mapping |
*/ |
if (swz_x == BRW_CHANNEL_X && |
swz_y == BRW_CHANNEL_Y && |
swz_z == BRW_CHANNEL_Z && |
swz_w == BRW_CHANNEL_W) |
{ |
; |
} |
else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w) |
{ |
string (file, "."); |
err |= control (file, "channel select", chan_sel, swz_x, NULL); |
} |
else |
{ |
string (file, "."); |
err |= control (file, "channel select", chan_sel, swz_x, NULL); |
err |= control (file, "channel select", chan_sel, swz_y, NULL); |
err |= control (file, "channel select", chan_sel, swz_z, NULL); |
err |= control (file, "channel select", chan_sel, swz_w, NULL); |
} |
err |= control (file, "src da16 reg type", reg_encoding, _reg_type, NULL); |
return err; |
} |
static int src0_3src (FILE *file, struct brw_instruction *inst) |
{ |
int err = 0; |
GLuint swz_x = (inst->bits2.da3src.src0_swizzle >> 0) & 0x3; |
GLuint swz_y = (inst->bits2.da3src.src0_swizzle >> 2) & 0x3; |
GLuint swz_z = (inst->bits2.da3src.src0_swizzle >> 4) & 0x3; |
GLuint swz_w = (inst->bits2.da3src.src0_swizzle >> 6) & 0x3; |
err |= control (file, "negate", negate, inst->bits1.da3src.src0_negate, NULL); |
err |= control (file, "abs", _abs, inst->bits1.da3src.src0_abs, NULL); |
err |= reg (file, BRW_GENERAL_REGISTER_FILE, inst->bits2.da3src.src0_reg_nr); |
if (err == -1) |
return 0; |
if (inst->bits2.da3src.src0_subreg_nr) |
format (file, ".%d", inst->bits2.da3src.src0_subreg_nr); |
string (file, "<4,1,1>"); |
err |= control (file, "src da16 reg type", reg_encoding, |
three_source_type_to_reg_type(inst->bits1.da3src.src_type), |
NULL); |
/* |
* Three kinds of swizzle display: |
* identity - nothing printed |
* 1->all - print the single channel |
* 1->1 - print the mapping |
*/ |
if (swz_x == BRW_CHANNEL_X && |
swz_y == BRW_CHANNEL_Y && |
swz_z == BRW_CHANNEL_Z && |
swz_w == BRW_CHANNEL_W) |
{ |
; |
} |
else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w) |
{ |
string (file, "."); |
err |= control (file, "channel select", chan_sel, swz_x, NULL); |
} |
else |
{ |
string (file, "."); |
err |= control (file, "channel select", chan_sel, swz_x, NULL); |
err |= control (file, "channel select", chan_sel, swz_y, NULL); |
err |= control (file, "channel select", chan_sel, swz_z, NULL); |
err |= control (file, "channel select", chan_sel, swz_w, NULL); |
} |
return err; |
} |
static int src1_3src (FILE *file, struct brw_instruction *inst) |
{ |
int err = 0; |
GLuint swz_x = (inst->bits2.da3src.src1_swizzle >> 0) & 0x3; |
GLuint swz_y = (inst->bits2.da3src.src1_swizzle >> 2) & 0x3; |
GLuint swz_z = (inst->bits2.da3src.src1_swizzle >> 4) & 0x3; |
GLuint swz_w = (inst->bits2.da3src.src1_swizzle >> 6) & 0x3; |
GLuint src1_subreg_nr = (inst->bits2.da3src.src1_subreg_nr_low | |
(inst->bits3.da3src.src1_subreg_nr_high << 2)); |
err |= control (file, "negate", negate, inst->bits1.da3src.src1_negate, |
NULL); |
err |= control (file, "abs", _abs, inst->bits1.da3src.src1_abs, NULL); |
err |= reg (file, BRW_GENERAL_REGISTER_FILE, |
inst->bits3.da3src.src1_reg_nr); |
if (err == -1) |
return 0; |
if (src1_subreg_nr) |
format (file, ".%d", src1_subreg_nr); |
string (file, "<4,1,1>"); |
err |= control (file, "src da16 reg type", reg_encoding, |
three_source_type_to_reg_type(inst->bits1.da3src.src_type), |
NULL); |
/* |
* Three kinds of swizzle display: |
* identity - nothing printed |
* 1->all - print the single channel |
* 1->1 - print the mapping |
*/ |
if (swz_x == BRW_CHANNEL_X && |
swz_y == BRW_CHANNEL_Y && |
swz_z == BRW_CHANNEL_Z && |
swz_w == BRW_CHANNEL_W) |
{ |
; |
} |
else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w) |
{ |
string (file, "."); |
err |= control (file, "channel select", chan_sel, swz_x, NULL); |
} |
else |
{ |
string (file, "."); |
err |= control (file, "channel select", chan_sel, swz_x, NULL); |
err |= control (file, "channel select", chan_sel, swz_y, NULL); |
err |= control (file, "channel select", chan_sel, swz_z, NULL); |
err |= control (file, "channel select", chan_sel, swz_w, NULL); |
} |
return err; |
} |
static int src2_3src (FILE *file, struct brw_instruction *inst) |
{ |
int err = 0; |
GLuint swz_x = (inst->bits3.da3src.src2_swizzle >> 0) & 0x3; |
GLuint swz_y = (inst->bits3.da3src.src2_swizzle >> 2) & 0x3; |
GLuint swz_z = (inst->bits3.da3src.src2_swizzle >> 4) & 0x3; |
GLuint swz_w = (inst->bits3.da3src.src2_swizzle >> 6) & 0x3; |
err |= control (file, "negate", negate, inst->bits1.da3src.src2_negate, |
NULL); |
err |= control (file, "abs", _abs, inst->bits1.da3src.src2_abs, NULL); |
err |= reg (file, BRW_GENERAL_REGISTER_FILE, |
inst->bits3.da3src.src2_reg_nr); |
if (err == -1) |
return 0; |
if (inst->bits3.da3src.src2_subreg_nr) |
format (file, ".%d", inst->bits3.da3src.src2_subreg_nr); |
string (file, "<4,1,1>"); |
err |= control (file, "src da16 reg type", reg_encoding, |
three_source_type_to_reg_type(inst->bits1.da3src.src_type), |
NULL); |
/* |
* Three kinds of swizzle display: |
* identity - nothing printed |
* 1->all - print the single channel |
* 1->1 - print the mapping |
*/ |
if (swz_x == BRW_CHANNEL_X && |
swz_y == BRW_CHANNEL_Y && |
swz_z == BRW_CHANNEL_Z && |
swz_w == BRW_CHANNEL_W) |
{ |
; |
} |
else if (swz_x == swz_y && swz_x == swz_z && swz_x == swz_w) |
{ |
string (file, "."); |
err |= control (file, "channel select", chan_sel, swz_x, NULL); |
} |
else |
{ |
string (file, "."); |
err |= control (file, "channel select", chan_sel, swz_x, NULL); |
err |= control (file, "channel select", chan_sel, swz_y, NULL); |
err |= control (file, "channel select", chan_sel, swz_z, NULL); |
err |= control (file, "channel select", chan_sel, swz_w, NULL); |
} |
return err; |
} |
static int imm (FILE *file, GLuint type, struct brw_instruction *inst) { |
switch (type) { |
case BRW_REGISTER_TYPE_UD: |
format (file, "0x%08xUD", inst->bits3.ud); |
break; |
case BRW_REGISTER_TYPE_D: |
format (file, "%dD", inst->bits3.d); |
break; |
case BRW_REGISTER_TYPE_UW: |
format (file, "0x%04xUW", (uint16_t) inst->bits3.ud); |
break; |
case BRW_REGISTER_TYPE_W: |
format (file, "%dW", (int16_t) inst->bits3.d); |
break; |
case BRW_REGISTER_TYPE_UB: |
format (file, "0x%02xUB", (int8_t) inst->bits3.ud); |
break; |
case BRW_REGISTER_TYPE_VF: |
format (file, "Vector Float"); |
break; |
case BRW_REGISTER_TYPE_V: |
format (file, "0x%08xV", inst->bits3.ud); |
break; |
case BRW_REGISTER_TYPE_F: |
format (file, "%-gF", inst->bits3.f); |
} |
return 0; |
} |
static int src0 (FILE *file, struct brw_instruction *inst) |
{ |
if (inst->bits1.da1.src0_reg_file == BRW_IMMEDIATE_VALUE) |
return imm (file, inst->bits1.da1.src0_reg_type, |
inst); |
else if (inst->header.access_mode == BRW_ALIGN_1) |
{ |
if (inst->bits2.da1.src0_address_mode == BRW_ADDRESS_DIRECT) |
{ |
return src_da1 (file, |
inst->bits1.da1.src0_reg_type, |
inst->bits1.da1.src0_reg_file, |
inst->bits2.da1.src0_vert_stride, |
inst->bits2.da1.src0_width, |
inst->bits2.da1.src0_horiz_stride, |
inst->bits2.da1.src0_reg_nr, |
inst->bits2.da1.src0_subreg_nr, |
inst->bits2.da1.src0_abs, |
inst->bits2.da1.src0_negate); |
} |
else |
{ |
return src_ia1 (file, |
inst->bits1.ia1.src0_reg_type, |
inst->bits1.ia1.src0_reg_file, |
inst->bits2.ia1.src0_indirect_offset, |
inst->bits2.ia1.src0_subreg_nr, |
inst->bits2.ia1.src0_negate, |
inst->bits2.ia1.src0_abs, |
inst->bits2.ia1.src0_address_mode, |
inst->bits2.ia1.src0_horiz_stride, |
inst->bits2.ia1.src0_width, |
inst->bits2.ia1.src0_vert_stride); |
} |
} |
else |
{ |
if (inst->bits2.da16.src0_address_mode == BRW_ADDRESS_DIRECT) |
{ |
return src_da16 (file, |
inst->bits1.da16.src0_reg_type, |
inst->bits1.da16.src0_reg_file, |
inst->bits2.da16.src0_vert_stride, |
inst->bits2.da16.src0_reg_nr, |
inst->bits2.da16.src0_subreg_nr, |
inst->bits2.da16.src0_abs, |
inst->bits2.da16.src0_negate, |
inst->bits2.da16.src0_swz_x, |
inst->bits2.da16.src0_swz_y, |
inst->bits2.da16.src0_swz_z, |
inst->bits2.da16.src0_swz_w); |
} |
else |
{ |
string (file, "Indirect align16 address mode not supported"); |
return 1; |
} |
} |
} |
static int src1 (FILE *file, struct brw_instruction *inst) |
{ |
if (inst->bits1.da1.src1_reg_file == BRW_IMMEDIATE_VALUE) |
return imm (file, inst->bits1.da1.src1_reg_type, |
inst); |
else if (inst->header.access_mode == BRW_ALIGN_1) |
{ |
if (inst->bits3.da1.src1_address_mode == BRW_ADDRESS_DIRECT) |
{ |
return src_da1 (file, |
inst->bits1.da1.src1_reg_type, |
inst->bits1.da1.src1_reg_file, |
inst->bits3.da1.src1_vert_stride, |
inst->bits3.da1.src1_width, |
inst->bits3.da1.src1_horiz_stride, |
inst->bits3.da1.src1_reg_nr, |
inst->bits3.da1.src1_subreg_nr, |
inst->bits3.da1.src1_abs, |
inst->bits3.da1.src1_negate); |
} |
else |
{ |
return src_ia1 (file, |
inst->bits1.ia1.src1_reg_type, |
inst->bits1.ia1.src1_reg_file, |
inst->bits3.ia1.src1_indirect_offset, |
inst->bits3.ia1.src1_subreg_nr, |
inst->bits3.ia1.src1_negate, |
inst->bits3.ia1.src1_abs, |
inst->bits3.ia1.src1_address_mode, |
inst->bits3.ia1.src1_horiz_stride, |
inst->bits3.ia1.src1_width, |
inst->bits3.ia1.src1_vert_stride); |
} |
} |
else |
{ |
if (inst->bits3.da16.src1_address_mode == BRW_ADDRESS_DIRECT) |
{ |
return src_da16 (file, |
inst->bits1.da16.src1_reg_type, |
inst->bits1.da16.src1_reg_file, |
inst->bits3.da16.src1_vert_stride, |
inst->bits3.da16.src1_reg_nr, |
inst->bits3.da16.src1_subreg_nr, |
inst->bits3.da16.src1_abs, |
inst->bits3.da16.src1_negate, |
inst->bits3.da16.src1_swz_x, |
inst->bits3.da16.src1_swz_y, |
inst->bits3.da16.src1_swz_z, |
inst->bits3.da16.src1_swz_w); |
} |
else |
{ |
string (file, "Indirect align16 address mode not supported"); |
return 1; |
} |
} |
} |
int esize[6] = { |
[0] = 1, |
[1] = 2, |
[2] = 4, |
[3] = 8, |
[4] = 16, |
[5] = 32, |
}; |
static int qtr_ctrl(FILE *file, struct brw_instruction *inst) |
{ |
int qtr_ctl = inst->header.compression_control; |
int exec_size = esize[inst->header.execution_size]; |
if (exec_size == 8) { |
switch (qtr_ctl) { |
case 0: |
string (file, " 1Q"); |
break; |
case 1: |
string (file, " 2Q"); |
break; |
case 2: |
string (file, " 3Q"); |
break; |
case 3: |
string (file, " 4Q"); |
break; |
} |
} else if (exec_size == 16){ |
if (qtr_ctl < 2) |
string (file, " 1H"); |
else |
string (file, " 2H"); |
} |
return 0; |
} |
int brw_disasm (FILE *file, struct brw_instruction *inst, int gen) |
{ |
int err = 0; |
int space = 0; |
if (inst->header.predicate_control) { |
string (file, "("); |
err |= control (file, "predicate inverse", pred_inv, inst->header.predicate_inverse, NULL); |
format (file, "f%d", gen >= 7 ? inst->bits2.da1.flag_reg_nr : 0); |
if (inst->bits2.da1.flag_subreg_nr) |
format (file, ".%d", inst->bits2.da1.flag_subreg_nr); |
if (inst->header.access_mode == BRW_ALIGN_1) |
err |= control (file, "predicate control align1", pred_ctrl_align1, |
inst->header.predicate_control, NULL); |
else |
err |= control (file, "predicate control align16", pred_ctrl_align16, |
inst->header.predicate_control, NULL); |
string (file, ") "); |
} |
err |= print_opcode (file, inst->header.opcode); |
err |= control (file, "saturate", saturate, inst->header.saturate, NULL); |
err |= control (file, "debug control", debug_ctrl, inst->header.debug_control, NULL); |
if (inst->header.opcode == BRW_OPCODE_MATH) { |
string (file, " "); |
err |= control (file, "function", math_function, |
inst->header.destreg__conditionalmod, NULL); |
} else if (inst->header.opcode != BRW_OPCODE_SEND && |
inst->header.opcode != BRW_OPCODE_SENDC) { |
err |= control (file, "conditional modifier", conditional_modifier, |
inst->header.destreg__conditionalmod, NULL); |
/* If we're using the conditional modifier, print which flags reg is |
* used for it. Note that on gen6+, the embedded-condition SEL and |
* control flow doesn't update flags. |
*/ |
if (inst->header.destreg__conditionalmod && |
(gen < 6 || (inst->header.opcode != BRW_OPCODE_SEL && |
inst->header.opcode != BRW_OPCODE_IF && |
inst->header.opcode != BRW_OPCODE_WHILE))) { |
format (file, ".f%d", gen >= 7 ? inst->bits2.da1.flag_reg_nr : 0); |
if (inst->bits2.da1.flag_subreg_nr) |
format (file, ".%d", inst->bits2.da1.flag_subreg_nr); |
} |
} |
if (inst->header.opcode != BRW_OPCODE_NOP) { |
string (file, "("); |
err |= control (file, "execution size", exec_size, inst->header.execution_size, NULL); |
string (file, ")"); |
} |
if (inst->header.opcode == BRW_OPCODE_SEND && gen < 6) |
format (file, " %d", inst->header.destreg__conditionalmod); |
if (opcode[inst->header.opcode].nsrc == 3) { |
pad (file, 16); |
err |= dest_3src (file, inst); |
pad (file, 32); |
err |= src0_3src (file, inst); |
pad (file, 48); |
err |= src1_3src (file, inst); |
pad (file, 64); |
err |= src2_3src (file, inst); |
} else { |
if (opcode[inst->header.opcode].ndst > 0) { |
pad (file, 16); |
err |= dest (file, inst); |
} else if (gen == 7 && (inst->header.opcode == BRW_OPCODE_ELSE || |
inst->header.opcode == BRW_OPCODE_ENDIF || |
inst->header.opcode == BRW_OPCODE_WHILE)) { |
format (file, " %d", inst->bits3.break_cont.jip); |
} else if (gen == 6 && (inst->header.opcode == BRW_OPCODE_IF || |
inst->header.opcode == BRW_OPCODE_ELSE || |
inst->header.opcode == BRW_OPCODE_ENDIF || |
inst->header.opcode == BRW_OPCODE_WHILE)) { |
format (file, " %d", inst->bits1.branch_gen6.jump_count); |
} else if ((gen >= 6 && (inst->header.opcode == BRW_OPCODE_BREAK || |
inst->header.opcode == BRW_OPCODE_CONTINUE || |
inst->header.opcode == BRW_OPCODE_HALT)) || |
(gen == 7 && inst->header.opcode == BRW_OPCODE_IF)) { |
format (file, " %d %d", inst->bits3.break_cont.uip, inst->bits3.break_cont.jip); |
} else if (inst->header.opcode == BRW_OPCODE_JMPI) { |
format (file, " %d", inst->bits3.d); |
} |
if (opcode[inst->header.opcode].nsrc > 0) { |
pad (file, 32); |
err |= src0 (file, inst); |
} |
if (opcode[inst->header.opcode].nsrc > 1) { |
pad (file, 48); |
err |= src1 (file, inst); |
} |
} |
if (inst->header.opcode == BRW_OPCODE_SEND || |
inst->header.opcode == BRW_OPCODE_SENDC) { |
enum brw_message_target target; |
if (gen >= 6) |
target = inst->header.destreg__conditionalmod; |
else if (gen == 5) |
target = inst->bits2.send_gen5.sfid; |
else |
target = inst->bits3.generic.msg_target; |
newline (file); |
pad (file, 16); |
space = 0; |
if (gen >= 6) { |
err |= control (file, "target function", target_function_gen6, |
target, &space); |
} else { |
err |= control (file, "target function", target_function, |
target, &space); |
} |
switch (target) { |
case BRW_SFID_MATH: |
err |= control (file, "math function", math_function, |
inst->bits3.math.function, &space); |
err |= control (file, "math saturate", math_saturate, |
inst->bits3.math.saturate, &space); |
err |= control (file, "math signed", math_signed, |
inst->bits3.math.int_type, &space); |
err |= control (file, "math scalar", math_scalar, |
inst->bits3.math.data_type, &space); |
err |= control (file, "math precision", math_precision, |
inst->bits3.math.precision, &space); |
break; |
case BRW_SFID_SAMPLER: |
if (gen >= 7) { |
format (file, " (%d, %d, %d, %d)", |
inst->bits3.sampler_gen7.binding_table_index, |
inst->bits3.sampler_gen7.sampler, |
inst->bits3.sampler_gen7.msg_type, |
inst->bits3.sampler_gen7.simd_mode); |
} else if (gen >= 5) { |
format (file, " (%d, %d, %d, %d)", |
inst->bits3.sampler_gen5.binding_table_index, |
inst->bits3.sampler_gen5.sampler, |
inst->bits3.sampler_gen5.msg_type, |
inst->bits3.sampler_gen5.simd_mode); |
} else if (0 /* FINISHME: is_g4x */) { |
format (file, " (%d, %d)", |
inst->bits3.sampler_g4x.binding_table_index, |
inst->bits3.sampler_g4x.sampler); |
} else { |
format (file, " (%d, %d, ", |
inst->bits3.sampler.binding_table_index, |
inst->bits3.sampler.sampler); |
err |= control (file, "sampler target format", |
sampler_target_format, |
inst->bits3.sampler.return_format, NULL); |
string (file, ")"); |
} |
break; |
case BRW_SFID_DATAPORT_READ: |
if (gen >= 6) { |
format (file, " (%d, %d, %d, %d)", |
inst->bits3.gen6_dp.binding_table_index, |
inst->bits3.gen6_dp.msg_control, |
inst->bits3.gen6_dp.msg_type, |
inst->bits3.gen6_dp.send_commit_msg); |
} else if (gen >= 5 /* FINISHME: || is_g4x */) { |
format (file, " (%d, %d, %d)", |
inst->bits3.dp_read_gen5.binding_table_index, |
inst->bits3.dp_read_gen5.msg_control, |
inst->bits3.dp_read_gen5.msg_type); |
} else { |
format (file, " (%d, %d, %d)", |
inst->bits3.dp_read.binding_table_index, |
inst->bits3.dp_read.msg_control, |
inst->bits3.dp_read.msg_type); |
} |
break; |
case BRW_SFID_DATAPORT_WRITE: |
if (gen >= 7) { |
format (file, " ("); |
err |= control (file, "DP rc message type", |
dp_rc_msg_type_gen6, |
inst->bits3.gen7_dp.msg_type, &space); |
format (file, ", %d, %d, %d)", |
inst->bits3.gen7_dp.binding_table_index, |
inst->bits3.gen7_dp.msg_control, |
inst->bits3.gen7_dp.msg_type); |
} else if (gen == 6) { |
format (file, " ("); |
err |= control (file, "DP rc message type", |
dp_rc_msg_type_gen6, |
inst->bits3.gen6_dp.msg_type, &space); |
format (file, ", %d, %d, %d, %d)", |
inst->bits3.gen6_dp.binding_table_index, |
inst->bits3.gen6_dp.msg_control, |
inst->bits3.gen6_dp.msg_type, |
inst->bits3.gen6_dp.send_commit_msg); |
} else { |
format (file, " (%d, %d, %d, %d)", |
inst->bits3.dp_write.binding_table_index, |
(inst->bits3.dp_write.last_render_target << 3) | |
inst->bits3.dp_write.msg_control, |
inst->bits3.dp_write.msg_type, |
inst->bits3.dp_write.send_commit_msg); |
} |
break; |
case BRW_SFID_URB: |
if (gen >= 5) { |
format (file, " %d", inst->bits3.urb_gen5.offset); |
} else { |
format (file, " %d", inst->bits3.urb.offset); |
} |
space = 1; |
if (gen >= 5) { |
err |= control (file, "urb opcode", urb_opcode, |
inst->bits3.urb_gen5.opcode, &space); |
} |
err |= control (file, "urb swizzle", urb_swizzle, |
inst->bits3.urb.swizzle_control, &space); |
err |= control (file, "urb allocate", urb_allocate, |
inst->bits3.urb.allocate, &space); |
err |= control (file, "urb used", urb_used, |
inst->bits3.urb.used, &space); |
err |= control (file, "urb complete", urb_complete, |
inst->bits3.urb.complete, &space); |
break; |
case BRW_SFID_THREAD_SPAWNER: |
break; |
case GEN7_SFID_DATAPORT_DATA_CACHE: |
format (file, " (%d, %d, %d)", |
inst->bits3.gen7_dp.binding_table_index, |
inst->bits3.gen7_dp.msg_control, |
inst->bits3.gen7_dp.msg_type); |
break; |
default: |
format (file, "unsupported target %d", target); |
break; |
} |
if (space) |
string (file, " "); |
if (gen >= 5) { |
format (file, "mlen %d", |
inst->bits3.generic_gen5.msg_length); |
format (file, " rlen %d", |
inst->bits3.generic_gen5.response_length); |
} else { |
format (file, "mlen %d", |
inst->bits3.generic.msg_length); |
format (file, " rlen %d", |
inst->bits3.generic.response_length); |
} |
} |
pad (file, 64); |
if (inst->header.opcode != BRW_OPCODE_NOP) { |
string (file, "{"); |
space = 1; |
err |= control(file, "access mode", access_mode, inst->header.access_mode, &space); |
if (gen >= 6) |
err |= control (file, "write enable control", wectrl, inst->header.mask_control, &space); |
else |
err |= control (file, "mask control", mask_ctrl, inst->header.mask_control, &space); |
err |= control (file, "dependency control", dep_ctrl, inst->header.dependency_control, &space); |
if (gen >= 6) |
err |= qtr_ctrl (file, inst); |
else { |
if (inst->header.compression_control == BRW_COMPRESSION_COMPRESSED && |
opcode[inst->header.opcode].ndst > 0 && |
inst->bits1.da1.dest_reg_file == BRW_MESSAGE_REGISTER_FILE && |
inst->bits1.da1.dest_reg_nr & (1 << 7)) { |
format (file, " compr4"); |
} else { |
err |= control (file, "compression control", compr_ctrl, |
inst->header.compression_control, &space); |
} |
} |
err |= control (file, "thread control", thread_ctrl, inst->header.thread_control, &space); |
if (gen >= 6) |
err |= control (file, "acc write control", accwr, inst->header.acc_wr_control, &space); |
if (inst->header.opcode == BRW_OPCODE_SEND || |
inst->header.opcode == BRW_OPCODE_SENDC) |
err |= control (file, "end of thread", end_of_thread, |
inst->bits3.generic.end_of_thread, &space); |
if (space) |
string (file, " "); |
string (file, "}"); |
} |
string (file, ";"); |
newline (file); |
return err; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_draw.c |
---|
0,0 → 1,566 |
/************************************************************************** |
* |
* 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 <sys/errno.h> |
#include "main/glheader.h" |
#include "main/context.h" |
#include "main/condrender.h" |
#include "main/samplerobj.h" |
#include "main/state.h" |
#include "main/enums.h" |
#include "main/macros.h" |
#include "main/transformfeedback.h" |
#include "tnl/tnl.h" |
#include "vbo/vbo_context.h" |
#include "swrast/swrast.h" |
#include "swrast_setup/swrast_setup.h" |
#include "drivers/common/meta.h" |
#include "brw_blorp.h" |
#include "brw_draw.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "intel_batchbuffer.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#define FILE_DEBUG_FLAG DEBUG_PRIMS |
static GLuint prim_to_hw_prim[GL_POLYGON+1] = { |
_3DPRIM_POINTLIST, |
_3DPRIM_LINELIST, |
_3DPRIM_LINELOOP, |
_3DPRIM_LINESTRIP, |
_3DPRIM_TRILIST, |
_3DPRIM_TRISTRIP, |
_3DPRIM_TRIFAN, |
_3DPRIM_QUADLIST, |
_3DPRIM_QUADSTRIP, |
_3DPRIM_POLYGON |
}; |
static const GLenum reduced_prim[GL_POLYGON+1] = { |
GL_POINTS, |
GL_LINES, |
GL_LINES, |
GL_LINES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES, |
GL_TRIANGLES |
}; |
/* When the primitive changes, set a state bit and re-validate. Not |
* the nicest and would rather deal with this by having all the |
* programs be immune to the active primitive (ie. cope with all |
* possibilities). That may not be realistic however. |
*/ |
static void brw_set_prim(struct brw_context *brw, |
const struct _mesa_prim *prim) |
{ |
struct gl_context *ctx = &brw->ctx; |
uint32_t hw_prim = prim_to_hw_prim[prim->mode]; |
DBG("PRIM: %s\n", _mesa_lookup_enum_by_nr(prim->mode)); |
/* Slight optimization to avoid the GS program when not needed: |
*/ |
if (prim->mode == GL_QUAD_STRIP && |
ctx->Light.ShadeModel != GL_FLAT && |
ctx->Polygon.FrontMode == GL_FILL && |
ctx->Polygon.BackMode == GL_FILL) |
hw_prim = _3DPRIM_TRISTRIP; |
if (prim->mode == GL_QUADS && prim->count == 4 && |
ctx->Light.ShadeModel != GL_FLAT && |
ctx->Polygon.FrontMode == GL_FILL && |
ctx->Polygon.BackMode == GL_FILL) { |
hw_prim = _3DPRIM_TRIFAN; |
} |
if (hw_prim != brw->primitive) { |
brw->primitive = hw_prim; |
brw->state.dirty.brw |= BRW_NEW_PRIMITIVE; |
if (reduced_prim[prim->mode] != brw->reduced_primitive) { |
brw->reduced_primitive = reduced_prim[prim->mode]; |
brw->state.dirty.brw |= BRW_NEW_REDUCED_PRIMITIVE; |
} |
} |
} |
static void gen6_set_prim(struct brw_context *brw, |
const struct _mesa_prim *prim) |
{ |
uint32_t hw_prim; |
DBG("PRIM: %s\n", _mesa_lookup_enum_by_nr(prim->mode)); |
hw_prim = prim_to_hw_prim[prim->mode]; |
if (hw_prim != brw->primitive) { |
brw->primitive = hw_prim; |
brw->state.dirty.brw |= BRW_NEW_PRIMITIVE; |
} |
} |
/** |
* The hardware is capable of removing dangling vertices on its own; however, |
* prior to Gen6, we sometimes convert quads into trifans (and quad strips |
* into tristrips), since pre-Gen6 hardware requires a GS to render quads. |
* This function manually trims dangling vertices from a draw call involving |
* quads so that those dangling vertices won't get drawn when we convert to |
* trifans/tristrips. |
*/ |
static GLuint trim(GLenum prim, GLuint length) |
{ |
if (prim == GL_QUAD_STRIP) |
return length > 3 ? (length - length % 2) : 0; |
else if (prim == GL_QUADS) |
return length - length % 4; |
else |
return length; |
} |
static void brw_emit_prim(struct brw_context *brw, |
const struct _mesa_prim *prim, |
uint32_t hw_prim) |
{ |
int verts_per_instance; |
int vertex_access_type; |
int start_vertex_location; |
int base_vertex_location; |
DBG("PRIM: %s %d %d\n", _mesa_lookup_enum_by_nr(prim->mode), |
prim->start, prim->count); |
start_vertex_location = prim->start; |
base_vertex_location = prim->basevertex; |
if (prim->indexed) { |
vertex_access_type = GEN4_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM; |
start_vertex_location += brw->ib.start_vertex_offset; |
base_vertex_location += brw->vb.start_vertex_bias; |
} else { |
vertex_access_type = GEN4_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL; |
start_vertex_location += brw->vb.start_vertex_bias; |
} |
/* We only need to trim the primitive count on pre-Gen6. */ |
if (brw->gen < 6) |
verts_per_instance = trim(prim->mode, prim->count); |
else |
verts_per_instance = prim->count; |
/* If nothing to emit, just return. */ |
if (verts_per_instance == 0) |
return; |
/* If we're set to always flush, do it before and after the primitive emit. |
* We want to catch both missed flushes that hurt instruction/state cache |
* and missed flushes of the render cache as it heads to other parts of |
* the besides the draw code. |
*/ |
if (brw->always_flush_cache) { |
intel_batchbuffer_emit_mi_flush(brw); |
} |
BEGIN_BATCH(6); |
OUT_BATCH(CMD_3D_PRIM << 16 | (6 - 2) | |
hw_prim << GEN4_3DPRIM_TOPOLOGY_TYPE_SHIFT | |
vertex_access_type); |
OUT_BATCH(verts_per_instance); |
OUT_BATCH(start_vertex_location); |
OUT_BATCH(prim->num_instances); |
OUT_BATCH(prim->base_instance); |
OUT_BATCH(base_vertex_location); |
ADVANCE_BATCH(); |
brw->batch.need_workaround_flush = true; |
if (brw->always_flush_cache) { |
intel_batchbuffer_emit_mi_flush(brw); |
} |
} |
static void gen7_emit_prim(struct brw_context *brw, |
const struct _mesa_prim *prim, |
uint32_t hw_prim) |
{ |
int verts_per_instance; |
int vertex_access_type; |
int start_vertex_location; |
int base_vertex_location; |
DBG("PRIM: %s %d %d\n", _mesa_lookup_enum_by_nr(prim->mode), |
prim->start, prim->count); |
start_vertex_location = prim->start; |
base_vertex_location = prim->basevertex; |
if (prim->indexed) { |
vertex_access_type = GEN7_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM; |
start_vertex_location += brw->ib.start_vertex_offset; |
base_vertex_location += brw->vb.start_vertex_bias; |
} else { |
vertex_access_type = GEN7_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL; |
start_vertex_location += brw->vb.start_vertex_bias; |
} |
verts_per_instance = prim->count; |
/* If nothing to emit, just return. */ |
if (verts_per_instance == 0) |
return; |
/* If we're set to always flush, do it before and after the primitive emit. |
* We want to catch both missed flushes that hurt instruction/state cache |
* and missed flushes of the render cache as it heads to other parts of |
* the besides the draw code. |
*/ |
if (brw->always_flush_cache) { |
intel_batchbuffer_emit_mi_flush(brw); |
} |
BEGIN_BATCH(7); |
OUT_BATCH(CMD_3D_PRIM << 16 | (7 - 2)); |
OUT_BATCH(hw_prim | vertex_access_type); |
OUT_BATCH(verts_per_instance); |
OUT_BATCH(start_vertex_location); |
OUT_BATCH(prim->num_instances); |
OUT_BATCH(prim->base_instance); |
OUT_BATCH(base_vertex_location); |
ADVANCE_BATCH(); |
if (brw->always_flush_cache) { |
intel_batchbuffer_emit_mi_flush(brw); |
} |
} |
static void brw_merge_inputs( struct brw_context *brw, |
const struct gl_client_array *arrays[]) |
{ |
GLuint i; |
for (i = 0; i < brw->vb.nr_buffers; i++) { |
drm_intel_bo_unreference(brw->vb.buffers[i].bo); |
brw->vb.buffers[i].bo = NULL; |
} |
brw->vb.nr_buffers = 0; |
for (i = 0; i < VERT_ATTRIB_MAX; i++) { |
brw->vb.inputs[i].buffer = -1; |
brw->vb.inputs[i].glarray = arrays[i]; |
brw->vb.inputs[i].attrib = (gl_vert_attrib) i; |
} |
} |
/* |
* \brief Resolve buffers before drawing. |
* |
* Resolve the depth buffer's HiZ buffer and resolve the depth buffer of each |
* enabled depth texture. |
* |
* (In the future, this will also perform MSAA resolves). |
*/ |
static void |
brw_predraw_resolve_buffers(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct intel_renderbuffer *depth_irb; |
struct intel_texture_object *tex_obj; |
/* Resolve the depth buffer's HiZ buffer. */ |
depth_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH); |
if (depth_irb) |
intel_renderbuffer_resolve_hiz(brw, depth_irb); |
/* Resolve depth buffer of each enabled depth texture, and color buffer of |
* each fast-clear-enabled color texture. |
*/ |
for (int i = 0; i < BRW_MAX_TEX_UNIT; i++) { |
if (!ctx->Texture.Unit[i]._ReallyEnabled) |
continue; |
tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current); |
if (!tex_obj || !tex_obj->mt) |
continue; |
intel_miptree_all_slices_resolve_depth(brw, tex_obj->mt); |
intel_miptree_resolve_color(brw, tex_obj->mt); |
} |
} |
/** |
* \brief Call this after drawing to mark which buffers need resolving |
* |
* If the depth buffer was written to and if it has an accompanying HiZ |
* buffer, then mark that it needs a depth resolve. |
* |
* If the color buffer is a multisample window system buffer, then |
* mark that it needs a downsample. |
*/ |
static void brw_postdraw_set_buffers_need_resolve(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct intel_renderbuffer *front_irb = NULL; |
struct intel_renderbuffer *back_irb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); |
struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(fb, BUFFER_DEPTH); |
if (brw->is_front_buffer_rendering) |
front_irb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
if (front_irb) |
intel_renderbuffer_set_needs_downsample(front_irb); |
if (back_irb) |
intel_renderbuffer_set_needs_downsample(back_irb); |
if (depth_irb && ctx->Depth.Mask) |
intel_renderbuffer_set_needs_depth_resolve(depth_irb); |
} |
/* May fail if out of video memory for texture or vbo upload, or on |
* fallback conditions. |
*/ |
static bool brw_try_draw_prims( struct gl_context *ctx, |
const struct gl_client_array *arrays[], |
const struct _mesa_prim *prim, |
GLuint nr_prims, |
const struct _mesa_index_buffer *ib, |
GLuint min_index, |
GLuint max_index ) |
{ |
struct brw_context *brw = brw_context(ctx); |
bool retval = true; |
GLuint i; |
bool fail_next = false; |
if (ctx->NewState) |
_mesa_update_state( ctx ); |
/* We have to validate the textures *before* checking for fallbacks; |
* otherwise, the software fallback won't be able to rely on the |
* texture state, the firstLevel and lastLevel fields won't be |
* set in the intel texture object (they'll both be 0), and the |
* software fallback will segfault if it attempts to access any |
* texture level other than level 0. |
*/ |
brw_validate_textures( brw ); |
intel_prepare_render(brw); |
/* This workaround has to happen outside of brw_upload_state() because it |
* may flush the batchbuffer for a blit, affecting the state flags. |
*/ |
brw_workaround_depthstencil_alignment(brw, 0); |
/* Resolves must occur after updating renderbuffers, updating context state, |
* and finalizing textures but before setting up any hardware state for |
* this draw call. |
*/ |
brw_predraw_resolve_buffers(brw); |
/* Bind all inputs, derive varying and size information: |
*/ |
brw_merge_inputs( brw, arrays ); |
brw->ib.ib = ib; |
brw->state.dirty.brw |= BRW_NEW_INDICES; |
brw->vb.min_index = min_index; |
brw->vb.max_index = max_index; |
brw->state.dirty.brw |= BRW_NEW_VERTICES; |
for (i = 0; i < nr_prims; i++) { |
int estimated_max_prim_size; |
estimated_max_prim_size = 512; /* batchbuffer commands */ |
estimated_max_prim_size += (BRW_MAX_TEX_UNIT * |
(sizeof(struct brw_sampler_state) + |
sizeof(struct gen5_sampler_default_color))); |
estimated_max_prim_size += 1024; /* gen6 VS push constants */ |
estimated_max_prim_size += 1024; /* gen6 WM push constants */ |
estimated_max_prim_size += 512; /* misc. pad */ |
/* Flush the batch if it's approaching full, so that we don't wrap while |
* we've got validated state that needs to be in the same batch as the |
* primitives. |
*/ |
intel_batchbuffer_require_space(brw, estimated_max_prim_size, false); |
intel_batchbuffer_save_state(brw); |
if (brw->num_instances != prim->num_instances) { |
brw->num_instances = prim->num_instances; |
brw->state.dirty.brw |= BRW_NEW_VERTICES; |
} |
if (brw->basevertex != prim->basevertex) { |
brw->basevertex = prim->basevertex; |
brw->state.dirty.brw |= BRW_NEW_VERTICES; |
} |
if (brw->gen < 6) |
brw_set_prim(brw, &prim[i]); |
else |
gen6_set_prim(brw, &prim[i]); |
retry: |
/* Note that before the loop, brw->state.dirty.brw was set to != 0, and |
* that the state updated in the loop outside of this block is that in |
* *_set_prim or intel_batchbuffer_flush(), which only impacts |
* brw->state.dirty.brw. |
*/ |
if (brw->state.dirty.brw) { |
brw->no_batch_wrap = true; |
brw_upload_state(brw); |
} |
if (brw->gen >= 7) |
gen7_emit_prim(brw, &prim[i], brw->primitive); |
else |
brw_emit_prim(brw, &prim[i], brw->primitive); |
brw->no_batch_wrap = false; |
if (dri_bufmgr_check_aperture_space(&brw->batch.bo, 1)) { |
if (!fail_next) { |
intel_batchbuffer_reset_to_saved(brw); |
intel_batchbuffer_flush(brw); |
fail_next = true; |
goto retry; |
} else { |
if (intel_batchbuffer_flush(brw) == -ENOSPC) { |
static bool warned = false; |
if (!warned) { |
fprintf(stderr, "i965: Single primitive emit exceeded" |
"available aperture space\n"); |
warned = true; |
} |
retval = false; |
} |
} |
} |
} |
if (brw->always_flush_batch) |
intel_batchbuffer_flush(brw); |
brw_state_cache_check_size(brw); |
brw_postdraw_set_buffers_need_resolve(brw); |
return retval; |
} |
void brw_draw_prims( struct gl_context *ctx, |
const struct _mesa_prim *prim, |
GLuint nr_prims, |
const struct _mesa_index_buffer *ib, |
GLboolean index_bounds_valid, |
GLuint min_index, |
GLuint max_index, |
struct gl_transform_feedback_object *tfb_vertcount ) |
{ |
struct brw_context *brw = brw_context(ctx); |
const struct gl_client_array **arrays = ctx->Array._DrawArrays; |
if (!_mesa_check_conditional_render(ctx)) |
return; |
/* Handle primitive restart if needed */ |
if (brw_handle_primitive_restart(ctx, prim, nr_prims, ib)) { |
/* The draw was handled, so we can exit now */ |
return; |
} |
/* If we're going to have to upload any of the user's vertex arrays, then |
* get the minimum and maximum of their index buffer so we know what range |
* to upload. |
*/ |
if (!vbo_all_varyings_in_vbos(arrays) && !index_bounds_valid) |
vbo_get_minmax_indices(ctx, prim, ib, &min_index, &max_index, nr_prims); |
/* Do GL_SELECT and GL_FEEDBACK rendering using swrast, even though it |
* won't support all the extensions we support. |
*/ |
if (ctx->RenderMode != GL_RENDER) { |
perf_debug("%s render mode not supported in hardware\n", |
_mesa_lookup_enum_by_nr(ctx->RenderMode)); |
_swsetup_Wakeup(ctx); |
_tnl_wakeup(ctx); |
_tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); |
return; |
} |
/* Try drawing with the hardware, but don't do anything else if we can't |
* manage it. swrast doesn't support our featureset, so we can't fall back |
* to it. |
*/ |
brw_try_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); |
} |
void brw_draw_init( struct brw_context *brw ) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct vbo_context *vbo = vbo_context(ctx); |
int i; |
/* Register our drawing function: |
*/ |
vbo->draw_prims = brw_draw_prims; |
for (i = 0; i < VERT_ATTRIB_MAX; i++) |
brw->vb.inputs[i].buffer = -1; |
brw->vb.nr_buffers = 0; |
brw->vb.nr_enabled = 0; |
} |
void brw_draw_destroy( struct brw_context *brw ) |
{ |
int i; |
for (i = 0; i < brw->vb.nr_buffers; i++) { |
drm_intel_bo_unreference(brw->vb.buffers[i].bo); |
brw->vb.buffers[i].bo = NULL; |
} |
brw->vb.nr_buffers = 0; |
for (i = 0; i < brw->vb.nr_enabled; i++) { |
brw->vb.enabled[i]->buffer = -1; |
} |
brw->vb.nr_enabled = 0; |
drm_intel_bo_unreference(brw->ib.bo); |
brw->ib.bo = NULL; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_draw.h |
---|
0,0 → 1,56 |
/************************************************************************** |
* |
* Copyright 2005 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 BRW_DRAW_H |
#define BRW_DRAW_H |
#include "main/mtypes.h" /* for struct gl_context... */ |
#include "vbo/vbo.h" |
struct brw_context; |
void brw_draw_prims( struct gl_context *ctx, |
const struct _mesa_prim *prims, |
GLuint nr_prims, |
const struct _mesa_index_buffer *ib, |
GLboolean index_bounds_valid, |
GLuint min_index, |
GLuint max_index, |
struct gl_transform_feedback_object *tfb_vertcount ); |
void brw_draw_init( struct brw_context *brw ); |
void brw_draw_destroy( struct brw_context *brw ); |
/* brw_primitive_restart.c */ |
GLboolean |
brw_handle_primitive_restart(struct gl_context *ctx, |
const struct _mesa_prim *prim, |
GLuint nr_prims, |
const struct _mesa_index_buffer *ib); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_draw_upload.c |
---|
0,0 → 1,921 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/bufferobj.h" |
#include "main/context.h" |
#include "main/enums.h" |
#include "main/macros.h" |
#include "main/glformats.h" |
#include "brw_draw.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "intel_batchbuffer.h" |
#include "intel_buffer_objects.h" |
static GLuint double_types[5] = { |
0, |
BRW_SURFACEFORMAT_R64_FLOAT, |
BRW_SURFACEFORMAT_R64G64_FLOAT, |
BRW_SURFACEFORMAT_R64G64B64_FLOAT, |
BRW_SURFACEFORMAT_R64G64B64A64_FLOAT |
}; |
static GLuint float_types[5] = { |
0, |
BRW_SURFACEFORMAT_R32_FLOAT, |
BRW_SURFACEFORMAT_R32G32_FLOAT, |
BRW_SURFACEFORMAT_R32G32B32_FLOAT, |
BRW_SURFACEFORMAT_R32G32B32A32_FLOAT |
}; |
static GLuint half_float_types[5] = { |
0, |
BRW_SURFACEFORMAT_R16_FLOAT, |
BRW_SURFACEFORMAT_R16G16_FLOAT, |
BRW_SURFACEFORMAT_R16G16B16A16_FLOAT, |
BRW_SURFACEFORMAT_R16G16B16A16_FLOAT |
}; |
static GLuint fixed_point_types[5] = { |
0, |
BRW_SURFACEFORMAT_R32_SFIXED, |
BRW_SURFACEFORMAT_R32G32_SFIXED, |
BRW_SURFACEFORMAT_R32G32B32_SFIXED, |
BRW_SURFACEFORMAT_R32G32B32A32_SFIXED, |
}; |
static GLuint uint_types_direct[5] = { |
0, |
BRW_SURFACEFORMAT_R32_UINT, |
BRW_SURFACEFORMAT_R32G32_UINT, |
BRW_SURFACEFORMAT_R32G32B32_UINT, |
BRW_SURFACEFORMAT_R32G32B32A32_UINT |
}; |
static GLuint uint_types_norm[5] = { |
0, |
BRW_SURFACEFORMAT_R32_UNORM, |
BRW_SURFACEFORMAT_R32G32_UNORM, |
BRW_SURFACEFORMAT_R32G32B32_UNORM, |
BRW_SURFACEFORMAT_R32G32B32A32_UNORM |
}; |
static GLuint uint_types_scale[5] = { |
0, |
BRW_SURFACEFORMAT_R32_USCALED, |
BRW_SURFACEFORMAT_R32G32_USCALED, |
BRW_SURFACEFORMAT_R32G32B32_USCALED, |
BRW_SURFACEFORMAT_R32G32B32A32_USCALED |
}; |
static GLuint int_types_direct[5] = { |
0, |
BRW_SURFACEFORMAT_R32_SINT, |
BRW_SURFACEFORMAT_R32G32_SINT, |
BRW_SURFACEFORMAT_R32G32B32_SINT, |
BRW_SURFACEFORMAT_R32G32B32A32_SINT |
}; |
static GLuint int_types_norm[5] = { |
0, |
BRW_SURFACEFORMAT_R32_SNORM, |
BRW_SURFACEFORMAT_R32G32_SNORM, |
BRW_SURFACEFORMAT_R32G32B32_SNORM, |
BRW_SURFACEFORMAT_R32G32B32A32_SNORM |
}; |
static GLuint int_types_scale[5] = { |
0, |
BRW_SURFACEFORMAT_R32_SSCALED, |
BRW_SURFACEFORMAT_R32G32_SSCALED, |
BRW_SURFACEFORMAT_R32G32B32_SSCALED, |
BRW_SURFACEFORMAT_R32G32B32A32_SSCALED |
}; |
static GLuint ushort_types_direct[5] = { |
0, |
BRW_SURFACEFORMAT_R16_UINT, |
BRW_SURFACEFORMAT_R16G16_UINT, |
BRW_SURFACEFORMAT_R16G16B16A16_UINT, |
BRW_SURFACEFORMAT_R16G16B16A16_UINT |
}; |
static GLuint ushort_types_norm[5] = { |
0, |
BRW_SURFACEFORMAT_R16_UNORM, |
BRW_SURFACEFORMAT_R16G16_UNORM, |
BRW_SURFACEFORMAT_R16G16B16_UNORM, |
BRW_SURFACEFORMAT_R16G16B16A16_UNORM |
}; |
static GLuint ushort_types_scale[5] = { |
0, |
BRW_SURFACEFORMAT_R16_USCALED, |
BRW_SURFACEFORMAT_R16G16_USCALED, |
BRW_SURFACEFORMAT_R16G16B16_USCALED, |
BRW_SURFACEFORMAT_R16G16B16A16_USCALED |
}; |
static GLuint short_types_direct[5] = { |
0, |
BRW_SURFACEFORMAT_R16_SINT, |
BRW_SURFACEFORMAT_R16G16_SINT, |
BRW_SURFACEFORMAT_R16G16B16A16_SINT, |
BRW_SURFACEFORMAT_R16G16B16A16_SINT |
}; |
static GLuint short_types_norm[5] = { |
0, |
BRW_SURFACEFORMAT_R16_SNORM, |
BRW_SURFACEFORMAT_R16G16_SNORM, |
BRW_SURFACEFORMAT_R16G16B16_SNORM, |
BRW_SURFACEFORMAT_R16G16B16A16_SNORM |
}; |
static GLuint short_types_scale[5] = { |
0, |
BRW_SURFACEFORMAT_R16_SSCALED, |
BRW_SURFACEFORMAT_R16G16_SSCALED, |
BRW_SURFACEFORMAT_R16G16B16_SSCALED, |
BRW_SURFACEFORMAT_R16G16B16A16_SSCALED |
}; |
static GLuint ubyte_types_direct[5] = { |
0, |
BRW_SURFACEFORMAT_R8_UINT, |
BRW_SURFACEFORMAT_R8G8_UINT, |
BRW_SURFACEFORMAT_R8G8B8A8_UINT, |
BRW_SURFACEFORMAT_R8G8B8A8_UINT |
}; |
static GLuint ubyte_types_norm[5] = { |
0, |
BRW_SURFACEFORMAT_R8_UNORM, |
BRW_SURFACEFORMAT_R8G8_UNORM, |
BRW_SURFACEFORMAT_R8G8B8_UNORM, |
BRW_SURFACEFORMAT_R8G8B8A8_UNORM |
}; |
static GLuint ubyte_types_scale[5] = { |
0, |
BRW_SURFACEFORMAT_R8_USCALED, |
BRW_SURFACEFORMAT_R8G8_USCALED, |
BRW_SURFACEFORMAT_R8G8B8_USCALED, |
BRW_SURFACEFORMAT_R8G8B8A8_USCALED |
}; |
static GLuint byte_types_direct[5] = { |
0, |
BRW_SURFACEFORMAT_R8_SINT, |
BRW_SURFACEFORMAT_R8G8_SINT, |
BRW_SURFACEFORMAT_R8G8B8A8_SINT, |
BRW_SURFACEFORMAT_R8G8B8A8_SINT |
}; |
static GLuint byte_types_norm[5] = { |
0, |
BRW_SURFACEFORMAT_R8_SNORM, |
BRW_SURFACEFORMAT_R8G8_SNORM, |
BRW_SURFACEFORMAT_R8G8B8_SNORM, |
BRW_SURFACEFORMAT_R8G8B8A8_SNORM |
}; |
static GLuint byte_types_scale[5] = { |
0, |
BRW_SURFACEFORMAT_R8_SSCALED, |
BRW_SURFACEFORMAT_R8G8_SSCALED, |
BRW_SURFACEFORMAT_R8G8B8_SSCALED, |
BRW_SURFACEFORMAT_R8G8B8A8_SSCALED |
}; |
/** |
* Given vertex array type/size/format/normalized info, return |
* the appopriate hardware surface type. |
* Format will be GL_RGBA or possibly GL_BGRA for GLubyte[4] color arrays. |
*/ |
static unsigned |
get_surface_type(struct brw_context *brw, |
const struct gl_client_array *glarray) |
{ |
int size = glarray->Size; |
if (unlikely(INTEL_DEBUG & DEBUG_VERTS)) |
printf("type %s size %d normalized %d\n", |
_mesa_lookup_enum_by_nr(glarray->Type), |
glarray->Size, glarray->Normalized); |
if (glarray->Integer) { |
assert(glarray->Format == GL_RGBA); /* sanity check */ |
switch (glarray->Type) { |
case GL_INT: return int_types_direct[size]; |
case GL_SHORT: return short_types_direct[size]; |
case GL_BYTE: return byte_types_direct[size]; |
case GL_UNSIGNED_INT: return uint_types_direct[size]; |
case GL_UNSIGNED_SHORT: return ushort_types_direct[size]; |
case GL_UNSIGNED_BYTE: return ubyte_types_direct[size]; |
default: assert(0); return 0; |
} |
} else if (glarray->Normalized) { |
switch (glarray->Type) { |
case GL_DOUBLE: return double_types[size]; |
case GL_FLOAT: return float_types[size]; |
case GL_HALF_FLOAT: return half_float_types[size]; |
case GL_INT: return int_types_norm[size]; |
case GL_SHORT: return short_types_norm[size]; |
case GL_BYTE: return byte_types_norm[size]; |
case GL_UNSIGNED_INT: return uint_types_norm[size]; |
case GL_UNSIGNED_SHORT: return ushort_types_norm[size]; |
case GL_UNSIGNED_BYTE: |
if (glarray->Format == GL_BGRA) { |
/* See GL_EXT_vertex_array_bgra */ |
assert(size == 4); |
return BRW_SURFACEFORMAT_B8G8R8A8_UNORM; |
} |
else { |
return ubyte_types_norm[size]; |
} |
case GL_FIXED: |
if (brw->gen >= 8 || brw->is_haswell) |
return fixed_point_types[size]; |
/* This produces GL_FIXED inputs as values between INT32_MIN and |
* INT32_MAX, which will be scaled down by 1/65536 by the VS. |
*/ |
return int_types_scale[size]; |
/* See GL_ARB_vertex_type_2_10_10_10_rev. |
* W/A: Pre-Haswell, the hardware doesn't really support the formats we'd |
* like to use here, so upload everything as UINT and fix |
* it in the shader |
*/ |
case GL_INT_2_10_10_10_REV: |
assert(size == 4); |
if (brw->gen >= 8 || brw->is_haswell) { |
return glarray->Format == GL_BGRA |
? BRW_SURFACEFORMAT_B10G10R10A2_SNORM |
: BRW_SURFACEFORMAT_R10G10B10A2_SNORM; |
} |
return BRW_SURFACEFORMAT_R10G10B10A2_UINT; |
case GL_UNSIGNED_INT_2_10_10_10_REV: |
assert(size == 4); |
if (brw->gen >= 8 || brw->is_haswell) { |
return glarray->Format == GL_BGRA |
? BRW_SURFACEFORMAT_B10G10R10A2_UNORM |
: BRW_SURFACEFORMAT_R10G10B10A2_UNORM; |
} |
return BRW_SURFACEFORMAT_R10G10B10A2_UINT; |
default: assert(0); return 0; |
} |
} |
else { |
/* See GL_ARB_vertex_type_2_10_10_10_rev. |
* W/A: the hardware doesn't really support the formats we'd |
* like to use here, so upload everything as UINT and fix |
* it in the shader |
*/ |
if (glarray->Type == GL_INT_2_10_10_10_REV) { |
assert(size == 4); |
if (brw->gen >= 8 || brw->is_haswell) { |
return glarray->Format == GL_BGRA |
? BRW_SURFACEFORMAT_B10G10R10A2_SSCALED |
: BRW_SURFACEFORMAT_R10G10B10A2_SSCALED; |
} |
return BRW_SURFACEFORMAT_R10G10B10A2_UINT; |
} else if (glarray->Type == GL_UNSIGNED_INT_2_10_10_10_REV) { |
assert(size == 4); |
if (brw->gen >= 8 || brw->is_haswell) { |
return glarray->Format == GL_BGRA |
? BRW_SURFACEFORMAT_B10G10R10A2_USCALED |
: BRW_SURFACEFORMAT_R10G10B10A2_USCALED; |
} |
return BRW_SURFACEFORMAT_R10G10B10A2_UINT; |
} |
assert(glarray->Format == GL_RGBA); /* sanity check */ |
switch (glarray->Type) { |
case GL_DOUBLE: return double_types[size]; |
case GL_FLOAT: return float_types[size]; |
case GL_HALF_FLOAT: return half_float_types[size]; |
case GL_INT: return int_types_scale[size]; |
case GL_SHORT: return short_types_scale[size]; |
case GL_BYTE: return byte_types_scale[size]; |
case GL_UNSIGNED_INT: return uint_types_scale[size]; |
case GL_UNSIGNED_SHORT: return ushort_types_scale[size]; |
case GL_UNSIGNED_BYTE: return ubyte_types_scale[size]; |
case GL_FIXED: |
if (brw->gen >= 8 || brw->is_haswell) |
return fixed_point_types[size]; |
/* This produces GL_FIXED inputs as values between INT32_MIN and |
* INT32_MAX, which will be scaled down by 1/65536 by the VS. |
*/ |
return int_types_scale[size]; |
default: assert(0); return 0; |
} |
} |
} |
static GLuint get_index_type(GLenum type) |
{ |
switch (type) { |
case GL_UNSIGNED_BYTE: return BRW_INDEX_BYTE; |
case GL_UNSIGNED_SHORT: return BRW_INDEX_WORD; |
case GL_UNSIGNED_INT: return BRW_INDEX_DWORD; |
default: assert(0); return 0; |
} |
} |
static void |
copy_array_to_vbo_array(struct brw_context *brw, |
struct brw_vertex_element *element, |
int min, int max, |
struct brw_vertex_buffer *buffer, |
GLuint dst_stride) |
{ |
const int src_stride = element->glarray->StrideB; |
/* If the source stride is zero, we just want to upload the current |
* attribute once and set the buffer's stride to 0. There's no need |
* to replicate it out. |
*/ |
if (src_stride == 0) { |
intel_upload_data(brw, element->glarray->Ptr, |
element->glarray->_ElementSize, |
element->glarray->_ElementSize, |
&buffer->bo, &buffer->offset); |
buffer->stride = 0; |
return; |
} |
const unsigned char *src = element->glarray->Ptr + min * src_stride; |
int count = max - min + 1; |
GLuint size = count * dst_stride; |
if (dst_stride == src_stride) { |
intel_upload_data(brw, src, size, dst_stride, |
&buffer->bo, &buffer->offset); |
} else { |
char * const map = intel_upload_map(brw, size, dst_stride); |
char *dst = map; |
while (count--) { |
memcpy(dst, src, dst_stride); |
src += src_stride; |
dst += dst_stride; |
} |
intel_upload_unmap(brw, map, size, dst_stride, |
&buffer->bo, &buffer->offset); |
} |
buffer->stride = dst_stride; |
} |
static void brw_prepare_vertices(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* CACHE_NEW_VS_PROG */ |
GLbitfield64 vs_inputs = brw->vs.prog_data->inputs_read; |
const unsigned char *ptr = NULL; |
GLuint interleaved = 0; |
unsigned int min_index = brw->vb.min_index + brw->basevertex; |
unsigned int max_index = brw->vb.max_index + brw->basevertex; |
int delta, i, j; |
struct brw_vertex_element *upload[VERT_ATTRIB_MAX]; |
GLuint nr_uploads = 0; |
/* _NEW_POLYGON |
* |
* On gen6+, edge flags don't end up in the VUE (either in or out of the |
* VS). Instead, they're uploaded as the last vertex element, and the data |
* is passed sideband through the fixed function units. So, we need to |
* prepare the vertex buffer for it, but it's not present in inputs_read. |
*/ |
if (brw->gen >= 6 && (ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL)) { |
vs_inputs |= VERT_BIT_EDGEFLAG; |
} |
if (0) |
printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); |
/* Accumulate the list of enabled arrays. */ |
brw->vb.nr_enabled = 0; |
while (vs_inputs) { |
GLuint i = ffsll(vs_inputs) - 1; |
struct brw_vertex_element *input = &brw->vb.inputs[i]; |
vs_inputs &= ~BITFIELD64_BIT(i); |
brw->vb.enabled[brw->vb.nr_enabled++] = input; |
} |
if (brw->vb.nr_enabled == 0) |
return; |
if (brw->vb.nr_buffers) |
return; |
for (i = j = 0; i < brw->vb.nr_enabled; i++) { |
struct brw_vertex_element *input = brw->vb.enabled[i]; |
const struct gl_client_array *glarray = input->glarray; |
if (_mesa_is_bufferobj(glarray->BufferObj)) { |
struct intel_buffer_object *intel_buffer = |
intel_buffer_object(glarray->BufferObj); |
int k; |
/* If we have a VB set to be uploaded for this buffer object |
* already, reuse that VB state so that we emit fewer |
* relocations. |
*/ |
for (k = 0; k < i; k++) { |
const struct gl_client_array *other = brw->vb.enabled[k]->glarray; |
if (glarray->BufferObj == other->BufferObj && |
glarray->StrideB == other->StrideB && |
glarray->InstanceDivisor == other->InstanceDivisor && |
(uintptr_t)(glarray->Ptr - other->Ptr) < glarray->StrideB) |
{ |
input->buffer = brw->vb.enabled[k]->buffer; |
input->offset = glarray->Ptr - other->Ptr; |
break; |
} |
} |
if (k == i) { |
struct brw_vertex_buffer *buffer = &brw->vb.buffers[j]; |
/* Named buffer object: Just reference its contents directly. */ |
buffer->bo = intel_bufferobj_source(brw, |
intel_buffer, 1, |
&buffer->offset); |
drm_intel_bo_reference(buffer->bo); |
buffer->offset += (uintptr_t)glarray->Ptr; |
buffer->stride = glarray->StrideB; |
buffer->step_rate = glarray->InstanceDivisor; |
input->buffer = j++; |
input->offset = 0; |
} |
/* This is a common place to reach if the user mistakenly supplies |
* a pointer in place of a VBO offset. If we just let it go through, |
* we may end up dereferencing a pointer beyond the bounds of the |
* GTT. We would hope that the VBO's max_index would save us, but |
* Mesa appears to hand us min/max values not clipped to the |
* array object's _MaxElement, and _MaxElement frequently appears |
* to be wrong anyway. |
* |
* The VBO spec allows application termination in this case, and it's |
* probably a service to the poor programmer to do so rather than |
* trying to just not render. |
*/ |
assert(input->offset < brw->vb.buffers[input->buffer].bo->size); |
} else { |
/* Queue the buffer object up to be uploaded in the next pass, |
* when we've decided if we're doing interleaved or not. |
*/ |
if (nr_uploads == 0) { |
interleaved = glarray->StrideB; |
ptr = glarray->Ptr; |
} |
else if (interleaved != glarray->StrideB || |
glarray->Ptr < ptr || |
(uintptr_t)(glarray->Ptr - ptr) + glarray->_ElementSize > interleaved) |
{ |
/* If our stride is different from the first attribute's stride, |
* or if the first attribute's stride didn't cover our element, |
* disable the interleaved upload optimization. The second case |
* can most commonly occur in cases where there is a single vertex |
* and, for example, the data is stored on the application's |
* stack. |
* |
* NOTE: This will also disable the optimization in cases where |
* the data is in a different order than the array indices. |
* Something like: |
* |
* float data[...]; |
* glVertexAttribPointer(0, 4, GL_FLOAT, 32, &data[4]); |
* glVertexAttribPointer(1, 4, GL_FLOAT, 32, &data[0]); |
*/ |
interleaved = 0; |
} |
upload[nr_uploads++] = input; |
} |
} |
/* If we need to upload all the arrays, then we can trim those arrays to |
* only the used elements [min_index, max_index] so long as we adjust all |
* the values used in the 3DPRIMITIVE i.e. by setting the vertex bias. |
*/ |
brw->vb.start_vertex_bias = 0; |
delta = min_index; |
if (nr_uploads == brw->vb.nr_enabled) { |
brw->vb.start_vertex_bias = -delta; |
delta = 0; |
} |
/* Handle any arrays to be uploaded. */ |
if (nr_uploads > 1) { |
if (interleaved) { |
struct brw_vertex_buffer *buffer = &brw->vb.buffers[j]; |
/* All uploads are interleaved, so upload the arrays together as |
* interleaved. First, upload the contents and set up upload[0]. |
*/ |
copy_array_to_vbo_array(brw, upload[0], min_index, max_index, |
buffer, interleaved); |
buffer->offset -= delta * interleaved; |
for (i = 0; i < nr_uploads; i++) { |
/* Then, just point upload[i] at upload[0]'s buffer. */ |
upload[i]->offset = |
((const unsigned char *)upload[i]->glarray->Ptr - ptr); |
upload[i]->buffer = j; |
} |
j++; |
nr_uploads = 0; |
} |
} |
/* Upload non-interleaved arrays */ |
for (i = 0; i < nr_uploads; i++) { |
struct brw_vertex_buffer *buffer = &brw->vb.buffers[j]; |
if (upload[i]->glarray->InstanceDivisor == 0) { |
copy_array_to_vbo_array(brw, upload[i], min_index, max_index, |
buffer, upload[i]->glarray->_ElementSize); |
} else { |
/* This is an instanced attribute, since its InstanceDivisor |
* is not zero. Therefore, its data will be stepped after the |
* instanced draw has been run InstanceDivisor times. |
*/ |
uint32_t instanced_attr_max_index = |
(brw->num_instances - 1) / upload[i]->glarray->InstanceDivisor; |
copy_array_to_vbo_array(brw, upload[i], 0, instanced_attr_max_index, |
buffer, upload[i]->glarray->_ElementSize); |
} |
buffer->offset -= delta * buffer->stride; |
buffer->step_rate = upload[i]->glarray->InstanceDivisor; |
upload[i]->buffer = j++; |
upload[i]->offset = 0; |
} |
brw->vb.nr_buffers = j; |
} |
static void brw_emit_vertices(struct brw_context *brw) |
{ |
GLuint i, nr_elements; |
brw_prepare_vertices(brw); |
brw_emit_query_begin(brw); |
nr_elements = brw->vb.nr_enabled + brw->vs.prog_data->uses_vertexid; |
/* If the VS doesn't read any inputs (calculating vertex position from |
* a state variable for some reason, for example), emit a single pad |
* VERTEX_ELEMENT struct and bail. |
* |
* The stale VB state stays in place, but they don't do anything unless |
* a VE loads from them. |
*/ |
if (nr_elements == 0) { |
BEGIN_BATCH(3); |
OUT_BATCH((_3DSTATE_VERTEX_ELEMENTS << 16) | 1); |
if (brw->gen >= 6) { |
OUT_BATCH((0 << GEN6_VE0_INDEX_SHIFT) | |
GEN6_VE0_VALID | |
(BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) | |
(0 << BRW_VE0_SRC_OFFSET_SHIFT)); |
} else { |
OUT_BATCH((0 << BRW_VE0_INDEX_SHIFT) | |
BRW_VE0_VALID | |
(BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT) | |
(0 << BRW_VE0_SRC_OFFSET_SHIFT)); |
} |
OUT_BATCH((BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_0_SHIFT) | |
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) | |
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) | |
(BRW_VE1_COMPONENT_STORE_1_FLT << BRW_VE1_COMPONENT_3_SHIFT)); |
CACHED_BATCH(); |
return; |
} |
/* Now emit VB and VEP state packets. |
*/ |
if (brw->vb.nr_buffers) { |
if (brw->gen >= 6) { |
assert(brw->vb.nr_buffers <= 33); |
} else { |
assert(brw->vb.nr_buffers <= 17); |
} |
BEGIN_BATCH(1 + 4*brw->vb.nr_buffers); |
OUT_BATCH((_3DSTATE_VERTEX_BUFFERS << 16) | (4*brw->vb.nr_buffers - 1)); |
for (i = 0; i < brw->vb.nr_buffers; i++) { |
struct brw_vertex_buffer *buffer = &brw->vb.buffers[i]; |
uint32_t dw0; |
if (brw->gen >= 6) { |
dw0 = buffer->step_rate |
? GEN6_VB0_ACCESS_INSTANCEDATA |
: GEN6_VB0_ACCESS_VERTEXDATA; |
dw0 |= i << GEN6_VB0_INDEX_SHIFT; |
} else { |
dw0 = buffer->step_rate |
? BRW_VB0_ACCESS_INSTANCEDATA |
: BRW_VB0_ACCESS_VERTEXDATA; |
dw0 |= i << BRW_VB0_INDEX_SHIFT; |
} |
if (brw->gen >= 7) |
dw0 |= GEN7_VB0_ADDRESS_MODIFYENABLE; |
if (brw->is_haswell) |
dw0 |= GEN7_MOCS_L3 << 16; |
OUT_BATCH(dw0 | (buffer->stride << BRW_VB0_PITCH_SHIFT)); |
OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->offset); |
if (brw->gen >= 5) { |
OUT_RELOC(buffer->bo, I915_GEM_DOMAIN_VERTEX, 0, buffer->bo->size - 1); |
} else |
OUT_BATCH(0); |
OUT_BATCH(buffer->step_rate); |
} |
ADVANCE_BATCH(); |
} |
/* The hardware allows one more VERTEX_ELEMENTS than VERTEX_BUFFERS, presumably |
* for VertexID/InstanceID. |
*/ |
if (brw->gen >= 6) { |
assert(nr_elements <= 34); |
} else { |
assert(nr_elements <= 18); |
} |
struct brw_vertex_element *gen6_edgeflag_input = NULL; |
BEGIN_BATCH(1 + nr_elements * 2); |
OUT_BATCH((_3DSTATE_VERTEX_ELEMENTS << 16) | (2 * nr_elements - 1)); |
for (i = 0; i < brw->vb.nr_enabled; i++) { |
struct brw_vertex_element *input = brw->vb.enabled[i]; |
uint32_t format = get_surface_type(brw, input->glarray); |
uint32_t comp0 = BRW_VE1_COMPONENT_STORE_SRC; |
uint32_t comp1 = BRW_VE1_COMPONENT_STORE_SRC; |
uint32_t comp2 = BRW_VE1_COMPONENT_STORE_SRC; |
uint32_t comp3 = BRW_VE1_COMPONENT_STORE_SRC; |
/* The gen4 driver expects edgeflag to come in as a float, and passes |
* that float on to the tests in the clipper. Mesa's current vertex |
* attribute value for EdgeFlag is stored as a float, which works out. |
* glEdgeFlagPointer, on the other hand, gives us an unnormalized |
* integer ubyte. Just rewrite that to convert to a float. |
*/ |
if (input->attrib == VERT_ATTRIB_EDGEFLAG) { |
/* Gen6+ passes edgeflag as sideband along with the vertex, instead |
* of in the VUE. We have to upload it sideband as the last vertex |
* element according to the B-Spec. |
*/ |
if (brw->gen >= 6) { |
gen6_edgeflag_input = input; |
continue; |
} |
if (format == BRW_SURFACEFORMAT_R8_UINT) |
format = BRW_SURFACEFORMAT_R8_SSCALED; |
} |
switch (input->glarray->Size) { |
case 0: comp0 = BRW_VE1_COMPONENT_STORE_0; |
case 1: comp1 = BRW_VE1_COMPONENT_STORE_0; |
case 2: comp2 = BRW_VE1_COMPONENT_STORE_0; |
case 3: comp3 = input->glarray->Integer ? BRW_VE1_COMPONENT_STORE_1_INT |
: BRW_VE1_COMPONENT_STORE_1_FLT; |
break; |
} |
if (brw->gen >= 6) { |
OUT_BATCH((input->buffer << GEN6_VE0_INDEX_SHIFT) | |
GEN6_VE0_VALID | |
(format << BRW_VE0_FORMAT_SHIFT) | |
(input->offset << BRW_VE0_SRC_OFFSET_SHIFT)); |
} else { |
OUT_BATCH((input->buffer << BRW_VE0_INDEX_SHIFT) | |
BRW_VE0_VALID | |
(format << BRW_VE0_FORMAT_SHIFT) | |
(input->offset << BRW_VE0_SRC_OFFSET_SHIFT)); |
} |
if (brw->gen >= 5) |
OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) | |
(comp1 << BRW_VE1_COMPONENT_1_SHIFT) | |
(comp2 << BRW_VE1_COMPONENT_2_SHIFT) | |
(comp3 << BRW_VE1_COMPONENT_3_SHIFT)); |
else |
OUT_BATCH((comp0 << BRW_VE1_COMPONENT_0_SHIFT) | |
(comp1 << BRW_VE1_COMPONENT_1_SHIFT) | |
(comp2 << BRW_VE1_COMPONENT_2_SHIFT) | |
(comp3 << BRW_VE1_COMPONENT_3_SHIFT) | |
((i * 4) << BRW_VE1_DST_OFFSET_SHIFT)); |
} |
if (brw->gen >= 6 && gen6_edgeflag_input) { |
uint32_t format = get_surface_type(brw, gen6_edgeflag_input->glarray); |
OUT_BATCH((gen6_edgeflag_input->buffer << GEN6_VE0_INDEX_SHIFT) | |
GEN6_VE0_VALID | |
GEN6_VE0_EDGE_FLAG_ENABLE | |
(format << BRW_VE0_FORMAT_SHIFT) | |
(gen6_edgeflag_input->offset << BRW_VE0_SRC_OFFSET_SHIFT)); |
OUT_BATCH((BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT) | |
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_1_SHIFT) | |
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) | |
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT)); |
} |
if (brw->vs.prog_data->uses_vertexid) { |
uint32_t dw0 = 0, dw1 = 0; |
dw1 = ((BRW_VE1_COMPONENT_STORE_VID << BRW_VE1_COMPONENT_0_SHIFT) | |
(BRW_VE1_COMPONENT_STORE_IID << BRW_VE1_COMPONENT_1_SHIFT) | |
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_2_SHIFT) | |
(BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT)); |
if (brw->gen >= 6) { |
dw0 |= GEN6_VE0_VALID; |
} else { |
dw0 |= BRW_VE0_VALID; |
dw1 |= (i * 4) << BRW_VE1_DST_OFFSET_SHIFT; |
} |
/* Note that for gl_VertexID, gl_InstanceID, and gl_PrimitiveID values, |
* the format is ignored and the value is always int. |
*/ |
OUT_BATCH(dw0); |
OUT_BATCH(dw1); |
} |
CACHED_BATCH(); |
} |
const struct brw_tracked_state brw_vertices = { |
.dirty = { |
.mesa = _NEW_POLYGON, |
.brw = BRW_NEW_BATCH | BRW_NEW_VERTICES, |
.cache = CACHE_NEW_VS_PROG, |
}, |
.emit = brw_emit_vertices, |
}; |
static void brw_upload_indices(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
const struct _mesa_index_buffer *index_buffer = brw->ib.ib; |
GLuint ib_size; |
drm_intel_bo *bo = NULL; |
struct gl_buffer_object *bufferobj; |
GLuint offset; |
GLuint ib_type_size; |
if (index_buffer == NULL) |
return; |
ib_type_size = _mesa_sizeof_type(index_buffer->type); |
ib_size = ib_type_size * index_buffer->count; |
bufferobj = index_buffer->obj; |
/* Turn into a proper VBO: |
*/ |
if (!_mesa_is_bufferobj(bufferobj)) { |
/* Get new bufferobj, offset: |
*/ |
intel_upload_data(brw, index_buffer->ptr, ib_size, ib_type_size, |
&bo, &offset); |
brw->ib.start_vertex_offset = offset / ib_type_size; |
} else { |
offset = (GLuint) (unsigned long) index_buffer->ptr; |
/* If the index buffer isn't aligned to its element size, we have to |
* rebase it into a temporary. |
*/ |
if ((ib_type_size - 1) & offset) { |
perf_debug("copying index buffer to a temporary to work around " |
"misaligned offset %d\n", offset); |
GLubyte *map = ctx->Driver.MapBufferRange(ctx, |
offset, |
ib_size, |
GL_MAP_READ_BIT, |
bufferobj); |
intel_upload_data(brw, map, ib_size, ib_type_size, &bo, &offset); |
brw->ib.start_vertex_offset = offset / ib_type_size; |
ctx->Driver.UnmapBuffer(ctx, bufferobj); |
} else { |
/* Use CMD_3D_PRIM's start_vertex_offset to avoid re-uploading |
* the index buffer state when we're just moving the start index |
* of our drawing. |
*/ |
brw->ib.start_vertex_offset = offset / ib_type_size; |
bo = intel_bufferobj_source(brw, |
intel_buffer_object(bufferobj), |
ib_type_size, |
&offset); |
drm_intel_bo_reference(bo); |
brw->ib.start_vertex_offset += offset / ib_type_size; |
} |
} |
if (brw->ib.bo != bo) { |
drm_intel_bo_unreference(brw->ib.bo); |
brw->ib.bo = bo; |
brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER; |
} else { |
drm_intel_bo_unreference(bo); |
} |
if (index_buffer->type != brw->ib.type) { |
brw->ib.type = index_buffer->type; |
brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER; |
} |
} |
const struct brw_tracked_state brw_indices = { |
.dirty = { |
.mesa = 0, |
.brw = BRW_NEW_INDICES, |
.cache = 0, |
}, |
.emit = brw_upload_indices, |
}; |
static void brw_emit_index_buffer(struct brw_context *brw) |
{ |
const struct _mesa_index_buffer *index_buffer = brw->ib.ib; |
GLuint cut_index_setting; |
if (index_buffer == NULL) |
return; |
if (brw->prim_restart.enable_cut_index && !brw->is_haswell) { |
cut_index_setting = BRW_CUT_INDEX_ENABLE; |
} else { |
cut_index_setting = 0; |
} |
BEGIN_BATCH(3); |
OUT_BATCH(CMD_INDEX_BUFFER << 16 | |
cut_index_setting | |
get_index_type(index_buffer->type) << 8 | |
1); |
OUT_RELOC(brw->ib.bo, |
I915_GEM_DOMAIN_VERTEX, 0, |
0); |
OUT_RELOC(brw->ib.bo, |
I915_GEM_DOMAIN_VERTEX, 0, |
brw->ib.bo->size - 1); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state brw_index_buffer = { |
.dirty = { |
.mesa = 0, |
.brw = BRW_NEW_BATCH | BRW_NEW_INDEX_BUFFER, |
.cache = 0, |
}, |
.emit = brw_emit_index_buffer, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_eu.c |
---|
0,0 → 1,265 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "brw_context.h" |
#include "brw_defines.h" |
#include "brw_eu.h" |
#include "glsl/ralloc.h" |
/* Returns the corresponding conditional mod for swapping src0 and |
* src1 in e.g. CMP. |
*/ |
uint32_t |
brw_swap_cmod(uint32_t cmod) |
{ |
switch (cmod) { |
case BRW_CONDITIONAL_Z: |
case BRW_CONDITIONAL_NZ: |
return cmod; |
case BRW_CONDITIONAL_G: |
return BRW_CONDITIONAL_L; |
case BRW_CONDITIONAL_GE: |
return BRW_CONDITIONAL_LE; |
case BRW_CONDITIONAL_L: |
return BRW_CONDITIONAL_G; |
case BRW_CONDITIONAL_LE: |
return BRW_CONDITIONAL_GE; |
default: |
return ~0; |
} |
} |
/* How does predicate control work when execution_size != 8? Do I |
* need to test/set for 0xffff when execution_size is 16? |
*/ |
void brw_set_predicate_control_flag_value( struct brw_compile *p, GLuint value ) |
{ |
p->current->header.predicate_control = BRW_PREDICATE_NONE; |
if (value != 0xff) { |
if (value != p->flag_value) { |
brw_push_insn_state(p); |
brw_MOV(p, brw_flag_reg(0, 0), brw_imm_uw(value)); |
p->flag_value = value; |
brw_pop_insn_state(p); |
} |
p->current->header.predicate_control = BRW_PREDICATE_NORMAL; |
} |
} |
void brw_set_predicate_control( struct brw_compile *p, GLuint pc ) |
{ |
p->current->header.predicate_control = pc; |
} |
void brw_set_predicate_inverse(struct brw_compile *p, bool predicate_inverse) |
{ |
p->current->header.predicate_inverse = predicate_inverse; |
} |
void brw_set_conditionalmod( struct brw_compile *p, GLuint conditional ) |
{ |
p->current->header.destreg__conditionalmod = conditional; |
} |
void brw_set_flag_reg(struct brw_compile *p, int reg, int subreg) |
{ |
p->current->bits2.da1.flag_reg_nr = reg; |
p->current->bits2.da1.flag_subreg_nr = subreg; |
} |
void brw_set_access_mode( struct brw_compile *p, GLuint access_mode ) |
{ |
p->current->header.access_mode = access_mode; |
} |
void |
brw_set_compression_control(struct brw_compile *p, |
enum brw_compression compression_control) |
{ |
p->compressed = (compression_control == BRW_COMPRESSION_COMPRESSED); |
if (p->brw->gen >= 6) { |
/* Since we don't use the 32-wide support in gen6, we translate |
* the pre-gen6 compression control here. |
*/ |
switch (compression_control) { |
case BRW_COMPRESSION_NONE: |
/* This is the "use the first set of bits of dmask/vmask/arf |
* according to execsize" option. |
*/ |
p->current->header.compression_control = GEN6_COMPRESSION_1Q; |
break; |
case BRW_COMPRESSION_2NDHALF: |
/* For 8-wide, this is "use the second set of 8 bits." */ |
p->current->header.compression_control = GEN6_COMPRESSION_2Q; |
break; |
case BRW_COMPRESSION_COMPRESSED: |
/* For 16-wide instruction compression, use the first set of 16 bits |
* since we don't do 32-wide dispatch. |
*/ |
p->current->header.compression_control = GEN6_COMPRESSION_1H; |
break; |
default: |
assert(!"not reached"); |
p->current->header.compression_control = GEN6_COMPRESSION_1H; |
break; |
} |
} else { |
p->current->header.compression_control = compression_control; |
} |
} |
void brw_set_mask_control( struct brw_compile *p, GLuint value ) |
{ |
p->current->header.mask_control = value; |
} |
void brw_set_saturate( struct brw_compile *p, bool enable ) |
{ |
p->current->header.saturate = enable; |
} |
void brw_set_acc_write_control(struct brw_compile *p, GLuint value) |
{ |
if (p->brw->gen >= 6) |
p->current->header.acc_wr_control = value; |
} |
void brw_push_insn_state( struct brw_compile *p ) |
{ |
assert(p->current != &p->stack[BRW_EU_MAX_INSN_STACK-1]); |
memcpy(p->current+1, p->current, sizeof(struct brw_instruction)); |
p->compressed_stack[p->current - p->stack] = p->compressed; |
p->current++; |
} |
void brw_pop_insn_state( struct brw_compile *p ) |
{ |
assert(p->current != p->stack); |
p->current--; |
p->compressed = p->compressed_stack[p->current - p->stack]; |
} |
/*********************************************************************** |
*/ |
void |
brw_init_compile(struct brw_context *brw, struct brw_compile *p, void *mem_ctx) |
{ |
memset(p, 0, sizeof(*p)); |
p->brw = brw; |
/* |
* Set the initial instruction store array size to 1024, if found that |
* isn't enough, then it will double the store size at brw_next_insn() |
* until out of memory. |
*/ |
p->store_size = 1024; |
p->store = rzalloc_array(mem_ctx, struct brw_instruction, p->store_size); |
p->nr_insn = 0; |
p->current = p->stack; |
p->compressed = false; |
memset(p->current, 0, sizeof(p->current[0])); |
p->mem_ctx = mem_ctx; |
/* Some defaults? |
*/ |
brw_set_mask_control(p, BRW_MASK_ENABLE); /* what does this do? */ |
brw_set_saturate(p, 0); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_set_predicate_control_flag_value(p, 0xff); |
/* Set up control flow stack */ |
p->if_stack_depth = 0; |
p->if_stack_array_size = 16; |
p->if_stack = rzalloc_array(mem_ctx, int, p->if_stack_array_size); |
p->loop_stack_depth = 0; |
p->loop_stack_array_size = 16; |
p->loop_stack = rzalloc_array(mem_ctx, int, p->loop_stack_array_size); |
p->if_depth_in_loop = rzalloc_array(mem_ctx, int, p->loop_stack_array_size); |
brw_init_compaction_tables(brw); |
} |
const GLuint *brw_get_program( struct brw_compile *p, |
GLuint *sz ) |
{ |
brw_compact_instructions(p); |
*sz = p->next_insn_offset; |
return (const GLuint *)p->store; |
} |
void |
brw_dump_compile(struct brw_compile *p, FILE *out, int start, int end) |
{ |
struct brw_context *brw = p->brw; |
void *store = p->store; |
bool dump_hex = false; |
for (int offset = start; offset < end;) { |
struct brw_instruction *insn = store + offset; |
struct brw_instruction uncompacted; |
printf("0x%08x: ", offset); |
if (insn->header.cmpt_control) { |
struct brw_compact_instruction *compacted = (void *)insn; |
if (dump_hex) { |
printf("0x%08x 0x%08x ", |
((uint32_t *)insn)[1], |
((uint32_t *)insn)[0]); |
} |
brw_uncompact_instruction(brw, &uncompacted, compacted); |
insn = &uncompacted; |
offset += 8; |
} else { |
if (dump_hex) { |
printf("0x%08x 0x%08x 0x%08x 0x%08x ", |
((uint32_t *)insn)[3], |
((uint32_t *)insn)[2], |
((uint32_t *)insn)[1], |
((uint32_t *)insn)[0]); |
} |
offset += 16; |
} |
brw_disasm(stdout, insn, p->brw->gen); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_eu.h |
---|
0,0 → 1,413 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 BRW_EU_H |
#define BRW_EU_H |
#include <stdbool.h> |
#include "brw_structs.h" |
#include "brw_defines.h" |
#include "brw_reg.h" |
#include "program/prog_instruction.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
#define BRW_EU_MAX_INSN_STACK 5 |
struct brw_compile { |
struct brw_instruction *store; |
int store_size; |
GLuint nr_insn; |
unsigned int next_insn_offset; |
void *mem_ctx; |
/* Allow clients to push/pop instruction state: |
*/ |
struct brw_instruction stack[BRW_EU_MAX_INSN_STACK]; |
bool compressed_stack[BRW_EU_MAX_INSN_STACK]; |
struct brw_instruction *current; |
GLuint flag_value; |
bool single_program_flow; |
bool compressed; |
struct brw_context *brw; |
/* Control flow stacks: |
* - if_stack contains IF and ELSE instructions which must be patched |
* (and popped) once the matching ENDIF instruction is encountered. |
* |
* Just store the instruction pointer(an index). |
*/ |
int *if_stack; |
int if_stack_depth; |
int if_stack_array_size; |
/** |
* loop_stack contains the instruction pointers of the starts of loops which |
* must be patched (and popped) once the matching WHILE instruction is |
* encountered. |
*/ |
int *loop_stack; |
/** |
* pre-gen6, the BREAK and CONT instructions had to tell how many IF/ENDIF |
* blocks they were popping out of, to fix up the mask stack. This tracks |
* the IF/ENDIF nesting in each current nested loop level. |
*/ |
int *if_depth_in_loop; |
int loop_stack_depth; |
int loop_stack_array_size; |
}; |
static INLINE struct brw_instruction *current_insn( struct brw_compile *p) |
{ |
return &p->store[p->nr_insn]; |
} |
void brw_pop_insn_state( struct brw_compile *p ); |
void brw_push_insn_state( struct brw_compile *p ); |
void brw_set_mask_control( struct brw_compile *p, GLuint value ); |
void brw_set_saturate( struct brw_compile *p, bool enable ); |
void brw_set_access_mode( struct brw_compile *p, GLuint access_mode ); |
void brw_set_compression_control(struct brw_compile *p, enum brw_compression c); |
void brw_set_predicate_control_flag_value( struct brw_compile *p, GLuint value ); |
void brw_set_predicate_control( struct brw_compile *p, GLuint pc ); |
void brw_set_predicate_inverse(struct brw_compile *p, bool predicate_inverse); |
void brw_set_conditionalmod( struct brw_compile *p, GLuint conditional ); |
void brw_set_flag_reg(struct brw_compile *p, int reg, int subreg); |
void brw_set_acc_write_control(struct brw_compile *p, GLuint value); |
void brw_init_compile(struct brw_context *, struct brw_compile *p, |
void *mem_ctx); |
void brw_dump_compile(struct brw_compile *p, FILE *out, int start, int end); |
const GLuint *brw_get_program( struct brw_compile *p, GLuint *sz ); |
struct brw_instruction *brw_next_insn(struct brw_compile *p, GLuint opcode); |
void brw_set_dest(struct brw_compile *p, struct brw_instruction *insn, |
struct brw_reg dest); |
void brw_set_src0(struct brw_compile *p, struct brw_instruction *insn, |
struct brw_reg reg); |
void gen6_resolve_implied_move(struct brw_compile *p, |
struct brw_reg *src, |
GLuint msg_reg_nr); |
/* Helpers for regular instructions: |
*/ |
#define ALU1(OP) \ |
struct brw_instruction *brw_##OP(struct brw_compile *p, \ |
struct brw_reg dest, \ |
struct brw_reg src0); |
#define ALU2(OP) \ |
struct brw_instruction *brw_##OP(struct brw_compile *p, \ |
struct brw_reg dest, \ |
struct brw_reg src0, \ |
struct brw_reg src1); |
#define ALU3(OP) \ |
struct brw_instruction *brw_##OP(struct brw_compile *p, \ |
struct brw_reg dest, \ |
struct brw_reg src0, \ |
struct brw_reg src1, \ |
struct brw_reg src2); |
#define ROUND(OP) \ |
void brw_##OP(struct brw_compile *p, struct brw_reg dest, struct brw_reg src0); |
ALU1(MOV) |
ALU2(SEL) |
ALU1(NOT) |
ALU2(AND) |
ALU2(OR) |
ALU2(XOR) |
ALU2(SHR) |
ALU2(SHL) |
ALU2(RSR) |
ALU2(RSL) |
ALU2(ASR) |
ALU1(F32TO16) |
ALU1(F16TO32) |
ALU2(JMPI) |
ALU2(ADD) |
ALU2(AVG) |
ALU2(MUL) |
ALU1(FRC) |
ALU1(RNDD) |
ALU2(MAC) |
ALU2(MACH) |
ALU1(LZD) |
ALU2(DP4) |
ALU2(DPH) |
ALU2(DP3) |
ALU2(DP2) |
ALU2(LINE) |
ALU2(PLN) |
ALU3(MAD) |
ALU3(LRP) |
ALU1(BFREV) |
ALU3(BFE) |
ALU2(BFI1) |
ALU3(BFI2) |
ALU1(FBH) |
ALU1(FBL) |
ALU1(CBIT) |
ROUND(RNDZ) |
ROUND(RNDE) |
#undef ALU1 |
#undef ALU2 |
#undef ALU3 |
#undef ROUND |
/* Helpers for SEND instruction: |
*/ |
void brw_set_sampler_message(struct brw_compile *p, |
struct brw_instruction *insn, |
GLuint binding_table_index, |
GLuint sampler, |
GLuint msg_type, |
GLuint response_length, |
GLuint msg_length, |
GLuint header_present, |
GLuint simd_mode, |
GLuint return_format); |
void brw_set_dp_read_message(struct brw_compile *p, |
struct brw_instruction *insn, |
GLuint binding_table_index, |
GLuint msg_control, |
GLuint msg_type, |
GLuint target_cache, |
GLuint msg_length, |
bool header_present, |
GLuint response_length); |
void brw_set_dp_write_message(struct brw_compile *p, |
struct brw_instruction *insn, |
GLuint binding_table_index, |
GLuint msg_control, |
GLuint msg_type, |
GLuint msg_length, |
bool header_present, |
GLuint last_render_target, |
GLuint response_length, |
GLuint end_of_thread, |
GLuint send_commit_msg); |
void brw_urb_WRITE(struct brw_compile *p, |
struct brw_reg dest, |
GLuint msg_reg_nr, |
struct brw_reg src0, |
bool allocate, |
bool used, |
GLuint msg_length, |
GLuint response_length, |
bool eot, |
bool writes_complete, |
GLuint offset, |
GLuint swizzle); |
void brw_ff_sync(struct brw_compile *p, |
struct brw_reg dest, |
GLuint msg_reg_nr, |
struct brw_reg src0, |
bool allocate, |
GLuint response_length, |
bool eot); |
void brw_svb_write(struct brw_compile *p, |
struct brw_reg dest, |
GLuint msg_reg_nr, |
struct brw_reg src0, |
GLuint binding_table_index, |
bool send_commit_msg); |
void brw_fb_WRITE(struct brw_compile *p, |
int dispatch_width, |
GLuint msg_reg_nr, |
struct brw_reg src0, |
GLuint msg_control, |
GLuint binding_table_index, |
GLuint msg_length, |
GLuint response_length, |
bool eot, |
bool header_present); |
void brw_SAMPLE(struct brw_compile *p, |
struct brw_reg dest, |
GLuint msg_reg_nr, |
struct brw_reg src0, |
GLuint binding_table_index, |
GLuint sampler, |
GLuint msg_type, |
GLuint response_length, |
GLuint msg_length, |
GLuint header_present, |
GLuint simd_mode, |
GLuint return_format); |
void brw_math( struct brw_compile *p, |
struct brw_reg dest, |
GLuint function, |
GLuint msg_reg_nr, |
struct brw_reg src, |
GLuint data_type, |
GLuint precision ); |
void brw_math2(struct brw_compile *p, |
struct brw_reg dest, |
GLuint function, |
struct brw_reg src0, |
struct brw_reg src1); |
void brw_oword_block_read(struct brw_compile *p, |
struct brw_reg dest, |
struct brw_reg mrf, |
uint32_t offset, |
uint32_t bind_table_index); |
void brw_oword_block_read_scratch(struct brw_compile *p, |
struct brw_reg dest, |
struct brw_reg mrf, |
int num_regs, |
GLuint offset); |
void brw_oword_block_write_scratch(struct brw_compile *p, |
struct brw_reg mrf, |
int num_regs, |
GLuint offset); |
void brw_shader_time_add(struct brw_compile *p, |
struct brw_reg payload, |
uint32_t surf_index); |
/* If/else/endif. Works by manipulating the execution flags on each |
* channel. |
*/ |
struct brw_instruction *brw_IF(struct brw_compile *p, |
GLuint execute_size); |
struct brw_instruction *gen6_IF(struct brw_compile *p, uint32_t conditional, |
struct brw_reg src0, struct brw_reg src1); |
void brw_ELSE(struct brw_compile *p); |
void brw_ENDIF(struct brw_compile *p); |
/* DO/WHILE loops: |
*/ |
struct brw_instruction *brw_DO(struct brw_compile *p, |
GLuint execute_size); |
struct brw_instruction *brw_WHILE(struct brw_compile *p); |
struct brw_instruction *brw_BREAK(struct brw_compile *p); |
struct brw_instruction *brw_CONT(struct brw_compile *p); |
struct brw_instruction *gen6_CONT(struct brw_compile *p); |
struct brw_instruction *gen6_HALT(struct brw_compile *p); |
/* Forward jumps: |
*/ |
void brw_land_fwd_jump(struct brw_compile *p, int jmp_insn_idx); |
void brw_NOP(struct brw_compile *p); |
void brw_WAIT(struct brw_compile *p); |
/* Special case: there is never a destination, execution size will be |
* taken from src0: |
*/ |
void brw_CMP(struct brw_compile *p, |
struct brw_reg dest, |
GLuint conditional, |
struct brw_reg src0, |
struct brw_reg src1); |
/*********************************************************************** |
* brw_eu_util.c: |
*/ |
void brw_copy_indirect_to_indirect(struct brw_compile *p, |
struct brw_indirect dst_ptr, |
struct brw_indirect src_ptr, |
GLuint count); |
void brw_copy_from_indirect(struct brw_compile *p, |
struct brw_reg dst, |
struct brw_indirect ptr, |
GLuint count); |
void brw_copy4(struct brw_compile *p, |
struct brw_reg dst, |
struct brw_reg src, |
GLuint count); |
void brw_copy8(struct brw_compile *p, |
struct brw_reg dst, |
struct brw_reg src, |
GLuint count); |
void brw_math_invert( struct brw_compile *p, |
struct brw_reg dst, |
struct brw_reg src); |
void brw_set_src1(struct brw_compile *p, |
struct brw_instruction *insn, |
struct brw_reg reg); |
void brw_set_uip_jip(struct brw_compile *p); |
uint32_t brw_swap_cmod(uint32_t cmod); |
/* brw_eu_compact.c */ |
void brw_init_compaction_tables(struct brw_context *brw); |
void brw_compact_instructions(struct brw_compile *p); |
void brw_uncompact_instruction(struct brw_context *brw, |
struct brw_instruction *dst, |
struct brw_compact_instruction *src); |
bool brw_try_compact_instruction(struct brw_compile *p, |
struct brw_compact_instruction *dst, |
struct brw_instruction *src); |
void brw_debug_compact_uncompact(struct brw_context *brw, |
struct brw_instruction *orig, |
struct brw_instruction *uncompacted); |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_eu_compact.c |
---|
0,0 → 1,805 |
/* |
* 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. |
*/ |
/** @file brw_eu_compact.c |
* |
* Instruction compaction is a feature of gm45 and newer hardware that allows |
* for a smaller instruction encoding. |
* |
* The instruction cache is on the order of 32KB, and many programs generate |
* far more instructions than that. The instruction cache is built to barely |
* keep up with instruction dispatch abaility in cache hit cases -- L1 |
* instruction cache misses that still hit in the next level could limit |
* throughput by around 50%. |
* |
* The idea of instruction compaction is that most instructions use a tiny |
* subset of the GPU functionality, so we can encode what would be a 16 byte |
* instruction in 8 bytes using some lookup tables for various fields. |
*/ |
#include "brw_context.h" |
#include "brw_eu.h" |
static const uint32_t gen6_control_index_table[32] = { |
0b00000000000000000, |
0b01000000000000000, |
0b00110000000000000, |
0b00000000100000000, |
0b00010000000000000, |
0b00001000100000000, |
0b00000000100000010, |
0b00000000000000010, |
0b01000000100000000, |
0b01010000000000000, |
0b10110000000000000, |
0b00100000000000000, |
0b11010000000000000, |
0b11000000000000000, |
0b01001000100000000, |
0b01000000000001000, |
0b01000000000000100, |
0b00000000000001000, |
0b00000000000000100, |
0b00111000100000000, |
0b00001000100000010, |
0b00110000100000000, |
0b00110000000000001, |
0b00100000000000001, |
0b00110000000000010, |
0b00110000000000101, |
0b00110000000001001, |
0b00110000000010000, |
0b00110000000000011, |
0b00110000000000100, |
0b00110000100001000, |
0b00100000000001001 |
}; |
static const uint32_t gen6_datatype_table[32] = { |
0b001001110000000000, |
0b001000110000100000, |
0b001001110000000001, |
0b001000000001100000, |
0b001010110100101001, |
0b001000000110101101, |
0b001100011000101100, |
0b001011110110101101, |
0b001000000111101100, |
0b001000000001100001, |
0b001000110010100101, |
0b001000000001000001, |
0b001000001000110001, |
0b001000001000101001, |
0b001000000000100000, |
0b001000001000110010, |
0b001010010100101001, |
0b001011010010100101, |
0b001000000110100101, |
0b001100011000101001, |
0b001011011000101100, |
0b001011010110100101, |
0b001011110110100101, |
0b001111011110111101, |
0b001111011110111100, |
0b001111011110111101, |
0b001111011110011101, |
0b001111011110111110, |
0b001000000000100001, |
0b001000000000100010, |
0b001001111111011101, |
0b001000001110111110, |
}; |
static const uint32_t gen6_subreg_table[32] = { |
0b000000000000000, |
0b000000000000100, |
0b000000110000000, |
0b111000000000000, |
0b011110000001000, |
0b000010000000000, |
0b000000000010000, |
0b000110000001100, |
0b001000000000000, |
0b000001000000000, |
0b000001010010100, |
0b000000001010110, |
0b010000000000000, |
0b110000000000000, |
0b000100000000000, |
0b000000010000000, |
0b000000000001000, |
0b100000000000000, |
0b000001010000000, |
0b001010000000000, |
0b001100000000000, |
0b000000001010100, |
0b101101010010100, |
0b010100000000000, |
0b000000010001111, |
0b011000000000000, |
0b111110000000000, |
0b101000000000000, |
0b000000000001111, |
0b000100010001111, |
0b001000010001111, |
0b000110000000000, |
}; |
static const uint32_t gen6_src_index_table[32] = { |
0b000000000000, |
0b010110001000, |
0b010001101000, |
0b001000101000, |
0b011010010000, |
0b000100100000, |
0b010001101100, |
0b010101110000, |
0b011001111000, |
0b001100101000, |
0b010110001100, |
0b001000100000, |
0b010110001010, |
0b000000000010, |
0b010101010000, |
0b010101101000, |
0b111101001100, |
0b111100101100, |
0b011001110000, |
0b010110001001, |
0b010101011000, |
0b001101001000, |
0b010000101100, |
0b010000000000, |
0b001101110000, |
0b001100010000, |
0b001100000000, |
0b010001101010, |
0b001101111000, |
0b000001110000, |
0b001100100000, |
0b001101010000, |
}; |
static const uint32_t gen7_control_index_table[32] = { |
0b0000000000000000010, |
0b0000100000000000000, |
0b0000100000000000001, |
0b0000100000000000010, |
0b0000100000000000011, |
0b0000100000000000100, |
0b0000100000000000101, |
0b0000100000000000111, |
0b0000100000000001000, |
0b0000100000000001001, |
0b0000100000000001101, |
0b0000110000000000000, |
0b0000110000000000001, |
0b0000110000000000010, |
0b0000110000000000011, |
0b0000110000000000100, |
0b0000110000000000101, |
0b0000110000000000111, |
0b0000110000000001001, |
0b0000110000000001101, |
0b0000110000000010000, |
0b0000110000100000000, |
0b0001000000000000000, |
0b0001000000000000010, |
0b0001000000000000100, |
0b0001000000100000000, |
0b0010110000000000000, |
0b0010110000000010000, |
0b0011000000000000000, |
0b0011000000100000000, |
0b0101000000000000000, |
0b0101000000100000000 |
}; |
static const uint32_t gen7_datatype_table[32] = { |
0b001000000000000001, |
0b001000000000100000, |
0b001000000000100001, |
0b001000000001100001, |
0b001000000010111101, |
0b001000001011111101, |
0b001000001110100001, |
0b001000001110100101, |
0b001000001110111101, |
0b001000010000100001, |
0b001000110000100000, |
0b001000110000100001, |
0b001001010010100101, |
0b001001110010100100, |
0b001001110010100101, |
0b001111001110111101, |
0b001111011110011101, |
0b001111011110111100, |
0b001111011110111101, |
0b001111111110111100, |
0b000000001000001100, |
0b001000000000111101, |
0b001000000010100101, |
0b001000010000100000, |
0b001001010010100100, |
0b001001110010000100, |
0b001010010100001001, |
0b001101111110111101, |
0b001111111110111101, |
0b001011110110101100, |
0b001010010100101000, |
0b001010110100101000 |
}; |
static const uint32_t gen7_subreg_table[32] = { |
0b000000000000000, |
0b000000000000001, |
0b000000000001000, |
0b000000000001111, |
0b000000000010000, |
0b000000010000000, |
0b000000100000000, |
0b000000110000000, |
0b000001000000000, |
0b000001000010000, |
0b000010100000000, |
0b001000000000000, |
0b001000000000001, |
0b001000010000001, |
0b001000010000010, |
0b001000010000011, |
0b001000010000100, |
0b001000010000111, |
0b001000010001000, |
0b001000010001110, |
0b001000010001111, |
0b001000110000000, |
0b001000111101000, |
0b010000000000000, |
0b010000110000000, |
0b011000000000000, |
0b011110010000111, |
0b100000000000000, |
0b101000000000000, |
0b110000000000000, |
0b111000000000000, |
0b111000000011100 |
}; |
static const uint32_t gen7_src_index_table[32] = { |
0b000000000000, |
0b000000000010, |
0b000000010000, |
0b000000010010, |
0b000000011000, |
0b000000100000, |
0b000000101000, |
0b000001001000, |
0b000001010000, |
0b000001110000, |
0b000001111000, |
0b001100000000, |
0b001100000010, |
0b001100001000, |
0b001100010000, |
0b001100010010, |
0b001100100000, |
0b001100101000, |
0b001100111000, |
0b001101000000, |
0b001101000010, |
0b001101001000, |
0b001101010000, |
0b001101100000, |
0b001101101000, |
0b001101110000, |
0b001101110001, |
0b001101111000, |
0b010001101000, |
0b010001101001, |
0b010001101010, |
0b010110001000 |
}; |
static const uint32_t *control_index_table; |
static const uint32_t *datatype_table; |
static const uint32_t *subreg_table; |
static const uint32_t *src_index_table; |
static bool |
set_control_index(struct brw_context *brw, |
struct brw_compact_instruction *dst, |
struct brw_instruction *src) |
{ |
uint32_t *src_u32 = (uint32_t *)src; |
uint32_t uncompacted = 0; |
uncompacted |= ((src_u32[0] >> 8) & 0xffff) << 0; |
uncompacted |= ((src_u32[0] >> 31) & 0x1) << 16; |
/* On gen7, the flag register number gets integrated into the control |
* index. |
*/ |
if (brw->gen >= 7) |
uncompacted |= ((src_u32[2] >> 25) & 0x3) << 17; |
for (int i = 0; i < 32; i++) { |
if (control_index_table[i] == uncompacted) { |
dst->dw0.control_index = i; |
return true; |
} |
} |
return false; |
} |
static bool |
set_datatype_index(struct brw_compact_instruction *dst, |
struct brw_instruction *src) |
{ |
uint32_t uncompacted = 0; |
uncompacted |= src->bits1.ud & 0x7fff; |
uncompacted |= (src->bits1.ud >> 29) << 15; |
for (int i = 0; i < 32; i++) { |
if (datatype_table[i] == uncompacted) { |
dst->dw0.data_type_index = i; |
return true; |
} |
} |
return false; |
} |
static bool |
set_subreg_index(struct brw_compact_instruction *dst, |
struct brw_instruction *src) |
{ |
uint32_t uncompacted = 0; |
uncompacted |= src->bits1.da1.dest_subreg_nr << 0; |
uncompacted |= src->bits2.da1.src0_subreg_nr << 5; |
uncompacted |= src->bits3.da1.src1_subreg_nr << 10; |
for (int i = 0; i < 32; i++) { |
if (subreg_table[i] == uncompacted) { |
dst->dw0.sub_reg_index = i; |
return true; |
} |
} |
return false; |
} |
static bool |
get_src_index(uint32_t uncompacted, |
uint32_t *compacted) |
{ |
for (int i = 0; i < 32; i++) { |
if (src_index_table[i] == uncompacted) { |
*compacted = i; |
return true; |
} |
} |
return false; |
} |
static bool |
set_src0_index(struct brw_compact_instruction *dst, |
struct brw_instruction *src) |
{ |
uint32_t compacted, uncompacted = 0; |
uncompacted |= (src->bits2.ud >> 13) & 0xfff; |
if (!get_src_index(uncompacted, &compacted)) |
return false; |
dst->dw0.src0_index = compacted & 0x3; |
dst->dw1.src0_index = compacted >> 2; |
return true; |
} |
static bool |
set_src1_index(struct brw_compact_instruction *dst, |
struct brw_instruction *src) |
{ |
uint32_t compacted, uncompacted = 0; |
uncompacted |= (src->bits3.ud >> 13) & 0xfff; |
if (!get_src_index(uncompacted, &compacted)) |
return false; |
dst->dw1.src1_index = compacted; |
return true; |
} |
/** |
* Tries to compact instruction src into dst. |
* |
* It doesn't modify dst unless src is compactable, which is relied on by |
* brw_compact_instructions(). |
*/ |
bool |
brw_try_compact_instruction(struct brw_compile *p, |
struct brw_compact_instruction *dst, |
struct brw_instruction *src) |
{ |
struct brw_context *brw = p->brw; |
struct brw_compact_instruction temp; |
if (src->header.opcode == BRW_OPCODE_IF || |
src->header.opcode == BRW_OPCODE_ELSE || |
src->header.opcode == BRW_OPCODE_ENDIF || |
src->header.opcode == BRW_OPCODE_HALT || |
src->header.opcode == BRW_OPCODE_DO || |
src->header.opcode == BRW_OPCODE_WHILE) { |
/* FINISHME: The fixup code below, and brw_set_uip_jip and friends, needs |
* to be able to handle compacted flow control instructions.. |
*/ |
return false; |
} |
/* FINISHME: immediates */ |
if (src->bits1.da1.src0_reg_file == BRW_IMMEDIATE_VALUE || |
src->bits1.da1.src1_reg_file == BRW_IMMEDIATE_VALUE) |
return false; |
memset(&temp, 0, sizeof(temp)); |
temp.dw0.opcode = src->header.opcode; |
temp.dw0.debug_control = src->header.debug_control; |
if (!set_control_index(brw, &temp, src)) |
return false; |
if (!set_datatype_index(&temp, src)) |
return false; |
if (!set_subreg_index(&temp, src)) |
return false; |
temp.dw0.acc_wr_control = src->header.acc_wr_control; |
temp.dw0.conditionalmod = src->header.destreg__conditionalmod; |
if (brw->gen <= 6) |
temp.dw0.flag_subreg_nr = src->bits2.da1.flag_subreg_nr; |
temp.dw0.cmpt_ctrl = 1; |
if (!set_src0_index(&temp, src)) |
return false; |
if (!set_src1_index(&temp, src)) |
return false; |
temp.dw1.dst_reg_nr = src->bits1.da1.dest_reg_nr; |
temp.dw1.src0_reg_nr = src->bits2.da1.src0_reg_nr; |
temp.dw1.src1_reg_nr = src->bits3.da1.src1_reg_nr; |
*dst = temp; |
return true; |
} |
static void |
set_uncompacted_control(struct brw_context *brw, |
struct brw_instruction *dst, |
struct brw_compact_instruction *src) |
{ |
uint32_t *dst_u32 = (uint32_t *)dst; |
uint32_t uncompacted = control_index_table[src->dw0.control_index]; |
dst_u32[0] |= ((uncompacted >> 0) & 0xffff) << 8; |
dst_u32[0] |= ((uncompacted >> 16) & 0x1) << 31; |
if (brw->gen >= 7) |
dst_u32[2] |= ((uncompacted >> 17) & 0x3) << 25; |
} |
static void |
set_uncompacted_datatype(struct brw_instruction *dst, |
struct brw_compact_instruction *src) |
{ |
uint32_t uncompacted = datatype_table[src->dw0.data_type_index]; |
dst->bits1.ud &= ~(0x7 << 29); |
dst->bits1.ud |= ((uncompacted >> 15) & 0x7) << 29; |
dst->bits1.ud &= ~0x7fff; |
dst->bits1.ud |= uncompacted & 0x7fff; |
} |
static void |
set_uncompacted_subreg(struct brw_instruction *dst, |
struct brw_compact_instruction *src) |
{ |
uint32_t uncompacted = subreg_table[src->dw0.sub_reg_index]; |
dst->bits1.da1.dest_subreg_nr = (uncompacted >> 0) & 0x1f; |
dst->bits2.da1.src0_subreg_nr = (uncompacted >> 5) & 0x1f; |
dst->bits3.da1.src1_subreg_nr = (uncompacted >> 10) & 0x1f; |
} |
static void |
set_uncompacted_src0(struct brw_instruction *dst, |
struct brw_compact_instruction *src) |
{ |
uint32_t compacted = src->dw0.src0_index | src->dw1.src0_index << 2; |
uint32_t uncompacted = src_index_table[compacted]; |
dst->bits2.ud |= uncompacted << 13; |
} |
static void |
set_uncompacted_src1(struct brw_instruction *dst, |
struct brw_compact_instruction *src) |
{ |
uint32_t uncompacted = src_index_table[src->dw1.src1_index]; |
dst->bits3.ud |= uncompacted << 13; |
} |
void |
brw_uncompact_instruction(struct brw_context *brw, |
struct brw_instruction *dst, |
struct brw_compact_instruction *src) |
{ |
memset(dst, 0, sizeof(*dst)); |
dst->header.opcode = src->dw0.opcode; |
dst->header.debug_control = src->dw0.debug_control; |
set_uncompacted_control(brw, dst, src); |
set_uncompacted_datatype(dst, src); |
set_uncompacted_subreg(dst, src); |
dst->header.acc_wr_control = src->dw0.acc_wr_control; |
dst->header.destreg__conditionalmod = src->dw0.conditionalmod; |
if (brw->gen <= 6) |
dst->bits2.da1.flag_subreg_nr = src->dw0.flag_subreg_nr; |
set_uncompacted_src0(dst, src); |
set_uncompacted_src1(dst, src); |
dst->bits1.da1.dest_reg_nr = src->dw1.dst_reg_nr; |
dst->bits2.da1.src0_reg_nr = src->dw1.src0_reg_nr; |
dst->bits3.da1.src1_reg_nr = src->dw1.src1_reg_nr; |
} |
void brw_debug_compact_uncompact(struct brw_context *brw, |
struct brw_instruction *orig, |
struct brw_instruction *uncompacted) |
{ |
fprintf(stderr, "Instruction compact/uncompact changed (gen%d):\n", |
brw->gen); |
fprintf(stderr, " before: "); |
brw_disasm(stderr, orig, brw->gen); |
fprintf(stderr, " after: "); |
brw_disasm(stderr, uncompacted, brw->gen); |
uint32_t *before_bits = (uint32_t *)orig; |
uint32_t *after_bits = (uint32_t *)uncompacted; |
printf(" changed bits:\n"); |
for (int i = 0; i < 128; i++) { |
uint32_t before = before_bits[i / 32] & (1 << (i & 31)); |
uint32_t after = after_bits[i / 32] & (1 << (i & 31)); |
if (before != after) { |
printf(" bit %d, %s to %s\n", i, |
before ? "set" : "unset", |
after ? "set" : "unset"); |
} |
} |
} |
static int |
compacted_between(int old_ip, int old_target_ip, int *compacted_counts) |
{ |
int this_compacted_count = compacted_counts[old_ip]; |
int target_compacted_count = compacted_counts[old_target_ip]; |
return target_compacted_count - this_compacted_count; |
} |
static void |
update_uip_jip(struct brw_instruction *insn, int this_old_ip, |
int *compacted_counts) |
{ |
int target_old_ip; |
target_old_ip = this_old_ip + insn->bits3.break_cont.jip; |
insn->bits3.break_cont.jip -= compacted_between(this_old_ip, |
target_old_ip, |
compacted_counts); |
target_old_ip = this_old_ip + insn->bits3.break_cont.uip; |
insn->bits3.break_cont.uip -= compacted_between(this_old_ip, |
target_old_ip, |
compacted_counts); |
} |
void |
brw_init_compaction_tables(struct brw_context *brw) |
{ |
assert(gen6_control_index_table[ARRAY_SIZE(gen6_control_index_table) - 1] != 0); |
assert(gen6_datatype_table[ARRAY_SIZE(gen6_datatype_table) - 1] != 0); |
assert(gen6_subreg_table[ARRAY_SIZE(gen6_subreg_table) - 1] != 0); |
assert(gen6_src_index_table[ARRAY_SIZE(gen6_src_index_table) - 1] != 0); |
assert(gen7_control_index_table[ARRAY_SIZE(gen6_control_index_table) - 1] != 0); |
assert(gen7_datatype_table[ARRAY_SIZE(gen6_datatype_table) - 1] != 0); |
assert(gen7_subreg_table[ARRAY_SIZE(gen6_subreg_table) - 1] != 0); |
assert(gen7_src_index_table[ARRAY_SIZE(gen6_src_index_table) - 1] != 0); |
switch (brw->gen) { |
case 7: |
control_index_table = gen7_control_index_table; |
datatype_table = gen7_datatype_table; |
subreg_table = gen7_subreg_table; |
src_index_table = gen7_src_index_table; |
break; |
case 6: |
control_index_table = gen6_control_index_table; |
datatype_table = gen6_datatype_table; |
subreg_table = gen6_subreg_table; |
src_index_table = gen6_src_index_table; |
break; |
default: |
return; |
} |
} |
void |
brw_compact_instructions(struct brw_compile *p) |
{ |
struct brw_context *brw = p->brw; |
void *store = p->store; |
/* For an instruction at byte offset 8*i before compaction, this is the number |
* of compacted instructions that preceded it. |
*/ |
int compacted_counts[p->next_insn_offset / 8]; |
/* For an instruction at byte offset 8*i after compaction, this is the |
* 8-byte offset it was at before compaction. |
*/ |
int old_ip[p->next_insn_offset / 8]; |
if (brw->gen < 6) |
return; |
int src_offset; |
int offset = 0; |
int compacted_count = 0; |
for (src_offset = 0; src_offset < p->nr_insn * 16;) { |
struct brw_instruction *src = store + src_offset; |
void *dst = store + offset; |
old_ip[offset / 8] = src_offset / 8; |
compacted_counts[src_offset / 8] = compacted_count; |
struct brw_instruction saved = *src; |
if (!src->header.cmpt_control && |
brw_try_compact_instruction(p, dst, src)) { |
compacted_count++; |
if (INTEL_DEBUG) { |
struct brw_instruction uncompacted; |
brw_uncompact_instruction(brw, &uncompacted, dst); |
if (memcmp(&saved, &uncompacted, sizeof(uncompacted))) { |
brw_debug_compact_uncompact(brw, &saved, &uncompacted); |
} |
} |
offset += 8; |
src_offset += 16; |
} else { |
int size = src->header.cmpt_control ? 8 : 16; |
/* It appears that the end of thread SEND instruction needs to be |
* aligned, or the GPU hangs. |
*/ |
if ((src->header.opcode == BRW_OPCODE_SEND || |
src->header.opcode == BRW_OPCODE_SENDC) && |
src->bits3.generic.end_of_thread && |
(offset & 8) != 0) { |
struct brw_compact_instruction *align = store + offset; |
memset(align, 0, sizeof(*align)); |
align->dw0.opcode = BRW_OPCODE_NOP; |
align->dw0.cmpt_ctrl = 1; |
offset += 8; |
old_ip[offset / 8] = src_offset / 8; |
dst = store + offset; |
} |
/* If we didn't compact this intruction, we need to move it down into |
* place. |
*/ |
if (offset != src_offset) { |
memmove(dst, src, size); |
} |
offset += size; |
src_offset += size; |
} |
} |
/* Fix up control flow offsets. */ |
p->next_insn_offset = offset; |
for (offset = 0; offset < p->next_insn_offset;) { |
struct brw_instruction *insn = store + offset; |
int this_old_ip = old_ip[offset / 8]; |
int this_compacted_count = compacted_counts[this_old_ip]; |
int target_old_ip, target_compacted_count; |
switch (insn->header.opcode) { |
case BRW_OPCODE_BREAK: |
case BRW_OPCODE_CONTINUE: |
case BRW_OPCODE_HALT: |
update_uip_jip(insn, this_old_ip, compacted_counts); |
break; |
case BRW_OPCODE_IF: |
case BRW_OPCODE_ELSE: |
case BRW_OPCODE_ENDIF: |
case BRW_OPCODE_WHILE: |
if (brw->gen == 6) { |
target_old_ip = this_old_ip + insn->bits1.branch_gen6.jump_count; |
target_compacted_count = compacted_counts[target_old_ip]; |
insn->bits1.branch_gen6.jump_count -= (target_compacted_count - |
this_compacted_count); |
} else { |
update_uip_jip(insn, this_old_ip, compacted_counts); |
} |
break; |
} |
if (insn->header.cmpt_control) { |
offset += 8; |
} else { |
offset += 16; |
} |
} |
/* p->nr_insn is counting the number of uncompacted instructions still, so |
* divide. We do want to be sure there's a valid instruction in any |
* alignment padding, so that the next compression pass (for the FS 8/16 |
* compile passes) parses correctly. |
*/ |
if (p->next_insn_offset & 8) { |
struct brw_compact_instruction *align = store + offset; |
memset(align, 0, sizeof(*align)); |
align->dw0.opcode = BRW_OPCODE_NOP; |
align->dw0.cmpt_ctrl = 1; |
p->next_insn_offset += 8; |
} |
p->nr_insn = p->next_insn_offset / 16; |
if (0) { |
fprintf(stdout, "dumping compacted program\n"); |
brw_dump_compile(p, stdout, 0, p->next_insn_offset); |
int cmp = 0; |
for (offset = 0; offset < p->next_insn_offset;) { |
struct brw_instruction *insn = store + offset; |
if (insn->header.cmpt_control) { |
offset += 8; |
cmp++; |
} else { |
offset += 16; |
} |
} |
fprintf(stderr, "%db/%db saved (%d%%)\n", cmp * 8, offset + cmp * 8, |
cmp * 8 * 100 / (offset + cmp * 8)); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_eu_emit.c |
---|
0,0 → 1,2528 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "brw_context.h" |
#include "brw_defines.h" |
#include "brw_eu.h" |
#include "glsl/ralloc.h" |
/*********************************************************************** |
* Internal helper for constructing instructions |
*/ |
static void guess_execution_size(struct brw_compile *p, |
struct brw_instruction *insn, |
struct brw_reg reg) |
{ |
if (reg.width == BRW_WIDTH_8 && p->compressed) |
insn->header.execution_size = BRW_EXECUTE_16; |
else |
insn->header.execution_size = reg.width; /* note - definitions are compatible */ |
} |
/** |
* Prior to Sandybridge, the SEND instruction accepted non-MRF source |
* registers, implicitly moving the operand to a message register. |
* |
* On Sandybridge, this is no longer the case. This function performs the |
* explicit move; it should be called before emitting a SEND instruction. |
*/ |
void |
gen6_resolve_implied_move(struct brw_compile *p, |
struct brw_reg *src, |
GLuint msg_reg_nr) |
{ |
struct brw_context *brw = p->brw; |
if (brw->gen < 6) |
return; |
if (src->file == BRW_MESSAGE_REGISTER_FILE) |
return; |
if (src->file != BRW_ARCHITECTURE_REGISTER_FILE || src->nr != BRW_ARF_NULL) { |
brw_push_insn_state(p); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_MOV(p, retype(brw_message_reg(msg_reg_nr), BRW_REGISTER_TYPE_UD), |
retype(*src, BRW_REGISTER_TYPE_UD)); |
brw_pop_insn_state(p); |
} |
*src = brw_message_reg(msg_reg_nr); |
} |
static void |
gen7_convert_mrf_to_grf(struct brw_compile *p, struct brw_reg *reg) |
{ |
/* From the Ivybridge PRM, Volume 4 Part 3, page 218 ("send"): |
* "The send with EOT should use register space R112-R127 for <src>. This is |
* to enable loading of a new thread into the same slot while the message |
* with EOT for current thread is pending dispatch." |
* |
* Since we're pretending to have 16 MRFs anyway, we may as well use the |
* registers required for messages with EOT. |
*/ |
struct brw_context *brw = p->brw; |
if (brw->gen == 7 && reg->file == BRW_MESSAGE_REGISTER_FILE) { |
reg->file = BRW_GENERAL_REGISTER_FILE; |
reg->nr += GEN7_MRF_HACK_START; |
} |
} |
void |
brw_set_dest(struct brw_compile *p, struct brw_instruction *insn, |
struct brw_reg dest) |
{ |
if (dest.file != BRW_ARCHITECTURE_REGISTER_FILE && |
dest.file != BRW_MESSAGE_REGISTER_FILE) |
assert(dest.nr < 128); |
gen7_convert_mrf_to_grf(p, &dest); |
insn->bits1.da1.dest_reg_file = dest.file; |
insn->bits1.da1.dest_reg_type = dest.type; |
insn->bits1.da1.dest_address_mode = dest.address_mode; |
if (dest.address_mode == BRW_ADDRESS_DIRECT) { |
insn->bits1.da1.dest_reg_nr = dest.nr; |
if (insn->header.access_mode == BRW_ALIGN_1) { |
insn->bits1.da1.dest_subreg_nr = dest.subnr; |
if (dest.hstride == BRW_HORIZONTAL_STRIDE_0) |
dest.hstride = BRW_HORIZONTAL_STRIDE_1; |
insn->bits1.da1.dest_horiz_stride = dest.hstride; |
} |
else { |
insn->bits1.da16.dest_subreg_nr = dest.subnr / 16; |
insn->bits1.da16.dest_writemask = dest.dw1.bits.writemask; |
/* From the Ivybridge PRM, Vol 4, Part 3, Section 5.2.4.1: |
* Although Dst.HorzStride is a don't care for Align16, HW needs |
* this to be programmed as "01". |
*/ |
insn->bits1.da16.dest_horiz_stride = 1; |
} |
} |
else { |
insn->bits1.ia1.dest_subreg_nr = dest.subnr; |
/* These are different sizes in align1 vs align16: |
*/ |
if (insn->header.access_mode == BRW_ALIGN_1) { |
insn->bits1.ia1.dest_indirect_offset = dest.dw1.bits.indirect_offset; |
if (dest.hstride == BRW_HORIZONTAL_STRIDE_0) |
dest.hstride = BRW_HORIZONTAL_STRIDE_1; |
insn->bits1.ia1.dest_horiz_stride = dest.hstride; |
} |
else { |
insn->bits1.ia16.dest_indirect_offset = dest.dw1.bits.indirect_offset; |
/* even ignored in da16, still need to set as '01' */ |
insn->bits1.ia16.dest_horiz_stride = 1; |
} |
} |
/* NEW: Set the execution size based on dest.width and |
* insn->compression_control: |
*/ |
guess_execution_size(p, insn, dest); |
} |
extern int reg_type_size[]; |
static void |
validate_reg(struct brw_instruction *insn, struct brw_reg reg) |
{ |
int hstride_for_reg[] = {0, 1, 2, 4}; |
int vstride_for_reg[] = {0, 1, 2, 4, 8, 16, 32, 64, 128, 256}; |
int width_for_reg[] = {1, 2, 4, 8, 16}; |
int execsize_for_reg[] = {1, 2, 4, 8, 16}; |
int width, hstride, vstride, execsize; |
if (reg.file == BRW_IMMEDIATE_VALUE) { |
/* 3.3.6: Region Parameters. Restriction: Immediate vectors |
* mean the destination has to be 128-bit aligned and the |
* destination horiz stride has to be a word. |
*/ |
if (reg.type == BRW_REGISTER_TYPE_V) { |
assert(hstride_for_reg[insn->bits1.da1.dest_horiz_stride] * |
reg_type_size[insn->bits1.da1.dest_reg_type] == 2); |
} |
return; |
} |
if (reg.file == BRW_ARCHITECTURE_REGISTER_FILE && |
reg.file == BRW_ARF_NULL) |
return; |
assert(reg.hstride >= 0 && reg.hstride < Elements(hstride_for_reg)); |
hstride = hstride_for_reg[reg.hstride]; |
if (reg.vstride == 0xf) { |
vstride = -1; |
} else { |
assert(reg.vstride >= 0 && reg.vstride < Elements(vstride_for_reg)); |
vstride = vstride_for_reg[reg.vstride]; |
} |
assert(reg.width >= 0 && reg.width < Elements(width_for_reg)); |
width = width_for_reg[reg.width]; |
assert(insn->header.execution_size >= 0 && |
insn->header.execution_size < Elements(execsize_for_reg)); |
execsize = execsize_for_reg[insn->header.execution_size]; |
/* Restrictions from 3.3.10: Register Region Restrictions. */ |
/* 3. */ |
assert(execsize >= width); |
/* 4. */ |
if (execsize == width && hstride != 0) { |
assert(vstride == -1 || vstride == width * hstride); |
} |
/* 5. */ |
if (execsize == width && hstride == 0) { |
/* no restriction on vstride. */ |
} |
/* 6. */ |
if (width == 1) { |
assert(hstride == 0); |
} |
/* 7. */ |
if (execsize == 1 && width == 1) { |
assert(hstride == 0); |
assert(vstride == 0); |
} |
/* 8. */ |
if (vstride == 0 && hstride == 0) { |
assert(width == 1); |
} |
/* 10. Check destination issues. */ |
} |
void |
brw_set_src0(struct brw_compile *p, struct brw_instruction *insn, |
struct brw_reg reg) |
{ |
struct brw_context *brw = p->brw; |
if (reg.type != BRW_ARCHITECTURE_REGISTER_FILE) |
assert(reg.nr < 128); |
gen7_convert_mrf_to_grf(p, ®); |
if (brw->gen >= 6 && (insn->header.opcode == BRW_OPCODE_SEND || |
insn->header.opcode == BRW_OPCODE_SENDC)) { |
/* Any source modifiers or regions will be ignored, since this just |
* identifies the MRF/GRF to start reading the message contents from. |
* Check for some likely failures. |
*/ |
assert(!reg.negate); |
assert(!reg.abs); |
assert(reg.address_mode == BRW_ADDRESS_DIRECT); |
} |
validate_reg(insn, reg); |
insn->bits1.da1.src0_reg_file = reg.file; |
insn->bits1.da1.src0_reg_type = reg.type; |
insn->bits2.da1.src0_abs = reg.abs; |
insn->bits2.da1.src0_negate = reg.negate; |
insn->bits2.da1.src0_address_mode = reg.address_mode; |
if (reg.file == BRW_IMMEDIATE_VALUE) { |
insn->bits3.ud = reg.dw1.ud; |
/* Required to set some fields in src1 as well: |
*/ |
insn->bits1.da1.src1_reg_file = 0; /* arf */ |
insn->bits1.da1.src1_reg_type = reg.type; |
} |
else |
{ |
if (reg.address_mode == BRW_ADDRESS_DIRECT) { |
if (insn->header.access_mode == BRW_ALIGN_1) { |
insn->bits2.da1.src0_subreg_nr = reg.subnr; |
insn->bits2.da1.src0_reg_nr = reg.nr; |
} |
else { |
insn->bits2.da16.src0_subreg_nr = reg.subnr / 16; |
insn->bits2.da16.src0_reg_nr = reg.nr; |
} |
} |
else { |
insn->bits2.ia1.src0_subreg_nr = reg.subnr; |
if (insn->header.access_mode == BRW_ALIGN_1) { |
insn->bits2.ia1.src0_indirect_offset = reg.dw1.bits.indirect_offset; |
} |
else { |
insn->bits2.ia16.src0_subreg_nr = reg.dw1.bits.indirect_offset; |
} |
} |
if (insn->header.access_mode == BRW_ALIGN_1) { |
if (reg.width == BRW_WIDTH_1 && |
insn->header.execution_size == BRW_EXECUTE_1) { |
insn->bits2.da1.src0_horiz_stride = BRW_HORIZONTAL_STRIDE_0; |
insn->bits2.da1.src0_width = BRW_WIDTH_1; |
insn->bits2.da1.src0_vert_stride = BRW_VERTICAL_STRIDE_0; |
} |
else { |
insn->bits2.da1.src0_horiz_stride = reg.hstride; |
insn->bits2.da1.src0_width = reg.width; |
insn->bits2.da1.src0_vert_stride = reg.vstride; |
} |
} |
else { |
insn->bits2.da16.src0_swz_x = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_X); |
insn->bits2.da16.src0_swz_y = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Y); |
insn->bits2.da16.src0_swz_z = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Z); |
insn->bits2.da16.src0_swz_w = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_W); |
/* This is an oddity of the fact we're using the same |
* descriptions for registers in align_16 as align_1: |
*/ |
if (reg.vstride == BRW_VERTICAL_STRIDE_8) |
insn->bits2.da16.src0_vert_stride = BRW_VERTICAL_STRIDE_4; |
else |
insn->bits2.da16.src0_vert_stride = reg.vstride; |
} |
} |
} |
void brw_set_src1(struct brw_compile *p, |
struct brw_instruction *insn, |
struct brw_reg reg) |
{ |
assert(reg.file != BRW_MESSAGE_REGISTER_FILE); |
if (reg.type != BRW_ARCHITECTURE_REGISTER_FILE) |
assert(reg.nr < 128); |
gen7_convert_mrf_to_grf(p, ®); |
validate_reg(insn, reg); |
insn->bits1.da1.src1_reg_file = reg.file; |
insn->bits1.da1.src1_reg_type = reg.type; |
insn->bits3.da1.src1_abs = reg.abs; |
insn->bits3.da1.src1_negate = reg.negate; |
/* Only src1 can be immediate in two-argument instructions. |
*/ |
assert(insn->bits1.da1.src0_reg_file != BRW_IMMEDIATE_VALUE); |
if (reg.file == BRW_IMMEDIATE_VALUE) { |
insn->bits3.ud = reg.dw1.ud; |
} |
else { |
/* This is a hardware restriction, which may or may not be lifted |
* in the future: |
*/ |
assert (reg.address_mode == BRW_ADDRESS_DIRECT); |
/* assert (reg.file == BRW_GENERAL_REGISTER_FILE); */ |
if (insn->header.access_mode == BRW_ALIGN_1) { |
insn->bits3.da1.src1_subreg_nr = reg.subnr; |
insn->bits3.da1.src1_reg_nr = reg.nr; |
} |
else { |
insn->bits3.da16.src1_subreg_nr = reg.subnr / 16; |
insn->bits3.da16.src1_reg_nr = reg.nr; |
} |
if (insn->header.access_mode == BRW_ALIGN_1) { |
if (reg.width == BRW_WIDTH_1 && |
insn->header.execution_size == BRW_EXECUTE_1) { |
insn->bits3.da1.src1_horiz_stride = BRW_HORIZONTAL_STRIDE_0; |
insn->bits3.da1.src1_width = BRW_WIDTH_1; |
insn->bits3.da1.src1_vert_stride = BRW_VERTICAL_STRIDE_0; |
} |
else { |
insn->bits3.da1.src1_horiz_stride = reg.hstride; |
insn->bits3.da1.src1_width = reg.width; |
insn->bits3.da1.src1_vert_stride = reg.vstride; |
} |
} |
else { |
insn->bits3.da16.src1_swz_x = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_X); |
insn->bits3.da16.src1_swz_y = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Y); |
insn->bits3.da16.src1_swz_z = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_Z); |
insn->bits3.da16.src1_swz_w = BRW_GET_SWZ(reg.dw1.bits.swizzle, BRW_CHANNEL_W); |
/* This is an oddity of the fact we're using the same |
* descriptions for registers in align_16 as align_1: |
*/ |
if (reg.vstride == BRW_VERTICAL_STRIDE_8) |
insn->bits3.da16.src1_vert_stride = BRW_VERTICAL_STRIDE_4; |
else |
insn->bits3.da16.src1_vert_stride = reg.vstride; |
} |
} |
} |
/** |
* Set the Message Descriptor and Extended Message Descriptor fields |
* for SEND messages. |
* |
* \note This zeroes out the Function Control bits, so it must be called |
* \b before filling out any message-specific data. Callers can |
* choose not to fill in irrelevant bits; they will be zero. |
*/ |
static void |
brw_set_message_descriptor(struct brw_compile *p, |
struct brw_instruction *inst, |
enum brw_message_target sfid, |
unsigned msg_length, |
unsigned response_length, |
bool header_present, |
bool end_of_thread) |
{ |
struct brw_context *brw = p->brw; |
brw_set_src1(p, inst, brw_imm_d(0)); |
if (brw->gen >= 5) { |
inst->bits3.generic_gen5.header_present = header_present; |
inst->bits3.generic_gen5.response_length = response_length; |
inst->bits3.generic_gen5.msg_length = msg_length; |
inst->bits3.generic_gen5.end_of_thread = end_of_thread; |
if (brw->gen >= 6) { |
/* On Gen6+ Message target/SFID goes in bits 27:24 of the header */ |
inst->header.destreg__conditionalmod = sfid; |
} else { |
/* Set Extended Message Descriptor (ex_desc) */ |
inst->bits2.send_gen5.sfid = sfid; |
inst->bits2.send_gen5.end_of_thread = end_of_thread; |
} |
} else { |
inst->bits3.generic.response_length = response_length; |
inst->bits3.generic.msg_length = msg_length; |
inst->bits3.generic.msg_target = sfid; |
inst->bits3.generic.end_of_thread = end_of_thread; |
} |
} |
static void brw_set_math_message( struct brw_compile *p, |
struct brw_instruction *insn, |
GLuint function, |
GLuint integer_type, |
bool low_precision, |
GLuint dataType ) |
{ |
struct brw_context *brw = p->brw; |
unsigned msg_length; |
unsigned response_length; |
/* Infer message length from the function */ |
switch (function) { |
case BRW_MATH_FUNCTION_POW: |
case BRW_MATH_FUNCTION_INT_DIV_QUOTIENT: |
case BRW_MATH_FUNCTION_INT_DIV_REMAINDER: |
case BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER: |
msg_length = 2; |
break; |
default: |
msg_length = 1; |
break; |
} |
/* Infer response length from the function */ |
switch (function) { |
case BRW_MATH_FUNCTION_SINCOS: |
case BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER: |
response_length = 2; |
break; |
default: |
response_length = 1; |
break; |
} |
brw_set_message_descriptor(p, insn, BRW_SFID_MATH, |
msg_length, response_length, false, false); |
if (brw->gen == 5) { |
insn->bits3.math_gen5.function = function; |
insn->bits3.math_gen5.int_type = integer_type; |
insn->bits3.math_gen5.precision = low_precision; |
insn->bits3.math_gen5.saturate = insn->header.saturate; |
insn->bits3.math_gen5.data_type = dataType; |
insn->bits3.math_gen5.snapshot = 0; |
} else { |
insn->bits3.math.function = function; |
insn->bits3.math.int_type = integer_type; |
insn->bits3.math.precision = low_precision; |
insn->bits3.math.saturate = insn->header.saturate; |
insn->bits3.math.data_type = dataType; |
} |
insn->header.saturate = 0; |
} |
static void brw_set_ff_sync_message(struct brw_compile *p, |
struct brw_instruction *insn, |
bool allocate, |
GLuint response_length, |
bool end_of_thread) |
{ |
brw_set_message_descriptor(p, insn, BRW_SFID_URB, |
1, response_length, true, end_of_thread); |
insn->bits3.urb_gen5.opcode = 1; /* FF_SYNC */ |
insn->bits3.urb_gen5.offset = 0; /* Not used by FF_SYNC */ |
insn->bits3.urb_gen5.swizzle_control = 0; /* Not used by FF_SYNC */ |
insn->bits3.urb_gen5.allocate = allocate; |
insn->bits3.urb_gen5.used = 0; /* Not used by FF_SYNC */ |
insn->bits3.urb_gen5.complete = 0; /* Not used by FF_SYNC */ |
} |
static void brw_set_urb_message( struct brw_compile *p, |
struct brw_instruction *insn, |
bool allocate, |
bool used, |
GLuint msg_length, |
GLuint response_length, |
bool end_of_thread, |
bool complete, |
GLuint offset, |
GLuint swizzle_control ) |
{ |
struct brw_context *brw = p->brw; |
brw_set_message_descriptor(p, insn, BRW_SFID_URB, |
msg_length, response_length, true, end_of_thread); |
if (brw->gen == 7) { |
insn->bits3.urb_gen7.opcode = 0; /* URB_WRITE_HWORD */ |
insn->bits3.urb_gen7.offset = offset; |
assert(swizzle_control != BRW_URB_SWIZZLE_TRANSPOSE); |
insn->bits3.urb_gen7.swizzle_control = swizzle_control; |
/* per_slot_offset = 0 makes it ignore offsets in message header */ |
insn->bits3.urb_gen7.per_slot_offset = 0; |
insn->bits3.urb_gen7.complete = complete; |
} else if (brw->gen >= 5) { |
insn->bits3.urb_gen5.opcode = 0; /* URB_WRITE */ |
insn->bits3.urb_gen5.offset = offset; |
insn->bits3.urb_gen5.swizzle_control = swizzle_control; |
insn->bits3.urb_gen5.allocate = allocate; |
insn->bits3.urb_gen5.used = used; /* ? */ |
insn->bits3.urb_gen5.complete = complete; |
} else { |
insn->bits3.urb.opcode = 0; /* ? */ |
insn->bits3.urb.offset = offset; |
insn->bits3.urb.swizzle_control = swizzle_control; |
insn->bits3.urb.allocate = allocate; |
insn->bits3.urb.used = used; /* ? */ |
insn->bits3.urb.complete = complete; |
} |
} |
void |
brw_set_dp_write_message(struct brw_compile *p, |
struct brw_instruction *insn, |
GLuint binding_table_index, |
GLuint msg_control, |
GLuint msg_type, |
GLuint msg_length, |
bool header_present, |
GLuint last_render_target, |
GLuint response_length, |
GLuint end_of_thread, |
GLuint send_commit_msg) |
{ |
struct brw_context *brw = p->brw; |
unsigned sfid; |
if (brw->gen >= 7) { |
/* Use the Render Cache for RT writes; otherwise use the Data Cache */ |
if (msg_type == GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE) |
sfid = GEN6_SFID_DATAPORT_RENDER_CACHE; |
else |
sfid = GEN7_SFID_DATAPORT_DATA_CACHE; |
} else if (brw->gen == 6) { |
/* Use the render cache for all write messages. */ |
sfid = GEN6_SFID_DATAPORT_RENDER_CACHE; |
} else { |
sfid = BRW_SFID_DATAPORT_WRITE; |
} |
brw_set_message_descriptor(p, insn, sfid, msg_length, response_length, |
header_present, end_of_thread); |
if (brw->gen >= 7) { |
insn->bits3.gen7_dp.binding_table_index = binding_table_index; |
insn->bits3.gen7_dp.msg_control = msg_control; |
insn->bits3.gen7_dp.last_render_target = last_render_target; |
insn->bits3.gen7_dp.msg_type = msg_type; |
} else if (brw->gen == 6) { |
insn->bits3.gen6_dp.binding_table_index = binding_table_index; |
insn->bits3.gen6_dp.msg_control = msg_control; |
insn->bits3.gen6_dp.last_render_target = last_render_target; |
insn->bits3.gen6_dp.msg_type = msg_type; |
insn->bits3.gen6_dp.send_commit_msg = send_commit_msg; |
} else if (brw->gen == 5) { |
insn->bits3.dp_write_gen5.binding_table_index = binding_table_index; |
insn->bits3.dp_write_gen5.msg_control = msg_control; |
insn->bits3.dp_write_gen5.last_render_target = last_render_target; |
insn->bits3.dp_write_gen5.msg_type = msg_type; |
insn->bits3.dp_write_gen5.send_commit_msg = send_commit_msg; |
} else { |
insn->bits3.dp_write.binding_table_index = binding_table_index; |
insn->bits3.dp_write.msg_control = msg_control; |
insn->bits3.dp_write.last_render_target = last_render_target; |
insn->bits3.dp_write.msg_type = msg_type; |
insn->bits3.dp_write.send_commit_msg = send_commit_msg; |
} |
} |
void |
brw_set_dp_read_message(struct brw_compile *p, |
struct brw_instruction *insn, |
GLuint binding_table_index, |
GLuint msg_control, |
GLuint msg_type, |
GLuint target_cache, |
GLuint msg_length, |
bool header_present, |
GLuint response_length) |
{ |
struct brw_context *brw = p->brw; |
unsigned sfid; |
if (brw->gen >= 7) { |
sfid = GEN7_SFID_DATAPORT_DATA_CACHE; |
} else if (brw->gen == 6) { |
if (target_cache == BRW_DATAPORT_READ_TARGET_RENDER_CACHE) |
sfid = GEN6_SFID_DATAPORT_RENDER_CACHE; |
else |
sfid = GEN6_SFID_DATAPORT_SAMPLER_CACHE; |
} else { |
sfid = BRW_SFID_DATAPORT_READ; |
} |
brw_set_message_descriptor(p, insn, sfid, msg_length, response_length, |
header_present, false); |
if (brw->gen >= 7) { |
insn->bits3.gen7_dp.binding_table_index = binding_table_index; |
insn->bits3.gen7_dp.msg_control = msg_control; |
insn->bits3.gen7_dp.last_render_target = 0; |
insn->bits3.gen7_dp.msg_type = msg_type; |
} else if (brw->gen == 6) { |
insn->bits3.gen6_dp.binding_table_index = binding_table_index; |
insn->bits3.gen6_dp.msg_control = msg_control; |
insn->bits3.gen6_dp.last_render_target = 0; |
insn->bits3.gen6_dp.msg_type = msg_type; |
insn->bits3.gen6_dp.send_commit_msg = 0; |
} else if (brw->gen == 5) { |
insn->bits3.dp_read_gen5.binding_table_index = binding_table_index; |
insn->bits3.dp_read_gen5.msg_control = msg_control; |
insn->bits3.dp_read_gen5.msg_type = msg_type; |
insn->bits3.dp_read_gen5.target_cache = target_cache; |
} else if (brw->is_g4x) { |
insn->bits3.dp_read_g4x.binding_table_index = binding_table_index; /*0:7*/ |
insn->bits3.dp_read_g4x.msg_control = msg_control; /*8:10*/ |
insn->bits3.dp_read_g4x.msg_type = msg_type; /*11:13*/ |
insn->bits3.dp_read_g4x.target_cache = target_cache; /*14:15*/ |
} else { |
insn->bits3.dp_read.binding_table_index = binding_table_index; /*0:7*/ |
insn->bits3.dp_read.msg_control = msg_control; /*8:11*/ |
insn->bits3.dp_read.msg_type = msg_type; /*12:13*/ |
insn->bits3.dp_read.target_cache = target_cache; /*14:15*/ |
} |
} |
void |
brw_set_sampler_message(struct brw_compile *p, |
struct brw_instruction *insn, |
GLuint binding_table_index, |
GLuint sampler, |
GLuint msg_type, |
GLuint response_length, |
GLuint msg_length, |
GLuint header_present, |
GLuint simd_mode, |
GLuint return_format) |
{ |
struct brw_context *brw = p->brw; |
brw_set_message_descriptor(p, insn, BRW_SFID_SAMPLER, msg_length, |
response_length, header_present, false); |
if (brw->gen >= 7) { |
insn->bits3.sampler_gen7.binding_table_index = binding_table_index; |
insn->bits3.sampler_gen7.sampler = sampler; |
insn->bits3.sampler_gen7.msg_type = msg_type; |
insn->bits3.sampler_gen7.simd_mode = simd_mode; |
} else if (brw->gen >= 5) { |
insn->bits3.sampler_gen5.binding_table_index = binding_table_index; |
insn->bits3.sampler_gen5.sampler = sampler; |
insn->bits3.sampler_gen5.msg_type = msg_type; |
insn->bits3.sampler_gen5.simd_mode = simd_mode; |
} else if (brw->is_g4x) { |
insn->bits3.sampler_g4x.binding_table_index = binding_table_index; |
insn->bits3.sampler_g4x.sampler = sampler; |
insn->bits3.sampler_g4x.msg_type = msg_type; |
} else { |
insn->bits3.sampler.binding_table_index = binding_table_index; |
insn->bits3.sampler.sampler = sampler; |
insn->bits3.sampler.msg_type = msg_type; |
insn->bits3.sampler.return_format = return_format; |
} |
} |
#define next_insn brw_next_insn |
struct brw_instruction * |
brw_next_insn(struct brw_compile *p, GLuint opcode) |
{ |
struct brw_instruction *insn; |
if (p->nr_insn + 1 > p->store_size) { |
if (0) |
printf("incresing the store size to %d\n", p->store_size << 1); |
p->store_size <<= 1; |
p->store = reralloc(p->mem_ctx, p->store, |
struct brw_instruction, p->store_size); |
if (!p->store) |
assert(!"realloc eu store memeory failed"); |
} |
p->next_insn_offset += 16; |
insn = &p->store[p->nr_insn++]; |
memcpy(insn, p->current, sizeof(*insn)); |
/* Reset this one-shot flag: |
*/ |
if (p->current->header.destreg__conditionalmod) { |
p->current->header.destreg__conditionalmod = 0; |
p->current->header.predicate_control = BRW_PREDICATE_NORMAL; |
} |
insn->header.opcode = opcode; |
return insn; |
} |
static struct brw_instruction *brw_alu1( struct brw_compile *p, |
GLuint opcode, |
struct brw_reg dest, |
struct brw_reg src ) |
{ |
struct brw_instruction *insn = next_insn(p, opcode); |
brw_set_dest(p, insn, dest); |
brw_set_src0(p, insn, src); |
return insn; |
} |
static struct brw_instruction *brw_alu2(struct brw_compile *p, |
GLuint opcode, |
struct brw_reg dest, |
struct brw_reg src0, |
struct brw_reg src1 ) |
{ |
struct brw_instruction *insn = next_insn(p, opcode); |
brw_set_dest(p, insn, dest); |
brw_set_src0(p, insn, src0); |
brw_set_src1(p, insn, src1); |
return insn; |
} |
static int |
get_3src_subreg_nr(struct brw_reg reg) |
{ |
if (reg.vstride == BRW_VERTICAL_STRIDE_0) { |
assert(brw_is_single_value_swizzle(reg.dw1.bits.swizzle)); |
return reg.subnr / 4 + BRW_GET_SWZ(reg.dw1.bits.swizzle, 0); |
} else { |
return reg.subnr / 4; |
} |
} |
static struct brw_instruction *brw_alu3(struct brw_compile *p, |
GLuint opcode, |
struct brw_reg dest, |
struct brw_reg src0, |
struct brw_reg src1, |
struct brw_reg src2) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn = next_insn(p, opcode); |
gen7_convert_mrf_to_grf(p, &dest); |
assert(insn->header.access_mode == BRW_ALIGN_16); |
assert(dest.file == BRW_GENERAL_REGISTER_FILE || |
dest.file == BRW_MESSAGE_REGISTER_FILE); |
assert(dest.nr < 128); |
assert(dest.address_mode == BRW_ADDRESS_DIRECT); |
assert(dest.type == BRW_REGISTER_TYPE_F || |
dest.type == BRW_REGISTER_TYPE_D || |
dest.type == BRW_REGISTER_TYPE_UD); |
insn->bits1.da3src.dest_reg_file = (dest.file == BRW_MESSAGE_REGISTER_FILE); |
insn->bits1.da3src.dest_reg_nr = dest.nr; |
insn->bits1.da3src.dest_subreg_nr = dest.subnr / 16; |
insn->bits1.da3src.dest_writemask = dest.dw1.bits.writemask; |
guess_execution_size(p, insn, dest); |
assert(src0.file == BRW_GENERAL_REGISTER_FILE); |
assert(src0.address_mode == BRW_ADDRESS_DIRECT); |
assert(src0.nr < 128); |
insn->bits2.da3src.src0_swizzle = src0.dw1.bits.swizzle; |
insn->bits2.da3src.src0_subreg_nr = get_3src_subreg_nr(src0); |
insn->bits2.da3src.src0_reg_nr = src0.nr; |
insn->bits1.da3src.src0_abs = src0.abs; |
insn->bits1.da3src.src0_negate = src0.negate; |
insn->bits2.da3src.src0_rep_ctrl = src0.vstride == BRW_VERTICAL_STRIDE_0; |
assert(src1.file == BRW_GENERAL_REGISTER_FILE); |
assert(src1.address_mode == BRW_ADDRESS_DIRECT); |
assert(src1.nr < 128); |
insn->bits2.da3src.src1_swizzle = src1.dw1.bits.swizzle; |
insn->bits2.da3src.src1_subreg_nr_low = get_3src_subreg_nr(src1) & 0x3; |
insn->bits3.da3src.src1_subreg_nr_high = get_3src_subreg_nr(src1) >> 2; |
insn->bits2.da3src.src1_rep_ctrl = src1.vstride == BRW_VERTICAL_STRIDE_0; |
insn->bits3.da3src.src1_reg_nr = src1.nr; |
insn->bits1.da3src.src1_abs = src1.abs; |
insn->bits1.da3src.src1_negate = src1.negate; |
assert(src2.file == BRW_GENERAL_REGISTER_FILE); |
assert(src2.address_mode == BRW_ADDRESS_DIRECT); |
assert(src2.nr < 128); |
insn->bits3.da3src.src2_swizzle = src2.dw1.bits.swizzle; |
insn->bits3.da3src.src2_subreg_nr = get_3src_subreg_nr(src2); |
insn->bits3.da3src.src2_rep_ctrl = src2.vstride == BRW_VERTICAL_STRIDE_0; |
insn->bits3.da3src.src2_reg_nr = src2.nr; |
insn->bits1.da3src.src2_abs = src2.abs; |
insn->bits1.da3src.src2_negate = src2.negate; |
if (brw->gen >= 7) { |
/* Set both the source and destination types based on dest.type, |
* ignoring the source register types. The MAD and LRP emitters ensure |
* that all four types are float. The BFE and BFI2 emitters, however, |
* may send us mixed D and UD types and want us to ignore that and use |
* the destination type. |
*/ |
switch (dest.type) { |
case BRW_REGISTER_TYPE_F: |
insn->bits1.da3src.src_type = BRW_3SRC_TYPE_F; |
insn->bits1.da3src.dst_type = BRW_3SRC_TYPE_F; |
break; |
case BRW_REGISTER_TYPE_D: |
insn->bits1.da3src.src_type = BRW_3SRC_TYPE_D; |
insn->bits1.da3src.dst_type = BRW_3SRC_TYPE_D; |
break; |
case BRW_REGISTER_TYPE_UD: |
insn->bits1.da3src.src_type = BRW_3SRC_TYPE_UD; |
insn->bits1.da3src.dst_type = BRW_3SRC_TYPE_UD; |
break; |
} |
} |
return insn; |
} |
/*********************************************************************** |
* Convenience routines. |
*/ |
#define ALU1(OP) \ |
struct brw_instruction *brw_##OP(struct brw_compile *p, \ |
struct brw_reg dest, \ |
struct brw_reg src0) \ |
{ \ |
return brw_alu1(p, BRW_OPCODE_##OP, dest, src0); \ |
} |
#define ALU2(OP) \ |
struct brw_instruction *brw_##OP(struct brw_compile *p, \ |
struct brw_reg dest, \ |
struct brw_reg src0, \ |
struct brw_reg src1) \ |
{ \ |
return brw_alu2(p, BRW_OPCODE_##OP, dest, src0, src1); \ |
} |
#define ALU3(OP) \ |
struct brw_instruction *brw_##OP(struct brw_compile *p, \ |
struct brw_reg dest, \ |
struct brw_reg src0, \ |
struct brw_reg src1, \ |
struct brw_reg src2) \ |
{ \ |
return brw_alu3(p, BRW_OPCODE_##OP, dest, src0, src1, src2); \ |
} |
#define ALU3F(OP) \ |
struct brw_instruction *brw_##OP(struct brw_compile *p, \ |
struct brw_reg dest, \ |
struct brw_reg src0, \ |
struct brw_reg src1, \ |
struct brw_reg src2) \ |
{ \ |
assert(dest.type == BRW_REGISTER_TYPE_F); \ |
assert(src0.type == BRW_REGISTER_TYPE_F); \ |
assert(src1.type == BRW_REGISTER_TYPE_F); \ |
assert(src2.type == BRW_REGISTER_TYPE_F); \ |
return brw_alu3(p, BRW_OPCODE_##OP, dest, src0, src1, src2); \ |
} |
/* Rounding operations (other than RNDD) require two instructions - the first |
* stores a rounded value (possibly the wrong way) in the dest register, but |
* also sets a per-channel "increment bit" in the flag register. A predicated |
* add of 1.0 fixes dest to contain the desired result. |
* |
* Sandybridge and later appear to round correctly without an ADD. |
*/ |
#define ROUND(OP) \ |
void brw_##OP(struct brw_compile *p, \ |
struct brw_reg dest, \ |
struct brw_reg src) \ |
{ \ |
struct brw_instruction *rnd, *add; \ |
rnd = next_insn(p, BRW_OPCODE_##OP); \ |
brw_set_dest(p, rnd, dest); \ |
brw_set_src0(p, rnd, src); \ |
\ |
if (p->brw->gen < 6) { \ |
/* turn on round-increments */ \ |
rnd->header.destreg__conditionalmod = BRW_CONDITIONAL_R; \ |
add = brw_ADD(p, dest, dest, brw_imm_f(1.0f)); \ |
add->header.predicate_control = BRW_PREDICATE_NORMAL; \ |
} \ |
} |
ALU1(MOV) |
ALU2(SEL) |
ALU1(NOT) |
ALU2(AND) |
ALU2(OR) |
ALU2(XOR) |
ALU2(SHR) |
ALU2(SHL) |
ALU2(RSR) |
ALU2(RSL) |
ALU2(ASR) |
ALU1(F32TO16) |
ALU1(F16TO32) |
ALU1(FRC) |
ALU1(RNDD) |
ALU2(MAC) |
ALU2(MACH) |
ALU1(LZD) |
ALU2(DP4) |
ALU2(DPH) |
ALU2(DP3) |
ALU2(DP2) |
ALU2(LINE) |
ALU2(PLN) |
ALU3F(MAD) |
ALU3F(LRP) |
ALU1(BFREV) |
ALU3(BFE) |
ALU2(BFI1) |
ALU3(BFI2) |
ALU1(FBH) |
ALU1(FBL) |
ALU1(CBIT) |
ROUND(RNDZ) |
ROUND(RNDE) |
struct brw_instruction *brw_ADD(struct brw_compile *p, |
struct brw_reg dest, |
struct brw_reg src0, |
struct brw_reg src1) |
{ |
/* 6.2.2: add */ |
if (src0.type == BRW_REGISTER_TYPE_F || |
(src0.file == BRW_IMMEDIATE_VALUE && |
src0.type == BRW_REGISTER_TYPE_VF)) { |
assert(src1.type != BRW_REGISTER_TYPE_UD); |
assert(src1.type != BRW_REGISTER_TYPE_D); |
} |
if (src1.type == BRW_REGISTER_TYPE_F || |
(src1.file == BRW_IMMEDIATE_VALUE && |
src1.type == BRW_REGISTER_TYPE_VF)) { |
assert(src0.type != BRW_REGISTER_TYPE_UD); |
assert(src0.type != BRW_REGISTER_TYPE_D); |
} |
return brw_alu2(p, BRW_OPCODE_ADD, dest, src0, src1); |
} |
struct brw_instruction *brw_AVG(struct brw_compile *p, |
struct brw_reg dest, |
struct brw_reg src0, |
struct brw_reg src1) |
{ |
assert(dest.type == src0.type); |
assert(src0.type == src1.type); |
switch (src0.type) { |
case BRW_REGISTER_TYPE_B: |
case BRW_REGISTER_TYPE_UB: |
case BRW_REGISTER_TYPE_W: |
case BRW_REGISTER_TYPE_UW: |
case BRW_REGISTER_TYPE_D: |
case BRW_REGISTER_TYPE_UD: |
break; |
default: |
assert(!"Bad type for brw_AVG"); |
} |
return brw_alu2(p, BRW_OPCODE_AVG, dest, src0, src1); |
} |
struct brw_instruction *brw_MUL(struct brw_compile *p, |
struct brw_reg dest, |
struct brw_reg src0, |
struct brw_reg src1) |
{ |
/* 6.32.38: mul */ |
if (src0.type == BRW_REGISTER_TYPE_D || |
src0.type == BRW_REGISTER_TYPE_UD || |
src1.type == BRW_REGISTER_TYPE_D || |
src1.type == BRW_REGISTER_TYPE_UD) { |
assert(dest.type != BRW_REGISTER_TYPE_F); |
} |
if (src0.type == BRW_REGISTER_TYPE_F || |
(src0.file == BRW_IMMEDIATE_VALUE && |
src0.type == BRW_REGISTER_TYPE_VF)) { |
assert(src1.type != BRW_REGISTER_TYPE_UD); |
assert(src1.type != BRW_REGISTER_TYPE_D); |
} |
if (src1.type == BRW_REGISTER_TYPE_F || |
(src1.file == BRW_IMMEDIATE_VALUE && |
src1.type == BRW_REGISTER_TYPE_VF)) { |
assert(src0.type != BRW_REGISTER_TYPE_UD); |
assert(src0.type != BRW_REGISTER_TYPE_D); |
} |
assert(src0.file != BRW_ARCHITECTURE_REGISTER_FILE || |
src0.nr != BRW_ARF_ACCUMULATOR); |
assert(src1.file != BRW_ARCHITECTURE_REGISTER_FILE || |
src1.nr != BRW_ARF_ACCUMULATOR); |
return brw_alu2(p, BRW_OPCODE_MUL, dest, src0, src1); |
} |
void brw_NOP(struct brw_compile *p) |
{ |
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_NOP); |
brw_set_dest(p, insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD)); |
brw_set_src0(p, insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD)); |
brw_set_src1(p, insn, brw_imm_ud(0x0)); |
} |
/*********************************************************************** |
* Comparisons, if/else/endif |
*/ |
struct brw_instruction *brw_JMPI(struct brw_compile *p, |
struct brw_reg dest, |
struct brw_reg src0, |
struct brw_reg src1) |
{ |
struct brw_instruction *insn = brw_alu2(p, BRW_OPCODE_JMPI, dest, src0, src1); |
insn->header.execution_size = 1; |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
insn->header.mask_control = BRW_MASK_DISABLE; |
p->current->header.predicate_control = BRW_PREDICATE_NONE; |
return insn; |
} |
static void |
push_if_stack(struct brw_compile *p, struct brw_instruction *inst) |
{ |
p->if_stack[p->if_stack_depth] = inst - p->store; |
p->if_stack_depth++; |
if (p->if_stack_array_size <= p->if_stack_depth) { |
p->if_stack_array_size *= 2; |
p->if_stack = reralloc(p->mem_ctx, p->if_stack, int, |
p->if_stack_array_size); |
} |
} |
static struct brw_instruction * |
pop_if_stack(struct brw_compile *p) |
{ |
p->if_stack_depth--; |
return &p->store[p->if_stack[p->if_stack_depth]]; |
} |
static void |
push_loop_stack(struct brw_compile *p, struct brw_instruction *inst) |
{ |
if (p->loop_stack_array_size < p->loop_stack_depth) { |
p->loop_stack_array_size *= 2; |
p->loop_stack = reralloc(p->mem_ctx, p->loop_stack, int, |
p->loop_stack_array_size); |
p->if_depth_in_loop = reralloc(p->mem_ctx, p->if_depth_in_loop, int, |
p->loop_stack_array_size); |
} |
p->loop_stack[p->loop_stack_depth] = inst - p->store; |
p->loop_stack_depth++; |
p->if_depth_in_loop[p->loop_stack_depth] = 0; |
} |
static struct brw_instruction * |
get_inner_do_insn(struct brw_compile *p) |
{ |
return &p->store[p->loop_stack[p->loop_stack_depth - 1]]; |
} |
/* EU takes the value from the flag register and pushes it onto some |
* sort of a stack (presumably merging with any flag value already on |
* the stack). Within an if block, the flags at the top of the stack |
* control execution on each channel of the unit, eg. on each of the |
* 16 pixel values in our wm programs. |
* |
* When the matching 'else' instruction is reached (presumably by |
* countdown of the instruction count patched in by our ELSE/ENDIF |
* functions), the relevent flags are inverted. |
* |
* When the matching 'endif' instruction is reached, the flags are |
* popped off. If the stack is now empty, normal execution resumes. |
*/ |
struct brw_instruction * |
brw_IF(struct brw_compile *p, GLuint execute_size) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn; |
insn = next_insn(p, BRW_OPCODE_IF); |
/* Override the defaults for this instruction: |
*/ |
if (brw->gen < 6) { |
brw_set_dest(p, insn, brw_ip_reg()); |
brw_set_src0(p, insn, brw_ip_reg()); |
brw_set_src1(p, insn, brw_imm_d(0x0)); |
} else if (brw->gen == 6) { |
brw_set_dest(p, insn, brw_imm_w(0)); |
insn->bits1.branch_gen6.jump_count = 0; |
brw_set_src0(p, insn, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); |
brw_set_src1(p, insn, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); |
} else { |
brw_set_dest(p, insn, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); |
brw_set_src0(p, insn, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); |
brw_set_src1(p, insn, brw_imm_ud(0)); |
insn->bits3.break_cont.jip = 0; |
insn->bits3.break_cont.uip = 0; |
} |
insn->header.execution_size = execute_size; |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
insn->header.predicate_control = BRW_PREDICATE_NORMAL; |
insn->header.mask_control = BRW_MASK_ENABLE; |
if (!p->single_program_flow) |
insn->header.thread_control = BRW_THREAD_SWITCH; |
p->current->header.predicate_control = BRW_PREDICATE_NONE; |
push_if_stack(p, insn); |
p->if_depth_in_loop[p->loop_stack_depth]++; |
return insn; |
} |
/* This function is only used for gen6-style IF instructions with an |
* embedded comparison (conditional modifier). It is not used on gen7. |
*/ |
struct brw_instruction * |
gen6_IF(struct brw_compile *p, uint32_t conditional, |
struct brw_reg src0, struct brw_reg src1) |
{ |
struct brw_instruction *insn; |
insn = next_insn(p, BRW_OPCODE_IF); |
brw_set_dest(p, insn, brw_imm_w(0)); |
if (p->compressed) { |
insn->header.execution_size = BRW_EXECUTE_16; |
} else { |
insn->header.execution_size = BRW_EXECUTE_8; |
} |
insn->bits1.branch_gen6.jump_count = 0; |
brw_set_src0(p, insn, src0); |
brw_set_src1(p, insn, src1); |
assert(insn->header.compression_control == BRW_COMPRESSION_NONE); |
assert(insn->header.predicate_control == BRW_PREDICATE_NONE); |
insn->header.destreg__conditionalmod = conditional; |
if (!p->single_program_flow) |
insn->header.thread_control = BRW_THREAD_SWITCH; |
push_if_stack(p, insn); |
return insn; |
} |
/** |
* In single-program-flow (SPF) mode, convert IF and ELSE into ADDs. |
*/ |
static void |
convert_IF_ELSE_to_ADD(struct brw_compile *p, |
struct brw_instruction *if_inst, |
struct brw_instruction *else_inst) |
{ |
/* The next instruction (where the ENDIF would be, if it existed) */ |
struct brw_instruction *next_inst = &p->store[p->nr_insn]; |
assert(p->single_program_flow); |
assert(if_inst != NULL && if_inst->header.opcode == BRW_OPCODE_IF); |
assert(else_inst == NULL || else_inst->header.opcode == BRW_OPCODE_ELSE); |
assert(if_inst->header.execution_size == BRW_EXECUTE_1); |
/* Convert IF to an ADD instruction that moves the instruction pointer |
* to the first instruction of the ELSE block. If there is no ELSE |
* block, point to where ENDIF would be. Reverse the predicate. |
* |
* There's no need to execute an ENDIF since we don't need to do any |
* stack operations, and if we're currently executing, we just want to |
* continue normally. |
*/ |
if_inst->header.opcode = BRW_OPCODE_ADD; |
if_inst->header.predicate_inverse = 1; |
if (else_inst != NULL) { |
/* Convert ELSE to an ADD instruction that points where the ENDIF |
* would be. |
*/ |
else_inst->header.opcode = BRW_OPCODE_ADD; |
if_inst->bits3.ud = (else_inst - if_inst + 1) * 16; |
else_inst->bits3.ud = (next_inst - else_inst) * 16; |
} else { |
if_inst->bits3.ud = (next_inst - if_inst) * 16; |
} |
} |
/** |
* Patch IF and ELSE instructions with appropriate jump targets. |
*/ |
static void |
patch_IF_ELSE(struct brw_compile *p, |
struct brw_instruction *if_inst, |
struct brw_instruction *else_inst, |
struct brw_instruction *endif_inst) |
{ |
struct brw_context *brw = p->brw; |
/* We shouldn't be patching IF and ELSE instructions in single program flow |
* mode when gen < 6, because in single program flow mode on those |
* platforms, we convert flow control instructions to conditional ADDs that |
* operate on IP (see brw_ENDIF). |
* |
* However, on Gen6, writing to IP doesn't work in single program flow mode |
* (see the SandyBridge PRM, Volume 4 part 2, p79: "When SPF is ON, IP may |
* not be updated by non-flow control instructions."). And on later |
* platforms, there is no significant benefit to converting control flow |
* instructions to conditional ADDs. So we do patch IF and ELSE |
* instructions in single program flow mode on those platforms. |
*/ |
if (brw->gen < 6) |
assert(!p->single_program_flow); |
assert(if_inst != NULL && if_inst->header.opcode == BRW_OPCODE_IF); |
assert(endif_inst != NULL); |
assert(else_inst == NULL || else_inst->header.opcode == BRW_OPCODE_ELSE); |
unsigned br = 1; |
/* Jump count is for 64bit data chunk each, so one 128bit instruction |
* requires 2 chunks. |
*/ |
if (brw->gen >= 5) |
br = 2; |
assert(endif_inst->header.opcode == BRW_OPCODE_ENDIF); |
endif_inst->header.execution_size = if_inst->header.execution_size; |
if (else_inst == NULL) { |
/* Patch IF -> ENDIF */ |
if (brw->gen < 6) { |
/* Turn it into an IFF, which means no mask stack operations for |
* all-false and jumping past the ENDIF. |
*/ |
if_inst->header.opcode = BRW_OPCODE_IFF; |
if_inst->bits3.if_else.jump_count = br * (endif_inst - if_inst + 1); |
if_inst->bits3.if_else.pop_count = 0; |
if_inst->bits3.if_else.pad0 = 0; |
} else if (brw->gen == 6) { |
/* As of gen6, there is no IFF and IF must point to the ENDIF. */ |
if_inst->bits1.branch_gen6.jump_count = br * (endif_inst - if_inst); |
} else { |
if_inst->bits3.break_cont.uip = br * (endif_inst - if_inst); |
if_inst->bits3.break_cont.jip = br * (endif_inst - if_inst); |
} |
} else { |
else_inst->header.execution_size = if_inst->header.execution_size; |
/* Patch IF -> ELSE */ |
if (brw->gen < 6) { |
if_inst->bits3.if_else.jump_count = br * (else_inst - if_inst); |
if_inst->bits3.if_else.pop_count = 0; |
if_inst->bits3.if_else.pad0 = 0; |
} else if (brw->gen == 6) { |
if_inst->bits1.branch_gen6.jump_count = br * (else_inst - if_inst + 1); |
} |
/* Patch ELSE -> ENDIF */ |
if (brw->gen < 6) { |
/* BRW_OPCODE_ELSE pre-gen6 should point just past the |
* matching ENDIF. |
*/ |
else_inst->bits3.if_else.jump_count = br*(endif_inst - else_inst + 1); |
else_inst->bits3.if_else.pop_count = 1; |
else_inst->bits3.if_else.pad0 = 0; |
} else if (brw->gen == 6) { |
/* BRW_OPCODE_ELSE on gen6 should point to the matching ENDIF. */ |
else_inst->bits1.branch_gen6.jump_count = br*(endif_inst - else_inst); |
} else { |
/* The IF instruction's JIP should point just past the ELSE */ |
if_inst->bits3.break_cont.jip = br * (else_inst - if_inst + 1); |
/* The IF instruction's UIP and ELSE's JIP should point to ENDIF */ |
if_inst->bits3.break_cont.uip = br * (endif_inst - if_inst); |
else_inst->bits3.break_cont.jip = br * (endif_inst - else_inst); |
} |
} |
} |
void |
brw_ELSE(struct brw_compile *p) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn; |
insn = next_insn(p, BRW_OPCODE_ELSE); |
if (brw->gen < 6) { |
brw_set_dest(p, insn, brw_ip_reg()); |
brw_set_src0(p, insn, brw_ip_reg()); |
brw_set_src1(p, insn, brw_imm_d(0x0)); |
} else if (brw->gen == 6) { |
brw_set_dest(p, insn, brw_imm_w(0)); |
insn->bits1.branch_gen6.jump_count = 0; |
brw_set_src0(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src1(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
} else { |
brw_set_dest(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src0(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src1(p, insn, brw_imm_ud(0)); |
insn->bits3.break_cont.jip = 0; |
insn->bits3.break_cont.uip = 0; |
} |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
insn->header.mask_control = BRW_MASK_ENABLE; |
if (!p->single_program_flow) |
insn->header.thread_control = BRW_THREAD_SWITCH; |
push_if_stack(p, insn); |
} |
void |
brw_ENDIF(struct brw_compile *p) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn = NULL; |
struct brw_instruction *else_inst = NULL; |
struct brw_instruction *if_inst = NULL; |
struct brw_instruction *tmp; |
bool emit_endif = true; |
/* In single program flow mode, we can express IF and ELSE instructions |
* equivalently as ADD instructions that operate on IP. On platforms prior |
* to Gen6, flow control instructions cause an implied thread switch, so |
* this is a significant savings. |
* |
* However, on Gen6, writing to IP doesn't work in single program flow mode |
* (see the SandyBridge PRM, Volume 4 part 2, p79: "When SPF is ON, IP may |
* not be updated by non-flow control instructions."). And on later |
* platforms, there is no significant benefit to converting control flow |
* instructions to conditional ADDs. So we only do this trick on Gen4 and |
* Gen5. |
*/ |
if (brw->gen < 6 && p->single_program_flow) |
emit_endif = false; |
/* |
* A single next_insn() may change the base adress of instruction store |
* memory(p->store), so call it first before referencing the instruction |
* store pointer from an index |
*/ |
if (emit_endif) |
insn = next_insn(p, BRW_OPCODE_ENDIF); |
/* Pop the IF and (optional) ELSE instructions from the stack */ |
p->if_depth_in_loop[p->loop_stack_depth]--; |
tmp = pop_if_stack(p); |
if (tmp->header.opcode == BRW_OPCODE_ELSE) { |
else_inst = tmp; |
tmp = pop_if_stack(p); |
} |
if_inst = tmp; |
if (!emit_endif) { |
/* ENDIF is useless; don't bother emitting it. */ |
convert_IF_ELSE_to_ADD(p, if_inst, else_inst); |
return; |
} |
if (brw->gen < 6) { |
brw_set_dest(p, insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD)); |
brw_set_src0(p, insn, retype(brw_vec4_grf(0,0), BRW_REGISTER_TYPE_UD)); |
brw_set_src1(p, insn, brw_imm_d(0x0)); |
} else if (brw->gen == 6) { |
brw_set_dest(p, insn, brw_imm_w(0)); |
brw_set_src0(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src1(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
} else { |
brw_set_dest(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src0(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src1(p, insn, brw_imm_ud(0)); |
} |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
insn->header.mask_control = BRW_MASK_ENABLE; |
insn->header.thread_control = BRW_THREAD_SWITCH; |
/* Also pop item off the stack in the endif instruction: */ |
if (brw->gen < 6) { |
insn->bits3.if_else.jump_count = 0; |
insn->bits3.if_else.pop_count = 1; |
insn->bits3.if_else.pad0 = 0; |
} else if (brw->gen == 6) { |
insn->bits1.branch_gen6.jump_count = 2; |
} else { |
insn->bits3.break_cont.jip = 2; |
} |
patch_IF_ELSE(p, if_inst, else_inst, insn); |
} |
struct brw_instruction *brw_BREAK(struct brw_compile *p) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn; |
insn = next_insn(p, BRW_OPCODE_BREAK); |
if (brw->gen >= 6) { |
brw_set_dest(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src0(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src1(p, insn, brw_imm_d(0x0)); |
} else { |
brw_set_dest(p, insn, brw_ip_reg()); |
brw_set_src0(p, insn, brw_ip_reg()); |
brw_set_src1(p, insn, brw_imm_d(0x0)); |
insn->bits3.if_else.pad0 = 0; |
insn->bits3.if_else.pop_count = p->if_depth_in_loop[p->loop_stack_depth]; |
} |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
insn->header.execution_size = BRW_EXECUTE_8; |
return insn; |
} |
struct brw_instruction *gen6_CONT(struct brw_compile *p) |
{ |
struct brw_instruction *insn; |
insn = next_insn(p, BRW_OPCODE_CONTINUE); |
brw_set_dest(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src0(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_dest(p, insn, brw_ip_reg()); |
brw_set_src0(p, insn, brw_ip_reg()); |
brw_set_src1(p, insn, brw_imm_d(0x0)); |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
insn->header.execution_size = BRW_EXECUTE_8; |
return insn; |
} |
struct brw_instruction *brw_CONT(struct brw_compile *p) |
{ |
struct brw_instruction *insn; |
insn = next_insn(p, BRW_OPCODE_CONTINUE); |
brw_set_dest(p, insn, brw_ip_reg()); |
brw_set_src0(p, insn, brw_ip_reg()); |
brw_set_src1(p, insn, brw_imm_d(0x0)); |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
insn->header.execution_size = BRW_EXECUTE_8; |
/* insn->header.mask_control = BRW_MASK_DISABLE; */ |
insn->bits3.if_else.pad0 = 0; |
insn->bits3.if_else.pop_count = p->if_depth_in_loop[p->loop_stack_depth]; |
return insn; |
} |
struct brw_instruction *gen6_HALT(struct brw_compile *p) |
{ |
struct brw_instruction *insn; |
insn = next_insn(p, BRW_OPCODE_HALT); |
brw_set_dest(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src0(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src1(p, insn, brw_imm_d(0x0)); /* UIP and JIP, updated later. */ |
if (p->compressed) { |
insn->header.execution_size = BRW_EXECUTE_16; |
} else { |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
insn->header.execution_size = BRW_EXECUTE_8; |
} |
return insn; |
} |
/* DO/WHILE loop: |
* |
* The DO/WHILE is just an unterminated loop -- break or continue are |
* used for control within the loop. We have a few ways they can be |
* done. |
* |
* For uniform control flow, the WHILE is just a jump, so ADD ip, ip, |
* jip and no DO instruction. |
* |
* For non-uniform control flow pre-gen6, there's a DO instruction to |
* push the mask, and a WHILE to jump back, and BREAK to get out and |
* pop the mask. |
* |
* For gen6, there's no more mask stack, so no need for DO. WHILE |
* just points back to the first instruction of the loop. |
*/ |
struct brw_instruction *brw_DO(struct brw_compile *p, GLuint execute_size) |
{ |
struct brw_context *brw = p->brw; |
if (brw->gen >= 6 || p->single_program_flow) { |
push_loop_stack(p, &p->store[p->nr_insn]); |
return &p->store[p->nr_insn]; |
} else { |
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_DO); |
push_loop_stack(p, insn); |
/* Override the defaults for this instruction: |
*/ |
brw_set_dest(p, insn, brw_null_reg()); |
brw_set_src0(p, insn, brw_null_reg()); |
brw_set_src1(p, insn, brw_null_reg()); |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
insn->header.execution_size = execute_size; |
insn->header.predicate_control = BRW_PREDICATE_NONE; |
/* insn->header.mask_control = BRW_MASK_ENABLE; */ |
/* insn->header.mask_control = BRW_MASK_DISABLE; */ |
return insn; |
} |
} |
/** |
* For pre-gen6, we patch BREAK/CONT instructions to point at the WHILE |
* instruction here. |
* |
* For gen6+, see brw_set_uip_jip(), which doesn't care so much about the loop |
* nesting, since it can always just point to the end of the block/current loop. |
*/ |
static void |
brw_patch_break_cont(struct brw_compile *p, struct brw_instruction *while_inst) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *do_inst = get_inner_do_insn(p); |
struct brw_instruction *inst; |
int br = (brw->gen == 5) ? 2 : 1; |
for (inst = while_inst - 1; inst != do_inst; inst--) { |
/* If the jump count is != 0, that means that this instruction has already |
* been patched because it's part of a loop inside of the one we're |
* patching. |
*/ |
if (inst->header.opcode == BRW_OPCODE_BREAK && |
inst->bits3.if_else.jump_count == 0) { |
inst->bits3.if_else.jump_count = br * ((while_inst - inst) + 1); |
} else if (inst->header.opcode == BRW_OPCODE_CONTINUE && |
inst->bits3.if_else.jump_count == 0) { |
inst->bits3.if_else.jump_count = br * (while_inst - inst); |
} |
} |
} |
struct brw_instruction *brw_WHILE(struct brw_compile *p) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn, *do_insn; |
GLuint br = 1; |
if (brw->gen >= 5) |
br = 2; |
if (brw->gen >= 7) { |
insn = next_insn(p, BRW_OPCODE_WHILE); |
do_insn = get_inner_do_insn(p); |
brw_set_dest(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src0(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src1(p, insn, brw_imm_ud(0)); |
insn->bits3.break_cont.jip = br * (do_insn - insn); |
insn->header.execution_size = BRW_EXECUTE_8; |
} else if (brw->gen == 6) { |
insn = next_insn(p, BRW_OPCODE_WHILE); |
do_insn = get_inner_do_insn(p); |
brw_set_dest(p, insn, brw_imm_w(0)); |
insn->bits1.branch_gen6.jump_count = br * (do_insn - insn); |
brw_set_src0(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
brw_set_src1(p, insn, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
insn->header.execution_size = BRW_EXECUTE_8; |
} else { |
if (p->single_program_flow) { |
insn = next_insn(p, BRW_OPCODE_ADD); |
do_insn = get_inner_do_insn(p); |
brw_set_dest(p, insn, brw_ip_reg()); |
brw_set_src0(p, insn, brw_ip_reg()); |
brw_set_src1(p, insn, brw_imm_d((do_insn - insn) * 16)); |
insn->header.execution_size = BRW_EXECUTE_1; |
} else { |
insn = next_insn(p, BRW_OPCODE_WHILE); |
do_insn = get_inner_do_insn(p); |
assert(do_insn->header.opcode == BRW_OPCODE_DO); |
brw_set_dest(p, insn, brw_ip_reg()); |
brw_set_src0(p, insn, brw_ip_reg()); |
brw_set_src1(p, insn, brw_imm_d(0)); |
insn->header.execution_size = do_insn->header.execution_size; |
insn->bits3.if_else.jump_count = br * (do_insn - insn + 1); |
insn->bits3.if_else.pop_count = 0; |
insn->bits3.if_else.pad0 = 0; |
brw_patch_break_cont(p, insn); |
} |
} |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
p->current->header.predicate_control = BRW_PREDICATE_NONE; |
p->loop_stack_depth--; |
return insn; |
} |
/* FORWARD JUMPS: |
*/ |
void brw_land_fwd_jump(struct brw_compile *p, int jmp_insn_idx) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *jmp_insn = &p->store[jmp_insn_idx]; |
GLuint jmpi = 1; |
if (brw->gen >= 5) |
jmpi = 2; |
assert(jmp_insn->header.opcode == BRW_OPCODE_JMPI); |
assert(jmp_insn->bits1.da1.src1_reg_file == BRW_IMMEDIATE_VALUE); |
jmp_insn->bits3.ud = jmpi * (p->nr_insn - jmp_insn_idx - 1); |
} |
/* To integrate with the above, it makes sense that the comparison |
* instruction should populate the flag register. It might be simpler |
* just to use the flag reg for most WM tasks? |
*/ |
void brw_CMP(struct brw_compile *p, |
struct brw_reg dest, |
GLuint conditional, |
struct brw_reg src0, |
struct brw_reg src1) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_CMP); |
insn->header.destreg__conditionalmod = conditional; |
brw_set_dest(p, insn, dest); |
brw_set_src0(p, insn, src0); |
brw_set_src1(p, insn, src1); |
/* guess_execution_size(insn, src0); */ |
/* Make it so that future instructions will use the computed flag |
* value until brw_set_predicate_control_flag_value() is called |
* again. |
*/ |
if (dest.file == BRW_ARCHITECTURE_REGISTER_FILE && |
dest.nr == 0) { |
p->current->header.predicate_control = BRW_PREDICATE_NORMAL; |
p->flag_value = 0xff; |
} |
/* Item WaCMPInstNullDstForcesThreadSwitch in the Haswell Bspec workarounds |
* page says: |
* "Any CMP instruction with a null destination must use a {switch}." |
* |
* It also applies to other Gen7 platforms (IVB, BYT) even though it isn't |
* mentioned on their work-arounds pages. |
*/ |
if (brw->gen == 7) { |
if (dest.file == BRW_ARCHITECTURE_REGISTER_FILE && |
dest.nr == BRW_ARF_NULL) { |
insn->header.thread_control = BRW_THREAD_SWITCH; |
} |
} |
} |
/* Issue 'wait' instruction for n1, host could program MMIO |
to wake up thread. */ |
void brw_WAIT (struct brw_compile *p) |
{ |
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_WAIT); |
struct brw_reg src = brw_notification_1_reg(); |
brw_set_dest(p, insn, src); |
brw_set_src0(p, insn, src); |
brw_set_src1(p, insn, brw_null_reg()); |
insn->header.execution_size = 0; /* must */ |
insn->header.predicate_control = 0; |
insn->header.compression_control = 0; |
} |
/*********************************************************************** |
* Helpers for the various SEND message types: |
*/ |
/** Extended math function, float[8]. |
*/ |
void brw_math( struct brw_compile *p, |
struct brw_reg dest, |
GLuint function, |
GLuint msg_reg_nr, |
struct brw_reg src, |
GLuint data_type, |
GLuint precision ) |
{ |
struct brw_context *brw = p->brw; |
if (brw->gen >= 6) { |
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_MATH); |
assert(dest.file == BRW_GENERAL_REGISTER_FILE || |
(brw->gen >= 7 && dest.file == BRW_MESSAGE_REGISTER_FILE)); |
assert(src.file == BRW_GENERAL_REGISTER_FILE); |
assert(dest.hstride == BRW_HORIZONTAL_STRIDE_1); |
if (brw->gen == 6) |
assert(src.hstride == BRW_HORIZONTAL_STRIDE_1); |
/* Source modifiers are ignored for extended math instructions on Gen6. */ |
if (brw->gen == 6) { |
assert(!src.negate); |
assert(!src.abs); |
} |
if (function == BRW_MATH_FUNCTION_INT_DIV_QUOTIENT || |
function == BRW_MATH_FUNCTION_INT_DIV_REMAINDER || |
function == BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER) { |
assert(src.type != BRW_REGISTER_TYPE_F); |
} else { |
assert(src.type == BRW_REGISTER_TYPE_F); |
} |
/* Math is the same ISA format as other opcodes, except that CondModifier |
* becomes FC[3:0] and ThreadCtrl becomes FC[5:4]. |
*/ |
insn->header.destreg__conditionalmod = function; |
brw_set_dest(p, insn, dest); |
brw_set_src0(p, insn, src); |
brw_set_src1(p, insn, brw_null_reg()); |
} else { |
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND); |
/* Example code doesn't set predicate_control for send |
* instructions. |
*/ |
insn->header.predicate_control = 0; |
insn->header.destreg__conditionalmod = msg_reg_nr; |
brw_set_dest(p, insn, dest); |
brw_set_src0(p, insn, src); |
brw_set_math_message(p, |
insn, |
function, |
src.type == BRW_REGISTER_TYPE_D, |
precision, |
data_type); |
} |
} |
/** Extended math function, float[8]. |
*/ |
void brw_math2(struct brw_compile *p, |
struct brw_reg dest, |
GLuint function, |
struct brw_reg src0, |
struct brw_reg src1) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_MATH); |
assert(dest.file == BRW_GENERAL_REGISTER_FILE || |
(brw->gen >= 7 && dest.file == BRW_MESSAGE_REGISTER_FILE)); |
assert(src0.file == BRW_GENERAL_REGISTER_FILE); |
assert(src1.file == BRW_GENERAL_REGISTER_FILE); |
assert(dest.hstride == BRW_HORIZONTAL_STRIDE_1); |
if (brw->gen == 6) { |
assert(src0.hstride == BRW_HORIZONTAL_STRIDE_1); |
assert(src1.hstride == BRW_HORIZONTAL_STRIDE_1); |
} |
if (function == BRW_MATH_FUNCTION_INT_DIV_QUOTIENT || |
function == BRW_MATH_FUNCTION_INT_DIV_REMAINDER || |
function == BRW_MATH_FUNCTION_INT_DIV_QUOTIENT_AND_REMAINDER) { |
assert(src0.type != BRW_REGISTER_TYPE_F); |
assert(src1.type != BRW_REGISTER_TYPE_F); |
} else { |
assert(src0.type == BRW_REGISTER_TYPE_F); |
assert(src1.type == BRW_REGISTER_TYPE_F); |
} |
/* Source modifiers are ignored for extended math instructions on Gen6. */ |
if (brw->gen == 6) { |
assert(!src0.negate); |
assert(!src0.abs); |
assert(!src1.negate); |
assert(!src1.abs); |
} |
/* Math is the same ISA format as other opcodes, except that CondModifier |
* becomes FC[3:0] and ThreadCtrl becomes FC[5:4]. |
*/ |
insn->header.destreg__conditionalmod = function; |
brw_set_dest(p, insn, dest); |
brw_set_src0(p, insn, src0); |
brw_set_src1(p, insn, src1); |
} |
/** |
* Write a block of OWORDs (half a GRF each) from the scratch buffer, |
* using a constant offset per channel. |
* |
* The offset must be aligned to oword size (16 bytes). Used for |
* register spilling. |
*/ |
void brw_oword_block_write_scratch(struct brw_compile *p, |
struct brw_reg mrf, |
int num_regs, |
GLuint offset) |
{ |
struct brw_context *brw = p->brw; |
uint32_t msg_control, msg_type; |
int mlen; |
if (brw->gen >= 6) |
offset /= 16; |
mrf = retype(mrf, BRW_REGISTER_TYPE_UD); |
if (num_regs == 1) { |
msg_control = BRW_DATAPORT_OWORD_BLOCK_2_OWORDS; |
mlen = 2; |
} else { |
msg_control = BRW_DATAPORT_OWORD_BLOCK_4_OWORDS; |
mlen = 3; |
} |
/* Set up the message header. This is g0, with g0.2 filled with |
* the offset. We don't want to leave our offset around in g0 or |
* it'll screw up texture samples, so set it up inside the message |
* reg. |
*/ |
{ |
brw_push_insn_state(p); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_MOV(p, mrf, retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)); |
/* set message header global offset field (reg 0, element 2) */ |
brw_MOV(p, |
retype(brw_vec1_reg(BRW_MESSAGE_REGISTER_FILE, |
mrf.nr, |
2), BRW_REGISTER_TYPE_UD), |
brw_imm_ud(offset)); |
brw_pop_insn_state(p); |
} |
{ |
struct brw_reg dest; |
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND); |
int send_commit_msg; |
struct brw_reg src_header = retype(brw_vec8_grf(0, 0), |
BRW_REGISTER_TYPE_UW); |
if (insn->header.compression_control != BRW_COMPRESSION_NONE) { |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
src_header = vec16(src_header); |
} |
assert(insn->header.predicate_control == BRW_PREDICATE_NONE); |
insn->header.destreg__conditionalmod = mrf.nr; |
/* Until gen6, writes followed by reads from the same location |
* are not guaranteed to be ordered unless write_commit is set. |
* If set, then a no-op write is issued to the destination |
* register to set a dependency, and a read from the destination |
* can be used to ensure the ordering. |
* |
* For gen6, only writes between different threads need ordering |
* protection. Our use of DP writes is all about register |
* spilling within a thread. |
*/ |
if (brw->gen >= 6) { |
dest = retype(vec16(brw_null_reg()), BRW_REGISTER_TYPE_UW); |
send_commit_msg = 0; |
} else { |
dest = src_header; |
send_commit_msg = 1; |
} |
brw_set_dest(p, insn, dest); |
if (brw->gen >= 6) { |
brw_set_src0(p, insn, mrf); |
} else { |
brw_set_src0(p, insn, brw_null_reg()); |
} |
if (brw->gen >= 6) |
msg_type = GEN6_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE; |
else |
msg_type = BRW_DATAPORT_WRITE_MESSAGE_OWORD_BLOCK_WRITE; |
brw_set_dp_write_message(p, |
insn, |
255, /* binding table index (255=stateless) */ |
msg_control, |
msg_type, |
mlen, |
true, /* header_present */ |
0, /* not a render target */ |
send_commit_msg, /* response_length */ |
0, /* eot */ |
send_commit_msg); |
} |
} |
/** |
* Read a block of owords (half a GRF each) from the scratch buffer |
* using a constant index per channel. |
* |
* Offset must be aligned to oword size (16 bytes). Used for register |
* spilling. |
*/ |
void |
brw_oword_block_read_scratch(struct brw_compile *p, |
struct brw_reg dest, |
struct brw_reg mrf, |
int num_regs, |
GLuint offset) |
{ |
struct brw_context *brw = p->brw; |
uint32_t msg_control; |
int rlen; |
if (brw->gen >= 6) |
offset /= 16; |
mrf = retype(mrf, BRW_REGISTER_TYPE_UD); |
dest = retype(dest, BRW_REGISTER_TYPE_UW); |
if (num_regs == 1) { |
msg_control = BRW_DATAPORT_OWORD_BLOCK_2_OWORDS; |
rlen = 1; |
} else { |
msg_control = BRW_DATAPORT_OWORD_BLOCK_4_OWORDS; |
rlen = 2; |
} |
{ |
brw_push_insn_state(p); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
brw_MOV(p, mrf, retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)); |
/* set message header global offset field (reg 0, element 2) */ |
brw_MOV(p, |
retype(brw_vec1_reg(BRW_MESSAGE_REGISTER_FILE, |
mrf.nr, |
2), BRW_REGISTER_TYPE_UD), |
brw_imm_ud(offset)); |
brw_pop_insn_state(p); |
} |
{ |
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND); |
assert(insn->header.predicate_control == 0); |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
insn->header.destreg__conditionalmod = mrf.nr; |
brw_set_dest(p, insn, dest); /* UW? */ |
if (brw->gen >= 6) { |
brw_set_src0(p, insn, mrf); |
} else { |
brw_set_src0(p, insn, brw_null_reg()); |
} |
brw_set_dp_read_message(p, |
insn, |
255, /* binding table index (255=stateless) */ |
msg_control, |
BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ, /* msg_type */ |
BRW_DATAPORT_READ_TARGET_RENDER_CACHE, |
1, /* msg_length */ |
true, /* header_present */ |
rlen); |
} |
} |
/** |
* Read a float[4] vector from the data port Data Cache (const buffer). |
* Location (in buffer) should be a multiple of 16. |
* Used for fetching shader constants. |
*/ |
void brw_oword_block_read(struct brw_compile *p, |
struct brw_reg dest, |
struct brw_reg mrf, |
uint32_t offset, |
uint32_t bind_table_index) |
{ |
struct brw_context *brw = p->brw; |
/* On newer hardware, offset is in units of owords. */ |
if (brw->gen >= 6) |
offset /= 16; |
mrf = retype(mrf, BRW_REGISTER_TYPE_UD); |
brw_push_insn_state(p); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
brw_MOV(p, mrf, retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)); |
/* set message header global offset field (reg 0, element 2) */ |
brw_MOV(p, |
retype(brw_vec1_reg(BRW_MESSAGE_REGISTER_FILE, |
mrf.nr, |
2), BRW_REGISTER_TYPE_UD), |
brw_imm_ud(offset)); |
struct brw_instruction *insn = next_insn(p, BRW_OPCODE_SEND); |
insn->header.destreg__conditionalmod = mrf.nr; |
/* cast dest to a uword[8] vector */ |
dest = retype(vec8(dest), BRW_REGISTER_TYPE_UW); |
brw_set_dest(p, insn, dest); |
if (brw->gen >= 6) { |
brw_set_src0(p, insn, mrf); |
} else { |
brw_set_src0(p, insn, brw_null_reg()); |
} |
brw_set_dp_read_message(p, |
insn, |
bind_table_index, |
BRW_DATAPORT_OWORD_BLOCK_1_OWORDLOW, |
BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ, |
BRW_DATAPORT_READ_TARGET_DATA_CACHE, |
1, /* msg_length */ |
true, /* header_present */ |
1); /* response_length (1 reg, 2 owords!) */ |
brw_pop_insn_state(p); |
} |
void brw_fb_WRITE(struct brw_compile *p, |
int dispatch_width, |
GLuint msg_reg_nr, |
struct brw_reg src0, |
GLuint msg_control, |
GLuint binding_table_index, |
GLuint msg_length, |
GLuint response_length, |
bool eot, |
bool header_present) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn; |
GLuint msg_type; |
struct brw_reg dest; |
if (dispatch_width == 16) |
dest = retype(vec16(brw_null_reg()), BRW_REGISTER_TYPE_UW); |
else |
dest = retype(vec8(brw_null_reg()), BRW_REGISTER_TYPE_UW); |
if (brw->gen >= 6) { |
insn = next_insn(p, BRW_OPCODE_SENDC); |
} else { |
insn = next_insn(p, BRW_OPCODE_SEND); |
} |
/* The execution mask is ignored for render target writes. */ |
insn->header.predicate_control = 0; |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
if (brw->gen >= 6) { |
/* headerless version, just submit color payload */ |
src0 = brw_message_reg(msg_reg_nr); |
msg_type = GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE; |
} else { |
insn->header.destreg__conditionalmod = msg_reg_nr; |
msg_type = BRW_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_WRITE; |
} |
brw_set_dest(p, insn, dest); |
brw_set_src0(p, insn, src0); |
brw_set_dp_write_message(p, |
insn, |
binding_table_index, |
msg_control, |
msg_type, |
msg_length, |
header_present, |
eot, /* last render target write */ |
response_length, |
eot, |
0 /* send_commit_msg */); |
} |
/** |
* Texture sample instruction. |
* Note: the msg_type plus msg_length values determine exactly what kind |
* of sampling operation is performed. See volume 4, page 161 of docs. |
*/ |
void brw_SAMPLE(struct brw_compile *p, |
struct brw_reg dest, |
GLuint msg_reg_nr, |
struct brw_reg src0, |
GLuint binding_table_index, |
GLuint sampler, |
GLuint msg_type, |
GLuint response_length, |
GLuint msg_length, |
GLuint header_present, |
GLuint simd_mode, |
GLuint return_format) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn; |
gen6_resolve_implied_move(p, &src0, msg_reg_nr); |
insn = next_insn(p, BRW_OPCODE_SEND); |
insn->header.predicate_control = 0; /* XXX */ |
insn->header.compression_control = BRW_COMPRESSION_NONE; |
if (brw->gen < 6) |
insn->header.destreg__conditionalmod = msg_reg_nr; |
brw_set_dest(p, insn, dest); |
brw_set_src0(p, insn, src0); |
brw_set_sampler_message(p, insn, |
binding_table_index, |
sampler, |
msg_type, |
response_length, |
msg_length, |
header_present, |
simd_mode, |
return_format); |
} |
/* All these variables are pretty confusing - we might be better off |
* using bitmasks and macros for this, in the old style. Or perhaps |
* just having the caller instantiate the fields in dword3 itself. |
*/ |
void brw_urb_WRITE(struct brw_compile *p, |
struct brw_reg dest, |
GLuint msg_reg_nr, |
struct brw_reg src0, |
bool allocate, |
bool used, |
GLuint msg_length, |
GLuint response_length, |
bool eot, |
bool writes_complete, |
GLuint offset, |
GLuint swizzle) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn; |
gen6_resolve_implied_move(p, &src0, msg_reg_nr); |
if (brw->gen == 7) { |
/* Enable Channel Masks in the URB_WRITE_HWORD message header */ |
brw_push_insn_state(p); |
brw_set_access_mode(p, BRW_ALIGN_1); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
brw_OR(p, retype(brw_vec1_reg(BRW_MESSAGE_REGISTER_FILE, msg_reg_nr, 5), |
BRW_REGISTER_TYPE_UD), |
retype(brw_vec1_grf(0, 5), BRW_REGISTER_TYPE_UD), |
brw_imm_ud(0xff00)); |
brw_pop_insn_state(p); |
} |
insn = next_insn(p, BRW_OPCODE_SEND); |
assert(msg_length < BRW_MAX_MRF); |
brw_set_dest(p, insn, dest); |
brw_set_src0(p, insn, src0); |
brw_set_src1(p, insn, brw_imm_d(0)); |
if (brw->gen < 6) |
insn->header.destreg__conditionalmod = msg_reg_nr; |
brw_set_urb_message(p, |
insn, |
allocate, |
used, |
msg_length, |
response_length, |
eot, |
writes_complete, |
offset, |
swizzle); |
} |
static int |
next_ip(struct brw_compile *p, int ip) |
{ |
struct brw_instruction *insn = (void *)p->store + ip; |
if (insn->header.cmpt_control) |
return ip + 8; |
else |
return ip + 16; |
} |
static int |
brw_find_next_block_end(struct brw_compile *p, int start) |
{ |
int ip; |
void *store = p->store; |
for (ip = next_ip(p, start); ip < p->next_insn_offset; ip = next_ip(p, ip)) { |
struct brw_instruction *insn = store + ip; |
switch (insn->header.opcode) { |
case BRW_OPCODE_ENDIF: |
case BRW_OPCODE_ELSE: |
case BRW_OPCODE_WHILE: |
case BRW_OPCODE_HALT: |
return ip; |
} |
} |
return 0; |
} |
/* There is no DO instruction on gen6, so to find the end of the loop |
* we have to see if the loop is jumping back before our start |
* instruction. |
*/ |
static int |
brw_find_loop_end(struct brw_compile *p, int start) |
{ |
struct brw_context *brw = p->brw; |
int ip; |
int scale = 8; |
void *store = p->store; |
/* Always start after the instruction (such as a WHILE) we're trying to fix |
* up. |
*/ |
for (ip = next_ip(p, start); ip < p->next_insn_offset; ip = next_ip(p, ip)) { |
struct brw_instruction *insn = store + ip; |
if (insn->header.opcode == BRW_OPCODE_WHILE) { |
int jip = brw->gen == 6 ? insn->bits1.branch_gen6.jump_count |
: insn->bits3.break_cont.jip; |
if (ip + jip * scale <= start) |
return ip; |
} |
} |
assert(!"not reached"); |
return start; |
} |
/* After program generation, go back and update the UIP and JIP of |
* BREAK, CONT, and HALT instructions to their correct locations. |
*/ |
void |
brw_set_uip_jip(struct brw_compile *p) |
{ |
struct brw_context *brw = p->brw; |
int ip; |
int scale = 8; |
void *store = p->store; |
if (brw->gen < 6) |
return; |
for (ip = 0; ip < p->next_insn_offset; ip = next_ip(p, ip)) { |
struct brw_instruction *insn = store + ip; |
if (insn->header.cmpt_control) { |
/* Fixups for compacted BREAK/CONTINUE not supported yet. */ |
assert(insn->header.opcode != BRW_OPCODE_BREAK && |
insn->header.opcode != BRW_OPCODE_CONTINUE && |
insn->header.opcode != BRW_OPCODE_HALT); |
continue; |
} |
int block_end_ip = brw_find_next_block_end(p, ip); |
switch (insn->header.opcode) { |
case BRW_OPCODE_BREAK: |
assert(block_end_ip != 0); |
insn->bits3.break_cont.jip = (block_end_ip - ip) / scale; |
/* Gen7 UIP points to WHILE; Gen6 points just after it */ |
insn->bits3.break_cont.uip = |
(brw_find_loop_end(p, ip) - ip + |
(brw->gen == 6 ? 16 : 0)) / scale; |
break; |
case BRW_OPCODE_CONTINUE: |
assert(block_end_ip != 0); |
insn->bits3.break_cont.jip = (block_end_ip - ip) / scale; |
insn->bits3.break_cont.uip = |
(brw_find_loop_end(p, ip) - ip) / scale; |
assert(insn->bits3.break_cont.uip != 0); |
assert(insn->bits3.break_cont.jip != 0); |
break; |
case BRW_OPCODE_ENDIF: |
if (block_end_ip == 0) |
insn->bits3.break_cont.jip = 2; |
else |
insn->bits3.break_cont.jip = (block_end_ip - ip) / scale; |
break; |
case BRW_OPCODE_HALT: |
/* From the Sandy Bridge PRM (volume 4, part 2, section 8.3.19): |
* |
* "In case of the halt instruction not inside any conditional |
* code block, the value of <JIP> and <UIP> should be the |
* same. In case of the halt instruction inside conditional code |
* block, the <UIP> should be the end of the program, and the |
* <JIP> should be end of the most inner conditional code block." |
* |
* The uip will have already been set by whoever set up the |
* instruction. |
*/ |
if (block_end_ip == 0) { |
insn->bits3.break_cont.jip = insn->bits3.break_cont.uip; |
} else { |
insn->bits3.break_cont.jip = (block_end_ip - ip) / scale; |
} |
assert(insn->bits3.break_cont.uip != 0); |
assert(insn->bits3.break_cont.jip != 0); |
break; |
} |
} |
} |
void brw_ff_sync(struct brw_compile *p, |
struct brw_reg dest, |
GLuint msg_reg_nr, |
struct brw_reg src0, |
bool allocate, |
GLuint response_length, |
bool eot) |
{ |
struct brw_context *brw = p->brw; |
struct brw_instruction *insn; |
gen6_resolve_implied_move(p, &src0, msg_reg_nr); |
insn = next_insn(p, BRW_OPCODE_SEND); |
brw_set_dest(p, insn, dest); |
brw_set_src0(p, insn, src0); |
brw_set_src1(p, insn, brw_imm_d(0)); |
if (brw->gen < 6) |
insn->header.destreg__conditionalmod = msg_reg_nr; |
brw_set_ff_sync_message(p, |
insn, |
allocate, |
response_length, |
eot); |
} |
/** |
* Emit the SEND instruction necessary to generate stream output data on Gen6 |
* (for transform feedback). |
* |
* If send_commit_msg is true, this is the last piece of stream output data |
* from this thread, so send the data as a committed write. According to the |
* Sandy Bridge PRM (volume 2 part 1, section 4.5.1): |
* |
* "Prior to End of Thread with a URB_WRITE, the kernel must ensure all |
* writes are complete by sending the final write as a committed write." |
*/ |
void |
brw_svb_write(struct brw_compile *p, |
struct brw_reg dest, |
GLuint msg_reg_nr, |
struct brw_reg src0, |
GLuint binding_table_index, |
bool send_commit_msg) |
{ |
struct brw_instruction *insn; |
gen6_resolve_implied_move(p, &src0, msg_reg_nr); |
insn = next_insn(p, BRW_OPCODE_SEND); |
brw_set_dest(p, insn, dest); |
brw_set_src0(p, insn, src0); |
brw_set_src1(p, insn, brw_imm_d(0)); |
brw_set_dp_write_message(p, insn, |
binding_table_index, |
0, /* msg_control: ignored */ |
GEN6_DATAPORT_WRITE_MESSAGE_STREAMED_VB_WRITE, |
1, /* msg_length */ |
true, /* header_present */ |
0, /* last_render_target: ignored */ |
send_commit_msg, /* response_length */ |
0, /* end_of_thread */ |
send_commit_msg); /* send_commit_msg */ |
} |
/** |
* This instruction is generated as a single-channel align1 instruction by |
* both the VS and FS stages when using INTEL_DEBUG=shader_time. |
* |
* We can't use the typed atomic op in the FS because that has the execution |
* mask ANDed with the pixel mask, but we just want to write the one dword for |
* all the pixels. |
* |
* We don't use the SIMD4x2 atomic ops in the VS because want to just write |
* one u32. So we use the same untyped atomic write message as the pixel |
* shader. |
* |
* The untyped atomic operation requires a BUFFER surface type with RAW |
* format, and is only accessible through the legacy DATA_CACHE dataport |
* messages. |
*/ |
void brw_shader_time_add(struct brw_compile *p, |
struct brw_reg payload, |
uint32_t surf_index) |
{ |
struct brw_context *brw = p->brw; |
assert(brw->gen >= 7); |
brw_push_insn_state(p); |
brw_set_access_mode(p, BRW_ALIGN_1); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND); |
brw_pop_insn_state(p); |
/* We use brw_vec1_reg and unmasked because we want to increment the given |
* offset only once. |
*/ |
brw_set_dest(p, send, brw_vec1_reg(BRW_ARCHITECTURE_REGISTER_FILE, |
BRW_ARF_NULL, 0)); |
brw_set_src0(p, send, brw_vec1_reg(payload.file, |
payload.nr, 0)); |
uint32_t sfid, msg_type; |
if (brw->is_haswell) { |
sfid = HSW_SFID_DATAPORT_DATA_CACHE_1; |
msg_type = HSW_DATAPORT_DC_PORT1_UNTYPED_ATOMIC_OP; |
} else { |
sfid = GEN7_SFID_DATAPORT_DATA_CACHE; |
msg_type = GEN7_DATAPORT_DC_UNTYPED_ATOMIC_OP; |
} |
bool header_present = false; |
bool eot = false; |
uint32_t mlen = 2; /* offset, value */ |
uint32_t rlen = 0; |
brw_set_message_descriptor(p, send, sfid, mlen, rlen, header_present, eot); |
send->bits3.ud |= msg_type << 14; |
send->bits3.ud |= 0 << 13; /* no return data */ |
send->bits3.ud |= 1 << 12; /* SIMD8 mode */ |
send->bits3.ud |= BRW_AOP_ADD << 8; |
send->bits3.ud |= surf_index << 0; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_eu_util.c |
---|
0,0 → 1,125 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "brw_context.h" |
#include "brw_defines.h" |
#include "brw_eu.h" |
void brw_math_invert( struct brw_compile *p, |
struct brw_reg dst, |
struct brw_reg src) |
{ |
brw_math( p, |
dst, |
BRW_MATH_FUNCTION_INV, |
0, |
src, |
BRW_MATH_PRECISION_FULL, |
BRW_MATH_DATA_VECTOR ); |
} |
void brw_copy4(struct brw_compile *p, |
struct brw_reg dst, |
struct brw_reg src, |
GLuint count) |
{ |
GLuint i; |
dst = vec4(dst); |
src = vec4(src); |
for (i = 0; i < count; i++) |
{ |
GLuint delta = i*32; |
brw_MOV(p, byte_offset(dst, delta), byte_offset(src, delta)); |
brw_MOV(p, byte_offset(dst, delta+16), byte_offset(src, delta+16)); |
} |
} |
void brw_copy8(struct brw_compile *p, |
struct brw_reg dst, |
struct brw_reg src, |
GLuint count) |
{ |
GLuint i; |
dst = vec8(dst); |
src = vec8(src); |
for (i = 0; i < count; i++) |
{ |
GLuint delta = i*32; |
brw_MOV(p, byte_offset(dst, delta), byte_offset(src, delta)); |
} |
} |
void brw_copy_indirect_to_indirect(struct brw_compile *p, |
struct brw_indirect dst_ptr, |
struct brw_indirect src_ptr, |
GLuint count) |
{ |
GLuint i; |
for (i = 0; i < count; i++) |
{ |
GLuint delta = i*32; |
brw_MOV(p, deref_4f(dst_ptr, delta), deref_4f(src_ptr, delta)); |
brw_MOV(p, deref_4f(dst_ptr, delta+16), deref_4f(src_ptr, delta+16)); |
} |
} |
void brw_copy_from_indirect(struct brw_compile *p, |
struct brw_reg dst, |
struct brw_indirect ptr, |
GLuint count) |
{ |
GLuint i; |
dst = vec4(dst); |
for (i = 0; i < count; i++) |
{ |
GLuint delta = i*32; |
brw_MOV(p, byte_offset(dst, delta), deref_4f(ptr, delta)); |
brw_MOV(p, byte_offset(dst, delta+16), deref_4f(ptr, delta+16)); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs.cpp |
---|
0,0 → 1,3186 |
/* |
* Copyright © 2010 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. |
*/ |
/** @file brw_fs.cpp |
* |
* This file drives the GLSL IR -> LIR translation, contains the |
* optimizations on the LIR, and drives the generation of native code |
* from the LIR. |
*/ |
extern "C" { |
#include <sys/types.h> |
#include "main/hash_table.h" |
#include "main/macros.h" |
#include "main/shaderobj.h" |
#include "main/uniforms.h" |
#include "main/fbobject.h" |
#include "program/prog_parameter.h" |
#include "program/prog_print.h" |
#include "program/register_allocate.h" |
#include "program/sampler.h" |
#include "program/hash_table.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_wm.h" |
} |
#include "brw_fs.h" |
#include "glsl/glsl_types.h" |
void |
fs_inst::init() |
{ |
memset(this, 0, sizeof(*this)); |
this->opcode = BRW_OPCODE_NOP; |
this->conditional_mod = BRW_CONDITIONAL_NONE; |
this->dst = reg_undef; |
this->src[0] = reg_undef; |
this->src[1] = reg_undef; |
this->src[2] = reg_undef; |
/* This will be the case for almost all instructions. */ |
this->regs_written = 1; |
} |
fs_inst::fs_inst() |
{ |
init(); |
} |
fs_inst::fs_inst(enum opcode opcode) |
{ |
init(); |
this->opcode = opcode; |
} |
fs_inst::fs_inst(enum opcode opcode, fs_reg dst) |
{ |
init(); |
this->opcode = opcode; |
this->dst = dst; |
if (dst.file == GRF) |
assert(dst.reg_offset >= 0); |
} |
fs_inst::fs_inst(enum opcode opcode, fs_reg dst, fs_reg src0) |
{ |
init(); |
this->opcode = opcode; |
this->dst = dst; |
this->src[0] = src0; |
if (dst.file == GRF) |
assert(dst.reg_offset >= 0); |
if (src[0].file == GRF) |
assert(src[0].reg_offset >= 0); |
} |
fs_inst::fs_inst(enum opcode opcode, fs_reg dst, fs_reg src0, fs_reg src1) |
{ |
init(); |
this->opcode = opcode; |
this->dst = dst; |
this->src[0] = src0; |
this->src[1] = src1; |
if (dst.file == GRF) |
assert(dst.reg_offset >= 0); |
if (src[0].file == GRF) |
assert(src[0].reg_offset >= 0); |
if (src[1].file == GRF) |
assert(src[1].reg_offset >= 0); |
} |
fs_inst::fs_inst(enum opcode opcode, fs_reg dst, |
fs_reg src0, fs_reg src1, fs_reg src2) |
{ |
init(); |
this->opcode = opcode; |
this->dst = dst; |
this->src[0] = src0; |
this->src[1] = src1; |
this->src[2] = src2; |
if (dst.file == GRF) |
assert(dst.reg_offset >= 0); |
if (src[0].file == GRF) |
assert(src[0].reg_offset >= 0); |
if (src[1].file == GRF) |
assert(src[1].reg_offset >= 0); |
if (src[2].file == GRF) |
assert(src[2].reg_offset >= 0); |
} |
#define ALU1(op) \ |
fs_inst * \ |
fs_visitor::op(fs_reg dst, fs_reg src0) \ |
{ \ |
return new(mem_ctx) fs_inst(BRW_OPCODE_##op, dst, src0); \ |
} |
#define ALU2(op) \ |
fs_inst * \ |
fs_visitor::op(fs_reg dst, fs_reg src0, fs_reg src1) \ |
{ \ |
return new(mem_ctx) fs_inst(BRW_OPCODE_##op, dst, src0, src1); \ |
} |
#define ALU3(op) \ |
fs_inst * \ |
fs_visitor::op(fs_reg dst, fs_reg src0, fs_reg src1, fs_reg src2) \ |
{ \ |
return new(mem_ctx) fs_inst(BRW_OPCODE_##op, dst, src0, src1, src2);\ |
} |
ALU1(NOT) |
ALU1(MOV) |
ALU1(FRC) |
ALU1(RNDD) |
ALU1(RNDE) |
ALU1(RNDZ) |
ALU2(ADD) |
ALU2(MUL) |
ALU2(MACH) |
ALU2(AND) |
ALU2(OR) |
ALU2(XOR) |
ALU2(SHL) |
ALU2(SHR) |
ALU2(ASR) |
ALU3(LRP) |
ALU1(BFREV) |
ALU3(BFE) |
ALU2(BFI1) |
ALU3(BFI2) |
ALU1(FBH) |
ALU1(FBL) |
ALU1(CBIT) |
/** Gen4 predicated IF. */ |
fs_inst * |
fs_visitor::IF(uint32_t predicate) |
{ |
fs_inst *inst = new(mem_ctx) fs_inst(BRW_OPCODE_IF); |
inst->predicate = predicate; |
return inst; |
} |
/** Gen6+ IF with embedded comparison. */ |
fs_inst * |
fs_visitor::IF(fs_reg src0, fs_reg src1, uint32_t condition) |
{ |
assert(brw->gen >= 6); |
fs_inst *inst = new(mem_ctx) fs_inst(BRW_OPCODE_IF, |
reg_null_d, src0, src1); |
inst->conditional_mod = condition; |
return inst; |
} |
/** |
* CMP: Sets the low bit of the destination channels with the result |
* of the comparison, while the upper bits are undefined, and updates |
* the flag register with the packed 16 bits of the result. |
*/ |
fs_inst * |
fs_visitor::CMP(fs_reg dst, fs_reg src0, fs_reg src1, uint32_t condition) |
{ |
fs_inst *inst; |
/* Take the instruction: |
* |
* CMP null<d> src0<f> src1<f> |
* |
* Original gen4 does type conversion to the destination type before |
* comparison, producing garbage results for floating point comparisons. |
* gen5 does the comparison on the execution type (resolved source types), |
* so dst type doesn't matter. gen6 does comparison and then uses the |
* result as if it was the dst type with no conversion, which happens to |
* mostly work out for float-interpreted-as-int since our comparisons are |
* for >0, =0, <0. |
*/ |
if (brw->gen == 4) { |
dst.type = src0.type; |
if (dst.file == HW_REG) |
dst.fixed_hw_reg.type = dst.type; |
} |
resolve_ud_negate(&src0); |
resolve_ud_negate(&src1); |
inst = new(mem_ctx) fs_inst(BRW_OPCODE_CMP, dst, src0, src1); |
inst->conditional_mod = condition; |
return inst; |
} |
exec_list |
fs_visitor::VARYING_PULL_CONSTANT_LOAD(fs_reg dst, fs_reg surf_index, |
fs_reg varying_offset, |
uint32_t const_offset) |
{ |
exec_list instructions; |
fs_inst *inst; |
/* We have our constant surface use a pitch of 4 bytes, so our index can |
* be any component of a vector, and then we load 4 contiguous |
* components starting from that. |
* |
* We break down the const_offset to a portion added to the variable |
* offset and a portion done using reg_offset, which means that if you |
* have GLSL using something like "uniform vec4 a[20]; gl_FragColor = |
* a[i]", we'll temporarily generate 4 vec4 loads from offset i * 4, and |
* CSE can later notice that those loads are all the same and eliminate |
* the redundant ones. |
*/ |
fs_reg vec4_offset = fs_reg(this, glsl_type::int_type); |
instructions.push_tail(ADD(vec4_offset, |
varying_offset, const_offset & ~3)); |
int scale = 1; |
if (brw->gen == 4 && dispatch_width == 8) { |
/* Pre-gen5, we can either use a SIMD8 message that requires (header, |
* u, v, r) as parameters, or we can just use the SIMD16 message |
* consisting of (header, u). We choose the second, at the cost of a |
* longer return length. |
*/ |
scale = 2; |
} |
enum opcode op; |
if (brw->gen >= 7) |
op = FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7; |
else |
op = FS_OPCODE_VARYING_PULL_CONSTANT_LOAD; |
fs_reg vec4_result = fs_reg(GRF, virtual_grf_alloc(4 * scale), dst.type); |
inst = new(mem_ctx) fs_inst(op, vec4_result, surf_index, vec4_offset); |
inst->regs_written = 4 * scale; |
instructions.push_tail(inst); |
if (brw->gen < 7) { |
inst->base_mrf = 13; |
inst->header_present = true; |
if (brw->gen == 4) |
inst->mlen = 3; |
else |
inst->mlen = 1 + dispatch_width / 8; |
} |
vec4_result.reg_offset += (const_offset & 3) * scale; |
instructions.push_tail(MOV(dst, vec4_result)); |
return instructions; |
} |
/** |
* A helper for MOV generation for fixing up broken hardware SEND dependency |
* handling. |
*/ |
fs_inst * |
fs_visitor::DEP_RESOLVE_MOV(int grf) |
{ |
fs_inst *inst = MOV(brw_null_reg(), fs_reg(GRF, grf, BRW_REGISTER_TYPE_F)); |
inst->ir = NULL; |
inst->annotation = "send dependency resolve"; |
/* The caller always wants uncompressed to emit the minimal extra |
* dependencies, and to avoid having to deal with aligning its regs to 2. |
*/ |
inst->force_uncompressed = true; |
return inst; |
} |
bool |
fs_inst::equals(fs_inst *inst) |
{ |
return (opcode == inst->opcode && |
dst.equals(inst->dst) && |
src[0].equals(inst->src[0]) && |
src[1].equals(inst->src[1]) && |
src[2].equals(inst->src[2]) && |
saturate == inst->saturate && |
predicate == inst->predicate && |
conditional_mod == inst->conditional_mod && |
mlen == inst->mlen && |
base_mrf == inst->base_mrf && |
sampler == inst->sampler && |
target == inst->target && |
eot == inst->eot && |
header_present == inst->header_present && |
shadow_compare == inst->shadow_compare && |
offset == inst->offset); |
} |
bool |
fs_inst::overwrites_reg(const fs_reg ®) |
{ |
return (reg.file == dst.file && |
reg.reg == dst.reg && |
reg.reg_offset >= dst.reg_offset && |
reg.reg_offset < dst.reg_offset + regs_written); |
} |
bool |
fs_inst::is_send_from_grf() |
{ |
return (opcode == FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7 || |
opcode == SHADER_OPCODE_SHADER_TIME_ADD || |
(opcode == FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD && |
src[1].file == GRF)); |
} |
bool |
fs_visitor::can_do_source_mods(fs_inst *inst) |
{ |
if (brw->gen == 6 && inst->is_math()) |
return false; |
if (inst->is_send_from_grf()) |
return false; |
return true; |
} |
void |
fs_reg::init() |
{ |
memset(this, 0, sizeof(*this)); |
this->smear = -1; |
} |
/** Generic unset register constructor. */ |
fs_reg::fs_reg() |
{ |
init(); |
this->file = BAD_FILE; |
} |
/** Immediate value constructor. */ |
fs_reg::fs_reg(float f) |
{ |
init(); |
this->file = IMM; |
this->type = BRW_REGISTER_TYPE_F; |
this->imm.f = f; |
} |
/** Immediate value constructor. */ |
fs_reg::fs_reg(int32_t i) |
{ |
init(); |
this->file = IMM; |
this->type = BRW_REGISTER_TYPE_D; |
this->imm.i = i; |
} |
/** Immediate value constructor. */ |
fs_reg::fs_reg(uint32_t u) |
{ |
init(); |
this->file = IMM; |
this->type = BRW_REGISTER_TYPE_UD; |
this->imm.u = u; |
} |
/** Fixed brw_reg Immediate value constructor. */ |
fs_reg::fs_reg(struct brw_reg fixed_hw_reg) |
{ |
init(); |
this->file = HW_REG; |
this->fixed_hw_reg = fixed_hw_reg; |
this->type = fixed_hw_reg.type; |
} |
bool |
fs_reg::equals(const fs_reg &r) const |
{ |
return (file == r.file && |
reg == r.reg && |
reg_offset == r.reg_offset && |
type == r.type && |
negate == r.negate && |
abs == r.abs && |
!reladdr && !r.reladdr && |
memcmp(&fixed_hw_reg, &r.fixed_hw_reg, |
sizeof(fixed_hw_reg)) == 0 && |
smear == r.smear && |
imm.u == r.imm.u); |
} |
bool |
fs_reg::is_zero() const |
{ |
if (file != IMM) |
return false; |
return type == BRW_REGISTER_TYPE_F ? imm.f == 0.0 : imm.i == 0; |
} |
bool |
fs_reg::is_one() const |
{ |
if (file != IMM) |
return false; |
return type == BRW_REGISTER_TYPE_F ? imm.f == 1.0 : imm.i == 1; |
} |
bool |
fs_reg::is_valid_3src() const |
{ |
return file == GRF || file == UNIFORM; |
} |
int |
fs_visitor::type_size(const struct glsl_type *type) |
{ |
unsigned int size, i; |
switch (type->base_type) { |
case GLSL_TYPE_UINT: |
case GLSL_TYPE_INT: |
case GLSL_TYPE_FLOAT: |
case GLSL_TYPE_BOOL: |
return type->components(); |
case GLSL_TYPE_ARRAY: |
return type_size(type->fields.array) * type->length; |
case GLSL_TYPE_STRUCT: |
size = 0; |
for (i = 0; i < type->length; i++) { |
size += type_size(type->fields.structure[i].type); |
} |
return size; |
case GLSL_TYPE_SAMPLER: |
/* Samplers take up no register space, since they're baked in at |
* link time. |
*/ |
return 0; |
case GLSL_TYPE_VOID: |
case GLSL_TYPE_ERROR: |
case GLSL_TYPE_INTERFACE: |
assert(!"not reached"); |
break; |
} |
return 0; |
} |
fs_reg |
fs_visitor::get_timestamp() |
{ |
assert(brw->gen >= 7); |
fs_reg ts = fs_reg(retype(brw_vec1_reg(BRW_ARCHITECTURE_REGISTER_FILE, |
BRW_ARF_TIMESTAMP, |
0), |
BRW_REGISTER_TYPE_UD)); |
fs_reg dst = fs_reg(this, glsl_type::uint_type); |
fs_inst *mov = emit(MOV(dst, ts)); |
/* We want to read the 3 fields we care about (mostly field 0, but also 2) |
* even if it's not enabled in the dispatch. |
*/ |
mov->force_writemask_all = true; |
mov->force_uncompressed = true; |
/* The caller wants the low 32 bits of the timestamp. Since it's running |
* at the GPU clock rate of ~1.2ghz, it will roll over every ~3 seconds, |
* which is plenty of time for our purposes. It is identical across the |
* EUs, but since it's tracking GPU core speed it will increment at a |
* varying rate as render P-states change. |
* |
* The caller could also check if render P-states have changed (or anything |
* else that might disrupt timing) by setting smear to 2 and checking if |
* that field is != 0. |
*/ |
dst.smear = 0; |
return dst; |
} |
void |
fs_visitor::emit_shader_time_begin() |
{ |
current_annotation = "shader time start"; |
shader_start_time = get_timestamp(); |
} |
void |
fs_visitor::emit_shader_time_end() |
{ |
current_annotation = "shader time end"; |
enum shader_time_shader_type type, written_type, reset_type; |
if (dispatch_width == 8) { |
type = ST_FS8; |
written_type = ST_FS8_WRITTEN; |
reset_type = ST_FS8_RESET; |
} else { |
assert(dispatch_width == 16); |
type = ST_FS16; |
written_type = ST_FS16_WRITTEN; |
reset_type = ST_FS16_RESET; |
} |
fs_reg shader_end_time = get_timestamp(); |
/* Check that there weren't any timestamp reset events (assuming these |
* were the only two timestamp reads that happened). |
*/ |
fs_reg reset = shader_end_time; |
reset.smear = 2; |
fs_inst *test = emit(AND(reg_null_d, reset, fs_reg(1u))); |
test->conditional_mod = BRW_CONDITIONAL_Z; |
emit(IF(BRW_PREDICATE_NORMAL)); |
push_force_uncompressed(); |
fs_reg start = shader_start_time; |
start.negate = true; |
fs_reg diff = fs_reg(this, glsl_type::uint_type); |
emit(ADD(diff, start, shader_end_time)); |
/* If there were no instructions between the two timestamp gets, the diff |
* is 2 cycles. Remove that overhead, so I can forget about that when |
* trying to determine the time taken for single instructions. |
*/ |
emit(ADD(diff, diff, fs_reg(-2u))); |
emit_shader_time_write(type, diff); |
emit_shader_time_write(written_type, fs_reg(1u)); |
emit(BRW_OPCODE_ELSE); |
emit_shader_time_write(reset_type, fs_reg(1u)); |
emit(BRW_OPCODE_ENDIF); |
pop_force_uncompressed(); |
} |
void |
fs_visitor::emit_shader_time_write(enum shader_time_shader_type type, |
fs_reg value) |
{ |
int shader_time_index = |
brw_get_shader_time_index(brw, shader_prog, &fp->Base, type); |
fs_reg offset = fs_reg(shader_time_index * SHADER_TIME_STRIDE); |
fs_reg payload; |
if (dispatch_width == 8) |
payload = fs_reg(this, glsl_type::uvec2_type); |
else |
payload = fs_reg(this, glsl_type::uint_type); |
emit(fs_inst(SHADER_OPCODE_SHADER_TIME_ADD, |
fs_reg(), payload, offset, value)); |
} |
void |
fs_visitor::fail(const char *format, ...) |
{ |
va_list va; |
char *msg; |
if (failed) |
return; |
failed = true; |
va_start(va, format); |
msg = ralloc_vasprintf(mem_ctx, format, va); |
va_end(va); |
msg = ralloc_asprintf(mem_ctx, "FS compile failed: %s\n", msg); |
this->fail_msg = msg; |
if (INTEL_DEBUG & DEBUG_WM) { |
fprintf(stderr, "%s", msg); |
} |
} |
fs_inst * |
fs_visitor::emit(enum opcode opcode) |
{ |
return emit(fs_inst(opcode)); |
} |
fs_inst * |
fs_visitor::emit(enum opcode opcode, fs_reg dst) |
{ |
return emit(fs_inst(opcode, dst)); |
} |
fs_inst * |
fs_visitor::emit(enum opcode opcode, fs_reg dst, fs_reg src0) |
{ |
return emit(fs_inst(opcode, dst, src0)); |
} |
fs_inst * |
fs_visitor::emit(enum opcode opcode, fs_reg dst, fs_reg src0, fs_reg src1) |
{ |
return emit(fs_inst(opcode, dst, src0, src1)); |
} |
fs_inst * |
fs_visitor::emit(enum opcode opcode, fs_reg dst, |
fs_reg src0, fs_reg src1, fs_reg src2) |
{ |
return emit(fs_inst(opcode, dst, src0, src1, src2)); |
} |
void |
fs_visitor::push_force_uncompressed() |
{ |
force_uncompressed_stack++; |
} |
void |
fs_visitor::pop_force_uncompressed() |
{ |
force_uncompressed_stack--; |
assert(force_uncompressed_stack >= 0); |
} |
void |
fs_visitor::push_force_sechalf() |
{ |
force_sechalf_stack++; |
} |
void |
fs_visitor::pop_force_sechalf() |
{ |
force_sechalf_stack--; |
assert(force_sechalf_stack >= 0); |
} |
/** |
* Returns true if the instruction has a flag that means it won't |
* update an entire destination register. |
* |
* For example, dead code elimination and live variable analysis want to know |
* when a write to a variable screens off any preceding values that were in |
* it. |
*/ |
bool |
fs_inst::is_partial_write() |
{ |
return (this->predicate || |
this->force_uncompressed || |
this->force_sechalf); |
} |
/** |
* Returns how many MRFs an FS opcode will write over. |
* |
* Note that this is not the 0 or 1 implied writes in an actual gen |
* instruction -- the FS opcodes often generate MOVs in addition. |
*/ |
int |
fs_visitor::implied_mrf_writes(fs_inst *inst) |
{ |
if (inst->mlen == 0) |
return 0; |
switch (inst->opcode) { |
case SHADER_OPCODE_RCP: |
case SHADER_OPCODE_RSQ: |
case SHADER_OPCODE_SQRT: |
case SHADER_OPCODE_EXP2: |
case SHADER_OPCODE_LOG2: |
case SHADER_OPCODE_SIN: |
case SHADER_OPCODE_COS: |
return 1 * dispatch_width / 8; |
case SHADER_OPCODE_POW: |
case SHADER_OPCODE_INT_QUOTIENT: |
case SHADER_OPCODE_INT_REMAINDER: |
return 2 * dispatch_width / 8; |
case SHADER_OPCODE_TEX: |
case FS_OPCODE_TXB: |
case SHADER_OPCODE_TXD: |
case SHADER_OPCODE_TXF: |
case SHADER_OPCODE_TXF_MS: |
case SHADER_OPCODE_TXL: |
case SHADER_OPCODE_TXS: |
case SHADER_OPCODE_LOD: |
return 1; |
case FS_OPCODE_FB_WRITE: |
return 2; |
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD: |
case FS_OPCODE_UNSPILL: |
return 1; |
case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD: |
return inst->mlen; |
case FS_OPCODE_SPILL: |
return 2; |
default: |
assert(!"not reached"); |
return inst->mlen; |
} |
} |
int |
fs_visitor::virtual_grf_alloc(int size) |
{ |
if (virtual_grf_array_size <= virtual_grf_count) { |
if (virtual_grf_array_size == 0) |
virtual_grf_array_size = 16; |
else |
virtual_grf_array_size *= 2; |
virtual_grf_sizes = reralloc(mem_ctx, virtual_grf_sizes, int, |
virtual_grf_array_size); |
} |
virtual_grf_sizes[virtual_grf_count] = size; |
return virtual_grf_count++; |
} |
/** Fixed HW reg constructor. */ |
fs_reg::fs_reg(enum register_file file, int reg) |
{ |
init(); |
this->file = file; |
this->reg = reg; |
this->type = BRW_REGISTER_TYPE_F; |
} |
/** Fixed HW reg constructor. */ |
fs_reg::fs_reg(enum register_file file, int reg, uint32_t type) |
{ |
init(); |
this->file = file; |
this->reg = reg; |
this->type = type; |
} |
/** Automatic reg constructor. */ |
fs_reg::fs_reg(class fs_visitor *v, const struct glsl_type *type) |
{ |
init(); |
this->file = GRF; |
this->reg = v->virtual_grf_alloc(v->type_size(type)); |
this->reg_offset = 0; |
this->type = brw_type_for_base_type(type); |
} |
fs_reg * |
fs_visitor::variable_storage(ir_variable *var) |
{ |
return (fs_reg *)hash_table_find(this->variable_ht, var); |
} |
void |
import_uniforms_callback(const void *key, |
void *data, |
void *closure) |
{ |
struct hash_table *dst_ht = (struct hash_table *)closure; |
const fs_reg *reg = (const fs_reg *)data; |
if (reg->file != UNIFORM) |
return; |
hash_table_insert(dst_ht, data, key); |
} |
/* For 16-wide, we need to follow from the uniform setup of 8-wide dispatch. |
* This brings in those uniform definitions |
*/ |
void |
fs_visitor::import_uniforms(fs_visitor *v) |
{ |
hash_table_call_foreach(v->variable_ht, |
import_uniforms_callback, |
variable_ht); |
this->params_remap = v->params_remap; |
this->nr_params_remap = v->nr_params_remap; |
} |
/* Our support for uniforms is piggy-backed on the struct |
* gl_fragment_program, because that's where the values actually |
* get stored, rather than in some global gl_shader_program uniform |
* store. |
*/ |
void |
fs_visitor::setup_uniform_values(ir_variable *ir) |
{ |
int namelen = strlen(ir->name); |
/* The data for our (non-builtin) uniforms is stored in a series of |
* gl_uniform_driver_storage structs for each subcomponent that |
* glGetUniformLocation() could name. We know it's been set up in the same |
* order we'd walk the type, so walk the list of storage and find anything |
* with our name, or the prefix of a component that starts with our name. |
*/ |
unsigned params_before = c->prog_data.nr_params; |
for (unsigned u = 0; u < shader_prog->NumUserUniformStorage; u++) { |
struct gl_uniform_storage *storage = &shader_prog->UniformStorage[u]; |
if (strncmp(ir->name, storage->name, namelen) != 0 || |
(storage->name[namelen] != 0 && |
storage->name[namelen] != '.' && |
storage->name[namelen] != '[')) { |
continue; |
} |
unsigned slots = storage->type->component_slots(); |
if (storage->array_elements) |
slots *= storage->array_elements; |
for (unsigned i = 0; i < slots; i++) { |
c->prog_data.param[c->prog_data.nr_params++] = |
&storage->storage[i].f; |
} |
} |
/* Make sure we actually initialized the right amount of stuff here. */ |
assert(params_before + ir->type->component_slots() == |
c->prog_data.nr_params); |
(void)params_before; |
} |
/* Our support for builtin uniforms is even scarier than non-builtin. |
* It sits on top of the PROG_STATE_VAR parameters that are |
* automatically updated from GL context state. |
*/ |
void |
fs_visitor::setup_builtin_uniform_values(ir_variable *ir) |
{ |
const ir_state_slot *const slots = ir->state_slots; |
assert(ir->state_slots != NULL); |
for (unsigned int i = 0; i < ir->num_state_slots; i++) { |
/* This state reference has already been setup by ir_to_mesa, but we'll |
* get the same index back here. |
*/ |
int index = _mesa_add_state_reference(this->fp->Base.Parameters, |
(gl_state_index *)slots[i].tokens); |
/* Add each of the unique swizzles of the element as a parameter. |
* This'll end up matching the expected layout of the |
* array/matrix/structure we're trying to fill in. |
*/ |
int last_swiz = -1; |
for (unsigned int j = 0; j < 4; j++) { |
int swiz = GET_SWZ(slots[i].swizzle, j); |
if (swiz == last_swiz) |
break; |
last_swiz = swiz; |
c->prog_data.param[c->prog_data.nr_params++] = |
&fp->Base.Parameters->ParameterValues[index][swiz].f; |
} |
} |
} |
fs_reg * |
fs_visitor::emit_fragcoord_interpolation(ir_variable *ir) |
{ |
fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type); |
fs_reg wpos = *reg; |
bool flip = !ir->origin_upper_left ^ c->key.render_to_fbo; |
/* gl_FragCoord.x */ |
if (ir->pixel_center_integer) { |
emit(MOV(wpos, this->pixel_x)); |
} else { |
emit(ADD(wpos, this->pixel_x, fs_reg(0.5f))); |
} |
wpos.reg_offset++; |
/* gl_FragCoord.y */ |
if (!flip && ir->pixel_center_integer) { |
emit(MOV(wpos, this->pixel_y)); |
} else { |
fs_reg pixel_y = this->pixel_y; |
float offset = (ir->pixel_center_integer ? 0.0 : 0.5); |
if (flip) { |
pixel_y.negate = true; |
offset += c->key.drawable_height - 1.0; |
} |
emit(ADD(wpos, pixel_y, fs_reg(offset))); |
} |
wpos.reg_offset++; |
/* gl_FragCoord.z */ |
if (brw->gen >= 6) { |
emit(MOV(wpos, fs_reg(brw_vec8_grf(c->source_depth_reg, 0)))); |
} else { |
emit(FS_OPCODE_LINTERP, wpos, |
this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], |
this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], |
interp_reg(VARYING_SLOT_POS, 2)); |
} |
wpos.reg_offset++; |
/* gl_FragCoord.w: Already set up in emit_interpolation */ |
emit(BRW_OPCODE_MOV, wpos, this->wpos_w); |
return reg; |
} |
fs_inst * |
fs_visitor::emit_linterp(const fs_reg &attr, const fs_reg &interp, |
glsl_interp_qualifier interpolation_mode, |
bool is_centroid) |
{ |
brw_wm_barycentric_interp_mode barycoord_mode; |
if (brw->gen >= 6) { |
if (is_centroid) { |
if (interpolation_mode == INTERP_QUALIFIER_SMOOTH) |
barycoord_mode = BRW_WM_PERSPECTIVE_CENTROID_BARYCENTRIC; |
else |
barycoord_mode = BRW_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC; |
} else { |
if (interpolation_mode == INTERP_QUALIFIER_SMOOTH) |
barycoord_mode = BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC; |
else |
barycoord_mode = BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC; |
} |
} else { |
/* On Ironlake and below, there is only one interpolation mode. |
* Centroid interpolation doesn't mean anything on this hardware -- |
* there is no multisampling. |
*/ |
barycoord_mode = BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC; |
} |
return emit(FS_OPCODE_LINTERP, attr, |
this->delta_x[barycoord_mode], |
this->delta_y[barycoord_mode], interp); |
} |
fs_reg * |
fs_visitor::emit_general_interpolation(ir_variable *ir) |
{ |
fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type); |
reg->type = brw_type_for_base_type(ir->type->get_scalar_type()); |
fs_reg attr = *reg; |
unsigned int array_elements; |
const glsl_type *type; |
if (ir->type->is_array()) { |
array_elements = ir->type->length; |
if (array_elements == 0) { |
fail("dereferenced array '%s' has length 0\n", ir->name); |
} |
type = ir->type->fields.array; |
} else { |
array_elements = 1; |
type = ir->type; |
} |
glsl_interp_qualifier interpolation_mode = |
ir->determine_interpolation_mode(c->key.flat_shade); |
int location = ir->location; |
for (unsigned int i = 0; i < array_elements; i++) { |
for (unsigned int j = 0; j < type->matrix_columns; j++) { |
if (urb_setup[location] == -1) { |
/* If there's no incoming setup data for this slot, don't |
* emit interpolation for it. |
*/ |
attr.reg_offset += type->vector_elements; |
location++; |
continue; |
} |
if (interpolation_mode == INTERP_QUALIFIER_FLAT) { |
/* Constant interpolation (flat shading) case. The SF has |
* handed us defined values in only the constant offset |
* field of the setup reg. |
*/ |
for (unsigned int k = 0; k < type->vector_elements; k++) { |
struct brw_reg interp = interp_reg(location, k); |
interp = suboffset(interp, 3); |
interp.type = reg->type; |
emit(FS_OPCODE_CINTERP, attr, fs_reg(interp)); |
attr.reg_offset++; |
} |
} else { |
/* Smooth/noperspective interpolation case. */ |
for (unsigned int k = 0; k < type->vector_elements; k++) { |
/* FINISHME: At some point we probably want to push |
* this farther by giving similar treatment to the |
* other potentially constant components of the |
* attribute, as well as making brw_vs_constval.c |
* handle varyings other than gl_TexCoord. |
*/ |
struct brw_reg interp = interp_reg(location, k); |
emit_linterp(attr, fs_reg(interp), interpolation_mode, |
ir->centroid); |
if (brw->needs_unlit_centroid_workaround && ir->centroid) { |
/* Get the pixel/sample mask into f0 so that we know |
* which pixels are lit. Then, for each channel that is |
* unlit, replace the centroid data with non-centroid |
* data. |
*/ |
emit(FS_OPCODE_MOV_DISPATCH_TO_FLAGS); |
fs_inst *inst = emit_linterp(attr, fs_reg(interp), |
interpolation_mode, false); |
inst->predicate = BRW_PREDICATE_NORMAL; |
inst->predicate_inverse = true; |
} |
if (brw->gen < 6) { |
emit(BRW_OPCODE_MUL, attr, attr, this->pixel_w); |
} |
attr.reg_offset++; |
} |
} |
location++; |
} |
} |
return reg; |
} |
fs_reg * |
fs_visitor::emit_frontfacing_interpolation(ir_variable *ir) |
{ |
fs_reg *reg = new(this->mem_ctx) fs_reg(this, ir->type); |
/* The frontfacing comes in as a bit in the thread payload. */ |
if (brw->gen >= 6) { |
emit(BRW_OPCODE_ASR, *reg, |
fs_reg(retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_D)), |
fs_reg(15)); |
emit(BRW_OPCODE_NOT, *reg, *reg); |
emit(BRW_OPCODE_AND, *reg, *reg, fs_reg(1)); |
} else { |
struct brw_reg r1_6ud = retype(brw_vec1_grf(1, 6), BRW_REGISTER_TYPE_UD); |
/* bit 31 is "primitive is back face", so checking < (1 << 31) gives |
* us front face |
*/ |
emit(CMP(*reg, fs_reg(r1_6ud), fs_reg(1u << 31), BRW_CONDITIONAL_L)); |
emit(BRW_OPCODE_AND, *reg, *reg, fs_reg(1u)); |
} |
return reg; |
} |
fs_reg |
fs_visitor::fix_math_operand(fs_reg src) |
{ |
/* Can't do hstride == 0 args on gen6 math, so expand it out. We |
* might be able to do better by doing execsize = 1 math and then |
* expanding that result out, but we would need to be careful with |
* masking. |
* |
* The hardware ignores source modifiers (negate and abs) on math |
* instructions, so we also move to a temp to set those up. |
*/ |
if (brw->gen == 6 && src.file != UNIFORM && src.file != IMM && |
!src.abs && !src.negate) |
return src; |
/* Gen7 relaxes most of the above restrictions, but still can't use IMM |
* operands to math |
*/ |
if (brw->gen >= 7 && src.file != IMM) |
return src; |
fs_reg expanded = fs_reg(this, glsl_type::float_type); |
expanded.type = src.type; |
emit(BRW_OPCODE_MOV, expanded, src); |
return expanded; |
} |
fs_inst * |
fs_visitor::emit_math(enum opcode opcode, fs_reg dst, fs_reg src) |
{ |
switch (opcode) { |
case SHADER_OPCODE_RCP: |
case SHADER_OPCODE_RSQ: |
case SHADER_OPCODE_SQRT: |
case SHADER_OPCODE_EXP2: |
case SHADER_OPCODE_LOG2: |
case SHADER_OPCODE_SIN: |
case SHADER_OPCODE_COS: |
break; |
default: |
assert(!"not reached: bad math opcode"); |
return NULL; |
} |
/* Can't do hstride == 0 args to gen6 math, so expand it out. We |
* might be able to do better by doing execsize = 1 math and then |
* expanding that result out, but we would need to be careful with |
* masking. |
* |
* Gen 6 hardware ignores source modifiers (negate and abs) on math |
* instructions, so we also move to a temp to set those up. |
*/ |
if (brw->gen >= 6) |
src = fix_math_operand(src); |
fs_inst *inst = emit(opcode, dst, src); |
if (brw->gen < 6) { |
inst->base_mrf = 2; |
inst->mlen = dispatch_width / 8; |
} |
return inst; |
} |
fs_inst * |
fs_visitor::emit_math(enum opcode opcode, fs_reg dst, fs_reg src0, fs_reg src1) |
{ |
int base_mrf = 2; |
fs_inst *inst; |
switch (opcode) { |
case SHADER_OPCODE_INT_QUOTIENT: |
case SHADER_OPCODE_INT_REMAINDER: |
if (brw->gen >= 7 && dispatch_width == 16) |
fail("16-wide INTDIV unsupported\n"); |
break; |
case SHADER_OPCODE_POW: |
break; |
default: |
assert(!"not reached: unsupported binary math opcode."); |
return NULL; |
} |
if (brw->gen >= 6) { |
src0 = fix_math_operand(src0); |
src1 = fix_math_operand(src1); |
inst = emit(opcode, dst, src0, src1); |
} else { |
/* From the Ironlake PRM, Volume 4, Part 1, Section 6.1.13 |
* "Message Payload": |
* |
* "Operand0[7]. For the INT DIV functions, this operand is the |
* denominator." |
* ... |
* "Operand1[7]. For the INT DIV functions, this operand is the |
* numerator." |
*/ |
bool is_int_div = opcode != SHADER_OPCODE_POW; |
fs_reg &op0 = is_int_div ? src1 : src0; |
fs_reg &op1 = is_int_div ? src0 : src1; |
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + 1, op1.type), op1); |
inst = emit(opcode, dst, op0, reg_null_f); |
inst->base_mrf = base_mrf; |
inst->mlen = 2 * dispatch_width / 8; |
} |
return inst; |
} |
void |
fs_visitor::assign_curb_setup() |
{ |
c->prog_data.curb_read_length = ALIGN(c->prog_data.nr_params, 8) / 8; |
if (dispatch_width == 8) { |
c->prog_data.first_curbe_grf = c->nr_payload_regs; |
} else { |
c->prog_data.first_curbe_grf_16 = c->nr_payload_regs; |
} |
/* Map the offsets in the UNIFORM file to fixed HW regs. */ |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
for (unsigned int i = 0; i < 3; i++) { |
if (inst->src[i].file == UNIFORM) { |
int constant_nr = inst->src[i].reg + inst->src[i].reg_offset; |
struct brw_reg brw_reg = brw_vec1_grf(c->nr_payload_regs + |
constant_nr / 8, |
constant_nr % 8); |
inst->src[i].file = HW_REG; |
inst->src[i].fixed_hw_reg = retype(brw_reg, inst->src[i].type); |
} |
} |
} |
} |
void |
fs_visitor::calculate_urb_setup() |
{ |
for (unsigned int i = 0; i < VARYING_SLOT_MAX; i++) { |
urb_setup[i] = -1; |
} |
int urb_next = 0; |
/* Figure out where each of the incoming setup attributes lands. */ |
if (brw->gen >= 6) { |
for (unsigned int i = 0; i < VARYING_SLOT_MAX; i++) { |
if (fp->Base.InputsRead & BITFIELD64_BIT(i)) { |
urb_setup[i] = urb_next++; |
} |
} |
} else { |
/* FINISHME: The sf doesn't map VS->FS inputs for us very well. */ |
for (unsigned int i = 0; i < VARYING_SLOT_MAX; i++) { |
/* Point size is packed into the header, not as a general attribute */ |
if (i == VARYING_SLOT_PSIZ) |
continue; |
if (c->key.input_slots_valid & BITFIELD64_BIT(i)) { |
/* The back color slot is skipped when the front color is |
* also written to. In addition, some slots can be |
* written in the vertex shader and not read in the |
* fragment shader. So the register number must always be |
* incremented, mapped or not. |
*/ |
if (_mesa_varying_slot_in_fs((gl_varying_slot) i)) |
urb_setup[i] = urb_next; |
urb_next++; |
} |
} |
/* |
* It's a FS only attribute, and we did interpolation for this attribute |
* in SF thread. So, count it here, too. |
* |
* See compile_sf_prog() for more info. |
*/ |
if (fp->Base.InputsRead & BITFIELD64_BIT(VARYING_SLOT_PNTC)) |
urb_setup[VARYING_SLOT_PNTC] = urb_next++; |
} |
/* Each attribute is 4 setup channels, each of which is half a reg. */ |
c->prog_data.urb_read_length = urb_next * 2; |
} |
void |
fs_visitor::assign_urb_setup() |
{ |
int urb_start = c->nr_payload_regs + c->prog_data.curb_read_length; |
/* Offset all the urb_setup[] index by the actual position of the |
* setup regs, now that the location of the constants has been chosen. |
*/ |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
if (inst->opcode == FS_OPCODE_LINTERP) { |
assert(inst->src[2].file == HW_REG); |
inst->src[2].fixed_hw_reg.nr += urb_start; |
} |
if (inst->opcode == FS_OPCODE_CINTERP) { |
assert(inst->src[0].file == HW_REG); |
inst->src[0].fixed_hw_reg.nr += urb_start; |
} |
} |
this->first_non_payload_grf = urb_start + c->prog_data.urb_read_length; |
} |
/** |
* Split large virtual GRFs into separate components if we can. |
* |
* This is mostly duplicated with what brw_fs_vector_splitting does, |
* but that's really conservative because it's afraid of doing |
* splitting that doesn't result in real progress after the rest of |
* the optimization phases, which would cause infinite looping in |
* optimization. We can do it once here, safely. This also has the |
* opportunity to split interpolated values, or maybe even uniforms, |
* which we don't have at the IR level. |
* |
* We want to split, because virtual GRFs are what we register |
* allocate and spill (due to contiguousness requirements for some |
* instructions), and they're what we naturally generate in the |
* codegen process, but most virtual GRFs don't actually need to be |
* contiguous sets of GRFs. If we split, we'll end up with reduced |
* live intervals and better dead code elimination and coalescing. |
*/ |
void |
fs_visitor::split_virtual_grfs() |
{ |
int num_vars = this->virtual_grf_count; |
bool split_grf[num_vars]; |
int new_virtual_grf[num_vars]; |
/* Try to split anything > 0 sized. */ |
for (int i = 0; i < num_vars; i++) { |
if (this->virtual_grf_sizes[i] != 1) |
split_grf[i] = true; |
else |
split_grf[i] = false; |
} |
if (brw->has_pln && |
this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC].file == GRF) { |
/* PLN opcodes rely on the delta_xy being contiguous. We only have to |
* check this for BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC, because prior to |
* Gen6, that was the only supported interpolation mode, and since Gen6, |
* delta_x and delta_y are in fixed hardware registers. |
*/ |
split_grf[this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC].reg] = |
false; |
} |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
/* If there's a SEND message that requires contiguous destination |
* registers, no splitting is allowed. |
*/ |
if (inst->regs_written > 1) { |
split_grf[inst->dst.reg] = false; |
} |
/* If we're sending from a GRF, don't split it, on the assumption that |
* the send is reading the whole thing. |
*/ |
if (inst->is_send_from_grf()) { |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
split_grf[inst->src[i].reg] = false; |
} |
} |
} |
} |
/* Allocate new space for split regs. Note that the virtual |
* numbers will be contiguous. |
*/ |
for (int i = 0; i < num_vars; i++) { |
if (split_grf[i]) { |
new_virtual_grf[i] = virtual_grf_alloc(1); |
for (int j = 2; j < this->virtual_grf_sizes[i]; j++) { |
int reg = virtual_grf_alloc(1); |
assert(reg == new_virtual_grf[i] + j - 1); |
(void) reg; |
} |
this->virtual_grf_sizes[i] = 1; |
} |
} |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
if (inst->dst.file == GRF && |
split_grf[inst->dst.reg] && |
inst->dst.reg_offset != 0) { |
inst->dst.reg = (new_virtual_grf[inst->dst.reg] + |
inst->dst.reg_offset - 1); |
inst->dst.reg_offset = 0; |
} |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF && |
split_grf[inst->src[i].reg] && |
inst->src[i].reg_offset != 0) { |
inst->src[i].reg = (new_virtual_grf[inst->src[i].reg] + |
inst->src[i].reg_offset - 1); |
inst->src[i].reg_offset = 0; |
} |
} |
} |
this->live_intervals_valid = false; |
} |
/** |
* Remove unused virtual GRFs and compact the virtual_grf_* arrays. |
* |
* During code generation, we create tons of temporary variables, many of |
* which get immediately killed and are never used again. Yet, in later |
* optimization and analysis passes, such as compute_live_intervals, we need |
* to loop over all the virtual GRFs. Compacting them can save a lot of |
* overhead. |
*/ |
void |
fs_visitor::compact_virtual_grfs() |
{ |
/* Mark which virtual GRFs are used, and count how many. */ |
int remap_table[this->virtual_grf_count]; |
memset(remap_table, -1, sizeof(remap_table)); |
foreach_list(node, &this->instructions) { |
const fs_inst *inst = (const fs_inst *) node; |
if (inst->dst.file == GRF) |
remap_table[inst->dst.reg] = 0; |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) |
remap_table[inst->src[i].reg] = 0; |
} |
} |
/* In addition to registers used in instructions, fs_visitor keeps |
* direct references to certain special values which must be patched: |
*/ |
fs_reg *special[] = { |
&frag_depth, &pixel_x, &pixel_y, &pixel_w, &wpos_w, &dual_src_output, |
&outputs[0], &outputs[1], &outputs[2], &outputs[3], |
&outputs[4], &outputs[5], &outputs[6], &outputs[7], |
&delta_x[0], &delta_x[1], &delta_x[2], |
&delta_x[3], &delta_x[4], &delta_x[5], |
&delta_y[0], &delta_y[1], &delta_y[2], |
&delta_y[3], &delta_y[4], &delta_y[5], |
}; |
STATIC_ASSERT(BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT == 6); |
STATIC_ASSERT(BRW_MAX_DRAW_BUFFERS == 8); |
/* Treat all special values as used, to be conservative */ |
for (unsigned i = 0; i < ARRAY_SIZE(special); i++) { |
if (special[i]->file == GRF) |
remap_table[special[i]->reg] = 0; |
} |
/* Compact the GRF arrays. */ |
int new_index = 0; |
for (int i = 0; i < this->virtual_grf_count; i++) { |
if (remap_table[i] != -1) { |
remap_table[i] = new_index; |
virtual_grf_sizes[new_index] = virtual_grf_sizes[i]; |
if (live_intervals_valid) { |
virtual_grf_start[new_index] = virtual_grf_start[i]; |
virtual_grf_end[new_index] = virtual_grf_end[i]; |
} |
++new_index; |
} |
} |
this->virtual_grf_count = new_index; |
/* Patch all the instructions to use the newly renumbered registers */ |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *) node; |
if (inst->dst.file == GRF) |
inst->dst.reg = remap_table[inst->dst.reg]; |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) |
inst->src[i].reg = remap_table[inst->src[i].reg]; |
} |
} |
/* Patch all the references to special values */ |
for (unsigned i = 0; i < ARRAY_SIZE(special); i++) { |
if (special[i]->file == GRF && remap_table[special[i]->reg] != -1) |
special[i]->reg = remap_table[special[i]->reg]; |
} |
} |
bool |
fs_visitor::remove_dead_constants() |
{ |
if (dispatch_width == 8) { |
this->params_remap = ralloc_array(mem_ctx, int, c->prog_data.nr_params); |
this->nr_params_remap = c->prog_data.nr_params; |
for (unsigned int i = 0; i < c->prog_data.nr_params; i++) |
this->params_remap[i] = -1; |
/* Find which params are still in use. */ |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
for (int i = 0; i < 3; i++) { |
int constant_nr = inst->src[i].reg + inst->src[i].reg_offset; |
if (inst->src[i].file != UNIFORM) |
continue; |
/* Section 5.11 of the OpenGL 4.3 spec says: |
* |
* "Out-of-bounds reads return undefined values, which include |
* values from other variables of the active program or zero." |
*/ |
if (constant_nr < 0 || constant_nr >= (int)c->prog_data.nr_params) { |
constant_nr = 0; |
} |
/* For now, set this to non-negative. We'll give it the |
* actual new number in a moment, in order to keep the |
* register numbers nicely ordered. |
*/ |
this->params_remap[constant_nr] = 0; |
} |
} |
/* Figure out what the new numbers for the params will be. At some |
* point when we're doing uniform array access, we're going to want |
* to keep the distinction between .reg and .reg_offset, but for |
* now we don't care. |
*/ |
unsigned int new_nr_params = 0; |
for (unsigned int i = 0; i < c->prog_data.nr_params; i++) { |
if (this->params_remap[i] != -1) { |
this->params_remap[i] = new_nr_params++; |
} |
} |
/* Update the list of params to be uploaded to match our new numbering. */ |
for (unsigned int i = 0; i < c->prog_data.nr_params; i++) { |
int remapped = this->params_remap[i]; |
if (remapped == -1) |
continue; |
c->prog_data.param[remapped] = c->prog_data.param[i]; |
} |
c->prog_data.nr_params = new_nr_params; |
} else { |
/* This should have been generated in the 8-wide pass already. */ |
assert(this->params_remap); |
} |
/* Now do the renumbering of the shader to remove unused params. */ |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
for (int i = 0; i < 3; i++) { |
int constant_nr = inst->src[i].reg + inst->src[i].reg_offset; |
if (inst->src[i].file != UNIFORM) |
continue; |
/* as above alias to 0 */ |
if (constant_nr < 0 || constant_nr >= (int)this->nr_params_remap) { |
constant_nr = 0; |
} |
assert(this->params_remap[constant_nr] != -1); |
inst->src[i].reg = this->params_remap[constant_nr]; |
inst->src[i].reg_offset = 0; |
} |
} |
return true; |
} |
/* |
* Implements array access of uniforms by inserting a |
* PULL_CONSTANT_LOAD instruction. |
* |
* Unlike temporary GRF array access (where we don't support it due to |
* the difficulty of doing relative addressing on instruction |
* destinations), we could potentially do array access of uniforms |
* that were loaded in GRF space as push constants. In real-world |
* usage we've seen, though, the arrays being used are always larger |
* than we could load as push constants, so just always move all |
* uniform array access out to a pull constant buffer. |
*/ |
void |
fs_visitor::move_uniform_array_access_to_pull_constants() |
{ |
int pull_constant_loc[c->prog_data.nr_params]; |
for (unsigned int i = 0; i < c->prog_data.nr_params; i++) { |
pull_constant_loc[i] = -1; |
} |
/* Walk through and find array access of uniforms. Put a copy of that |
* uniform in the pull constant buffer. |
* |
* Note that we don't move constant-indexed accesses to arrays. No |
* testing has been done of the performance impact of this choice. |
*/ |
foreach_list_safe(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
for (int i = 0 ; i < 3; i++) { |
if (inst->src[i].file != UNIFORM || !inst->src[i].reladdr) |
continue; |
int uniform = inst->src[i].reg; |
/* If this array isn't already present in the pull constant buffer, |
* add it. |
*/ |
if (pull_constant_loc[uniform] == -1) { |
const float **values = &c->prog_data.param[uniform]; |
pull_constant_loc[uniform] = c->prog_data.nr_pull_params; |
assert(param_size[uniform]); |
for (int j = 0; j < param_size[uniform]; j++) { |
c->prog_data.pull_param[c->prog_data.nr_pull_params++] = |
values[j]; |
} |
} |
/* Set up the annotation tracking for new generated instructions. */ |
base_ir = inst->ir; |
current_annotation = inst->annotation; |
fs_reg surf_index = fs_reg((unsigned)SURF_INDEX_FRAG_CONST_BUFFER); |
fs_reg temp = fs_reg(this, glsl_type::float_type); |
exec_list list = VARYING_PULL_CONSTANT_LOAD(temp, |
surf_index, |
*inst->src[i].reladdr, |
pull_constant_loc[uniform] + |
inst->src[i].reg_offset); |
inst->insert_before(&list); |
inst->src[i].file = temp.file; |
inst->src[i].reg = temp.reg; |
inst->src[i].reg_offset = temp.reg_offset; |
inst->src[i].reladdr = NULL; |
} |
} |
} |
/** |
* Choose accesses from the UNIFORM file to demote to using the pull |
* constant buffer. |
* |
* We allow a fragment shader to have more than the specified minimum |
* maximum number of fragment shader uniform components (64). If |
* there are too many of these, they'd fill up all of register space. |
* So, this will push some of them out to the pull constant buffer and |
* update the program to load them. |
*/ |
void |
fs_visitor::setup_pull_constants() |
{ |
/* Only allow 16 registers (128 uniform components) as push constants. */ |
unsigned int max_uniform_components = 16 * 8; |
if (c->prog_data.nr_params <= max_uniform_components) |
return; |
if (dispatch_width == 16) { |
fail("Pull constants not supported in 16-wide\n"); |
return; |
} |
/* Just demote the end of the list. We could probably do better |
* here, demoting things that are rarely used in the program first. |
*/ |
unsigned int pull_uniform_base = max_uniform_components; |
int pull_constant_loc[c->prog_data.nr_params]; |
for (unsigned int i = 0; i < c->prog_data.nr_params; i++) { |
if (i < pull_uniform_base) { |
pull_constant_loc[i] = -1; |
} else { |
pull_constant_loc[i] = -1; |
/* If our constant is already being uploaded for reladdr purposes, |
* reuse it. |
*/ |
for (unsigned int j = 0; j < c->prog_data.nr_pull_params; j++) { |
if (c->prog_data.pull_param[j] == c->prog_data.param[i]) { |
pull_constant_loc[i] = j; |
break; |
} |
} |
if (pull_constant_loc[i] == -1) { |
int pull_index = c->prog_data.nr_pull_params++; |
c->prog_data.pull_param[pull_index] = c->prog_data.param[i]; |
pull_constant_loc[i] = pull_index;; |
} |
} |
} |
c->prog_data.nr_params = pull_uniform_base; |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file != UNIFORM) |
continue; |
int pull_index = pull_constant_loc[inst->src[i].reg + |
inst->src[i].reg_offset]; |
if (pull_index == -1) |
continue; |
assert(!inst->src[i].reladdr); |
fs_reg dst = fs_reg(this, glsl_type::float_type); |
fs_reg index = fs_reg((unsigned)SURF_INDEX_FRAG_CONST_BUFFER); |
fs_reg offset = fs_reg((unsigned)(pull_index * 4) & ~15); |
fs_inst *pull = |
new(mem_ctx) fs_inst(FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD, |
dst, index, offset); |
pull->ir = inst->ir; |
pull->annotation = inst->annotation; |
inst->insert_before(pull); |
inst->src[i].file = GRF; |
inst->src[i].reg = dst.reg; |
inst->src[i].reg_offset = 0; |
inst->src[i].smear = pull_index & 3; |
} |
} |
} |
bool |
fs_visitor::opt_algebraic() |
{ |
bool progress = false; |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
switch (inst->opcode) { |
case BRW_OPCODE_MUL: |
if (inst->src[1].file != IMM) |
continue; |
/* a * 1.0 = a */ |
if (inst->src[1].is_one()) { |
inst->opcode = BRW_OPCODE_MOV; |
inst->src[1] = reg_undef; |
progress = true; |
break; |
} |
/* a * 0.0 = 0.0 */ |
if (inst->src[1].is_zero()) { |
inst->opcode = BRW_OPCODE_MOV; |
inst->src[0] = inst->src[1]; |
inst->src[1] = reg_undef; |
progress = true; |
break; |
} |
break; |
case BRW_OPCODE_ADD: |
if (inst->src[1].file != IMM) |
continue; |
/* a + 0.0 = a */ |
if (inst->src[1].is_zero()) { |
inst->opcode = BRW_OPCODE_MOV; |
inst->src[1] = reg_undef; |
progress = true; |
break; |
} |
break; |
default: |
break; |
} |
} |
return progress; |
} |
/** |
* Removes any instructions writing a VGRF where that VGRF is not used by any |
* later instruction. |
*/ |
bool |
fs_visitor::dead_code_eliminate() |
{ |
bool progress = false; |
int pc = 0; |
calculate_live_intervals(); |
foreach_list_safe(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
if (inst->dst.file == GRF) { |
assert(this->virtual_grf_end[inst->dst.reg] >= pc); |
if (this->virtual_grf_end[inst->dst.reg] == pc) { |
inst->remove(); |
progress = true; |
} |
} |
pc++; |
} |
if (progress) |
live_intervals_valid = false; |
return progress; |
} |
struct dead_code_hash_key |
{ |
int vgrf; |
int reg_offset; |
}; |
static bool |
dead_code_hash_compare(const void *a, const void *b) |
{ |
return memcmp(a, b, sizeof(struct dead_code_hash_key)) == 0; |
} |
static void |
clear_dead_code_hash(struct hash_table *ht) |
{ |
struct hash_entry *entry; |
hash_table_foreach(ht, entry) { |
_mesa_hash_table_remove(ht, entry); |
} |
} |
static void |
insert_dead_code_hash(struct hash_table *ht, |
int vgrf, int reg_offset, fs_inst *inst) |
{ |
/* We don't bother freeing keys, because they'll be GCed with the ht. */ |
struct dead_code_hash_key *key = ralloc(ht, struct dead_code_hash_key); |
key->vgrf = vgrf; |
key->reg_offset = reg_offset; |
_mesa_hash_table_insert(ht, _mesa_hash_data(key, sizeof(*key)), key, inst); |
} |
static struct hash_entry * |
get_dead_code_hash_entry(struct hash_table *ht, int vgrf, int reg_offset) |
{ |
struct dead_code_hash_key key; |
key.vgrf = vgrf; |
key.reg_offset = reg_offset; |
return _mesa_hash_table_search(ht, _mesa_hash_data(&key, sizeof(key)), &key); |
} |
static void |
remove_dead_code_hash(struct hash_table *ht, |
int vgrf, int reg_offset) |
{ |
struct hash_entry *entry = get_dead_code_hash_entry(ht, vgrf, reg_offset); |
if (!entry) |
return; |
_mesa_hash_table_remove(ht, entry); |
} |
/** |
* Walks basic blocks, removing any regs that are written but not read before |
* being redefined. |
* |
* The dead_code_eliminate() function implements a global dead code |
* elimination, but it only handles the removing the last write to a register |
* if it's never read. This one can handle intermediate writes, but only |
* within a basic block. |
*/ |
bool |
fs_visitor::dead_code_eliminate_local() |
{ |
struct hash_table *ht; |
bool progress = false; |
ht = _mesa_hash_table_create(mem_ctx, dead_code_hash_compare); |
foreach_list_safe(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
/* At a basic block, empty the HT since we don't understand dataflow |
* here. |
*/ |
if (inst->is_control_flow()) { |
clear_dead_code_hash(ht); |
continue; |
} |
/* Clear the HT of any instructions that got read. */ |
for (int i = 0; i < 3; i++) { |
fs_reg src = inst->src[i]; |
if (src.file != GRF) |
continue; |
int read = 1; |
if (inst->is_send_from_grf()) |
read = virtual_grf_sizes[src.reg] - src.reg_offset; |
for (int reg_offset = src.reg_offset; |
reg_offset < src.reg_offset + read; |
reg_offset++) { |
remove_dead_code_hash(ht, src.reg, reg_offset); |
} |
} |
/* Add any update of a GRF to the HT, removing a previous write if it |
* wasn't read. |
*/ |
if (inst->dst.file == GRF) { |
if (inst->regs_written > 1) { |
/* We don't know how to trim channels from an instruction's |
* writes, so we can't incrementally remove unread channels from |
* it. Just remove whatever it overwrites from the table |
*/ |
for (int i = 0; i < inst->regs_written; i++) { |
remove_dead_code_hash(ht, |
inst->dst.reg, |
inst->dst.reg_offset + i); |
} |
} else { |
struct hash_entry *entry = |
get_dead_code_hash_entry(ht, inst->dst.reg, |
inst->dst.reg_offset); |
if (inst->is_partial_write()) { |
/* For a partial write, we can't remove any previous dead code |
* candidate, since we're just modifying their result, but we can |
* be dead code eliminiated ourselves. |
*/ |
if (entry) { |
entry->data = inst; |
} else { |
insert_dead_code_hash(ht, inst->dst.reg, inst->dst.reg_offset, |
inst); |
} |
} else { |
if (entry) { |
/* We're completely updating a channel, and there was a |
* previous write to the channel that wasn't read. Kill it! |
*/ |
fs_inst *inst = (fs_inst *)entry->data; |
inst->remove(); |
progress = true; |
_mesa_hash_table_remove(ht, entry); |
} |
insert_dead_code_hash(ht, inst->dst.reg, inst->dst.reg_offset, |
inst); |
} |
} |
} |
} |
_mesa_hash_table_destroy(ht, NULL); |
if (progress) |
live_intervals_valid = false; |
return progress; |
} |
/** |
* Implements a second type of register coalescing: This one checks if |
* the two regs involved in a raw move don't interfere, in which case |
* they can both by stored in the same place and the MOV removed. |
*/ |
bool |
fs_visitor::register_coalesce_2() |
{ |
bool progress = false; |
calculate_live_intervals(); |
foreach_list_safe(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
if (inst->opcode != BRW_OPCODE_MOV || |
inst->is_partial_write() || |
inst->saturate || |
inst->src[0].file != GRF || |
inst->src[0].negate || |
inst->src[0].abs || |
inst->src[0].smear != -1 || |
inst->dst.file != GRF || |
inst->dst.type != inst->src[0].type || |
virtual_grf_sizes[inst->src[0].reg] != 1 || |
virtual_grf_interferes(inst->dst.reg, inst->src[0].reg)) { |
continue; |
} |
int reg_from = inst->src[0].reg; |
assert(inst->src[0].reg_offset == 0); |
int reg_to = inst->dst.reg; |
int reg_to_offset = inst->dst.reg_offset; |
foreach_list(node, &this->instructions) { |
fs_inst *scan_inst = (fs_inst *)node; |
if (scan_inst->dst.file == GRF && |
scan_inst->dst.reg == reg_from) { |
scan_inst->dst.reg = reg_to; |
scan_inst->dst.reg_offset = reg_to_offset; |
} |
for (int i = 0; i < 3; i++) { |
if (scan_inst->src[i].file == GRF && |
scan_inst->src[i].reg == reg_from) { |
scan_inst->src[i].reg = reg_to; |
scan_inst->src[i].reg_offset = reg_to_offset; |
} |
} |
} |
inst->remove(); |
/* We don't need to recalculate live intervals inside the loop despite |
* flagging live_intervals_valid because we only use live intervals for |
* the interferes test, and we must have had a situation where the |
* intervals were: |
* |
* from to |
* ^ |
* | |
* v |
* ^ |
* | |
* v |
* |
* Some register R that might get coalesced with one of these two could |
* only be referencing "to", otherwise "from"'s range would have been |
* longer. R's range could also only start at the end of "to" or later, |
* otherwise it will conflict with "to" when we try to coalesce "to" |
* into Rw anyway. |
*/ |
live_intervals_valid = false; |
progress = true; |
continue; |
} |
return progress; |
} |
bool |
fs_visitor::register_coalesce() |
{ |
bool progress = false; |
int if_depth = 0; |
int loop_depth = 0; |
foreach_list_safe(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
/* Make sure that we dominate the instructions we're going to |
* scan for interfering with our coalescing, or we won't have |
* scanned enough to see if anything interferes with our |
* coalescing. We don't dominate the following instructions if |
* we're in a loop or an if block. |
*/ |
switch (inst->opcode) { |
case BRW_OPCODE_DO: |
loop_depth++; |
break; |
case BRW_OPCODE_WHILE: |
loop_depth--; |
break; |
case BRW_OPCODE_IF: |
if_depth++; |
break; |
case BRW_OPCODE_ENDIF: |
if_depth--; |
break; |
default: |
break; |
} |
if (loop_depth || if_depth) |
continue; |
if (inst->opcode != BRW_OPCODE_MOV || |
inst->is_partial_write() || |
inst->saturate || |
inst->dst.file != GRF || (inst->src[0].file != GRF && |
inst->src[0].file != UNIFORM)|| |
inst->dst.type != inst->src[0].type) |
continue; |
bool has_source_modifiers = (inst->src[0].abs || |
inst->src[0].negate || |
inst->src[0].smear != -1 || |
inst->src[0].file == UNIFORM); |
/* Found a move of a GRF to a GRF. Let's see if we can coalesce |
* them: check for no writes to either one until the exit of the |
* program. |
*/ |
bool interfered = false; |
for (fs_inst *scan_inst = (fs_inst *)inst->next; |
!scan_inst->is_tail_sentinel(); |
scan_inst = (fs_inst *)scan_inst->next) { |
if (scan_inst->dst.file == GRF) { |
if (scan_inst->overwrites_reg(inst->dst) || |
scan_inst->overwrites_reg(inst->src[0])) { |
interfered = true; |
break; |
} |
} |
if (has_source_modifiers) { |
for (int i = 0; i < 3; i++) { |
if (scan_inst->src[i].file == GRF && |
scan_inst->src[i].reg == inst->dst.reg && |
scan_inst->src[i].reg_offset == inst->dst.reg_offset && |
inst->dst.type != scan_inst->src[i].type) |
{ |
interfered = true; |
break; |
} |
} |
} |
/* The gen6 MATH instruction can't handle source modifiers or |
* unusual register regions, so avoid coalescing those for |
* now. We should do something more specific. |
*/ |
if (has_source_modifiers && !can_do_source_mods(scan_inst)) { |
interfered = true; |
break; |
} |
/* The accumulator result appears to get used for the |
* conditional modifier generation. When negating a UD |
* value, there is a 33rd bit generated for the sign in the |
* accumulator value, so now you can't check, for example, |
* equality with a 32-bit value. See piglit fs-op-neg-uint. |
*/ |
if (scan_inst->conditional_mod && |
inst->src[0].negate && |
inst->src[0].type == BRW_REGISTER_TYPE_UD) { |
interfered = true; |
break; |
} |
} |
if (interfered) { |
continue; |
} |
/* Rewrite the later usage to point at the source of the move to |
* be removed. |
*/ |
for (fs_inst *scan_inst = inst; |
!scan_inst->is_tail_sentinel(); |
scan_inst = (fs_inst *)scan_inst->next) { |
for (int i = 0; i < 3; i++) { |
if (scan_inst->src[i].file == GRF && |
scan_inst->src[i].reg == inst->dst.reg && |
scan_inst->src[i].reg_offset == inst->dst.reg_offset) { |
fs_reg new_src = inst->src[0]; |
if (scan_inst->src[i].abs) { |
new_src.negate = 0; |
new_src.abs = 1; |
} |
new_src.negate ^= scan_inst->src[i].negate; |
scan_inst->src[i] = new_src; |
} |
} |
} |
inst->remove(); |
progress = true; |
} |
if (progress) |
live_intervals_valid = false; |
return progress; |
} |
bool |
fs_visitor::compute_to_mrf() |
{ |
bool progress = false; |
int next_ip = 0; |
calculate_live_intervals(); |
foreach_list_safe(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
int ip = next_ip; |
next_ip++; |
if (inst->opcode != BRW_OPCODE_MOV || |
inst->is_partial_write() || |
inst->dst.file != MRF || inst->src[0].file != GRF || |
inst->dst.type != inst->src[0].type || |
inst->src[0].abs || inst->src[0].negate || inst->src[0].smear != -1) |
continue; |
/* Work out which hardware MRF registers are written by this |
* instruction. |
*/ |
int mrf_low = inst->dst.reg & ~BRW_MRF_COMPR4; |
int mrf_high; |
if (inst->dst.reg & BRW_MRF_COMPR4) { |
mrf_high = mrf_low + 4; |
} else if (dispatch_width == 16 && |
(!inst->force_uncompressed && !inst->force_sechalf)) { |
mrf_high = mrf_low + 1; |
} else { |
mrf_high = mrf_low; |
} |
/* Can't compute-to-MRF this GRF if someone else was going to |
* read it later. |
*/ |
if (this->virtual_grf_end[inst->src[0].reg] > ip) |
continue; |
/* Found a move of a GRF to a MRF. Let's see if we can go |
* rewrite the thing that made this GRF to write into the MRF. |
*/ |
fs_inst *scan_inst; |
for (scan_inst = (fs_inst *)inst->prev; |
scan_inst->prev != NULL; |
scan_inst = (fs_inst *)scan_inst->prev) { |
if (scan_inst->dst.file == GRF && |
scan_inst->dst.reg == inst->src[0].reg) { |
/* Found the last thing to write our reg we want to turn |
* into a compute-to-MRF. |
*/ |
/* If this one instruction didn't populate all the |
* channels, bail. We might be able to rewrite everything |
* that writes that reg, but it would require smarter |
* tracking to delay the rewriting until complete success. |
*/ |
if (scan_inst->is_partial_write()) |
break; |
/* Things returning more than one register would need us to |
* understand coalescing out more than one MOV at a time. |
*/ |
if (scan_inst->regs_written > 1) |
break; |
/* SEND instructions can't have MRF as a destination. */ |
if (scan_inst->mlen) |
break; |
if (brw->gen == 6) { |
/* gen6 math instructions must have the destination be |
* GRF, so no compute-to-MRF for them. |
*/ |
if (scan_inst->is_math()) { |
break; |
} |
} |
if (scan_inst->dst.reg_offset == inst->src[0].reg_offset) { |
/* Found the creator of our MRF's source value. */ |
scan_inst->dst.file = MRF; |
scan_inst->dst.reg = inst->dst.reg; |
scan_inst->saturate |= inst->saturate; |
inst->remove(); |
progress = true; |
} |
break; |
} |
/* We don't handle control flow here. Most computation of |
* values that end up in MRFs are shortly before the MRF |
* write anyway. |
*/ |
if (scan_inst->is_control_flow() && scan_inst->opcode != BRW_OPCODE_IF) |
break; |
/* You can't read from an MRF, so if someone else reads our |
* MRF's source GRF that we wanted to rewrite, that stops us. |
*/ |
bool interfered = false; |
for (int i = 0; i < 3; i++) { |
if (scan_inst->src[i].file == GRF && |
scan_inst->src[i].reg == inst->src[0].reg && |
scan_inst->src[i].reg_offset == inst->src[0].reg_offset) { |
interfered = true; |
} |
} |
if (interfered) |
break; |
if (scan_inst->dst.file == MRF) { |
/* If somebody else writes our MRF here, we can't |
* compute-to-MRF before that. |
*/ |
int scan_mrf_low = scan_inst->dst.reg & ~BRW_MRF_COMPR4; |
int scan_mrf_high; |
if (scan_inst->dst.reg & BRW_MRF_COMPR4) { |
scan_mrf_high = scan_mrf_low + 4; |
} else if (dispatch_width == 16 && |
(!scan_inst->force_uncompressed && |
!scan_inst->force_sechalf)) { |
scan_mrf_high = scan_mrf_low + 1; |
} else { |
scan_mrf_high = scan_mrf_low; |
} |
if (mrf_low == scan_mrf_low || |
mrf_low == scan_mrf_high || |
mrf_high == scan_mrf_low || |
mrf_high == scan_mrf_high) { |
break; |
} |
} |
if (scan_inst->mlen > 0) { |
/* Found a SEND instruction, which means that there are |
* live values in MRFs from base_mrf to base_mrf + |
* scan_inst->mlen - 1. Don't go pushing our MRF write up |
* above it. |
*/ |
if (mrf_low >= scan_inst->base_mrf && |
mrf_low < scan_inst->base_mrf + scan_inst->mlen) { |
break; |
} |
if (mrf_high >= scan_inst->base_mrf && |
mrf_high < scan_inst->base_mrf + scan_inst->mlen) { |
break; |
} |
} |
} |
} |
if (progress) |
live_intervals_valid = false; |
return progress; |
} |
/** |
* Walks through basic blocks, looking for repeated MRF writes and |
* removing the later ones. |
*/ |
bool |
fs_visitor::remove_duplicate_mrf_writes() |
{ |
fs_inst *last_mrf_move[16]; |
bool progress = false; |
/* Need to update the MRF tracking for compressed instructions. */ |
if (dispatch_width == 16) |
return false; |
memset(last_mrf_move, 0, sizeof(last_mrf_move)); |
foreach_list_safe(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
if (inst->is_control_flow()) { |
memset(last_mrf_move, 0, sizeof(last_mrf_move)); |
} |
if (inst->opcode == BRW_OPCODE_MOV && |
inst->dst.file == MRF) { |
fs_inst *prev_inst = last_mrf_move[inst->dst.reg]; |
if (prev_inst && inst->equals(prev_inst)) { |
inst->remove(); |
progress = true; |
continue; |
} |
} |
/* Clear out the last-write records for MRFs that were overwritten. */ |
if (inst->dst.file == MRF) { |
last_mrf_move[inst->dst.reg] = NULL; |
} |
if (inst->mlen > 0) { |
/* Found a SEND instruction, which will include two or fewer |
* implied MRF writes. We could do better here. |
*/ |
for (int i = 0; i < implied_mrf_writes(inst); i++) { |
last_mrf_move[inst->base_mrf + i] = NULL; |
} |
} |
/* Clear out any MRF move records whose sources got overwritten. */ |
if (inst->dst.file == GRF) { |
for (unsigned int i = 0; i < Elements(last_mrf_move); i++) { |
if (last_mrf_move[i] && |
last_mrf_move[i]->src[0].reg == inst->dst.reg) { |
last_mrf_move[i] = NULL; |
} |
} |
} |
if (inst->opcode == BRW_OPCODE_MOV && |
inst->dst.file == MRF && |
inst->src[0].file == GRF && |
!inst->is_partial_write()) { |
last_mrf_move[inst->dst.reg] = inst; |
} |
} |
if (progress) |
live_intervals_valid = false; |
return progress; |
} |
static void |
clear_deps_for_inst_src(fs_inst *inst, int dispatch_width, bool *deps, |
int first_grf, int grf_len) |
{ |
bool inst_16wide = (dispatch_width > 8 && |
!inst->force_uncompressed && |
!inst->force_sechalf); |
/* Clear the flag for registers that actually got read (as expected). */ |
for (int i = 0; i < 3; i++) { |
int grf; |
if (inst->src[i].file == GRF) { |
grf = inst->src[i].reg; |
} else if (inst->src[i].file == HW_REG && |
inst->src[i].fixed_hw_reg.file == BRW_GENERAL_REGISTER_FILE) { |
grf = inst->src[i].fixed_hw_reg.nr; |
} else { |
continue; |
} |
if (grf >= first_grf && |
grf < first_grf + grf_len) { |
deps[grf - first_grf] = false; |
if (inst_16wide) |
deps[grf - first_grf + 1] = false; |
} |
} |
} |
/** |
* Implements this workaround for the original 965: |
* |
* "[DevBW, DevCL] Implementation Restrictions: As the hardware does not |
* check for post destination dependencies on this instruction, software |
* must ensure that there is no destination hazard for the case of ‘write |
* followed by a posted write’ shown in the following example. |
* |
* 1. mov r3 0 |
* 2. send r3.xy <rest of send instruction> |
* 3. mov r2 r3 |
* |
* Due to no post-destination dependency check on the ‘send’, the above |
* code sequence could have two instructions (1 and 2) in flight at the |
* same time that both consider ‘r3’ as the target of their final writes. |
*/ |
void |
fs_visitor::insert_gen4_pre_send_dependency_workarounds(fs_inst *inst) |
{ |
int reg_size = dispatch_width / 8; |
int write_len = inst->regs_written * reg_size; |
int first_write_grf = inst->dst.reg; |
bool needs_dep[BRW_MAX_MRF]; |
assert(write_len < (int)sizeof(needs_dep) - 1); |
memset(needs_dep, false, sizeof(needs_dep)); |
memset(needs_dep, true, write_len); |
clear_deps_for_inst_src(inst, dispatch_width, |
needs_dep, first_write_grf, write_len); |
/* Walk backwards looking for writes to registers we're writing which |
* aren't read since being written. If we hit the start of the program, |
* we assume that there are no outstanding dependencies on entry to the |
* program. |
*/ |
for (fs_inst *scan_inst = (fs_inst *)inst->prev; |
scan_inst != NULL; |
scan_inst = (fs_inst *)scan_inst->prev) { |
/* If we hit control flow, assume that there *are* outstanding |
* dependencies, and force their cleanup before our instruction. |
*/ |
if (scan_inst->is_control_flow()) { |
for (int i = 0; i < write_len; i++) { |
if (needs_dep[i]) { |
inst->insert_before(DEP_RESOLVE_MOV(first_write_grf + i)); |
} |
} |
return; |
} |
bool scan_inst_16wide = (dispatch_width > 8 && |
!scan_inst->force_uncompressed && |
!scan_inst->force_sechalf); |
/* We insert our reads as late as possible on the assumption that any |
* instruction but a MOV that might have left us an outstanding |
* dependency has more latency than a MOV. |
*/ |
if (scan_inst->dst.file == GRF) { |
for (int i = 0; i < scan_inst->regs_written; i++) { |
int reg = scan_inst->dst.reg + i * reg_size; |
if (reg >= first_write_grf && |
reg < first_write_grf + write_len && |
needs_dep[reg - first_write_grf]) { |
inst->insert_before(DEP_RESOLVE_MOV(reg)); |
needs_dep[reg - first_write_grf] = false; |
if (scan_inst_16wide) |
needs_dep[reg - first_write_grf + 1] = false; |
} |
} |
} |
/* Clear the flag for registers that actually got read (as expected). */ |
clear_deps_for_inst_src(scan_inst, dispatch_width, |
needs_dep, first_write_grf, write_len); |
/* Continue the loop only if we haven't resolved all the dependencies */ |
int i; |
for (i = 0; i < write_len; i++) { |
if (needs_dep[i]) |
break; |
} |
if (i == write_len) |
return; |
} |
} |
/** |
* Implements this workaround for the original 965: |
* |
* "[DevBW, DevCL] Errata: A destination register from a send can not be |
* used as a destination register until after it has been sourced by an |
* instruction with a different destination register. |
*/ |
void |
fs_visitor::insert_gen4_post_send_dependency_workarounds(fs_inst *inst) |
{ |
int write_len = inst->regs_written * dispatch_width / 8; |
int first_write_grf = inst->dst.reg; |
bool needs_dep[BRW_MAX_MRF]; |
assert(write_len < (int)sizeof(needs_dep) - 1); |
memset(needs_dep, false, sizeof(needs_dep)); |
memset(needs_dep, true, write_len); |
/* Walk forwards looking for writes to registers we're writing which aren't |
* read before being written. |
*/ |
for (fs_inst *scan_inst = (fs_inst *)inst->next; |
!scan_inst->is_tail_sentinel(); |
scan_inst = (fs_inst *)scan_inst->next) { |
/* If we hit control flow, force resolve all remaining dependencies. */ |
if (scan_inst->is_control_flow()) { |
for (int i = 0; i < write_len; i++) { |
if (needs_dep[i]) |
scan_inst->insert_before(DEP_RESOLVE_MOV(first_write_grf + i)); |
} |
return; |
} |
/* Clear the flag for registers that actually got read (as expected). */ |
clear_deps_for_inst_src(scan_inst, dispatch_width, |
needs_dep, first_write_grf, write_len); |
/* We insert our reads as late as possible since they're reading the |
* result of a SEND, which has massive latency. |
*/ |
if (scan_inst->dst.file == GRF && |
scan_inst->dst.reg >= first_write_grf && |
scan_inst->dst.reg < first_write_grf + write_len && |
needs_dep[scan_inst->dst.reg - first_write_grf]) { |
scan_inst->insert_before(DEP_RESOLVE_MOV(scan_inst->dst.reg)); |
needs_dep[scan_inst->dst.reg - first_write_grf] = false; |
} |
/* Continue the loop only if we haven't resolved all the dependencies */ |
int i; |
for (i = 0; i < write_len; i++) { |
if (needs_dep[i]) |
break; |
} |
if (i == write_len) |
return; |
} |
/* If we hit the end of the program, resolve all remaining dependencies out |
* of paranoia. |
*/ |
fs_inst *last_inst = (fs_inst *)this->instructions.get_tail(); |
assert(last_inst->eot); |
for (int i = 0; i < write_len; i++) { |
if (needs_dep[i]) |
last_inst->insert_before(DEP_RESOLVE_MOV(first_write_grf + i)); |
} |
} |
void |
fs_visitor::insert_gen4_send_dependency_workarounds() |
{ |
if (brw->gen != 4 || brw->is_g4x) |
return; |
/* Note that we're done with register allocation, so GRF fs_regs always |
* have a .reg_offset of 0. |
*/ |
foreach_list_safe(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
if (inst->mlen != 0 && inst->dst.file == GRF) { |
insert_gen4_pre_send_dependency_workarounds(inst); |
insert_gen4_post_send_dependency_workarounds(inst); |
} |
} |
} |
/** |
* Turns the generic expression-style uniform pull constant load instruction |
* into a hardware-specific series of instructions for loading a pull |
* constant. |
* |
* The expression style allows the CSE pass before this to optimize out |
* repeated loads from the same offset, and gives the pre-register-allocation |
* scheduling full flexibility, while the conversion to native instructions |
* allows the post-register-allocation scheduler the best information |
* possible. |
* |
* Note that execution masking for setting up pull constant loads is special: |
* the channels that need to be written are unrelated to the current execution |
* mask, since a later instruction will use one of the result channels as a |
* source operand for all 8 or 16 of its channels. |
*/ |
void |
fs_visitor::lower_uniform_pull_constant_loads() |
{ |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
if (inst->opcode != FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD) |
continue; |
if (brw->gen >= 7) { |
/* The offset arg before was a vec4-aligned byte offset. We need to |
* turn it into a dword offset. |
*/ |
fs_reg const_offset_reg = inst->src[1]; |
assert(const_offset_reg.file == IMM && |
const_offset_reg.type == BRW_REGISTER_TYPE_UD); |
const_offset_reg.imm.u /= 4; |
fs_reg payload = fs_reg(this, glsl_type::uint_type); |
/* This is actually going to be a MOV, but since only the first dword |
* is accessed, we have a special opcode to do just that one. Note |
* that this needs to be an operation that will be considered a def |
* by live variable analysis, or register allocation will explode. |
*/ |
fs_inst *setup = new(mem_ctx) fs_inst(FS_OPCODE_SET_SIMD4X2_OFFSET, |
payload, const_offset_reg); |
setup->force_writemask_all = true; |
setup->ir = inst->ir; |
setup->annotation = inst->annotation; |
inst->insert_before(setup); |
/* Similarly, this will only populate the first 4 channels of the |
* result register (since we only use smear values from 0-3), but we |
* don't tell the optimizer. |
*/ |
inst->opcode = FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD_GEN7; |
inst->src[1] = payload; |
this->live_intervals_valid = false; |
} else { |
/* Before register allocation, we didn't tell the scheduler about the |
* MRF we use. We know it's safe to use this MRF because nothing |
* else does except for register spill/unspill, which generates and |
* uses its MRF within a single IR instruction. |
*/ |
inst->base_mrf = 14; |
inst->mlen = 1; |
} |
} |
} |
void |
fs_visitor::dump_instruction(backend_instruction *be_inst) |
{ |
fs_inst *inst = (fs_inst *)be_inst; |
if (inst->predicate) { |
printf("(%cf0.%d) ", |
inst->predicate_inverse ? '-' : '+', |
inst->flag_subreg); |
} |
printf("%s", brw_instruction_name(inst->opcode)); |
if (inst->saturate) |
printf(".sat"); |
if (inst->conditional_mod) { |
printf(".cmod"); |
if (!inst->predicate && |
(brw->gen < 5 || (inst->opcode != BRW_OPCODE_SEL && |
inst->opcode != BRW_OPCODE_IF && |
inst->opcode != BRW_OPCODE_WHILE))) { |
printf(".f0.%d\n", inst->flag_subreg); |
} |
} |
printf(" "); |
switch (inst->dst.file) { |
case GRF: |
printf("vgrf%d", inst->dst.reg); |
if (inst->dst.reg_offset) |
printf("+%d", inst->dst.reg_offset); |
break; |
case MRF: |
printf("m%d", inst->dst.reg); |
break; |
case BAD_FILE: |
printf("(null)"); |
break; |
case UNIFORM: |
printf("***u%d***", inst->dst.reg); |
break; |
default: |
printf("???"); |
break; |
} |
printf(", "); |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].negate) |
printf("-"); |
if (inst->src[i].abs) |
printf("|"); |
switch (inst->src[i].file) { |
case GRF: |
printf("vgrf%d", inst->src[i].reg); |
if (inst->src[i].reg_offset) |
printf("+%d", inst->src[i].reg_offset); |
break; |
case MRF: |
printf("***m%d***", inst->src[i].reg); |
break; |
case UNIFORM: |
printf("u%d", inst->src[i].reg); |
if (inst->src[i].reg_offset) |
printf(".%d", inst->src[i].reg_offset); |
break; |
case BAD_FILE: |
printf("(null)"); |
break; |
case IMM: |
switch (inst->src[i].type) { |
case BRW_REGISTER_TYPE_F: |
printf("%ff", inst->src[i].imm.f); |
break; |
case BRW_REGISTER_TYPE_D: |
printf("%dd", inst->src[i].imm.i); |
break; |
case BRW_REGISTER_TYPE_UD: |
printf("%uu", inst->src[i].imm.u); |
break; |
default: |
printf("???"); |
break; |
} |
break; |
default: |
printf("???"); |
break; |
} |
if (inst->src[i].abs) |
printf("|"); |
if (i < 3) |
printf(", "); |
} |
printf(" "); |
if (inst->force_uncompressed) |
printf("1sthalf "); |
if (inst->force_sechalf) |
printf("2ndhalf "); |
printf("\n"); |
} |
/** |
* Possibly returns an instruction that set up @param reg. |
* |
* Sometimes we want to take the result of some expression/variable |
* dereference tree and rewrite the instruction generating the result |
* of the tree. When processing the tree, we know that the |
* instructions generated are all writing temporaries that are dead |
* outside of this tree. So, if we have some instructions that write |
* a temporary, we're free to point that temp write somewhere else. |
* |
* Note that this doesn't guarantee that the instruction generated |
* only reg -- it might be the size=4 destination of a texture instruction. |
*/ |
fs_inst * |
fs_visitor::get_instruction_generating_reg(fs_inst *start, |
fs_inst *end, |
fs_reg reg) |
{ |
if (end == start || |
end->is_partial_write() || |
reg.reladdr || |
!reg.equals(end->dst)) { |
return NULL; |
} else { |
return end; |
} |
} |
void |
fs_visitor::setup_payload_gen6() |
{ |
bool uses_depth = |
(fp->Base.InputsRead & (1 << VARYING_SLOT_POS)) != 0; |
unsigned barycentric_interp_modes = c->prog_data.barycentric_interp_modes; |
assert(brw->gen >= 6); |
/* R0-1: masks, pixel X/Y coordinates. */ |
c->nr_payload_regs = 2; |
/* R2: only for 32-pixel dispatch.*/ |
/* R3-26: barycentric interpolation coordinates. These appear in the |
* same order that they appear in the brw_wm_barycentric_interp_mode |
* enum. Each set of coordinates occupies 2 registers if dispatch width |
* == 8 and 4 registers if dispatch width == 16. Coordinates only |
* appear if they were enabled using the "Barycentric Interpolation |
* Mode" bits in WM_STATE. |
*/ |
for (int i = 0; i < BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT; ++i) { |
if (barycentric_interp_modes & (1 << i)) { |
c->barycentric_coord_reg[i] = c->nr_payload_regs; |
c->nr_payload_regs += 2; |
if (dispatch_width == 16) { |
c->nr_payload_regs += 2; |
} |
} |
} |
/* R27: interpolated depth if uses source depth */ |
if (uses_depth) { |
c->source_depth_reg = c->nr_payload_regs; |
c->nr_payload_regs++; |
if (dispatch_width == 16) { |
/* R28: interpolated depth if not 8-wide. */ |
c->nr_payload_regs++; |
} |
} |
/* R29: interpolated W set if GEN6_WM_USES_SOURCE_W. */ |
if (uses_depth) { |
c->source_w_reg = c->nr_payload_regs; |
c->nr_payload_regs++; |
if (dispatch_width == 16) { |
/* R30: interpolated W if not 8-wide. */ |
c->nr_payload_regs++; |
} |
} |
/* R31: MSAA position offsets. */ |
/* R32-: bary for 32-pixel. */ |
/* R58-59: interp W for 32-pixel. */ |
if (fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { |
c->source_depth_to_render_target = true; |
} |
} |
bool |
fs_visitor::run() |
{ |
sanity_param_count = fp->Base.Parameters->NumParameters; |
uint32_t orig_nr_params = c->prog_data.nr_params; |
if (brw->gen >= 6) |
setup_payload_gen6(); |
else |
setup_payload_gen4(); |
if (0) { |
emit_dummy_fs(); |
} else { |
if (INTEL_DEBUG & DEBUG_SHADER_TIME) |
emit_shader_time_begin(); |
calculate_urb_setup(); |
if (brw->gen < 6) |
emit_interpolation_setup_gen4(); |
else |
emit_interpolation_setup_gen6(); |
/* We handle discards by keeping track of the still-live pixels in f0.1. |
* Initialize it with the dispatched pixels. |
*/ |
if (fp->UsesKill) { |
fs_inst *discard_init = emit(FS_OPCODE_MOV_DISPATCH_TO_FLAGS); |
discard_init->flag_subreg = 1; |
} |
/* Generate FS IR for main(). (the visitor only descends into |
* functions called "main"). |
*/ |
if (shader) { |
foreach_list(node, &*shader->ir) { |
ir_instruction *ir = (ir_instruction *)node; |
base_ir = ir; |
this->result = reg_undef; |
ir->accept(this); |
} |
} else { |
emit_fragment_program_code(); |
} |
base_ir = NULL; |
if (failed) |
return false; |
emit(FS_OPCODE_PLACEHOLDER_HALT); |
emit_fb_writes(); |
split_virtual_grfs(); |
move_uniform_array_access_to_pull_constants(); |
setup_pull_constants(); |
bool progress; |
do { |
progress = false; |
compact_virtual_grfs(); |
progress = remove_duplicate_mrf_writes() || progress; |
progress = opt_algebraic() || progress; |
progress = opt_cse() || progress; |
progress = opt_copy_propagate() || progress; |
progress = dead_code_eliminate() || progress; |
progress = dead_code_eliminate_local() || progress; |
progress = register_coalesce() || progress; |
progress = register_coalesce_2() || progress; |
progress = compute_to_mrf() || progress; |
} while (progress); |
remove_dead_constants(); |
schedule_instructions(false); |
lower_uniform_pull_constant_loads(); |
assign_curb_setup(); |
assign_urb_setup(); |
if (0) { |
/* Debug of register spilling: Go spill everything. */ |
for (int i = 0; i < virtual_grf_count; i++) { |
spill_reg(i); |
} |
} |
if (0) |
assign_regs_trivial(); |
else { |
while (!assign_regs()) { |
if (failed) |
break; |
} |
} |
} |
assert(force_uncompressed_stack == 0); |
assert(force_sechalf_stack == 0); |
/* This must come after all optimization and register allocation, since |
* it inserts dead code that happens to have side effects, and it does |
* so based on the actual physical registers in use. |
*/ |
insert_gen4_send_dependency_workarounds(); |
if (failed) |
return false; |
schedule_instructions(true); |
if (dispatch_width == 8) { |
c->prog_data.reg_blocks = brw_register_blocks(grf_used); |
} else { |
c->prog_data.reg_blocks_16 = brw_register_blocks(grf_used); |
/* Make sure we didn't try to sneak in an extra uniform */ |
assert(orig_nr_params == c->prog_data.nr_params); |
(void) orig_nr_params; |
} |
/* If any state parameters were appended, then ParameterValues could have |
* been realloced, in which case the driver uniform storage set up by |
* _mesa_associate_uniform_storage() would point to freed memory. Make |
* sure that didn't happen. |
*/ |
assert(sanity_param_count == fp->Base.Parameters->NumParameters); |
return !failed; |
} |
const unsigned * |
brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c, |
struct gl_fragment_program *fp, |
struct gl_shader_program *prog, |
unsigned *final_assembly_size) |
{ |
bool start_busy = false; |
float start_time = 0; |
if (unlikely(brw->perf_debug)) { |
start_busy = (brw->batch.last_bo && |
drm_intel_bo_busy(brw->batch.last_bo)); |
start_time = get_time(); |
} |
struct brw_shader *shader = NULL; |
if (prog) |
shader = (brw_shader *) prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; |
if (unlikely(INTEL_DEBUG & DEBUG_WM)) { |
if (prog) { |
printf("GLSL IR for native fragment shader %d:\n", prog->Name); |
_mesa_print_ir(shader->ir, NULL); |
printf("\n\n"); |
} else { |
printf("ARB_fragment_program %d ir for native fragment shader\n", |
fp->Base.Id); |
_mesa_print_program(&fp->Base); |
} |
} |
/* Now the main event: Visit the shader IR and generate our FS IR for it. |
*/ |
fs_visitor v(brw, c, prog, fp, 8); |
if (!v.run()) { |
if (prog) { |
prog->LinkStatus = false; |
ralloc_strcat(&prog->InfoLog, v.fail_msg); |
} |
_mesa_problem(NULL, "Failed to compile fragment shader: %s\n", |
v.fail_msg); |
return NULL; |
} |
exec_list *simd16_instructions = NULL; |
fs_visitor v2(brw, c, prog, fp, 16); |
bool no16 = INTEL_DEBUG & DEBUG_NO16; |
if (brw->gen >= 5 && c->prog_data.nr_pull_params == 0 && likely(!no16)) { |
v2.import_uniforms(&v); |
if (!v2.run()) { |
perf_debug("16-wide shader failed to compile, falling back to " |
"8-wide at a 10-20%% performance cost: %s", v2.fail_msg); |
} else { |
simd16_instructions = &v2.instructions; |
} |
} |
c->prog_data.dispatch_width = 8; |
fs_generator g(brw, c, prog, fp, v.dual_src_output.file != BAD_FILE); |
const unsigned *generated = g.generate_assembly(&v.instructions, |
simd16_instructions, |
final_assembly_size); |
if (unlikely(brw->perf_debug) && shader) { |
if (shader->compiled_once) |
brw_wm_debug_recompile(brw, prog, &c->key); |
shader->compiled_once = true; |
if (start_busy && !drm_intel_bo_busy(brw->batch.last_bo)) { |
perf_debug("FS compile took %.03f ms and stalled the GPU\n", |
(get_time() - start_time) * 1000); |
} |
} |
return generated; |
} |
bool |
brw_fs_precompile(struct gl_context *ctx, struct gl_shader_program *prog) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct brw_wm_prog_key key; |
if (!prog->_LinkedShaders[MESA_SHADER_FRAGMENT]) |
return true; |
struct gl_fragment_program *fp = (struct gl_fragment_program *) |
prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program; |
struct brw_fragment_program *bfp = brw_fragment_program(fp); |
bool program_uses_dfdy = fp->UsesDFdy; |
memset(&key, 0, sizeof(key)); |
if (brw->gen < 6) { |
if (fp->UsesKill) |
key.iz_lookup |= IZ_PS_KILL_ALPHATEST_BIT; |
if (fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) |
key.iz_lookup |= IZ_PS_COMPUTES_DEPTH_BIT; |
/* Just assume depth testing. */ |
key.iz_lookup |= IZ_DEPTH_TEST_ENABLE_BIT; |
key.iz_lookup |= IZ_DEPTH_WRITE_ENABLE_BIT; |
} |
if (brw->gen < 6) |
key.input_slots_valid |= BITFIELD64_BIT(VARYING_SLOT_POS); |
for (int i = 0; i < VARYING_SLOT_MAX; i++) { |
if (!(fp->Base.InputsRead & BITFIELD64_BIT(i))) |
continue; |
if (brw->gen < 6) { |
if (_mesa_varying_slot_in_fs((gl_varying_slot) i)) |
key.input_slots_valid |= BITFIELD64_BIT(i); |
} |
} |
key.clamp_fragment_color = ctx->API == API_OPENGL_COMPAT; |
for (int i = 0; i < MAX_SAMPLERS; i++) { |
if (fp->Base.ShadowSamplers & (1 << i)) { |
/* Assume DEPTH_TEXTURE_MODE is the default: X, X, X, 1 */ |
key.tex.swizzles[i] = |
MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); |
} else { |
/* Color sampler: assume no swizzling. */ |
key.tex.swizzles[i] = SWIZZLE_XYZW; |
} |
} |
if (fp->Base.InputsRead & VARYING_BIT_POS) { |
key.drawable_height = ctx->DrawBuffer->Height; |
} |
if ((fp->Base.InputsRead & VARYING_BIT_POS) || program_uses_dfdy) { |
key.render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
} |
key.nr_color_regions = 1; |
key.program_string_id = bfp->id; |
uint32_t old_prog_offset = brw->wm.prog_offset; |
struct brw_wm_prog_data *old_prog_data = brw->wm.prog_data; |
bool success = do_wm_prog(brw, prog, bfp, &key); |
brw->wm.prog_offset = old_prog_offset; |
brw->wm.prog_data = old_prog_data; |
return success; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs.h |
---|
0,0 → 1,590 |
/* |
* Copyright © 2010 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#pragma once |
#include "brw_shader.h" |
extern "C" { |
#include <sys/types.h> |
#include "main/macros.h" |
#include "main/shaderobj.h" |
#include "main/uniforms.h" |
#include "program/prog_parameter.h" |
#include "program/prog_print.h" |
#include "program/prog_optimize.h" |
#include "program/register_allocate.h" |
#include "program/sampler.h" |
#include "program/hash_table.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_wm.h" |
#include "brw_shader.h" |
} |
#include "glsl/glsl_types.h" |
#include "glsl/ir.h" |
class bblock_t; |
namespace { |
struct acp_entry; |
} |
class fs_reg { |
public: |
/* Callers of this ralloc-based new need not call delete. It's |
* easier to just ralloc_free 'ctx' (or any of its ancestors). */ |
static void* operator new(size_t size, void *ctx) |
{ |
void *node; |
node = ralloc_size(ctx, size); |
assert(node != NULL); |
return node; |
} |
void init(); |
fs_reg(); |
fs_reg(float f); |
fs_reg(int32_t i); |
fs_reg(uint32_t u); |
fs_reg(struct brw_reg fixed_hw_reg); |
fs_reg(enum register_file file, int reg); |
fs_reg(enum register_file file, int reg, uint32_t type); |
fs_reg(class fs_visitor *v, const struct glsl_type *type); |
bool equals(const fs_reg &r) const; |
bool is_zero() const; |
bool is_one() const; |
bool is_valid_3src() const; |
/** Register file: ARF, GRF, MRF, IMM. */ |
enum register_file file; |
/** |
* Register number. For ARF/MRF, it's the hardware register. For |
* GRF, it's a virtual register number until register allocation |
*/ |
int reg; |
/** |
* For virtual registers, this is a hardware register offset from |
* the start of the register block (for example, a constant index |
* in an array access). |
*/ |
int reg_offset; |
/** Register type. BRW_REGISTER_TYPE_* */ |
int type; |
bool negate; |
bool abs; |
bool sechalf; |
struct brw_reg fixed_hw_reg; |
int smear; /* -1, or a channel of the reg to smear to all channels. */ |
/** Value for file == IMM */ |
union { |
int32_t i; |
uint32_t u; |
float f; |
} imm; |
fs_reg *reladdr; |
}; |
static const fs_reg reg_undef; |
static const fs_reg reg_null_f(ARF, BRW_ARF_NULL, BRW_REGISTER_TYPE_F); |
static const fs_reg reg_null_d(ARF, BRW_ARF_NULL, BRW_REGISTER_TYPE_D); |
class ip_record : public exec_node { |
public: |
static void* operator new(size_t size, void *ctx) |
{ |
void *node; |
node = rzalloc_size(ctx, size); |
assert(node != NULL); |
return node; |
} |
ip_record(int ip) |
{ |
this->ip = ip; |
} |
int ip; |
}; |
class fs_inst : public backend_instruction { |
public: |
/* Callers of this ralloc-based new need not call delete. It's |
* easier to just ralloc_free 'ctx' (or any of its ancestors). */ |
static void* operator new(size_t size, void *ctx) |
{ |
void *node; |
node = rzalloc_size(ctx, size); |
assert(node != NULL); |
return node; |
} |
void init(); |
fs_inst(); |
fs_inst(enum opcode opcode); |
fs_inst(enum opcode opcode, fs_reg dst); |
fs_inst(enum opcode opcode, fs_reg dst, fs_reg src0); |
fs_inst(enum opcode opcode, fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst(enum opcode opcode, fs_reg dst, |
fs_reg src0, fs_reg src1,fs_reg src2); |
bool equals(fs_inst *inst); |
bool overwrites_reg(const fs_reg ®); |
bool is_send_from_grf(); |
bool is_partial_write(); |
fs_reg dst; |
fs_reg src[3]; |
bool saturate; |
int conditional_mod; /**< BRW_CONDITIONAL_* */ |
/* Chooses which flag subregister (f0.0 or f0.1) is used for conditional |
* mod and predication. |
*/ |
uint8_t flag_subreg; |
int mlen; /**< SEND message length */ |
int regs_written; /**< Number of vgrfs written by a SEND message, or 1 */ |
int base_mrf; /**< First MRF in the SEND message, if mlen is nonzero. */ |
uint32_t texture_offset; /**< Texture offset bitfield */ |
int sampler; |
int target; /**< MRT target. */ |
bool eot; |
bool header_present; |
bool shadow_compare; |
bool force_uncompressed; |
bool force_sechalf; |
bool force_writemask_all; |
uint32_t offset; /* spill/unspill offset */ |
/** @{ |
* Annotation for the generated IR. One of the two can be set. |
*/ |
const void *ir; |
const char *annotation; |
/** @} */ |
}; |
/** |
* The fragment shader front-end. |
* |
* Translates either GLSL IR or Mesa IR (for ARB_fragment_program) into FS IR. |
*/ |
class fs_visitor : public backend_visitor |
{ |
public: |
fs_visitor(struct brw_context *brw, |
struct brw_wm_compile *c, |
struct gl_shader_program *shader_prog, |
struct gl_fragment_program *fp, |
unsigned dispatch_width); |
~fs_visitor(); |
fs_reg *variable_storage(ir_variable *var); |
int virtual_grf_alloc(int size); |
void import_uniforms(fs_visitor *v); |
void visit(ir_variable *ir); |
void visit(ir_assignment *ir); |
void visit(ir_dereference_variable *ir); |
void visit(ir_dereference_record *ir); |
void visit(ir_dereference_array *ir); |
void visit(ir_expression *ir); |
void visit(ir_texture *ir); |
void visit(ir_if *ir); |
void visit(ir_constant *ir); |
void visit(ir_swizzle *ir); |
void visit(ir_return *ir); |
void visit(ir_loop *ir); |
void visit(ir_loop_jump *ir); |
void visit(ir_discard *ir); |
void visit(ir_call *ir); |
void visit(ir_function *ir); |
void visit(ir_function_signature *ir); |
void swizzle_result(ir_texture *ir, fs_reg orig_val, int sampler); |
bool can_do_source_mods(fs_inst *inst); |
fs_inst *emit(fs_inst inst); |
fs_inst *emit(fs_inst *inst); |
void emit(exec_list list); |
fs_inst *emit(enum opcode opcode); |
fs_inst *emit(enum opcode opcode, fs_reg dst); |
fs_inst *emit(enum opcode opcode, fs_reg dst, fs_reg src0); |
fs_inst *emit(enum opcode opcode, fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst *emit(enum opcode opcode, fs_reg dst, |
fs_reg src0, fs_reg src1, fs_reg src2); |
fs_inst *MOV(fs_reg dst, fs_reg src); |
fs_inst *NOT(fs_reg dst, fs_reg src); |
fs_inst *RNDD(fs_reg dst, fs_reg src); |
fs_inst *RNDE(fs_reg dst, fs_reg src); |
fs_inst *RNDZ(fs_reg dst, fs_reg src); |
fs_inst *FRC(fs_reg dst, fs_reg src); |
fs_inst *ADD(fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst *MUL(fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst *MACH(fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst *MAC(fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst *SHL(fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst *SHR(fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst *ASR(fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst *AND(fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst *OR(fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst *XOR(fs_reg dst, fs_reg src0, fs_reg src1); |
fs_inst *IF(uint32_t predicate); |
fs_inst *IF(fs_reg src0, fs_reg src1, uint32_t condition); |
fs_inst *CMP(fs_reg dst, fs_reg src0, fs_reg src1, |
uint32_t condition); |
fs_inst *LRP(fs_reg dst, fs_reg a, fs_reg y, fs_reg x); |
fs_inst *DEP_RESOLVE_MOV(int grf); |
fs_inst *BFREV(fs_reg dst, fs_reg value); |
fs_inst *BFE(fs_reg dst, fs_reg bits, fs_reg offset, fs_reg value); |
fs_inst *BFI1(fs_reg dst, fs_reg bits, fs_reg offset); |
fs_inst *BFI2(fs_reg dst, fs_reg bfi1_dst, fs_reg insert, fs_reg base); |
fs_inst *FBH(fs_reg dst, fs_reg value); |
fs_inst *FBL(fs_reg dst, fs_reg value); |
fs_inst *CBIT(fs_reg dst, fs_reg value); |
int type_size(const struct glsl_type *type); |
fs_inst *get_instruction_generating_reg(fs_inst *start, |
fs_inst *end, |
fs_reg reg); |
exec_list VARYING_PULL_CONSTANT_LOAD(fs_reg dst, fs_reg surf_index, |
fs_reg varying_offset, |
uint32_t const_offset); |
bool run(); |
void setup_payload_gen4(); |
void setup_payload_gen6(); |
void assign_curb_setup(); |
void calculate_urb_setup(); |
void assign_urb_setup(); |
bool assign_regs(); |
void assign_regs_trivial(); |
void setup_payload_interference(struct ra_graph *g, int payload_reg_count, |
int first_payload_node); |
void setup_mrf_hack_interference(struct ra_graph *g, |
int first_mrf_hack_node); |
int choose_spill_reg(struct ra_graph *g); |
void spill_reg(int spill_reg); |
void split_virtual_grfs(); |
void compact_virtual_grfs(); |
void move_uniform_array_access_to_pull_constants(); |
void setup_pull_constants(); |
void calculate_live_intervals(); |
bool opt_algebraic(); |
bool opt_cse(); |
bool opt_cse_local(bblock_t *block, exec_list *aeb); |
bool opt_copy_propagate(); |
bool try_copy_propagate(fs_inst *inst, int arg, acp_entry *entry); |
bool try_constant_propagate(fs_inst *inst, acp_entry *entry); |
bool opt_copy_propagate_local(void *mem_ctx, bblock_t *block, |
exec_list *acp); |
bool register_coalesce(); |
bool register_coalesce_2(); |
bool compute_to_mrf(); |
bool dead_code_eliminate(); |
bool dead_code_eliminate_local(); |
bool remove_dead_constants(); |
bool remove_duplicate_mrf_writes(); |
bool virtual_grf_interferes(int a, int b); |
void schedule_instructions(bool post_reg_alloc); |
void insert_gen4_send_dependency_workarounds(); |
void insert_gen4_pre_send_dependency_workarounds(fs_inst *inst); |
void insert_gen4_post_send_dependency_workarounds(fs_inst *inst); |
void fail(const char *msg, ...); |
void lower_uniform_pull_constant_loads(); |
void push_force_uncompressed(); |
void pop_force_uncompressed(); |
void push_force_sechalf(); |
void pop_force_sechalf(); |
void emit_dummy_fs(); |
fs_reg *emit_fragcoord_interpolation(ir_variable *ir); |
fs_inst *emit_linterp(const fs_reg &attr, const fs_reg &interp, |
glsl_interp_qualifier interpolation_mode, |
bool is_centroid); |
fs_reg *emit_frontfacing_interpolation(ir_variable *ir); |
fs_reg *emit_general_interpolation(ir_variable *ir); |
void emit_interpolation_setup_gen4(); |
void emit_interpolation_setup_gen6(); |
fs_reg rescale_texcoord(ir_texture *ir, fs_reg coordinate, |
bool is_rect, int sampler, int texunit); |
fs_inst *emit_texture_gen4(ir_texture *ir, fs_reg dst, fs_reg coordinate, |
fs_reg shadow_comp, fs_reg lod, fs_reg lod2); |
fs_inst *emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate, |
fs_reg shadow_comp, fs_reg lod, fs_reg lod2, |
fs_reg sample_index); |
fs_inst *emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate, |
fs_reg shadow_comp, fs_reg lod, fs_reg lod2, |
fs_reg sample_index); |
fs_reg fix_math_operand(fs_reg src); |
fs_inst *emit_math(enum opcode op, fs_reg dst, fs_reg src0); |
fs_inst *emit_math(enum opcode op, fs_reg dst, fs_reg src0, fs_reg src1); |
void emit_lrp(fs_reg dst, fs_reg x, fs_reg y, fs_reg a); |
void emit_minmax(uint32_t conditionalmod, fs_reg dst, |
fs_reg src0, fs_reg src1); |
bool try_emit_saturate(ir_expression *ir); |
bool try_emit_mad(ir_expression *ir, int mul_arg); |
void emit_bool_to_cond_code(ir_rvalue *condition); |
void emit_if_gen6(ir_if *ir); |
void emit_unspill(fs_inst *inst, fs_reg reg, uint32_t spill_offset); |
void emit_fragment_program_code(); |
void setup_fp_regs(); |
fs_reg get_fp_src_reg(const prog_src_register *src); |
fs_reg get_fp_dst_reg(const prog_dst_register *dst); |
void emit_fp_alu1(enum opcode opcode, |
const struct prog_instruction *fpi, |
fs_reg dst, fs_reg src); |
void emit_fp_alu2(enum opcode opcode, |
const struct prog_instruction *fpi, |
fs_reg dst, fs_reg src0, fs_reg src1); |
void emit_fp_scalar_write(const struct prog_instruction *fpi, |
fs_reg dst, fs_reg src); |
void emit_fp_scalar_math(enum opcode opcode, |
const struct prog_instruction *fpi, |
fs_reg dst, fs_reg src); |
void emit_fp_minmax(const struct prog_instruction *fpi, |
fs_reg dst, fs_reg src0, fs_reg src1); |
void emit_fp_sop(uint32_t conditional_mod, |
const struct prog_instruction *fpi, |
fs_reg dst, fs_reg src0, fs_reg src1, fs_reg one); |
void emit_color_write(int target, int index, int first_color_mrf); |
void emit_fb_writes(); |
void emit_shader_time_begin(); |
void emit_shader_time_end(); |
void emit_shader_time_write(enum shader_time_shader_type type, |
fs_reg value); |
bool try_rewrite_rhs_to_dst(ir_assignment *ir, |
fs_reg dst, |
fs_reg src, |
fs_inst *pre_rhs_inst, |
fs_inst *last_rhs_inst); |
void emit_assignment_writes(fs_reg &l, fs_reg &r, |
const glsl_type *type, bool predicated); |
void resolve_ud_negate(fs_reg *reg); |
void resolve_bool_comparison(ir_rvalue *rvalue, fs_reg *reg); |
fs_reg get_timestamp(); |
struct brw_reg interp_reg(int location, int channel); |
void setup_uniform_values(ir_variable *ir); |
void setup_builtin_uniform_values(ir_variable *ir); |
int implied_mrf_writes(fs_inst *inst); |
void dump_instruction(backend_instruction *inst); |
struct gl_fragment_program *fp; |
struct brw_wm_compile *c; |
unsigned int sanity_param_count; |
int param_size[MAX_UNIFORMS * 4]; |
int *virtual_grf_sizes; |
int virtual_grf_count; |
int virtual_grf_array_size; |
int *virtual_grf_start; |
int *virtual_grf_end; |
bool live_intervals_valid; |
/* This is the map from UNIFORM hw_reg + reg_offset as generated by |
* the visitor to the packed uniform number after |
* remove_dead_constants() that represents the actual uploaded |
* uniform index. |
*/ |
int *params_remap; |
int nr_params_remap; |
struct hash_table *variable_ht; |
fs_reg frag_depth; |
fs_reg outputs[BRW_MAX_DRAW_BUFFERS]; |
unsigned output_components[BRW_MAX_DRAW_BUFFERS]; |
fs_reg dual_src_output; |
int first_non_payload_grf; |
/** Either BRW_MAX_GRF or GEN7_MRF_HACK_START */ |
int max_grf; |
int urb_setup[VARYING_SLOT_MAX]; |
fs_reg *fp_temp_regs; |
fs_reg *fp_input_regs; |
/** @{ debug annotation info */ |
const char *current_annotation; |
const void *base_ir; |
/** @} */ |
bool failed; |
char *fail_msg; |
/* Result of last visit() method. */ |
fs_reg result; |
fs_reg pixel_x; |
fs_reg pixel_y; |
fs_reg wpos_w; |
fs_reg pixel_w; |
fs_reg delta_x[BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT]; |
fs_reg delta_y[BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT]; |
fs_reg shader_start_time; |
int grf_used; |
const unsigned dispatch_width; /**< 8 or 16 */ |
int force_uncompressed_stack; |
int force_sechalf_stack; |
}; |
/** |
* The fragment shader code generator. |
* |
* Translates FS IR to actual i965 assembly code. |
*/ |
class fs_generator |
{ |
public: |
fs_generator(struct brw_context *brw, |
struct brw_wm_compile *c, |
struct gl_shader_program *prog, |
struct gl_fragment_program *fp, |
bool dual_source_output); |
~fs_generator(); |
const unsigned *generate_assembly(exec_list *simd8_instructions, |
exec_list *simd16_instructions, |
unsigned *assembly_size); |
private: |
void generate_code(exec_list *instructions); |
void generate_fb_write(fs_inst *inst); |
void generate_pixel_xy(struct brw_reg dst, bool is_x); |
void generate_linterp(fs_inst *inst, struct brw_reg dst, |
struct brw_reg *src); |
void generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src); |
void generate_math1_gen7(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src); |
void generate_math2_gen7(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src0, |
struct brw_reg src1); |
void generate_math1_gen6(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src); |
void generate_math2_gen6(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src0, |
struct brw_reg src1); |
void generate_math_gen4(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src); |
void generate_math_g45(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src); |
void generate_ddx(fs_inst *inst, struct brw_reg dst, struct brw_reg src); |
void generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src, |
bool negate_value); |
void generate_spill(fs_inst *inst, struct brw_reg src); |
void generate_unspill(fs_inst *inst, struct brw_reg dst); |
void generate_uniform_pull_constant_load(fs_inst *inst, struct brw_reg dst, |
struct brw_reg index, |
struct brw_reg offset); |
void generate_uniform_pull_constant_load_gen7(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg surf_index, |
struct brw_reg offset); |
void generate_varying_pull_constant_load(fs_inst *inst, struct brw_reg dst, |
struct brw_reg index, |
struct brw_reg offset); |
void generate_varying_pull_constant_load_gen7(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg index, |
struct brw_reg offset); |
void generate_mov_dispatch_to_flags(fs_inst *inst); |
void generate_set_simd4x2_offset(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg offset); |
void generate_discard_jump(fs_inst *inst); |
void generate_pack_half_2x16_split(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg x, |
struct brw_reg y); |
void generate_unpack_half_2x16_split(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src); |
void generate_shader_time_add(fs_inst *inst, |
struct brw_reg payload, |
struct brw_reg offset, |
struct brw_reg value); |
void patch_discard_jumps_to_fb_writes(); |
struct brw_context *brw; |
struct gl_context *ctx; |
struct brw_compile *p; |
struct brw_wm_compile *c; |
struct gl_shader_program *prog; |
struct gl_shader *shader; |
const struct gl_fragment_program *fp; |
unsigned dispatch_width; /**< 8 or 16 */ |
exec_list discard_halt_patches; |
bool dual_source_output; |
void *mem_ctx; |
}; |
bool brw_do_channel_expressions(struct exec_list *instructions); |
bool brw_do_vector_splitting(struct exec_list *instructions); |
bool brw_fs_precompile(struct gl_context *ctx, struct gl_shader_program *prog); |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp |
---|
0,0 → 1,423 |
/* |
* Copyright © 2010 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. |
*/ |
/** |
* \file brw_wm_channel_expressions.cpp |
* |
* Breaks vector operations down into operations on each component. |
* |
* The 965 fragment shader receives 8 or 16 pixels at a time, so each |
* channel of a vector is laid out as 1 or 2 8-float registers. Each |
* ALU operation operates on one of those channel registers. As a |
* result, there is no value to the 965 fragment shader in tracking |
* "vector" expressions in the sense of GLSL fragment shaders, when |
* doing a channel at a time may help in constant folding, algebraic |
* simplification, and reducing the liveness of channel registers. |
* |
* The exception to the desire to break everything down to floats is |
* texturing. The texture sampler returns a writemasked masked |
* 4/8-register sequence containing the texture values. We don't want |
* to dispatch to the sampler separately for each channel we need, so |
* we do retain the vector types in that case. |
*/ |
extern "C" { |
#include "main/core.h" |
#include "brw_wm.h" |
} |
#include "glsl/ir.h" |
#include "glsl/ir_expression_flattening.h" |
#include "glsl/glsl_types.h" |
class ir_channel_expressions_visitor : public ir_hierarchical_visitor { |
public: |
ir_channel_expressions_visitor() |
{ |
this->progress = false; |
this->mem_ctx = NULL; |
} |
ir_visitor_status visit_leave(ir_assignment *); |
ir_rvalue *get_element(ir_variable *var, unsigned int element); |
void assign(ir_assignment *ir, int elem, ir_rvalue *val); |
bool progress; |
void *mem_ctx; |
}; |
static bool |
channel_expressions_predicate(ir_instruction *ir) |
{ |
ir_expression *expr = ir->as_expression(); |
unsigned int i; |
if (!expr) |
return false; |
for (i = 0; i < expr->get_num_operands(); i++) { |
if (expr->operands[i]->type->is_vector()) |
return true; |
} |
return false; |
} |
bool |
brw_do_channel_expressions(exec_list *instructions) |
{ |
ir_channel_expressions_visitor v; |
/* Pull out any matrix expression to a separate assignment to a |
* temp. This will make our handling of the breakdown to |
* operations on the matrix's vector components much easier. |
*/ |
do_expression_flattening(instructions, channel_expressions_predicate); |
visit_list_elements(&v, instructions); |
return v.progress; |
} |
ir_rvalue * |
ir_channel_expressions_visitor::get_element(ir_variable *var, unsigned int elem) |
{ |
ir_dereference *deref; |
if (var->type->is_scalar()) |
return new(mem_ctx) ir_dereference_variable(var); |
assert(elem < var->type->components()); |
deref = new(mem_ctx) ir_dereference_variable(var); |
return new(mem_ctx) ir_swizzle(deref, elem, 0, 0, 0, 1); |
} |
void |
ir_channel_expressions_visitor::assign(ir_assignment *ir, int elem, ir_rvalue *val) |
{ |
ir_dereference *lhs = ir->lhs->clone(mem_ctx, NULL); |
ir_assignment *assign; |
/* This assign-of-expression should have been generated by the |
* expression flattening visitor (since we never short circit to |
* not flatten, even for plain assignments of variables), so the |
* writemask is always full. |
*/ |
assert(ir->write_mask == (1 << ir->lhs->type->components()) - 1); |
assign = new(mem_ctx) ir_assignment(lhs, val, NULL, (1 << elem)); |
ir->insert_before(assign); |
} |
ir_visitor_status |
ir_channel_expressions_visitor::visit_leave(ir_assignment *ir) |
{ |
ir_expression *expr = ir->rhs->as_expression(); |
bool found_vector = false; |
unsigned int i, vector_elements = 1; |
ir_variable *op_var[3]; |
if (!expr) |
return visit_continue; |
if (!this->mem_ctx) |
this->mem_ctx = ralloc_parent(ir); |
for (i = 0; i < expr->get_num_operands(); i++) { |
if (expr->operands[i]->type->is_vector()) { |
found_vector = true; |
vector_elements = expr->operands[i]->type->vector_elements; |
break; |
} |
} |
if (!found_vector) |
return visit_continue; |
/* Store the expression operands in temps so we can use them |
* multiple times. |
*/ |
for (i = 0; i < expr->get_num_operands(); i++) { |
ir_assignment *assign; |
ir_dereference *deref; |
assert(!expr->operands[i]->type->is_matrix()); |
op_var[i] = new(mem_ctx) ir_variable(expr->operands[i]->type, |
"channel_expressions", |
ir_var_temporary); |
ir->insert_before(op_var[i]); |
deref = new(mem_ctx) ir_dereference_variable(op_var[i]); |
assign = new(mem_ctx) ir_assignment(deref, |
expr->operands[i], |
NULL); |
ir->insert_before(assign); |
} |
const glsl_type *element_type = glsl_type::get_instance(ir->lhs->type->base_type, |
1, 1); |
/* OK, time to break down this vector operation. */ |
switch (expr->operation) { |
case ir_unop_bit_not: |
case ir_unop_logic_not: |
case ir_unop_neg: |
case ir_unop_abs: |
case ir_unop_sign: |
case ir_unop_rcp: |
case ir_unop_rsq: |
case ir_unop_sqrt: |
case ir_unop_exp: |
case ir_unop_log: |
case ir_unop_exp2: |
case ir_unop_log2: |
case ir_unop_bitcast_i2f: |
case ir_unop_bitcast_f2i: |
case ir_unop_bitcast_f2u: |
case ir_unop_bitcast_u2f: |
case ir_unop_i2u: |
case ir_unop_u2i: |
case ir_unop_f2i: |
case ir_unop_f2u: |
case ir_unop_i2f: |
case ir_unop_f2b: |
case ir_unop_b2f: |
case ir_unop_i2b: |
case ir_unop_b2i: |
case ir_unop_u2f: |
case ir_unop_trunc: |
case ir_unop_ceil: |
case ir_unop_floor: |
case ir_unop_fract: |
case ir_unop_round_even: |
case ir_unop_sin: |
case ir_unop_cos: |
case ir_unop_sin_reduced: |
case ir_unop_cos_reduced: |
case ir_unop_dFdx: |
case ir_unop_dFdy: |
case ir_unop_bitfield_reverse: |
case ir_unop_bit_count: |
case ir_unop_find_msb: |
case ir_unop_find_lsb: |
for (i = 0; i < vector_elements; i++) { |
ir_rvalue *op0 = get_element(op_var[0], i); |
assign(ir, i, new(mem_ctx) ir_expression(expr->operation, |
element_type, |
op0, |
NULL)); |
} |
break; |
case ir_binop_add: |
case ir_binop_sub: |
case ir_binop_mul: |
case ir_binop_div: |
case ir_binop_mod: |
case ir_binop_min: |
case ir_binop_max: |
case ir_binop_pow: |
case ir_binop_lshift: |
case ir_binop_rshift: |
case ir_binop_bit_and: |
case ir_binop_bit_xor: |
case ir_binop_bit_or: |
case ir_binop_less: |
case ir_binop_greater: |
case ir_binop_lequal: |
case ir_binop_gequal: |
case ir_binop_equal: |
case ir_binop_nequal: |
for (i = 0; i < vector_elements; i++) { |
ir_rvalue *op0 = get_element(op_var[0], i); |
ir_rvalue *op1 = get_element(op_var[1], i); |
assign(ir, i, new(mem_ctx) ir_expression(expr->operation, |
element_type, |
op0, |
op1)); |
} |
break; |
case ir_unop_any: { |
ir_expression *temp; |
temp = new(mem_ctx) ir_expression(ir_binop_logic_or, |
element_type, |
get_element(op_var[0], 0), |
get_element(op_var[0], 1)); |
for (i = 2; i < vector_elements; i++) { |
temp = new(mem_ctx) ir_expression(ir_binop_logic_or, |
element_type, |
get_element(op_var[0], i), |
temp); |
} |
assign(ir, 0, temp); |
break; |
} |
case ir_binop_dot: { |
ir_expression *last = NULL; |
for (i = 0; i < vector_elements; i++) { |
ir_rvalue *op0 = get_element(op_var[0], i); |
ir_rvalue *op1 = get_element(op_var[1], i); |
ir_expression *temp; |
temp = new(mem_ctx) ir_expression(ir_binop_mul, |
element_type, |
op0, |
op1); |
if (last) { |
last = new(mem_ctx) ir_expression(ir_binop_add, |
element_type, |
temp, |
last); |
} else { |
last = temp; |
} |
} |
assign(ir, 0, last); |
break; |
} |
case ir_binop_logic_and: |
case ir_binop_logic_xor: |
case ir_binop_logic_or: |
ir->print(); |
printf("\n"); |
assert(!"not reached: expression operates on scalars only"); |
break; |
case ir_binop_all_equal: |
case ir_binop_any_nequal: { |
ir_expression *last = NULL; |
for (i = 0; i < vector_elements; i++) { |
ir_rvalue *op0 = get_element(op_var[0], i); |
ir_rvalue *op1 = get_element(op_var[1], i); |
ir_expression *temp; |
ir_expression_operation join; |
if (expr->operation == ir_binop_all_equal) |
join = ir_binop_logic_and; |
else |
join = ir_binop_logic_or; |
temp = new(mem_ctx) ir_expression(expr->operation, |
element_type, |
op0, |
op1); |
if (last) { |
last = new(mem_ctx) ir_expression(join, |
element_type, |
temp, |
last); |
} else { |
last = temp; |
} |
} |
assign(ir, 0, last); |
break; |
} |
case ir_unop_noise: |
assert(!"noise should have been broken down to function call"); |
break; |
case ir_binop_bfm: { |
/* Does not need to be scalarized, since its result will be identical |
* for all channels. |
*/ |
ir_rvalue *op0 = get_element(op_var[0], 0); |
ir_rvalue *op1 = get_element(op_var[1], 0); |
assign(ir, 0, new(mem_ctx) ir_expression(expr->operation, |
element_type, |
op0, |
op1)); |
break; |
} |
case ir_binop_ubo_load: |
assert(!"not yet supported"); |
break; |
case ir_triop_lrp: |
case ir_triop_bitfield_extract: |
for (i = 0; i < vector_elements; i++) { |
ir_rvalue *op0 = get_element(op_var[0], i); |
ir_rvalue *op1 = get_element(op_var[1], i); |
ir_rvalue *op2 = get_element(op_var[2], i); |
assign(ir, i, new(mem_ctx) ir_expression(expr->operation, |
element_type, |
op0, |
op1, |
op2)); |
} |
break; |
case ir_triop_bfi: { |
/* Only a single BFM is needed for multiple BFIs. */ |
ir_rvalue *op0 = get_element(op_var[0], 0); |
for (i = 0; i < vector_elements; i++) { |
ir_rvalue *op1 = get_element(op_var[1], i); |
ir_rvalue *op2 = get_element(op_var[2], i); |
assign(ir, i, new(mem_ctx) ir_expression(expr->operation, |
element_type, |
op0->clone(mem_ctx, NULL), |
op1, |
op2)); |
} |
break; |
} |
case ir_unop_pack_snorm_2x16: |
case ir_unop_pack_snorm_4x8: |
case ir_unop_pack_unorm_2x16: |
case ir_unop_pack_unorm_4x8: |
case ir_unop_pack_half_2x16: |
case ir_unop_unpack_snorm_2x16: |
case ir_unop_unpack_snorm_4x8: |
case ir_unop_unpack_unorm_2x16: |
case ir_unop_unpack_unorm_4x8: |
case ir_unop_unpack_half_2x16: |
case ir_binop_vector_extract: |
case ir_triop_vector_insert: |
case ir_quadop_bitfield_insert: |
case ir_quadop_vector: |
assert(!"should have been lowered"); |
break; |
case ir_unop_unpack_half_2x16_split_x: |
case ir_unop_unpack_half_2x16_split_y: |
case ir_binop_pack_half_2x16_split: |
assert("!not reached: expression operates on scalars only"); |
break; |
} |
ir->remove(); |
this->progress = true; |
return visit_continue; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp |
---|
0,0 → 1,479 |
/* |
* 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. |
*/ |
/** @file brw_fs_copy_propagation.cpp |
* |
* Support for global copy propagation in two passes: A local pass that does |
* intra-block copy (and constant) propagation, and a global pass that uses |
* dataflow analysis on the copies available at the end of each block to re-do |
* local copy propagation with more copies available. |
* |
* See Muchnik's Advanced Compiler Design and Implementation, section |
* 12.5 (p356). |
*/ |
#define ACP_HASH_SIZE 16 |
#include "main/bitset.h" |
#include "brw_fs.h" |
#include "brw_cfg.h" |
namespace { /* avoid conflict with opt_copy_propagation_elements */ |
struct acp_entry : public exec_node { |
fs_reg dst; |
fs_reg src; |
}; |
struct block_data { |
/** |
* Which entries in the fs_copy_prop_dataflow acp table are live at the |
* start of this block. This is the useful output of the analysis, since |
* it lets us plug those into the local copy propagation on the second |
* pass. |
*/ |
BITSET_WORD *livein; |
/** |
* Which entries in the fs_copy_prop_dataflow acp table are live at the end |
* of this block. This is done in initial setup from the per-block acps |
* returned by the first local copy prop pass. |
*/ |
BITSET_WORD *liveout; |
/** |
* Which entries in the fs_copy_prop_dataflow acp table are killed over the |
* course of this block. |
*/ |
BITSET_WORD *kill; |
}; |
class fs_copy_prop_dataflow |
{ |
public: |
fs_copy_prop_dataflow(void *mem_ctx, cfg_t *cfg, |
exec_list *out_acp[ACP_HASH_SIZE]); |
void setup_kills(); |
void run(); |
void *mem_ctx; |
cfg_t *cfg; |
acp_entry **acp; |
int num_acp; |
int bitset_words; |
struct block_data *bd; |
}; |
} /* anonymous namespace */ |
fs_copy_prop_dataflow::fs_copy_prop_dataflow(void *mem_ctx, cfg_t *cfg, |
exec_list *out_acp[ACP_HASH_SIZE]) |
: mem_ctx(mem_ctx), cfg(cfg) |
{ |
bd = rzalloc_array(mem_ctx, struct block_data, cfg->num_blocks); |
num_acp = 0; |
for (int b = 0; b < cfg->num_blocks; b++) { |
for (int i = 0; i < ACP_HASH_SIZE; i++) { |
foreach_list(entry_node, &out_acp[b][i]) { |
num_acp++; |
} |
} |
} |
acp = rzalloc_array(mem_ctx, struct acp_entry *, num_acp); |
bitset_words = BITSET_WORDS(num_acp); |
int next_acp = 0; |
for (int b = 0; b < cfg->num_blocks; b++) { |
bd[b].livein = rzalloc_array(bd, BITSET_WORD, bitset_words); |
bd[b].liveout = rzalloc_array(bd, BITSET_WORD, bitset_words); |
bd[b].kill = rzalloc_array(bd, BITSET_WORD, bitset_words); |
for (int i = 0; i < ACP_HASH_SIZE; i++) { |
foreach_list(entry_node, &out_acp[b][i]) { |
acp_entry *entry = (acp_entry *)entry_node; |
acp[next_acp] = entry; |
BITSET_SET(bd[b].liveout, next_acp); |
next_acp++; |
} |
} |
} |
assert(next_acp == num_acp); |
setup_kills(); |
run(); |
} |
/** |
* Walk the set of instructions in the block, marking which entries in the acp |
* are killed by the block. |
*/ |
void |
fs_copy_prop_dataflow::setup_kills() |
{ |
for (int b = 0; b < cfg->num_blocks; b++) { |
bblock_t *block = cfg->blocks[b]; |
for (fs_inst *inst = (fs_inst *)block->start; |
inst != block->end->next; |
inst = (fs_inst *)inst->next) { |
if (inst->dst.file != GRF) |
continue; |
for (int i = 0; i < num_acp; i++) { |
if (inst->overwrites_reg(acp[i]->dst) || |
inst->overwrites_reg(acp[i]->src)) { |
BITSET_SET(bd[b].kill, i); |
} |
} |
} |
} |
} |
/** |
* Walk the set of instructions in the block, marking which entries in the acp |
* are killed by the block. |
*/ |
void |
fs_copy_prop_dataflow::run() |
{ |
bool cont = true; |
while (cont) { |
cont = false; |
for (int b = 0; b < cfg->num_blocks; b++) { |
for (int i = 0; i < bitset_words; i++) { |
BITSET_WORD new_liveout = (bd[b].livein[i] & |
~bd[b].kill[i] & |
~bd[b].liveout[i]); |
if (new_liveout) { |
bd[b].liveout[i] |= new_liveout; |
cont = true; |
} |
/* Update livein: if it's live at the end of all parents, it's |
* live at our start. |
*/ |
BITSET_WORD new_livein = ~bd[b].livein[i]; |
foreach_list(block_node, &cfg->blocks[b]->parents) { |
bblock_link *link = (bblock_link *)block_node; |
bblock_t *block = link->block; |
new_livein &= bd[block->block_num].liveout[i]; |
if (!new_livein) |
break; |
} |
if (new_livein) { |
bd[b].livein[i] |= new_livein; |
cont = true; |
} |
} |
} |
} |
} |
bool |
fs_visitor::try_copy_propagate(fs_inst *inst, int arg, acp_entry *entry) |
{ |
if (entry->src.file == IMM) |
return false; |
if (inst->src[arg].file != entry->dst.file || |
inst->src[arg].reg != entry->dst.reg || |
inst->src[arg].reg_offset != entry->dst.reg_offset) { |
return false; |
} |
/* See resolve_ud_negate() and comment in brw_fs_emit.cpp. */ |
if (inst->conditional_mod && |
inst->src[arg].type == BRW_REGISTER_TYPE_UD && |
entry->src.negate) |
return false; |
bool has_source_modifiers = entry->src.abs || entry->src.negate; |
if ((has_source_modifiers || entry->src.file == UNIFORM || |
entry->src.smear != -1) && !can_do_source_mods(inst)) |
return false; |
if (has_source_modifiers && entry->dst.type != inst->src[arg].type) |
return false; |
inst->src[arg].file = entry->src.file; |
inst->src[arg].reg = entry->src.reg; |
inst->src[arg].reg_offset = entry->src.reg_offset; |
if (entry->src.smear != -1) |
inst->src[arg].smear = entry->src.smear; |
if (!inst->src[arg].abs) { |
inst->src[arg].abs = entry->src.abs; |
inst->src[arg].negate ^= entry->src.negate; |
} |
return true; |
} |
bool |
fs_visitor::try_constant_propagate(fs_inst *inst, acp_entry *entry) |
{ |
bool progress = false; |
if (entry->src.file != IMM) |
return false; |
for (int i = 2; i >= 0; i--) { |
if (inst->src[i].file != entry->dst.file || |
inst->src[i].reg != entry->dst.reg || |
inst->src[i].reg_offset != entry->dst.reg_offset) |
continue; |
/* Don't bother with cases that should have been taken care of by the |
* GLSL compiler's constant folding pass. |
*/ |
if (inst->src[i].negate || inst->src[i].abs) |
continue; |
switch (inst->opcode) { |
case BRW_OPCODE_MOV: |
inst->src[i] = entry->src; |
progress = true; |
break; |
case BRW_OPCODE_MACH: |
case BRW_OPCODE_MUL: |
case BRW_OPCODE_ADD: |
if (i == 1) { |
inst->src[i] = entry->src; |
progress = true; |
} else if (i == 0 && inst->src[1].file != IMM) { |
/* Fit this constant in by commuting the operands. |
* Exception: we can't do this for 32-bit integer MUL/MACH |
* because it's asymmetric. |
*/ |
if ((inst->opcode == BRW_OPCODE_MUL || |
inst->opcode == BRW_OPCODE_MACH) && |
(inst->src[1].type == BRW_REGISTER_TYPE_D || |
inst->src[1].type == BRW_REGISTER_TYPE_UD)) |
break; |
inst->src[0] = inst->src[1]; |
inst->src[1] = entry->src; |
progress = true; |
} |
break; |
case BRW_OPCODE_CMP: |
case BRW_OPCODE_IF: |
if (i == 1) { |
inst->src[i] = entry->src; |
progress = true; |
} else if (i == 0 && inst->src[1].file != IMM) { |
uint32_t new_cmod; |
new_cmod = brw_swap_cmod(inst->conditional_mod); |
if (new_cmod != ~0u) { |
/* Fit this constant in by swapping the operands and |
* flipping the test |
*/ |
inst->src[0] = inst->src[1]; |
inst->src[1] = entry->src; |
inst->conditional_mod = new_cmod; |
progress = true; |
} |
} |
break; |
case BRW_OPCODE_SEL: |
if (i == 1) { |
inst->src[i] = entry->src; |
progress = true; |
} else if (i == 0 && inst->src[1].file != IMM) { |
inst->src[0] = inst->src[1]; |
inst->src[1] = entry->src; |
/* If this was predicated, flipping operands means |
* we also need to flip the predicate. |
*/ |
if (inst->conditional_mod == BRW_CONDITIONAL_NONE) { |
inst->predicate_inverse = |
!inst->predicate_inverse; |
} |
progress = true; |
} |
break; |
case SHADER_OPCODE_RCP: |
/* The hardware doesn't do math on immediate values |
* (because why are you doing that, seriously?), but |
* the correct answer is to just constant fold it |
* anyway. |
*/ |
assert(i == 0); |
if (inst->src[0].imm.f != 0.0f) { |
inst->opcode = BRW_OPCODE_MOV; |
inst->src[0] = entry->src; |
inst->src[0].imm.f = 1.0f / inst->src[0].imm.f; |
progress = true; |
} |
break; |
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD: |
inst->src[i] = entry->src; |
progress = true; |
break; |
default: |
break; |
} |
} |
return progress; |
} |
/* Walks a basic block and does copy propagation on it using the acp |
* list. |
*/ |
bool |
fs_visitor::opt_copy_propagate_local(void *mem_ctx, bblock_t *block, |
exec_list *acp) |
{ |
bool progress = false; |
for (fs_inst *inst = (fs_inst *)block->start; |
inst != block->end->next; |
inst = (fs_inst *)inst->next) { |
/* Try propagating into this instruction. */ |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file != GRF) |
continue; |
foreach_list(entry_node, &acp[inst->src[i].reg % ACP_HASH_SIZE]) { |
acp_entry *entry = (acp_entry *)entry_node; |
if (try_constant_propagate(inst, entry)) |
progress = true; |
if (try_copy_propagate(inst, i, entry)) |
progress = true; |
} |
} |
/* kill the destination from the ACP */ |
if (inst->dst.file == GRF) { |
foreach_list_safe(entry_node, &acp[inst->dst.reg % ACP_HASH_SIZE]) { |
acp_entry *entry = (acp_entry *)entry_node; |
if (inst->overwrites_reg(entry->dst)) { |
entry->remove(); |
} |
} |
/* Oops, we only have the chaining hash based on the destination, not |
* the source, so walk across the entire table. |
*/ |
for (int i = 0; i < ACP_HASH_SIZE; i++) { |
foreach_list_safe(entry_node, &acp[i]) { |
acp_entry *entry = (acp_entry *)entry_node; |
if (inst->overwrites_reg(entry->src)) |
entry->remove(); |
} |
} |
} |
/* If this instruction's source could potentially be folded into the |
* operand of another instruction, add it to the ACP. |
*/ |
if (inst->opcode == BRW_OPCODE_MOV && |
inst->dst.file == GRF && |
((inst->src[0].file == GRF && |
(inst->src[0].reg != inst->dst.reg || |
inst->src[0].reg_offset != inst->dst.reg_offset)) || |
inst->src[0].file == UNIFORM || |
inst->src[0].file == IMM) && |
inst->src[0].type == inst->dst.type && |
!inst->saturate && |
!inst->is_partial_write()) { |
acp_entry *entry = ralloc(mem_ctx, acp_entry); |
entry->dst = inst->dst; |
entry->src = inst->src[0]; |
acp[entry->dst.reg % ACP_HASH_SIZE].push_tail(entry); |
} |
} |
return progress; |
} |
bool |
fs_visitor::opt_copy_propagate() |
{ |
bool progress = false; |
void *mem_ctx = ralloc_context(this->mem_ctx); |
cfg_t cfg(this); |
exec_list *out_acp[cfg.num_blocks]; |
for (int i = 0; i < cfg.num_blocks; i++) |
out_acp[i] = new exec_list [ACP_HASH_SIZE]; |
/* First, walk through each block doing local copy propagation and getting |
* the set of copies available at the end of the block. |
*/ |
for (int b = 0; b < cfg.num_blocks; b++) { |
bblock_t *block = cfg.blocks[b]; |
progress = opt_copy_propagate_local(mem_ctx, block, |
out_acp[b]) || progress; |
} |
/* Do dataflow analysis for those available copies. */ |
fs_copy_prop_dataflow dataflow(mem_ctx, &cfg, out_acp); |
/* Next, re-run local copy propagation, this time with the set of copies |
* provided by the dataflow analysis available at the start of a block. |
*/ |
for (int b = 0; b < cfg.num_blocks; b++) { |
bblock_t *block = cfg.blocks[b]; |
exec_list in_acp[ACP_HASH_SIZE]; |
for (int i = 0; i < dataflow.num_acp; i++) { |
if (BITSET_TEST(dataflow.bd[b].livein, i)) { |
struct acp_entry *entry = dataflow.acp[i]; |
in_acp[entry->dst.reg % ACP_HASH_SIZE].push_tail(entry); |
} |
} |
progress = opt_copy_propagate_local(mem_ctx, block, in_acp) || progress; |
} |
for (int i = 0; i < cfg.num_blocks; i++) |
delete [] out_acp[i]; |
ralloc_free(mem_ctx); |
if (progress) |
live_intervals_valid = false; |
return progress; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs_cse.cpp |
---|
0,0 → 1,233 |
/* |
* 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 "brw_fs.h" |
#include "brw_cfg.h" |
/** @file brw_fs_cse.cpp |
* |
* Support for local common subexpression elimination. |
* |
* See Muchnik's Advanced Compiler Design and Implementation, section |
* 13.1 (p378). |
*/ |
namespace { |
struct aeb_entry : public exec_node { |
/** The instruction that generates the expression value. */ |
fs_inst *generator; |
/** The temporary where the value is stored. */ |
fs_reg tmp; |
}; |
} |
static bool |
is_expression(const fs_inst *const inst) |
{ |
switch (inst->opcode) { |
case BRW_OPCODE_SEL: |
case BRW_OPCODE_NOT: |
case BRW_OPCODE_AND: |
case BRW_OPCODE_OR: |
case BRW_OPCODE_XOR: |
case BRW_OPCODE_SHR: |
case BRW_OPCODE_SHL: |
case BRW_OPCODE_RSR: |
case BRW_OPCODE_RSL: |
case BRW_OPCODE_ASR: |
case BRW_OPCODE_ADD: |
case BRW_OPCODE_MUL: |
case BRW_OPCODE_FRC: |
case BRW_OPCODE_RNDU: |
case BRW_OPCODE_RNDD: |
case BRW_OPCODE_RNDE: |
case BRW_OPCODE_RNDZ: |
case BRW_OPCODE_LINE: |
case BRW_OPCODE_PLN: |
case BRW_OPCODE_MAD: |
case BRW_OPCODE_LRP: |
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD: |
case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7: |
case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD: |
case FS_OPCODE_CINTERP: |
case FS_OPCODE_LINTERP: |
return true; |
default: |
return false; |
} |
} |
static bool |
operands_match(fs_reg *xs, fs_reg *ys) |
{ |
return xs[0].equals(ys[0]) && xs[1].equals(ys[1]) && xs[2].equals(ys[2]); |
} |
bool |
fs_visitor::opt_cse_local(bblock_t *block, exec_list *aeb) |
{ |
bool progress = false; |
void *mem_ctx = ralloc_context(this->mem_ctx); |
int ip = block->start_ip; |
for (fs_inst *inst = (fs_inst *)block->start; |
inst != block->end->next; |
inst = (fs_inst *) inst->next) { |
/* Skip some cases. */ |
if (is_expression(inst) && !inst->is_partial_write() && |
!inst->conditional_mod) |
{ |
bool found = false; |
aeb_entry *entry; |
foreach_list(entry_node, aeb) { |
entry = (aeb_entry *) entry_node; |
/* Match current instruction's expression against those in AEB. */ |
if (inst->opcode == entry->generator->opcode && |
inst->saturate == entry->generator->saturate && |
inst->dst.type == entry->generator->dst.type && |
operands_match(entry->generator->src, inst->src)) { |
found = true; |
progress = true; |
break; |
} |
} |
if (!found) { |
/* Our first sighting of this expression. Create an entry. */ |
aeb_entry *entry = ralloc(mem_ctx, aeb_entry); |
entry->tmp = reg_undef; |
entry->generator = inst; |
aeb->push_tail(entry); |
} else { |
/* This is at least our second sighting of this expression. |
* If we don't have a temporary already, make one. |
*/ |
bool no_existing_temp = entry->tmp.file == BAD_FILE; |
if (no_existing_temp) { |
int written = entry->generator->regs_written; |
fs_reg orig_dst = entry->generator->dst; |
fs_reg tmp = fs_reg(GRF, virtual_grf_alloc(written), |
orig_dst.type); |
entry->tmp = tmp; |
entry->generator->dst = tmp; |
for (int i = 0; i < written; i++) { |
fs_inst *copy = MOV(orig_dst, tmp); |
copy->force_writemask_all = |
entry->generator->force_writemask_all; |
entry->generator->insert_after(copy); |
orig_dst.reg_offset++; |
tmp.reg_offset++; |
} |
} |
/* dest <- temp */ |
int written = inst->regs_written; |
assert(written == entry->generator->regs_written); |
assert(inst->dst.type == entry->tmp.type); |
fs_reg dst = inst->dst; |
fs_reg tmp = entry->tmp; |
fs_inst *copy = NULL; |
for (int i = 0; i < written; i++) { |
copy = MOV(dst, tmp); |
copy->force_writemask_all = inst->force_writemask_all; |
inst->insert_before(copy); |
dst.reg_offset++; |
tmp.reg_offset++; |
} |
inst->remove(); |
/* Appending an instruction may have changed our bblock end. */ |
if (inst == block->end) { |
block->end = copy; |
} |
/* Continue iteration with copy->next */ |
inst = copy; |
} |
} |
foreach_list_safe(entry_node, aeb) { |
aeb_entry *entry = (aeb_entry *)entry_node; |
for (int i = 0; i < 3; i++) { |
fs_reg *src_reg = &entry->generator->src[i]; |
/* Kill all AEB entries that use the destination we just |
* overwrote. |
*/ |
if (inst->overwrites_reg(entry->generator->src[i])) { |
entry->remove(); |
ralloc_free(entry); |
break; |
} |
/* Kill any AEB entries using registers that don't get reused any |
* more -- a sure sign they'll fail operands_match(). |
*/ |
if (src_reg->file == GRF && virtual_grf_end[src_reg->reg] < ip) { |
entry->remove(); |
ralloc_free(entry); |
break; |
} |
} |
} |
ip++; |
} |
ralloc_free(mem_ctx); |
if (progress) |
this->live_intervals_valid = false; |
return progress; |
} |
bool |
fs_visitor::opt_cse() |
{ |
bool progress = false; |
calculate_live_intervals(); |
cfg_t cfg(this); |
for (int b = 0; b < cfg.num_blocks; b++) { |
bblock_t *block = cfg.blocks[b]; |
exec_list aeb; |
progress = opt_cse_local(block, &aeb) || progress; |
} |
return progress; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs_emit.cpp |
---|
0,0 → 1,1519 |
/* |
* Copyright © 2010 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. |
*/ |
/** @file brw_fs_emit.cpp |
* |
* This file supports emitting code from the FS LIR to the actual |
* native instructions. |
*/ |
extern "C" { |
#include "main/macros.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
} /* extern "C" */ |
#include "brw_fs.h" |
#include "brw_cfg.h" |
fs_generator::fs_generator(struct brw_context *brw, |
struct brw_wm_compile *c, |
struct gl_shader_program *prog, |
struct gl_fragment_program *fp, |
bool dual_source_output) |
: brw(brw), c(c), prog(prog), fp(fp), dual_source_output(dual_source_output) |
{ |
ctx = &brw->ctx; |
shader = prog ? prog->_LinkedShaders[MESA_SHADER_FRAGMENT] : NULL; |
mem_ctx = c; |
p = rzalloc(mem_ctx, struct brw_compile); |
brw_init_compile(brw, p, mem_ctx); |
} |
fs_generator::~fs_generator() |
{ |
} |
void |
fs_generator::patch_discard_jumps_to_fb_writes() |
{ |
if (brw->gen < 6 || this->discard_halt_patches.is_empty()) |
return; |
/* There is a somewhat strange undocumented requirement of using |
* HALT, according to the simulator. If some channel has HALTed to |
* a particular UIP, then by the end of the program, every channel |
* must have HALTed to that UIP. Furthermore, the tracking is a |
* stack, so you can't do the final halt of a UIP after starting |
* halting to a new UIP. |
* |
* Symptoms of not emitting this instruction on actual hardware |
* included GPU hangs and sparkly rendering on the piglit discard |
* tests. |
*/ |
struct brw_instruction *last_halt = gen6_HALT(p); |
last_halt->bits3.break_cont.uip = 2; |
last_halt->bits3.break_cont.jip = 2; |
int ip = p->nr_insn; |
foreach_list(node, &this->discard_halt_patches) { |
ip_record *patch_ip = (ip_record *)node; |
struct brw_instruction *patch = &p->store[patch_ip->ip]; |
assert(patch->header.opcode == BRW_OPCODE_HALT); |
/* HALT takes a half-instruction distance from the pre-incremented IP. */ |
patch->bits3.break_cont.uip = (ip - patch_ip->ip) * 2; |
} |
this->discard_halt_patches.make_empty(); |
} |
void |
fs_generator::generate_fb_write(fs_inst *inst) |
{ |
bool eot = inst->eot; |
struct brw_reg implied_header; |
uint32_t msg_control; |
/* Header is 2 regs, g0 and g1 are the contents. g0 will be implied |
* move, here's g1. |
*/ |
brw_push_insn_state(p); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
if (fp->UsesKill) { |
struct brw_reg pixel_mask; |
if (brw->gen >= 6) |
pixel_mask = retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW); |
else |
pixel_mask = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW); |
brw_MOV(p, pixel_mask, brw_flag_reg(0, 1)); |
} |
if (inst->header_present) { |
if (brw->gen >= 6) { |
brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED); |
brw_MOV(p, |
retype(brw_message_reg(inst->base_mrf), BRW_REGISTER_TYPE_UD), |
retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
if (inst->target > 0 && c->key.replicate_alpha) { |
/* Set "Source0 Alpha Present to RenderTarget" bit in message |
* header. |
*/ |
brw_OR(p, |
vec1(retype(brw_message_reg(inst->base_mrf), BRW_REGISTER_TYPE_UD)), |
vec1(retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)), |
brw_imm_ud(0x1 << 11)); |
} |
if (inst->target > 0) { |
/* Set the render target index for choosing BLEND_STATE. */ |
brw_MOV(p, retype(brw_vec1_reg(BRW_MESSAGE_REGISTER_FILE, |
inst->base_mrf, 2), |
BRW_REGISTER_TYPE_UD), |
brw_imm_ud(inst->target)); |
} |
implied_header = brw_null_reg(); |
} else { |
implied_header = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW); |
brw_MOV(p, |
brw_message_reg(inst->base_mrf + 1), |
brw_vec8_grf(1, 0)); |
} |
} else { |
implied_header = brw_null_reg(); |
} |
if (this->dual_source_output) |
msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_DUAL_SOURCE_SUBSPAN01; |
else if (dispatch_width == 16) |
msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD16_SINGLE_SOURCE; |
else |
msg_control = BRW_DATAPORT_RENDER_TARGET_WRITE_SIMD8_SINGLE_SOURCE_SUBSPAN01; |
brw_pop_insn_state(p); |
brw_fb_WRITE(p, |
dispatch_width, |
inst->base_mrf, |
implied_header, |
msg_control, |
inst->target, |
inst->mlen, |
0, |
eot, |
inst->header_present); |
} |
/* Computes the integer pixel x,y values from the origin. |
* |
* This is the basis of gl_FragCoord computation, but is also used |
* pre-gen6 for computing the deltas from v0 for computing |
* interpolation. |
*/ |
void |
fs_generator::generate_pixel_xy(struct brw_reg dst, bool is_x) |
{ |
struct brw_reg g1_uw = retype(brw_vec1_grf(1, 0), BRW_REGISTER_TYPE_UW); |
struct brw_reg src; |
struct brw_reg deltas; |
if (is_x) { |
src = stride(suboffset(g1_uw, 4), 2, 4, 0); |
deltas = brw_imm_v(0x10101010); |
} else { |
src = stride(suboffset(g1_uw, 5), 2, 4, 0); |
deltas = brw_imm_v(0x11001100); |
} |
if (dispatch_width == 16) { |
dst = vec16(dst); |
} |
/* We do this 8 or 16-wide, but since the destination is UW we |
* don't do compression in the 16-wide case. |
*/ |
brw_push_insn_state(p); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_ADD(p, dst, src, deltas); |
brw_pop_insn_state(p); |
} |
void |
fs_generator::generate_linterp(fs_inst *inst, |
struct brw_reg dst, struct brw_reg *src) |
{ |
struct brw_reg delta_x = src[0]; |
struct brw_reg delta_y = src[1]; |
struct brw_reg interp = src[2]; |
if (brw->has_pln && |
delta_y.nr == delta_x.nr + 1 && |
(brw->gen >= 6 || (delta_x.nr & 1) == 0)) { |
brw_PLN(p, dst, interp, delta_x); |
} else { |
brw_LINE(p, brw_null_reg(), interp, delta_x); |
brw_MAC(p, dst, suboffset(interp, 1), delta_y); |
} |
} |
void |
fs_generator::generate_math1_gen7(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src0) |
{ |
assert(inst->mlen == 0); |
brw_math(p, dst, |
brw_math_function(inst->opcode), |
0, src0, |
BRW_MATH_DATA_VECTOR, |
BRW_MATH_PRECISION_FULL); |
} |
void |
fs_generator::generate_math2_gen7(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src0, |
struct brw_reg src1) |
{ |
assert(inst->mlen == 0); |
brw_math2(p, dst, brw_math_function(inst->opcode), src0, src1); |
} |
void |
fs_generator::generate_math1_gen6(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src0) |
{ |
int op = brw_math_function(inst->opcode); |
assert(inst->mlen == 0); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_math(p, dst, |
op, |
0, src0, |
BRW_MATH_DATA_VECTOR, |
BRW_MATH_PRECISION_FULL); |
if (dispatch_width == 16) { |
brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); |
brw_math(p, sechalf(dst), |
op, |
0, sechalf(src0), |
BRW_MATH_DATA_VECTOR, |
BRW_MATH_PRECISION_FULL); |
brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED); |
} |
} |
void |
fs_generator::generate_math2_gen6(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src0, |
struct brw_reg src1) |
{ |
int op = brw_math_function(inst->opcode); |
assert(inst->mlen == 0); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_math2(p, dst, op, src0, src1); |
if (dispatch_width == 16) { |
brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); |
brw_math2(p, sechalf(dst), op, sechalf(src0), sechalf(src1)); |
brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED); |
} |
} |
void |
fs_generator::generate_math_gen4(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src) |
{ |
int op = brw_math_function(inst->opcode); |
assert(inst->mlen >= 1); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_math(p, dst, |
op, |
inst->base_mrf, src, |
BRW_MATH_DATA_VECTOR, |
BRW_MATH_PRECISION_FULL); |
if (dispatch_width == 16) { |
brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); |
brw_math(p, sechalf(dst), |
op, |
inst->base_mrf + 1, sechalf(src), |
BRW_MATH_DATA_VECTOR, |
BRW_MATH_PRECISION_FULL); |
brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED); |
} |
} |
void |
fs_generator::generate_math_g45(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src) |
{ |
if (inst->opcode == SHADER_OPCODE_POW || |
inst->opcode == SHADER_OPCODE_INT_QUOTIENT || |
inst->opcode == SHADER_OPCODE_INT_REMAINDER) { |
generate_math_gen4(inst, dst, src); |
return; |
} |
int op = brw_math_function(inst->opcode); |
assert(inst->mlen >= 1); |
brw_math(p, dst, |
op, |
inst->base_mrf, src, |
BRW_MATH_DATA_VECTOR, |
BRW_MATH_PRECISION_FULL); |
} |
void |
fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src) |
{ |
int msg_type = -1; |
int rlen = 4; |
uint32_t simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD8; |
uint32_t return_format; |
switch (dst.type) { |
case BRW_REGISTER_TYPE_D: |
return_format = BRW_SAMPLER_RETURN_FORMAT_SINT32; |
break; |
case BRW_REGISTER_TYPE_UD: |
return_format = BRW_SAMPLER_RETURN_FORMAT_UINT32; |
break; |
default: |
return_format = BRW_SAMPLER_RETURN_FORMAT_FLOAT32; |
break; |
} |
if (dispatch_width == 16) |
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16; |
if (brw->gen >= 5) { |
switch (inst->opcode) { |
case SHADER_OPCODE_TEX: |
if (inst->shadow_compare) { |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_COMPARE; |
} else { |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE; |
} |
break; |
case FS_OPCODE_TXB: |
if (inst->shadow_compare) { |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS_COMPARE; |
} else { |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_BIAS; |
} |
break; |
case SHADER_OPCODE_TXL: |
if (inst->shadow_compare) { |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LOD_COMPARE; |
} else { |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LOD; |
} |
break; |
case SHADER_OPCODE_TXS: |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_RESINFO; |
break; |
case SHADER_OPCODE_TXD: |
if (inst->shadow_compare) { |
/* Gen7.5+. Otherwise, lowered by brw_lower_texture_gradients(). */ |
assert(brw->is_haswell); |
msg_type = HSW_SAMPLER_MESSAGE_SAMPLE_DERIV_COMPARE; |
} else { |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_DERIVS; |
} |
break; |
case SHADER_OPCODE_TXF: |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LD; |
break; |
case SHADER_OPCODE_TXF_MS: |
if (brw->gen >= 7) |
msg_type = GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DMS; |
else |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LD; |
break; |
case SHADER_OPCODE_LOD: |
msg_type = GEN5_SAMPLER_MESSAGE_LOD; |
break; |
default: |
assert(!"not reached"); |
break; |
} |
} else { |
switch (inst->opcode) { |
case SHADER_OPCODE_TEX: |
/* Note that G45 and older determines shadow compare and dispatch width |
* from message length for most messages. |
*/ |
assert(dispatch_width == 8); |
msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE; |
if (inst->shadow_compare) { |
assert(inst->mlen == 6); |
} else { |
assert(inst->mlen <= 4); |
} |
break; |
case FS_OPCODE_TXB: |
if (inst->shadow_compare) { |
assert(inst->mlen == 6); |
msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_BIAS_COMPARE; |
} else { |
assert(inst->mlen == 9); |
msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS; |
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16; |
} |
break; |
case SHADER_OPCODE_TXL: |
if (inst->shadow_compare) { |
assert(inst->mlen == 6); |
msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_LOD_COMPARE; |
} else { |
assert(inst->mlen == 9); |
msg_type = BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_LOD; |
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16; |
} |
break; |
case SHADER_OPCODE_TXD: |
/* There is no sample_d_c message; comparisons are done manually */ |
assert(inst->mlen == 7 || inst->mlen == 10); |
msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_GRADIENTS; |
break; |
case SHADER_OPCODE_TXF: |
assert(inst->mlen == 9); |
msg_type = BRW_SAMPLER_MESSAGE_SIMD16_LD; |
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16; |
break; |
case SHADER_OPCODE_TXS: |
assert(inst->mlen == 3); |
msg_type = BRW_SAMPLER_MESSAGE_SIMD16_RESINFO; |
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16; |
break; |
default: |
assert(!"not reached"); |
break; |
} |
} |
assert(msg_type != -1); |
if (simd_mode == BRW_SAMPLER_SIMD_MODE_SIMD16) { |
rlen = 8; |
dst = vec16(dst); |
} |
/* Load the message header if present. If there's a texture offset, |
* we need to set it up explicitly and load the offset bitfield. |
* Otherwise, we can use an implied move from g0 to the first message reg. |
*/ |
if (inst->texture_offset) { |
brw_push_insn_state(p); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
/* Explicitly set up the message header by copying g0 to the MRF. */ |
brw_MOV(p, retype(brw_message_reg(inst->base_mrf), BRW_REGISTER_TYPE_UD), |
retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)); |
/* Then set the offset bits in DWord 2. */ |
brw_MOV(p, retype(brw_vec1_reg(BRW_MESSAGE_REGISTER_FILE, |
inst->base_mrf, 2), BRW_REGISTER_TYPE_UD), |
brw_imm_ud(inst->texture_offset)); |
brw_pop_insn_state(p); |
} else if (inst->header_present) { |
/* Set up an implied move from g0 to the MRF. */ |
src = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW); |
} |
brw_SAMPLE(p, |
retype(dst, BRW_REGISTER_TYPE_UW), |
inst->base_mrf, |
src, |
SURF_INDEX_TEXTURE(inst->sampler), |
inst->sampler, |
msg_type, |
rlen, |
inst->mlen, |
inst->header_present, |
simd_mode, |
return_format); |
} |
/* For OPCODE_DDX and OPCODE_DDY, per channel of output we've got input |
* looking like: |
* |
* arg0: ss0.tl ss0.tr ss0.bl ss0.br ss1.tl ss1.tr ss1.bl ss1.br |
* |
* and we're trying to produce: |
* |
* DDX DDY |
* dst: (ss0.tr - ss0.tl) (ss0.tl - ss0.bl) |
* (ss0.tr - ss0.tl) (ss0.tr - ss0.br) |
* (ss0.br - ss0.bl) (ss0.tl - ss0.bl) |
* (ss0.br - ss0.bl) (ss0.tr - ss0.br) |
* (ss1.tr - ss1.tl) (ss1.tl - ss1.bl) |
* (ss1.tr - ss1.tl) (ss1.tr - ss1.br) |
* (ss1.br - ss1.bl) (ss1.tl - ss1.bl) |
* (ss1.br - ss1.bl) (ss1.tr - ss1.br) |
* |
* and add another set of two more subspans if in 16-pixel dispatch mode. |
* |
* For DDX, it ends up being easy: width = 2, horiz=0 gets us the same result |
* for each pair, and vertstride = 2 jumps us 2 elements after processing a |
* pair. But for DDY, it's harder, as we want to produce the pairs swizzled |
* between each other. We could probably do it like ddx and swizzle the right |
* order later, but bail for now and just produce |
* ((ss0.tl - ss0.bl)x4 (ss1.tl - ss1.bl)x4) |
*/ |
void |
fs_generator::generate_ddx(fs_inst *inst, struct brw_reg dst, struct brw_reg src) |
{ |
struct brw_reg src0 = brw_reg(src.file, src.nr, 1, |
BRW_REGISTER_TYPE_F, |
BRW_VERTICAL_STRIDE_2, |
BRW_WIDTH_2, |
BRW_HORIZONTAL_STRIDE_0, |
BRW_SWIZZLE_XYZW, WRITEMASK_XYZW); |
struct brw_reg src1 = brw_reg(src.file, src.nr, 0, |
BRW_REGISTER_TYPE_F, |
BRW_VERTICAL_STRIDE_2, |
BRW_WIDTH_2, |
BRW_HORIZONTAL_STRIDE_0, |
BRW_SWIZZLE_XYZW, WRITEMASK_XYZW); |
brw_ADD(p, dst, src0, negate(src1)); |
} |
/* The negate_value boolean is used to negate the derivative computation for |
* FBOs, since they place the origin at the upper left instead of the lower |
* left. |
*/ |
void |
fs_generator::generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src, |
bool negate_value) |
{ |
struct brw_reg src0 = brw_reg(src.file, src.nr, 0, |
BRW_REGISTER_TYPE_F, |
BRW_VERTICAL_STRIDE_4, |
BRW_WIDTH_4, |
BRW_HORIZONTAL_STRIDE_0, |
BRW_SWIZZLE_XYZW, WRITEMASK_XYZW); |
struct brw_reg src1 = brw_reg(src.file, src.nr, 2, |
BRW_REGISTER_TYPE_F, |
BRW_VERTICAL_STRIDE_4, |
BRW_WIDTH_4, |
BRW_HORIZONTAL_STRIDE_0, |
BRW_SWIZZLE_XYZW, WRITEMASK_XYZW); |
if (negate_value) |
brw_ADD(p, dst, src1, negate(src0)); |
else |
brw_ADD(p, dst, src0, negate(src1)); |
} |
void |
fs_generator::generate_discard_jump(fs_inst *inst) |
{ |
assert(brw->gen >= 6); |
/* This HALT will be patched up at FB write time to point UIP at the end of |
* the program, and at brw_uip_jip() JIP will be set to the end of the |
* current block (or the program). |
*/ |
this->discard_halt_patches.push_tail(new(mem_ctx) ip_record(p->nr_insn)); |
brw_push_insn_state(p); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
gen6_HALT(p); |
brw_pop_insn_state(p); |
} |
void |
fs_generator::generate_spill(fs_inst *inst, struct brw_reg src) |
{ |
assert(inst->mlen != 0); |
brw_MOV(p, |
retype(brw_message_reg(inst->base_mrf + 1), BRW_REGISTER_TYPE_UD), |
retype(src, BRW_REGISTER_TYPE_UD)); |
brw_oword_block_write_scratch(p, brw_message_reg(inst->base_mrf), 1, |
inst->offset); |
} |
void |
fs_generator::generate_unspill(fs_inst *inst, struct brw_reg dst) |
{ |
assert(inst->mlen != 0); |
brw_oword_block_read_scratch(p, dst, brw_message_reg(inst->base_mrf), 1, |
inst->offset); |
} |
void |
fs_generator::generate_uniform_pull_constant_load(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg index, |
struct brw_reg offset) |
{ |
assert(inst->mlen != 0); |
assert(index.file == BRW_IMMEDIATE_VALUE && |
index.type == BRW_REGISTER_TYPE_UD); |
uint32_t surf_index = index.dw1.ud; |
assert(offset.file == BRW_IMMEDIATE_VALUE && |
offset.type == BRW_REGISTER_TYPE_UD); |
uint32_t read_offset = offset.dw1.ud; |
brw_oword_block_read(p, dst, brw_message_reg(inst->base_mrf), |
read_offset, surf_index); |
} |
void |
fs_generator::generate_uniform_pull_constant_load_gen7(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg index, |
struct brw_reg offset) |
{ |
assert(inst->mlen == 0); |
assert(index.file == BRW_IMMEDIATE_VALUE && |
index.type == BRW_REGISTER_TYPE_UD); |
uint32_t surf_index = index.dw1.ud; |
assert(offset.file == BRW_GENERAL_REGISTER_FILE); |
/* Reference just the dword we need, to avoid angering validate_reg(). */ |
offset = brw_vec1_grf(offset.nr, 0); |
brw_push_insn_state(p); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND); |
brw_pop_insn_state(p); |
/* We use the SIMD4x2 mode because we want to end up with 4 components in |
* the destination loaded consecutively from the same offset (which appears |
* in the first component, and the rest are ignored). |
*/ |
dst.width = BRW_WIDTH_4; |
brw_set_dest(p, send, dst); |
brw_set_src0(p, send, offset); |
brw_set_sampler_message(p, send, |
surf_index, |
0, /* LD message ignores sampler unit */ |
GEN5_SAMPLER_MESSAGE_SAMPLE_LD, |
1, /* rlen */ |
1, /* mlen */ |
false, /* no header */ |
BRW_SAMPLER_SIMD_MODE_SIMD4X2, |
0); |
} |
void |
fs_generator::generate_varying_pull_constant_load(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg index, |
struct brw_reg offset) |
{ |
assert(brw->gen < 7); /* Should use the gen7 variant. */ |
assert(inst->header_present); |
assert(inst->mlen); |
assert(index.file == BRW_IMMEDIATE_VALUE && |
index.type == BRW_REGISTER_TYPE_UD); |
uint32_t surf_index = index.dw1.ud; |
uint32_t simd_mode, rlen, msg_type; |
if (dispatch_width == 16) { |
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16; |
rlen = 8; |
} else { |
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD8; |
rlen = 4; |
} |
if (brw->gen >= 5) |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LD; |
else { |
/* We always use the SIMD16 message so that we only have to load U, and |
* not V or R. |
*/ |
msg_type = BRW_SAMPLER_MESSAGE_SIMD16_LD; |
assert(inst->mlen == 3); |
assert(inst->regs_written == 8); |
rlen = 8; |
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16; |
} |
struct brw_reg offset_mrf = retype(brw_message_reg(inst->base_mrf + 1), |
BRW_REGISTER_TYPE_D); |
brw_MOV(p, offset_mrf, offset); |
struct brw_reg header = brw_vec8_grf(0, 0); |
gen6_resolve_implied_move(p, &header, inst->base_mrf); |
struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND); |
send->header.compression_control = BRW_COMPRESSION_NONE; |
brw_set_dest(p, send, dst); |
brw_set_src0(p, send, header); |
if (brw->gen < 6) |
send->header.destreg__conditionalmod = inst->base_mrf; |
/* Our surface is set up as floats, regardless of what actual data is |
* stored in it. |
*/ |
uint32_t return_format = BRW_SAMPLER_RETURN_FORMAT_FLOAT32; |
brw_set_sampler_message(p, send, |
surf_index, |
0, /* sampler (unused) */ |
msg_type, |
rlen, |
inst->mlen, |
inst->header_present, |
simd_mode, |
return_format); |
} |
void |
fs_generator::generate_varying_pull_constant_load_gen7(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg index, |
struct brw_reg offset) |
{ |
assert(brw->gen >= 7); |
/* Varying-offset pull constant loads are treated as a normal expression on |
* gen7, so the fact that it's a send message is hidden at the IR level. |
*/ |
assert(!inst->header_present); |
assert(!inst->mlen); |
assert(index.file == BRW_IMMEDIATE_VALUE && |
index.type == BRW_REGISTER_TYPE_UD); |
uint32_t surf_index = index.dw1.ud; |
uint32_t simd_mode, rlen, mlen; |
if (dispatch_width == 16) { |
mlen = 2; |
rlen = 8; |
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD16; |
} else { |
mlen = 1; |
rlen = 4; |
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD8; |
} |
struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND); |
brw_set_dest(p, send, dst); |
brw_set_src0(p, send, offset); |
brw_set_sampler_message(p, send, |
surf_index, |
0, /* LD message ignores sampler unit */ |
GEN5_SAMPLER_MESSAGE_SAMPLE_LD, |
rlen, |
mlen, |
false, /* no header */ |
simd_mode, |
0); |
} |
/** |
* Cause the current pixel/sample mask (from R1.7 bits 15:0) to be transferred |
* into the flags register (f0.0). |
* |
* Used only on Gen6 and above. |
*/ |
void |
fs_generator::generate_mov_dispatch_to_flags(fs_inst *inst) |
{ |
struct brw_reg flags = brw_flag_reg(0, inst->flag_subreg); |
struct brw_reg dispatch_mask; |
if (brw->gen >= 6) |
dispatch_mask = retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW); |
else |
dispatch_mask = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW); |
brw_push_insn_state(p); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
brw_MOV(p, flags, dispatch_mask); |
brw_pop_insn_state(p); |
} |
static uint32_t brw_file_from_reg(fs_reg *reg) |
{ |
switch (reg->file) { |
case ARF: |
return BRW_ARCHITECTURE_REGISTER_FILE; |
case GRF: |
return BRW_GENERAL_REGISTER_FILE; |
case MRF: |
return BRW_MESSAGE_REGISTER_FILE; |
case IMM: |
return BRW_IMMEDIATE_VALUE; |
default: |
assert(!"not reached"); |
return BRW_GENERAL_REGISTER_FILE; |
} |
} |
static struct brw_reg |
brw_reg_from_fs_reg(fs_reg *reg) |
{ |
struct brw_reg brw_reg; |
switch (reg->file) { |
case GRF: |
case ARF: |
case MRF: |
if (reg->smear == -1) { |
brw_reg = brw_vec8_reg(brw_file_from_reg(reg), reg->reg, 0); |
} else { |
brw_reg = brw_vec1_reg(brw_file_from_reg(reg), reg->reg, reg->smear); |
} |
brw_reg = retype(brw_reg, reg->type); |
if (reg->sechalf) |
brw_reg = sechalf(brw_reg); |
break; |
case IMM: |
switch (reg->type) { |
case BRW_REGISTER_TYPE_F: |
brw_reg = brw_imm_f(reg->imm.f); |
break; |
case BRW_REGISTER_TYPE_D: |
brw_reg = brw_imm_d(reg->imm.i); |
break; |
case BRW_REGISTER_TYPE_UD: |
brw_reg = brw_imm_ud(reg->imm.u); |
break; |
default: |
assert(!"not reached"); |
brw_reg = brw_null_reg(); |
break; |
} |
break; |
case HW_REG: |
brw_reg = reg->fixed_hw_reg; |
break; |
case BAD_FILE: |
/* Probably unused. */ |
brw_reg = brw_null_reg(); |
break; |
case UNIFORM: |
assert(!"not reached"); |
brw_reg = brw_null_reg(); |
break; |
default: |
assert(!"not reached"); |
brw_reg = brw_null_reg(); |
break; |
} |
if (reg->abs) |
brw_reg = brw_abs(brw_reg); |
if (reg->negate) |
brw_reg = negate(brw_reg); |
return brw_reg; |
} |
/** |
* Sets the first word of a vgrf for gen7+ simd4x2 uniform pull constant |
* sampler LD messages. |
* |
* We don't want to bake it into the send message's code generation because |
* that means we don't get a chance to schedule the instructions. |
*/ |
void |
fs_generator::generate_set_simd4x2_offset(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg value) |
{ |
assert(value.file == BRW_IMMEDIATE_VALUE); |
brw_push_insn_state(p); |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
brw_MOV(p, retype(brw_vec1_reg(dst.file, dst.nr, 0), value.type), value); |
brw_pop_insn_state(p); |
} |
/** |
* Change the register's data type from UD to W, doubling the strides in order |
* to compensate for halving the data type width. |
*/ |
static struct brw_reg |
ud_reg_to_w(struct brw_reg r) |
{ |
assert(r.type == BRW_REGISTER_TYPE_UD); |
r.type = BRW_REGISTER_TYPE_W; |
/* The BRW_*_STRIDE enums are defined so that incrementing the field |
* doubles the real stride. |
*/ |
if (r.hstride != 0) |
++r.hstride; |
if (r.vstride != 0) |
++r.vstride; |
return r; |
} |
void |
fs_generator::generate_pack_half_2x16_split(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg x, |
struct brw_reg y) |
{ |
assert(brw->gen >= 7); |
assert(dst.type == BRW_REGISTER_TYPE_UD); |
assert(x.type == BRW_REGISTER_TYPE_F); |
assert(y.type == BRW_REGISTER_TYPE_F); |
/* From the Ivybridge PRM, Vol4, Part3, Section 6.27 f32to16: |
* |
* Because this instruction does not have a 16-bit floating-point type, |
* the destination data type must be Word (W). |
* |
* The destination must be DWord-aligned and specify a horizontal stride |
* (HorzStride) of 2. The 16-bit result is stored in the lower word of |
* each destination channel and the upper word is not modified. |
*/ |
struct brw_reg dst_w = ud_reg_to_w(dst); |
/* Give each 32-bit channel of dst the form below , where "." means |
* unchanged. |
* 0x....hhhh |
*/ |
brw_F32TO16(p, dst_w, y); |
/* Now the form: |
* 0xhhhh0000 |
*/ |
brw_SHL(p, dst, dst, brw_imm_ud(16u)); |
/* And, finally the form of packHalf2x16's output: |
* 0xhhhhllll |
*/ |
brw_F32TO16(p, dst_w, x); |
} |
void |
fs_generator::generate_unpack_half_2x16_split(fs_inst *inst, |
struct brw_reg dst, |
struct brw_reg src) |
{ |
assert(brw->gen >= 7); |
assert(dst.type == BRW_REGISTER_TYPE_F); |
assert(src.type == BRW_REGISTER_TYPE_UD); |
/* From the Ivybridge PRM, Vol4, Part3, Section 6.26 f16to32: |
* |
* Because this instruction does not have a 16-bit floating-point type, |
* the source data type must be Word (W). The destination type must be |
* F (Float). |
*/ |
struct brw_reg src_w = ud_reg_to_w(src); |
/* Each channel of src has the form of unpackHalf2x16's input: 0xhhhhllll. |
* For the Y case, we wish to access only the upper word; therefore |
* a 16-bit subregister offset is needed. |
*/ |
assert(inst->opcode == FS_OPCODE_UNPACK_HALF_2x16_SPLIT_X || |
inst->opcode == FS_OPCODE_UNPACK_HALF_2x16_SPLIT_Y); |
if (inst->opcode == FS_OPCODE_UNPACK_HALF_2x16_SPLIT_Y) |
src_w.subnr += 2; |
brw_F16TO32(p, dst, src_w); |
} |
void |
fs_generator::generate_shader_time_add(fs_inst *inst, |
struct brw_reg payload, |
struct brw_reg offset, |
struct brw_reg value) |
{ |
assert(brw->gen >= 7); |
brw_push_insn_state(p); |
brw_set_mask_control(p, true); |
assert(payload.file == BRW_GENERAL_REGISTER_FILE); |
struct brw_reg payload_offset = retype(brw_vec1_grf(payload.nr, 0), |
offset.type); |
struct brw_reg payload_value = retype(brw_vec1_grf(payload.nr + 1, 0), |
value.type); |
assert(offset.file == BRW_IMMEDIATE_VALUE); |
if (value.file == BRW_GENERAL_REGISTER_FILE) { |
value.width = BRW_WIDTH_1; |
value.hstride = BRW_HORIZONTAL_STRIDE_0; |
value.vstride = BRW_VERTICAL_STRIDE_0; |
} else { |
assert(value.file == BRW_IMMEDIATE_VALUE); |
} |
/* Trying to deal with setup of the params from the IR is crazy in the FS8 |
* case, and we don't really care about squeezing every bit of performance |
* out of this path, so we just emit the MOVs from here. |
*/ |
brw_MOV(p, payload_offset, offset); |
brw_MOV(p, payload_value, value); |
brw_shader_time_add(p, payload, SURF_INDEX_WM_SHADER_TIME); |
brw_pop_insn_state(p); |
} |
void |
fs_generator::generate_code(exec_list *instructions) |
{ |
int last_native_insn_offset = p->next_insn_offset; |
const char *last_annotation_string = NULL; |
const void *last_annotation_ir = NULL; |
if (unlikely(INTEL_DEBUG & DEBUG_WM)) { |
if (shader) { |
printf("Native code for fragment shader %d (%d-wide dispatch):\n", |
prog->Name, dispatch_width); |
} else { |
printf("Native code for fragment program %d (%d-wide dispatch):\n", |
fp->Base.Id, dispatch_width); |
} |
} |
cfg_t *cfg = NULL; |
if (unlikely(INTEL_DEBUG & DEBUG_WM)) |
cfg = new(mem_ctx) cfg_t(mem_ctx, instructions); |
foreach_list(node, instructions) { |
fs_inst *inst = (fs_inst *)node; |
struct brw_reg src[3], dst; |
if (unlikely(INTEL_DEBUG & DEBUG_WM)) { |
foreach_list(node, &cfg->block_list) { |
bblock_link *link = (bblock_link *)node; |
bblock_t *block = link->block; |
if (block->start == inst) { |
printf(" START B%d", block->block_num); |
foreach_list(predecessor_node, &block->parents) { |
bblock_link *predecessor_link = |
(bblock_link *)predecessor_node; |
bblock_t *predecessor_block = predecessor_link->block; |
printf(" <-B%d", predecessor_block->block_num); |
} |
printf("\n"); |
} |
} |
if (last_annotation_ir != inst->ir) { |
last_annotation_ir = inst->ir; |
if (last_annotation_ir) { |
printf(" "); |
if (shader) |
((ir_instruction *)inst->ir)->print(); |
else { |
const prog_instruction *fpi; |
fpi = (const prog_instruction *)inst->ir; |
printf("%d: ", (int)(fpi - fp->Base.Instructions)); |
_mesa_fprint_instruction_opt(stdout, |
fpi, |
0, PROG_PRINT_DEBUG, NULL); |
} |
printf("\n"); |
} |
} |
if (last_annotation_string != inst->annotation) { |
last_annotation_string = inst->annotation; |
if (last_annotation_string) |
printf(" %s\n", last_annotation_string); |
} |
} |
for (unsigned int i = 0; i < 3; i++) { |
src[i] = brw_reg_from_fs_reg(&inst->src[i]); |
/* The accumulator result appears to get used for the |
* conditional modifier generation. When negating a UD |
* value, there is a 33rd bit generated for the sign in the |
* accumulator value, so now you can't check, for example, |
* equality with a 32-bit value. See piglit fs-op-neg-uvec4. |
*/ |
assert(!inst->conditional_mod || |
inst->src[i].type != BRW_REGISTER_TYPE_UD || |
!inst->src[i].negate); |
} |
dst = brw_reg_from_fs_reg(&inst->dst); |
brw_set_conditionalmod(p, inst->conditional_mod); |
brw_set_predicate_control(p, inst->predicate); |
brw_set_predicate_inverse(p, inst->predicate_inverse); |
brw_set_flag_reg(p, 0, inst->flag_subreg); |
brw_set_saturate(p, inst->saturate); |
brw_set_mask_control(p, inst->force_writemask_all); |
if (inst->force_uncompressed || dispatch_width == 8) { |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
} else if (inst->force_sechalf) { |
brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); |
} else { |
brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED); |
} |
switch (inst->opcode) { |
case BRW_OPCODE_MOV: |
brw_MOV(p, dst, src[0]); |
break; |
case BRW_OPCODE_ADD: |
brw_ADD(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_MUL: |
brw_MUL(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_MACH: |
brw_set_acc_write_control(p, 1); |
brw_MACH(p, dst, src[0], src[1]); |
brw_set_acc_write_control(p, 0); |
break; |
case BRW_OPCODE_MAD: |
brw_set_access_mode(p, BRW_ALIGN_16); |
if (dispatch_width == 16) { |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_MAD(p, dst, src[0], src[1], src[2]); |
brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); |
brw_MAD(p, sechalf(dst), sechalf(src[0]), sechalf(src[1]), sechalf(src[2])); |
brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED); |
} else { |
brw_MAD(p, dst, src[0], src[1], src[2]); |
} |
brw_set_access_mode(p, BRW_ALIGN_1); |
break; |
case BRW_OPCODE_LRP: |
brw_set_access_mode(p, BRW_ALIGN_16); |
if (dispatch_width == 16) { |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_LRP(p, dst, src[0], src[1], src[2]); |
brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); |
brw_LRP(p, sechalf(dst), sechalf(src[0]), sechalf(src[1]), sechalf(src[2])); |
brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED); |
} else { |
brw_LRP(p, dst, src[0], src[1], src[2]); |
} |
brw_set_access_mode(p, BRW_ALIGN_1); |
break; |
case BRW_OPCODE_FRC: |
brw_FRC(p, dst, src[0]); |
break; |
case BRW_OPCODE_RNDD: |
brw_RNDD(p, dst, src[0]); |
break; |
case BRW_OPCODE_RNDE: |
brw_RNDE(p, dst, src[0]); |
break; |
case BRW_OPCODE_RNDZ: |
brw_RNDZ(p, dst, src[0]); |
break; |
case BRW_OPCODE_AND: |
brw_AND(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_OR: |
brw_OR(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_XOR: |
brw_XOR(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_NOT: |
brw_NOT(p, dst, src[0]); |
break; |
case BRW_OPCODE_ASR: |
brw_ASR(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_SHR: |
brw_SHR(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_SHL: |
brw_SHL(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_F32TO16: |
brw_F32TO16(p, dst, src[0]); |
break; |
case BRW_OPCODE_F16TO32: |
brw_F16TO32(p, dst, src[0]); |
break; |
case BRW_OPCODE_CMP: |
brw_CMP(p, dst, inst->conditional_mod, src[0], src[1]); |
break; |
case BRW_OPCODE_SEL: |
brw_SEL(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_BFREV: |
/* BFREV only supports UD type for src and dst. */ |
brw_BFREV(p, retype(dst, BRW_REGISTER_TYPE_UD), |
retype(src[0], BRW_REGISTER_TYPE_UD)); |
break; |
case BRW_OPCODE_FBH: |
/* FBH only supports UD type for dst. */ |
brw_FBH(p, retype(dst, BRW_REGISTER_TYPE_UD), src[0]); |
break; |
case BRW_OPCODE_FBL: |
/* FBL only supports UD type for dst. */ |
brw_FBL(p, retype(dst, BRW_REGISTER_TYPE_UD), src[0]); |
break; |
case BRW_OPCODE_CBIT: |
/* CBIT only supports UD type for dst. */ |
brw_CBIT(p, retype(dst, BRW_REGISTER_TYPE_UD), src[0]); |
break; |
case BRW_OPCODE_BFE: |
brw_set_access_mode(p, BRW_ALIGN_16); |
if (dispatch_width == 16) { |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_BFE(p, dst, src[0], src[1], src[2]); |
brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); |
brw_BFE(p, sechalf(dst), sechalf(src[0]), sechalf(src[1]), sechalf(src[2])); |
brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED); |
} else { |
brw_BFE(p, dst, src[0], src[1], src[2]); |
} |
brw_set_access_mode(p, BRW_ALIGN_1); |
break; |
case BRW_OPCODE_BFI1: |
brw_BFI1(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_BFI2: |
brw_set_access_mode(p, BRW_ALIGN_16); |
if (dispatch_width == 16) { |
brw_set_compression_control(p, BRW_COMPRESSION_NONE); |
brw_BFI2(p, dst, src[0], src[1], src[2]); |
brw_set_compression_control(p, BRW_COMPRESSION_2NDHALF); |
brw_BFI2(p, sechalf(dst), sechalf(src[0]), sechalf(src[1]), sechalf(src[2])); |
brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED); |
} else { |
brw_BFI2(p, dst, src[0], src[1], src[2]); |
} |
brw_set_access_mode(p, BRW_ALIGN_1); |
break; |
case BRW_OPCODE_IF: |
if (inst->src[0].file != BAD_FILE) { |
/* The instruction has an embedded compare (only allowed on gen6) */ |
assert(brw->gen == 6); |
gen6_IF(p, inst->conditional_mod, src[0], src[1]); |
} else { |
brw_IF(p, dispatch_width == 16 ? BRW_EXECUTE_16 : BRW_EXECUTE_8); |
} |
break; |
case BRW_OPCODE_ELSE: |
brw_ELSE(p); |
break; |
case BRW_OPCODE_ENDIF: |
brw_ENDIF(p); |
break; |
case BRW_OPCODE_DO: |
brw_DO(p, BRW_EXECUTE_8); |
break; |
case BRW_OPCODE_BREAK: |
brw_BREAK(p); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
break; |
case BRW_OPCODE_CONTINUE: |
/* FINISHME: We need to write the loop instruction support still. */ |
if (brw->gen >= 6) |
gen6_CONT(p); |
else |
brw_CONT(p); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
break; |
case BRW_OPCODE_WHILE: |
brw_WHILE(p); |
break; |
case SHADER_OPCODE_RCP: |
case SHADER_OPCODE_RSQ: |
case SHADER_OPCODE_SQRT: |
case SHADER_OPCODE_EXP2: |
case SHADER_OPCODE_LOG2: |
case SHADER_OPCODE_SIN: |
case SHADER_OPCODE_COS: |
if (brw->gen >= 7) { |
generate_math1_gen7(inst, dst, src[0]); |
} else if (brw->gen == 6) { |
generate_math1_gen6(inst, dst, src[0]); |
} else if (brw->gen == 5 || brw->is_g4x) { |
generate_math_g45(inst, dst, src[0]); |
} else { |
generate_math_gen4(inst, dst, src[0]); |
} |
break; |
case SHADER_OPCODE_INT_QUOTIENT: |
case SHADER_OPCODE_INT_REMAINDER: |
case SHADER_OPCODE_POW: |
if (brw->gen >= 7) { |
generate_math2_gen7(inst, dst, src[0], src[1]); |
} else if (brw->gen == 6) { |
generate_math2_gen6(inst, dst, src[0], src[1]); |
} else { |
generate_math_gen4(inst, dst, src[0]); |
} |
break; |
case FS_OPCODE_PIXEL_X: |
generate_pixel_xy(dst, true); |
break; |
case FS_OPCODE_PIXEL_Y: |
generate_pixel_xy(dst, false); |
break; |
case FS_OPCODE_CINTERP: |
brw_MOV(p, dst, src[0]); |
break; |
case FS_OPCODE_LINTERP: |
generate_linterp(inst, dst, src); |
break; |
case SHADER_OPCODE_TEX: |
case FS_OPCODE_TXB: |
case SHADER_OPCODE_TXD: |
case SHADER_OPCODE_TXF: |
case SHADER_OPCODE_TXF_MS: |
case SHADER_OPCODE_TXL: |
case SHADER_OPCODE_TXS: |
case SHADER_OPCODE_LOD: |
generate_tex(inst, dst, src[0]); |
break; |
case FS_OPCODE_DDX: |
generate_ddx(inst, dst, src[0]); |
break; |
case FS_OPCODE_DDY: |
/* Make sure fp->UsesDFdy flag got set (otherwise there's no |
* guarantee that c->key.render_to_fbo is set). |
*/ |
assert(fp->UsesDFdy); |
generate_ddy(inst, dst, src[0], c->key.render_to_fbo); |
break; |
case FS_OPCODE_SPILL: |
generate_spill(inst, src[0]); |
break; |
case FS_OPCODE_UNSPILL: |
generate_unspill(inst, dst); |
break; |
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD: |
generate_uniform_pull_constant_load(inst, dst, src[0], src[1]); |
break; |
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD_GEN7: |
generate_uniform_pull_constant_load_gen7(inst, dst, src[0], src[1]); |
break; |
case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD: |
generate_varying_pull_constant_load(inst, dst, src[0], src[1]); |
break; |
case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7: |
generate_varying_pull_constant_load_gen7(inst, dst, src[0], src[1]); |
break; |
case FS_OPCODE_FB_WRITE: |
generate_fb_write(inst); |
break; |
case FS_OPCODE_MOV_DISPATCH_TO_FLAGS: |
generate_mov_dispatch_to_flags(inst); |
break; |
case FS_OPCODE_DISCARD_JUMP: |
generate_discard_jump(inst); |
break; |
case SHADER_OPCODE_SHADER_TIME_ADD: |
generate_shader_time_add(inst, src[0], src[1], src[2]); |
break; |
case FS_OPCODE_SET_SIMD4X2_OFFSET: |
generate_set_simd4x2_offset(inst, dst, src[0]); |
break; |
case FS_OPCODE_PACK_HALF_2x16_SPLIT: |
generate_pack_half_2x16_split(inst, dst, src[0], src[1]); |
break; |
case FS_OPCODE_UNPACK_HALF_2x16_SPLIT_X: |
case FS_OPCODE_UNPACK_HALF_2x16_SPLIT_Y: |
generate_unpack_half_2x16_split(inst, dst, src[0]); |
break; |
case FS_OPCODE_PLACEHOLDER_HALT: |
/* This is the place where the final HALT needs to be inserted if |
* we've emitted any discards. If not, this will emit no code. |
*/ |
patch_discard_jumps_to_fb_writes(); |
break; |
default: |
if (inst->opcode < (int) ARRAY_SIZE(opcode_descs)) { |
_mesa_problem(ctx, "Unsupported opcode `%s' in FS", |
opcode_descs[inst->opcode].name); |
} else { |
_mesa_problem(ctx, "Unsupported opcode %d in FS", inst->opcode); |
} |
abort(); |
} |
if (unlikely(INTEL_DEBUG & DEBUG_WM)) { |
brw_dump_compile(p, stdout, |
last_native_insn_offset, p->next_insn_offset); |
foreach_list(node, &cfg->block_list) { |
bblock_link *link = (bblock_link *)node; |
bblock_t *block = link->block; |
if (block->end == inst) { |
printf(" END B%d", block->block_num); |
foreach_list(successor_node, &block->children) { |
bblock_link *successor_link = |
(bblock_link *)successor_node; |
bblock_t *successor_block = successor_link->block; |
printf(" ->B%d", successor_block->block_num); |
} |
printf("\n"); |
} |
} |
} |
last_native_insn_offset = p->next_insn_offset; |
} |
if (unlikely(INTEL_DEBUG & DEBUG_WM)) { |
printf("\n"); |
} |
brw_set_uip_jip(p); |
/* OK, while the INTEL_DEBUG=wm above is very nice for debugging FS |
* emit issues, it doesn't get the jump distances into the output, |
* which is often something we want to debug. So this is here in |
* case you're doing that. |
*/ |
if (0) { |
brw_dump_compile(p, stdout, 0, p->next_insn_offset); |
} |
} |
const unsigned * |
fs_generator::generate_assembly(exec_list *simd8_instructions, |
exec_list *simd16_instructions, |
unsigned *assembly_size) |
{ |
dispatch_width = 8; |
generate_code(simd8_instructions); |
if (simd16_instructions) { |
/* We have to do a compaction pass now, or the one at the end of |
* execution will squash down where our prog_offset start needs |
* to be. |
*/ |
brw_compact_instructions(p); |
/* align to 64 byte boundary. */ |
while ((p->nr_insn * sizeof(struct brw_instruction)) % 64) { |
brw_NOP(p); |
} |
/* Save off the start of this 16-wide program */ |
c->prog_data.prog_offset_16 = p->nr_insn * sizeof(struct brw_instruction); |
brw_set_compression_control(p, BRW_COMPRESSION_COMPRESSED); |
dispatch_width = 16; |
generate_code(simd16_instructions); |
} |
return brw_get_program(p, assembly_size); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs_fp.cpp |
---|
0,0 → 1,767 |
/* |
* 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. |
*/ |
/** @file brw_fs_fp.cpp |
* |
* Implementation of the compiler for GL_ARB_fragment_program shaders on top |
* of the GLSL compiler backend. |
*/ |
#include "brw_context.h" |
#include "brw_fs.h" |
static fs_reg |
regoffset(fs_reg reg, int i) |
{ |
reg.reg_offset += i; |
return reg; |
} |
void |
fs_visitor::emit_fp_alu1(enum opcode opcode, |
const struct prog_instruction *fpi, |
fs_reg dst, fs_reg src) |
{ |
for (int i = 0; i < 4; i++) { |
if (fpi->DstReg.WriteMask & (1 << i)) |
emit(opcode, regoffset(dst, i), regoffset(src, i)); |
} |
} |
void |
fs_visitor::emit_fp_alu2(enum opcode opcode, |
const struct prog_instruction *fpi, |
fs_reg dst, fs_reg src0, fs_reg src1) |
{ |
for (int i = 0; i < 4; i++) { |
if (fpi->DstReg.WriteMask & (1 << i)) |
emit(opcode, regoffset(dst, i), |
regoffset(src0, i), regoffset(src1, i)); |
} |
} |
void |
fs_visitor::emit_fp_minmax(const prog_instruction *fpi, |
fs_reg dst, fs_reg src0, fs_reg src1) |
{ |
uint32_t conditionalmod; |
if (fpi->Opcode == OPCODE_MIN) |
conditionalmod = BRW_CONDITIONAL_L; |
else |
conditionalmod = BRW_CONDITIONAL_GE; |
for (int i = 0; i < 4; i++) { |
if (fpi->DstReg.WriteMask & (1 << i)) { |
emit_minmax(conditionalmod, regoffset(dst, i), |
regoffset(src0, i), regoffset(src1, i)); |
} |
} |
} |
void |
fs_visitor::emit_fp_sop(uint32_t conditional_mod, |
const struct prog_instruction *fpi, |
fs_reg dst, fs_reg src0, fs_reg src1, |
fs_reg one) |
{ |
for (int i = 0; i < 4; i++) { |
if (fpi->DstReg.WriteMask & (1 << i)) { |
fs_inst *inst; |
emit(CMP(reg_null_d, regoffset(src0, i), regoffset(src1, i), |
conditional_mod)); |
inst = emit(BRW_OPCODE_SEL, regoffset(dst, i), one, fs_reg(0.0f)); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
} |
} |
void |
fs_visitor::emit_fp_scalar_write(const struct prog_instruction *fpi, |
fs_reg dst, fs_reg src) |
{ |
for (int i = 0; i < 4; i++) { |
if (fpi->DstReg.WriteMask & (1 << i)) |
emit(MOV(regoffset(dst, i), src)); |
} |
} |
void |
fs_visitor::emit_fp_scalar_math(enum opcode opcode, |
const struct prog_instruction *fpi, |
fs_reg dst, fs_reg src) |
{ |
fs_reg temp = fs_reg(this, glsl_type::float_type); |
emit_math(opcode, temp, src); |
emit_fp_scalar_write(fpi, dst, temp); |
} |
void |
fs_visitor::emit_fragment_program_code() |
{ |
setup_fp_regs(); |
fs_reg null = fs_reg(brw_null_reg()); |
/* Keep a reg with 1.0 around, for reuse by emit_fp_sop so that it can just |
* be: |
* |
* sel.f0 dst 1.0 0.0 |
* |
* instead of |
* |
* mov dst 0.0 |
* mov.f0 dst 1.0 |
*/ |
fs_reg one = fs_reg(this, glsl_type::float_type); |
emit(MOV(one, fs_reg(1.0f))); |
for (unsigned int insn = 0; insn < fp->Base.NumInstructions; insn++) { |
const struct prog_instruction *fpi = &fp->Base.Instructions[insn]; |
base_ir = fpi; |
//_mesa_print_instruction(fpi); |
fs_reg dst; |
fs_reg src[3]; |
/* We always emit into a temporary destination register to avoid |
* aliasing issues. |
*/ |
dst = fs_reg(this, glsl_type::vec4_type); |
for (int i = 0; i < 3; i++) |
src[i] = get_fp_src_reg(&fpi->SrcReg[i]); |
switch (fpi->Opcode) { |
case OPCODE_ABS: |
src[0].abs = true; |
src[0].negate = false; |
emit_fp_alu1(BRW_OPCODE_MOV, fpi, dst, src[0]); |
break; |
case OPCODE_ADD: |
emit_fp_alu2(BRW_OPCODE_ADD, fpi, dst, src[0], src[1]); |
break; |
case OPCODE_CMP: |
for (int i = 0; i < 4; i++) { |
if (fpi->DstReg.WriteMask & (1 << i)) { |
fs_inst *inst; |
emit(CMP(null, regoffset(src[0], i), fs_reg(0.0f), |
BRW_CONDITIONAL_L)); |
inst = emit(BRW_OPCODE_SEL, regoffset(dst, i), |
regoffset(src[1], i), regoffset(src[2], i)); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
} |
break; |
case OPCODE_COS: |
emit_fp_scalar_math(SHADER_OPCODE_COS, fpi, dst, src[0]); |
break; |
case OPCODE_DP2: |
case OPCODE_DP3: |
case OPCODE_DP4: |
case OPCODE_DPH: { |
fs_reg mul = fs_reg(this, glsl_type::float_type); |
fs_reg acc = fs_reg(this, glsl_type::float_type); |
int count; |
switch (fpi->Opcode) { |
case OPCODE_DP2: count = 2; break; |
case OPCODE_DP3: count = 3; break; |
case OPCODE_DP4: count = 4; break; |
case OPCODE_DPH: count = 3; break; |
default: assert(!"not reached"); count = 0; break; |
} |
emit(MUL(acc, regoffset(src[0], 0), regoffset(src[1], 0))); |
for (int i = 1; i < count; i++) { |
emit(MUL(mul, regoffset(src[0], i), regoffset(src[1], i))); |
emit(ADD(acc, acc, mul)); |
} |
if (fpi->Opcode == OPCODE_DPH) |
emit(ADD(acc, acc, regoffset(src[1], 3))); |
emit_fp_scalar_write(fpi, dst, acc); |
break; |
} |
case OPCODE_DST: |
if (fpi->DstReg.WriteMask & WRITEMASK_X) |
emit(MOV(dst, fs_reg(1.0f))); |
if (fpi->DstReg.WriteMask & WRITEMASK_Y) { |
emit(MUL(regoffset(dst, 1), |
regoffset(src[0], 1), regoffset(src[1], 1))); |
} |
if (fpi->DstReg.WriteMask & WRITEMASK_Z) |
emit(MOV(regoffset(dst, 2), regoffset(src[0], 2))); |
if (fpi->DstReg.WriteMask & WRITEMASK_W) |
emit(MOV(regoffset(dst, 3), regoffset(src[1], 3))); |
break; |
case OPCODE_EX2: |
emit_fp_scalar_math(SHADER_OPCODE_EXP2, fpi, dst, src[0]); |
break; |
case OPCODE_FLR: |
emit_fp_alu1(BRW_OPCODE_RNDD, fpi, dst, src[0]); |
break; |
case OPCODE_FRC: |
emit_fp_alu1(BRW_OPCODE_FRC, fpi, dst, src[0]); |
break; |
case OPCODE_KIL: { |
for (int i = 0; i < 4; i++) { |
/* In most cases the argument to a KIL will be something like |
* TEMP[0].wwww, so there's no point in checking whether .w is < 0 |
* 4 times in a row. |
*/ |
if (i > 0 && |
GET_SWZ(fpi->SrcReg[0].Swizzle, i) == |
GET_SWZ(fpi->SrcReg[0].Swizzle, i - 1) && |
((fpi->SrcReg[0].Negate >> i) & 1) == |
((fpi->SrcReg[0].Negate >> (i - 1)) & 1)) { |
continue; |
} |
/* Emit an instruction that's predicated on the current |
* undiscarded pixels, and updates just those pixels to be |
* turned off. |
*/ |
fs_inst *cmp = emit(CMP(null, regoffset(src[0], i), fs_reg(0.0f), |
BRW_CONDITIONAL_GE)); |
cmp->predicate = BRW_PREDICATE_NORMAL; |
cmp->flag_subreg = 1; |
} |
break; |
} |
case OPCODE_LG2: |
emit_fp_scalar_math(SHADER_OPCODE_LOG2, fpi, dst, src[0]); |
break; |
case OPCODE_LIT: |
/* From the ARB_fragment_program spec: |
* |
* tmp = VectorLoad(op0); |
* if (tmp.x < 0) tmp.x = 0; |
* if (tmp.y < 0) tmp.y = 0; |
* if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon); |
* else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon; |
* result.x = 1.0; |
* result.y = tmp.x; |
* result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0; |
* result.w = 1.0; |
* |
* Note that we don't do the clamping to +/- 128. We didn't in |
* brw_wm_emit.c either. |
*/ |
if (fpi->DstReg.WriteMask & WRITEMASK_X) |
emit(MOV(regoffset(dst, 0), fs_reg(1.0f))); |
if (fpi->DstReg.WriteMask & WRITEMASK_YZ) { |
fs_inst *inst; |
emit(CMP(null, regoffset(src[0], 0), fs_reg(0.0f), |
BRW_CONDITIONAL_LE)); |
if (fpi->DstReg.WriteMask & WRITEMASK_Y) { |
emit(MOV(regoffset(dst, 1), regoffset(src[0], 0))); |
inst = emit(MOV(regoffset(dst, 1), fs_reg(0.0f))); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
if (fpi->DstReg.WriteMask & WRITEMASK_Z) { |
emit_math(SHADER_OPCODE_POW, regoffset(dst, 2), |
regoffset(src[0], 1), regoffset(src[0], 3)); |
inst = emit(MOV(regoffset(dst, 2), fs_reg(0.0f))); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
} |
if (fpi->DstReg.WriteMask & WRITEMASK_W) |
emit(MOV(regoffset(dst, 3), fs_reg(1.0f))); |
break; |
case OPCODE_LRP: |
for (int i = 0; i < 4; i++) { |
if (fpi->DstReg.WriteMask & (1 << i)) { |
fs_reg a = regoffset(src[0], i); |
fs_reg y = regoffset(src[1], i); |
fs_reg x = regoffset(src[2], i); |
emit_lrp(regoffset(dst, i), x, y, a); |
} |
} |
break; |
case OPCODE_MAD: |
for (int i = 0; i < 4; i++) { |
if (fpi->DstReg.WriteMask & (1 << i)) { |
fs_reg temp = fs_reg(this, glsl_type::float_type); |
emit(MUL(temp, regoffset(src[0], i), regoffset(src[1], i))); |
emit(ADD(regoffset(dst, i), temp, regoffset(src[2], i))); |
} |
} |
break; |
case OPCODE_MAX: |
emit_fp_minmax(fpi, dst, src[0], src[1]); |
break; |
case OPCODE_MOV: |
emit_fp_alu1(BRW_OPCODE_MOV, fpi, dst, src[0]); |
break; |
case OPCODE_MIN: |
emit_fp_minmax(fpi, dst, src[0], src[1]); |
break; |
case OPCODE_MUL: |
emit_fp_alu2(BRW_OPCODE_MUL, fpi, dst, src[0], src[1]); |
break; |
case OPCODE_POW: { |
fs_reg temp = fs_reg(this, glsl_type::float_type); |
emit_math(SHADER_OPCODE_POW, temp, src[0], src[1]); |
emit_fp_scalar_write(fpi, dst, temp); |
break; |
} |
case OPCODE_RCP: |
emit_fp_scalar_math(SHADER_OPCODE_RCP, fpi, dst, src[0]); |
break; |
case OPCODE_RSQ: |
emit_fp_scalar_math(SHADER_OPCODE_RSQ, fpi, dst, src[0]); |
break; |
case OPCODE_SCS: |
if (fpi->DstReg.WriteMask & WRITEMASK_X) { |
emit_math(SHADER_OPCODE_COS, regoffset(dst, 0), |
regoffset(src[0], 0)); |
} |
if (fpi->DstReg.WriteMask & WRITEMASK_Y) { |
emit_math(SHADER_OPCODE_SIN, regoffset(dst, 1), |
regoffset(src[0], 1)); |
} |
break; |
case OPCODE_SGE: |
emit_fp_sop(BRW_CONDITIONAL_GE, fpi, dst, src[0], src[1], one); |
break; |
case OPCODE_SIN: |
emit_fp_scalar_math(SHADER_OPCODE_SIN, fpi, dst, src[0]); |
break; |
case OPCODE_SLT: |
emit_fp_sop(BRW_CONDITIONAL_L, fpi, dst, src[0], src[1], one); |
break; |
case OPCODE_SUB: { |
fs_reg neg_src1 = src[1]; |
neg_src1.negate = !src[1].negate; |
emit_fp_alu2(BRW_OPCODE_ADD, fpi, dst, src[0], neg_src1); |
break; |
} |
case OPCODE_TEX: |
case OPCODE_TXB: |
case OPCODE_TXP: { |
/* We piggy-back on the GLSL IR support for texture setup. To do so, |
* we have to cook up an ir_texture that has the coordinate field |
* with appropriate type, and shadow_comparitor set or not. All the |
* other properties of ir_texture are passed in as arguments to the |
* emit_texture_gen* function. |
*/ |
ir_texture *ir = NULL; |
fs_reg lod; |
fs_reg dpdy; |
fs_reg coordinate = src[0]; |
fs_reg shadow_c; |
fs_reg sample_index; |
switch (fpi->Opcode) { |
case OPCODE_TEX: |
ir = new(mem_ctx) ir_texture(ir_tex); |
break; |
case OPCODE_TXP: { |
ir = new(mem_ctx) ir_texture(ir_tex); |
coordinate = fs_reg(this, glsl_type::vec3_type); |
fs_reg invproj = fs_reg(this, glsl_type::float_type); |
emit_math(SHADER_OPCODE_RCP, invproj, regoffset(src[0], 3)); |
for (int i = 0; i < 3; i++) { |
emit(MUL(regoffset(coordinate, i), |
regoffset(src[0], i), invproj)); |
} |
break; |
} |
case OPCODE_TXB: |
ir = new(mem_ctx) ir_texture(ir_txb); |
lod = regoffset(src[0], 3); |
break; |
default: |
assert(!"not reached"); |
break; |
} |
ir->type = glsl_type::vec4_type; |
const glsl_type *coordinate_type; |
switch (fpi->TexSrcTarget) { |
case TEXTURE_1D_INDEX: |
coordinate_type = glsl_type::float_type; |
break; |
case TEXTURE_2D_INDEX: |
case TEXTURE_1D_ARRAY_INDEX: |
case TEXTURE_RECT_INDEX: |
case TEXTURE_EXTERNAL_INDEX: |
coordinate_type = glsl_type::vec2_type; |
break; |
case TEXTURE_3D_INDEX: |
case TEXTURE_2D_ARRAY_INDEX: |
coordinate_type = glsl_type::vec3_type; |
break; |
case TEXTURE_CUBE_INDEX: { |
coordinate_type = glsl_type::vec3_type; |
fs_reg temp = fs_reg(this, glsl_type::float_type); |
fs_reg cubecoord = fs_reg(this, glsl_type::vec3_type); |
fs_reg abscoord = coordinate; |
abscoord.negate = false; |
abscoord.abs = true; |
emit_minmax(BRW_CONDITIONAL_GE, temp, |
regoffset(abscoord, 0), regoffset(abscoord, 1)); |
emit_minmax(BRW_CONDITIONAL_GE, temp, |
temp, regoffset(abscoord, 2)); |
emit_math(SHADER_OPCODE_RCP, temp, temp); |
for (int i = 0; i < 3; i++) { |
emit(MUL(regoffset(cubecoord, i), |
regoffset(coordinate, i), temp)); |
} |
coordinate = cubecoord; |
break; |
} |
default: |
assert(!"not reached"); |
coordinate_type = glsl_type::vec2_type; |
break; |
} |
ir_constant_data junk_data; |
ir->coordinate = new(mem_ctx) ir_constant(coordinate_type, &junk_data); |
if (fpi->TexShadow) { |
shadow_c = regoffset(coordinate, 2); |
ir->shadow_comparitor = new(mem_ctx) ir_constant(0.0f); |
} |
coordinate = rescale_texcoord(ir, coordinate, |
fpi->TexSrcTarget == TEXTURE_RECT_INDEX, |
fpi->TexSrcUnit, fpi->TexSrcUnit); |
fs_inst *inst; |
if (brw->gen >= 7) { |
inst = emit_texture_gen7(ir, dst, coordinate, shadow_c, lod, dpdy, sample_index); |
} else if (brw->gen >= 5) { |
inst = emit_texture_gen5(ir, dst, coordinate, shadow_c, lod, dpdy, sample_index); |
} else { |
inst = emit_texture_gen4(ir, dst, coordinate, shadow_c, lod, dpdy); |
} |
inst->sampler = fpi->TexSrcUnit; |
inst->shadow_compare = fpi->TexShadow; |
/* Reuse the GLSL swizzle_result() handler. */ |
swizzle_result(ir, dst, fpi->TexSrcUnit); |
dst = this->result; |
break; |
} |
case OPCODE_SWZ: |
/* Note that SWZ's extended swizzles are handled in the general |
* get_src_reg() code. |
*/ |
emit_fp_alu1(BRW_OPCODE_MOV, fpi, dst, src[0]); |
break; |
case OPCODE_XPD: |
for (int i = 0; i < 3; i++) { |
if (fpi->DstReg.WriteMask & (1 << i)) { |
int i1 = (i + 1) % 3; |
int i2 = (i + 2) % 3; |
fs_reg temp = fs_reg(this, glsl_type::float_type); |
fs_reg neg_src1_1 = regoffset(src[1], i1); |
neg_src1_1.negate = !neg_src1_1.negate; |
emit(MUL(temp, regoffset(src[0], i2), neg_src1_1)); |
emit(MUL(regoffset(dst, i), |
regoffset(src[0], i1), regoffset(src[1], i2))); |
emit(ADD(regoffset(dst, i), regoffset(dst, i), temp)); |
} |
} |
break; |
case OPCODE_END: |
break; |
default: |
_mesa_problem(ctx, "Unsupported opcode %s in fragment program\n", |
_mesa_opcode_string(fpi->Opcode)); |
} |
/* To handle saturates, we emit a MOV with a saturate bit, which |
* optimization should fold into the preceding instructions when safe. |
*/ |
if (fpi->Opcode != OPCODE_END) { |
fs_reg real_dst = get_fp_dst_reg(&fpi->DstReg); |
for (int i = 0; i < 4; i++) { |
if (fpi->DstReg.WriteMask & (1 << i)) { |
fs_inst *inst = emit(MOV(regoffset(real_dst, i), |
regoffset(dst, i))); |
inst->saturate = fpi->SaturateMode; |
} |
} |
} |
} |
/* Epilogue: |
* |
* Fragment depth has this strange convention of being the .z component of |
* a vec4. emit_fb_write() wants to see a float value, instead. |
*/ |
this->current_annotation = "result.depth write"; |
if (frag_depth.file != BAD_FILE) { |
fs_reg temp = fs_reg(this, glsl_type::float_type); |
emit(MOV(temp, regoffset(frag_depth, 2))); |
frag_depth = temp; |
} |
} |
void |
fs_visitor::setup_fp_regs() |
{ |
/* PROGRAM_TEMPORARY */ |
int num_temp = fp->Base.NumTemporaries; |
fp_temp_regs = rzalloc_array(mem_ctx, fs_reg, num_temp); |
for (int i = 0; i < num_temp; i++) |
fp_temp_regs[i] = fs_reg(this, glsl_type::vec4_type); |
/* PROGRAM_STATE_VAR etc. */ |
if (dispatch_width == 8) { |
for (unsigned p = 0; |
p < fp->Base.Parameters->NumParameters; p++) { |
for (unsigned int i = 0; i < 4; i++) { |
c->prog_data.param[c->prog_data.nr_params++] = |
&fp->Base.Parameters->ParameterValues[p][i].f; |
} |
} |
} |
fp_input_regs = rzalloc_array(mem_ctx, fs_reg, VARYING_SLOT_MAX); |
for (int i = 0; i < VARYING_SLOT_MAX; i++) { |
if (fp->Base.InputsRead & BITFIELD64_BIT(i)) { |
/* Make up a dummy instruction to reuse code for emitting |
* interpolation. |
*/ |
ir_variable *ir = new(mem_ctx) ir_variable(glsl_type::vec4_type, |
"fp_input", |
ir_var_shader_in); |
ir->location = i; |
this->current_annotation = ralloc_asprintf(ctx, "interpolate input %d", |
i); |
switch (i) { |
case VARYING_SLOT_POS: |
ir->pixel_center_integer = fp->PixelCenterInteger; |
ir->origin_upper_left = fp->OriginUpperLeft; |
fp_input_regs[i] = *emit_fragcoord_interpolation(ir); |
break; |
case VARYING_SLOT_FACE: |
fp_input_regs[i] = *emit_frontfacing_interpolation(ir); |
break; |
default: |
fp_input_regs[i] = *emit_general_interpolation(ir); |
if (i == VARYING_SLOT_FOGC) { |
emit(MOV(regoffset(fp_input_regs[i], 1), fs_reg(0.0f))); |
emit(MOV(regoffset(fp_input_regs[i], 2), fs_reg(0.0f))); |
emit(MOV(regoffset(fp_input_regs[i], 3), fs_reg(1.0f))); |
} |
break; |
} |
this->current_annotation = NULL; |
} |
} |
} |
fs_reg |
fs_visitor::get_fp_dst_reg(const prog_dst_register *dst) |
{ |
switch (dst->File) { |
case PROGRAM_TEMPORARY: |
return fp_temp_regs[dst->Index]; |
case PROGRAM_OUTPUT: |
if (dst->Index == FRAG_RESULT_DEPTH) { |
if (frag_depth.file == BAD_FILE) |
frag_depth = fs_reg(this, glsl_type::vec4_type); |
return frag_depth; |
} else if (dst->Index == FRAG_RESULT_COLOR) { |
if (outputs[0].file == BAD_FILE) { |
outputs[0] = fs_reg(this, glsl_type::vec4_type); |
output_components[0] = 4; |
/* Tell emit_fb_writes() to smear fragment.color across all the |
* color attachments. |
*/ |
for (int i = 1; i < c->key.nr_color_regions; i++) { |
outputs[i] = outputs[0]; |
output_components[i] = output_components[0]; |
} |
} |
return outputs[0]; |
} else { |
int output_index = dst->Index - FRAG_RESULT_DATA0; |
if (outputs[output_index].file == BAD_FILE) { |
outputs[output_index] = fs_reg(this, glsl_type::vec4_type); |
} |
output_components[output_index] = 4; |
return outputs[output_index]; |
} |
case PROGRAM_UNDEFINED: |
return fs_reg(); |
default: |
_mesa_problem(ctx, "bad dst register file: %s\n", |
_mesa_register_file_name((gl_register_file)dst->File)); |
return fs_reg(this, glsl_type::vec4_type); |
} |
} |
fs_reg |
fs_visitor::get_fp_src_reg(const prog_src_register *src) |
{ |
struct gl_program_parameter_list *plist = fp->Base.Parameters; |
fs_reg result; |
assert(!src->Abs); |
switch (src->File) { |
case PROGRAM_UNDEFINED: |
return fs_reg(); |
case PROGRAM_TEMPORARY: |
result = fp_temp_regs[src->Index]; |
break; |
case PROGRAM_INPUT: |
result = fp_input_regs[src->Index]; |
break; |
case PROGRAM_STATE_VAR: |
case PROGRAM_UNIFORM: |
case PROGRAM_CONSTANT: |
/* We actually want to look at the type in the Parameters list for this, |
* because this lets us upload constant builtin uniforms, as actual |
* constants. |
*/ |
switch (plist->Parameters[src->Index].Type) { |
case PROGRAM_CONSTANT: { |
result = fs_reg(this, glsl_type::vec4_type); |
for (int i = 0; i < 4; i++) { |
emit(MOV(regoffset(result, i), |
fs_reg(plist->ParameterValues[src->Index][i].f))); |
} |
break; |
} |
case PROGRAM_STATE_VAR: |
case PROGRAM_UNIFORM: |
result = fs_reg(UNIFORM, src->Index * 4); |
break; |
default: |
_mesa_problem(ctx, "bad uniform src register file: %s\n", |
_mesa_register_file_name((gl_register_file)src->File)); |
return fs_reg(this, glsl_type::vec4_type); |
} |
break; |
default: |
_mesa_problem(ctx, "bad src register file: %s\n", |
_mesa_register_file_name((gl_register_file)src->File)); |
return fs_reg(this, glsl_type::vec4_type); |
} |
if (src->Swizzle != SWIZZLE_NOOP || src->Negate) { |
fs_reg unswizzled = result; |
result = fs_reg(this, glsl_type::vec4_type); |
for (int i = 0; i < 4; i++) { |
bool negate = src->Negate & (1 << i); |
/* The ZERO, ONE, and Negate options are only used for OPCODE_SWZ, |
* but it costs us nothing to support it. |
*/ |
int src_swiz = GET_SWZ(src->Swizzle, i); |
if (src_swiz == SWIZZLE_ZERO) { |
emit(MOV(regoffset(result, i), fs_reg(0.0f))); |
} else if (src_swiz == SWIZZLE_ONE) { |
emit(MOV(regoffset(result, i), |
negate ? fs_reg(-1.0f) : fs_reg(1.0f))); |
} else { |
fs_reg src = regoffset(unswizzled, src_swiz); |
if (negate) |
src.negate = !src.negate; |
emit(MOV(regoffset(result, i), src)); |
} |
} |
} |
return result; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp |
---|
0,0 → 1,266 |
/* |
* 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_cfg.h" |
#include "brw_fs_live_variables.h" |
using namespace brw; |
/** @file brw_fs_live_variables.cpp |
* |
* Support for computing at the basic block level which variables |
* (virtual GRFs in our case) are live at entry and exit. |
* |
* See Muchnik's Advanced Compiler Design and Implementation, section |
* 14.1 (p444). |
*/ |
/** |
* Sets up the use[] and def[] bitsets. |
* |
* The basic-block-level live variable analysis needs to know which |
* variables get used before they're completely defined, and which |
* variables are completely defined before they're used. |
*/ |
void |
fs_live_variables::setup_def_use() |
{ |
int ip = 0; |
for (int b = 0; b < cfg->num_blocks; b++) { |
bblock_t *block = cfg->blocks[b]; |
assert(ip == block->start_ip); |
if (b > 0) |
assert(cfg->blocks[b - 1]->end_ip == ip - 1); |
for (fs_inst *inst = (fs_inst *)block->start; |
inst != block->end->next; |
inst = (fs_inst *)inst->next) { |
/* Set use[] for this instruction */ |
for (unsigned int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
int reg = inst->src[i].reg; |
if (!BITSET_TEST(bd[b].def, reg)) |
BITSET_SET(bd[b].use, reg); |
} |
} |
/* Check for unconditional writes to whole registers. These |
* are the things that screen off preceding definitions of a |
* variable, and thus qualify for being in def[]. |
*/ |
if (inst->dst.file == GRF && |
inst->regs_written == v->virtual_grf_sizes[inst->dst.reg] && |
!inst->is_partial_write()) { |
int reg = inst->dst.reg; |
if (!BITSET_TEST(bd[b].use, reg)) |
BITSET_SET(bd[b].def, reg); |
} |
ip++; |
} |
} |
} |
/** |
* The algorithm incrementally sets bits in liveout and livein, |
* propagating it through control flow. It will eventually terminate |
* because it only ever adds bits, and stops when no bits are added in |
* a pass. |
*/ |
void |
fs_live_variables::compute_live_variables() |
{ |
bool cont = true; |
while (cont) { |
cont = false; |
for (int b = 0; b < cfg->num_blocks; b++) { |
/* Update livein */ |
for (int i = 0; i < bitset_words; i++) { |
BITSET_WORD new_livein = (bd[b].use[i] | |
(bd[b].liveout[i] & ~bd[b].def[i])); |
if (new_livein & ~bd[b].livein[i]) { |
bd[b].livein[i] |= new_livein; |
cont = true; |
} |
} |
/* Update liveout */ |
foreach_list(block_node, &cfg->blocks[b]->children) { |
bblock_link *link = (bblock_link *)block_node; |
bblock_t *block = link->block; |
for (int i = 0; i < bitset_words; i++) { |
BITSET_WORD new_liveout = (bd[block->block_num].livein[i] & |
~bd[b].liveout[i]); |
if (new_liveout) { |
bd[b].liveout[i] |= new_liveout; |
cont = true; |
} |
} |
} |
} |
} |
} |
fs_live_variables::fs_live_variables(fs_visitor *v, cfg_t *cfg) |
: v(v), cfg(cfg) |
{ |
mem_ctx = ralloc_context(cfg->mem_ctx); |
num_vars = v->virtual_grf_count; |
bd = rzalloc_array(mem_ctx, struct block_data, cfg->num_blocks); |
bitset_words = BITSET_WORDS(v->virtual_grf_count); |
for (int i = 0; i < cfg->num_blocks; i++) { |
bd[i].def = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words); |
bd[i].use = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words); |
bd[i].livein = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words); |
bd[i].liveout = rzalloc_array(mem_ctx, BITSET_WORD, bitset_words); |
} |
setup_def_use(); |
compute_live_variables(); |
} |
fs_live_variables::~fs_live_variables() |
{ |
ralloc_free(mem_ctx); |
} |
#define MAX_INSTRUCTION (1 << 30) |
void |
fs_visitor::calculate_live_intervals() |
{ |
int num_vars = this->virtual_grf_count; |
if (this->live_intervals_valid) |
return; |
int *start = ralloc_array(mem_ctx, int, num_vars); |
int *end = ralloc_array(mem_ctx, int, num_vars); |
ralloc_free(this->virtual_grf_start); |
ralloc_free(this->virtual_grf_end); |
this->virtual_grf_start = start; |
this->virtual_grf_end = end; |
for (int i = 0; i < num_vars; i++) { |
start[i] = MAX_INSTRUCTION; |
end[i] = -1; |
} |
/* Start by setting up the intervals with no knowledge of control |
* flow. |
*/ |
int ip = 0; |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
for (unsigned int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
int reg = inst->src[i].reg; |
int end_ip = ip; |
/* In most cases, a register can be written over safely by the |
* same instruction that is its last use. For a single |
* instruction, the sources are dereferenced before writing of the |
* destination starts (naturally). This gets more complicated for |
* simd16, because the instruction: |
* |
* mov(16) g4<1>F g4<8,8,1>F g6<8,8,1>F |
* |
* is actually decoded in hardware as: |
* |
* mov(8) g4<1>F g4<8,8,1>F g6<8,8,1>F |
* mov(8) g5<1>F g5<8,8,1>F g7<8,8,1>F |
* |
* Which is safe. However, if we have uniform accesses |
* happening, we get into trouble: |
* |
* mov(8) g4<1>F g4<0,1,0>F g6<8,8,1>F |
* mov(8) g5<1>F g4<0,1,0>F g7<8,8,1>F |
* |
* Now our destination for the first instruction overwrote the |
* second instruction's src0, and we get garbage for those 8 |
* pixels. There's a similar issue for the pre-gen6 |
* pixel_x/pixel_y, which are registers of 16-bit values and thus |
* would get stomped by the first decode as well. |
*/ |
if (dispatch_width == 16 && (inst->src[i].smear >= 0 || |
(this->pixel_x.reg == reg || |
this->pixel_y.reg == reg))) { |
end_ip++; |
} |
start[reg] = MIN2(start[reg], ip); |
end[reg] = MAX2(end[reg], end_ip); |
} |
} |
if (inst->dst.file == GRF) { |
int reg = inst->dst.reg; |
start[reg] = MIN2(start[reg], ip); |
end[reg] = MAX2(end[reg], ip); |
} |
ip++; |
} |
/* Now, extend those intervals using our analysis of control flow. */ |
cfg_t cfg(this); |
fs_live_variables livevars(this, &cfg); |
for (int b = 0; b < cfg.num_blocks; b++) { |
for (int i = 0; i < num_vars; i++) { |
if (BITSET_TEST(livevars.bd[b].livein, i)) { |
start[i] = MIN2(start[i], cfg.blocks[b]->start_ip); |
end[i] = MAX2(end[i], cfg.blocks[b]->start_ip); |
} |
if (BITSET_TEST(livevars.bd[b].liveout, i)) { |
start[i] = MIN2(start[i], cfg.blocks[b]->end_ip); |
end[i] = MAX2(end[i], cfg.blocks[b]->end_ip); |
} |
} |
} |
this->live_intervals_valid = true; |
} |
bool |
fs_visitor::virtual_grf_interferes(int a, int b) |
{ |
return !(virtual_grf_end[a] <= virtual_grf_start[b] || |
virtual_grf_end[b] <= virtual_grf_start[a]); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs_live_variables.h |
---|
0,0 → 1,83 |
/* |
* 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_fs.h" |
#include "main/bitset.h" |
namespace brw { |
struct block_data { |
/** |
* Which variables are defined before being used in the block. |
* |
* Note that for our purposes, "defined" means unconditionally, completely |
* defined. |
*/ |
BITSET_WORD *def; |
/** |
* Which variables are used before being defined in the block. |
*/ |
BITSET_WORD *use; |
/** Which defs reach the entry point of the block. */ |
BITSET_WORD *livein; |
/** Which defs reach the exit point of the block. */ |
BITSET_WORD *liveout; |
}; |
class fs_live_variables { |
public: |
static void* operator new(size_t size, void *ctx) |
{ |
void *node; |
node = rzalloc_size(ctx, size); |
assert(node != NULL); |
return node; |
} |
fs_live_variables(fs_visitor *v, cfg_t *cfg); |
~fs_live_variables(); |
void setup_def_use(); |
void compute_live_variables(); |
fs_visitor *v; |
cfg_t *cfg; |
void *mem_ctx; |
int num_vars; |
int bitset_words; |
/** Per-basic-block information on live variables */ |
struct block_data *bd; |
}; |
} /* namespace brw */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp |
---|
0,0 → 1,662 |
/* |
* Copyright © 2010 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_fs.h" |
#include "glsl/glsl_types.h" |
#include "glsl/ir_optimization.h" |
static void |
assign_reg(int *reg_hw_locations, fs_reg *reg, int reg_width) |
{ |
if (reg->file == GRF) { |
assert(reg->reg_offset >= 0); |
reg->reg = reg_hw_locations[reg->reg] + reg->reg_offset * reg_width; |
reg->reg_offset = 0; |
} |
} |
void |
fs_visitor::assign_regs_trivial() |
{ |
int hw_reg_mapping[this->virtual_grf_count + 1]; |
int i; |
int reg_width = dispatch_width / 8; |
/* Note that compressed instructions require alignment to 2 registers. */ |
hw_reg_mapping[0] = ALIGN(this->first_non_payload_grf, reg_width); |
for (i = 1; i <= this->virtual_grf_count; i++) { |
hw_reg_mapping[i] = (hw_reg_mapping[i - 1] + |
this->virtual_grf_sizes[i - 1] * reg_width); |
} |
this->grf_used = hw_reg_mapping[this->virtual_grf_count]; |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
assign_reg(hw_reg_mapping, &inst->dst, reg_width); |
assign_reg(hw_reg_mapping, &inst->src[0], reg_width); |
assign_reg(hw_reg_mapping, &inst->src[1], reg_width); |
assign_reg(hw_reg_mapping, &inst->src[2], reg_width); |
} |
if (this->grf_used >= max_grf) { |
fail("Ran out of regs on trivial allocator (%d/%d)\n", |
this->grf_used, max_grf); |
} |
} |
static void |
brw_alloc_reg_set(struct brw_context *brw, int reg_width) |
{ |
int base_reg_count = BRW_MAX_GRF / reg_width; |
int index = reg_width - 1; |
/* The registers used to make up almost all values handled in the compiler |
* are a scalar value occupying a single register (or 2 registers in the |
* case of 16-wide, which is handled by dividing base_reg_count by 2 and |
* multiplying allocated register numbers by 2). Things that were |
* aggregates of scalar values at the GLSL level were split to scalar |
* values by split_virtual_grfs(). |
* |
* However, texture SEND messages return a series of contiguous registers. |
* We currently always ask for 4 registers, but we may convert that to use |
* less some day. |
* |
* Additionally, on gen5 we need aligned pairs of registers for the PLN |
* instruction, and on gen4 we need 8 contiguous regs for workaround simd16 |
* texturing. |
* |
* So we have a need for classes for 1, 2, 4, and 8 registers currently, |
* and we add in '3' to make indexing the array easier for the common case |
* (since we'll probably want it for texturing later). |
*/ |
const int class_count = 5; |
const int class_sizes[class_count] = {1, 2, 3, 4, 8}; |
/* Compute the total number of registers across all classes. */ |
int ra_reg_count = 0; |
for (int i = 0; i < class_count; i++) { |
ra_reg_count += base_reg_count - (class_sizes[i] - 1); |
} |
uint8_t *ra_reg_to_grf = ralloc_array(brw, uint8_t, ra_reg_count); |
struct ra_regs *regs = ra_alloc_reg_set(brw, ra_reg_count); |
if (brw->gen >= 6) |
ra_set_allocate_round_robin(regs); |
int *classes = ralloc_array(brw, int, class_count); |
int aligned_pairs_class = -1; |
/* Now, add the registers to their classes, and add the conflicts |
* between them and the base GRF registers (and also each other). |
*/ |
int reg = 0; |
int pairs_base_reg = 0; |
int pairs_reg_count = 0; |
for (int i = 0; i < class_count; i++) { |
int class_reg_count = base_reg_count - (class_sizes[i] - 1); |
classes[i] = ra_alloc_reg_class(regs); |
/* Save this off for the aligned pair class at the end. */ |
if (class_sizes[i] == 2) { |
pairs_base_reg = reg; |
pairs_reg_count = class_reg_count; |
} |
for (int j = 0; j < class_reg_count; j++) { |
ra_class_add_reg(regs, classes[i], reg); |
ra_reg_to_grf[reg] = j; |
for (int base_reg = j; |
base_reg < j + class_sizes[i]; |
base_reg++) { |
ra_add_transitive_reg_conflict(regs, base_reg, reg); |
} |
reg++; |
} |
} |
assert(reg == ra_reg_count); |
/* Add a special class for aligned pairs, which we'll put delta_x/y |
* in on gen5 so that we can do PLN. |
*/ |
if (brw->has_pln && reg_width == 1 && brw->gen < 6) { |
aligned_pairs_class = ra_alloc_reg_class(regs); |
for (int i = 0; i < pairs_reg_count; i++) { |
if ((ra_reg_to_grf[pairs_base_reg + i] & 1) == 0) { |
ra_class_add_reg(regs, aligned_pairs_class, pairs_base_reg + i); |
} |
} |
} |
ra_set_finalize(regs, NULL); |
brw->wm.reg_sets[index].regs = regs; |
brw->wm.reg_sets[index].classes = classes; |
brw->wm.reg_sets[index].ra_reg_to_grf = ra_reg_to_grf; |
brw->wm.reg_sets[index].aligned_pairs_class = aligned_pairs_class; |
} |
void |
brw_fs_alloc_reg_sets(struct brw_context *brw) |
{ |
brw_alloc_reg_set(brw, 1); |
brw_alloc_reg_set(brw, 2); |
} |
int |
count_to_loop_end(fs_inst *do_inst) |
{ |
int depth = 1; |
int ip = 1; |
for (fs_inst *inst = (fs_inst *)do_inst->next; |
depth > 0; |
inst = (fs_inst *)inst->next) { |
switch (inst->opcode) { |
case BRW_OPCODE_DO: |
depth++; |
break; |
case BRW_OPCODE_WHILE: |
depth--; |
break; |
default: |
break; |
} |
ip++; |
} |
return ip; |
} |
/** |
* Sets up interference between thread payload registers and the virtual GRFs |
* to be allocated for program temporaries. |
* |
* We want to be able to reallocate the payload for our virtual GRFs, notably |
* because the setup coefficients for a full set of 16 FS inputs takes up 8 of |
* our 128 registers. |
* |
* The layout of the payload registers is: |
* |
* 0..nr_payload_regs-1: fixed function setup (including bary coordinates). |
* nr_payload_regs..nr_payload_regs+curb_read_lengh-1: uniform data |
* nr_payload_regs+curb_read_lengh..first_non_payload_grf-1: setup coefficients. |
* |
* And we have payload_node_count nodes covering these registers in order |
* (note that in 16-wide, a node is two registers). |
*/ |
void |
fs_visitor::setup_payload_interference(struct ra_graph *g, |
int payload_node_count, |
int first_payload_node) |
{ |
int reg_width = dispatch_width / 8; |
int loop_depth = 0; |
int loop_end_ip = 0; |
int payload_last_use_ip[payload_node_count]; |
memset(payload_last_use_ip, 0, sizeof(payload_last_use_ip)); |
int ip = 0; |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
switch (inst->opcode) { |
case BRW_OPCODE_DO: |
loop_depth++; |
/* Since payload regs are deffed only at the start of the shader |
* execution, any uses of the payload within a loop mean the live |
* interval extends to the end of the outermost loop. Find the ip of |
* the end now. |
*/ |
if (loop_depth == 1) |
loop_end_ip = ip + count_to_loop_end(inst); |
break; |
case BRW_OPCODE_WHILE: |
loop_depth--; |
break; |
default: |
break; |
} |
int use_ip; |
if (loop_depth > 0) |
use_ip = loop_end_ip; |
else |
use_ip = ip; |
/* Note that UNIFORM args have been turned into FIXED_HW_REG by |
* assign_curbe_setup(), and interpolation uses fixed hardware regs from |
* the start (see interp_reg()). |
*/ |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == HW_REG && |
inst->src[i].fixed_hw_reg.file == BRW_GENERAL_REGISTER_FILE) { |
int node_nr = inst->src[i].fixed_hw_reg.nr / reg_width; |
if (node_nr >= payload_node_count) |
continue; |
payload_last_use_ip[node_nr] = use_ip; |
} |
} |
/* Special case instructions which have extra implied registers used. */ |
switch (inst->opcode) { |
case FS_OPCODE_FB_WRITE: |
/* We could omit this for the !inst->header_present case, except that |
* the simulator apparently incorrectly reads from g0/g1 instead of |
* sideband. It also really freaks out driver developers to see g0 |
* used in unusual places, so just always reserve it. |
*/ |
payload_last_use_ip[0 / reg_width] = use_ip; |
payload_last_use_ip[1 / reg_width] = use_ip; |
break; |
case FS_OPCODE_LINTERP: |
/* On gen6+ in 16-wide, there are 4 adjacent registers (so 2 nodes) |
* used by PLN's sourcing of the deltas, while we list only the first |
* two in the arguments (1 node). Pre-gen6, the deltas are computed |
* in normal VGRFs. |
*/ |
if (brw->gen >= 6) { |
int delta_x_arg = 0; |
if (inst->src[delta_x_arg].file == HW_REG && |
inst->src[delta_x_arg].fixed_hw_reg.file == |
BRW_GENERAL_REGISTER_FILE) { |
int sechalf_node = (inst->src[delta_x_arg].fixed_hw_reg.nr / |
reg_width) + 1; |
assert(sechalf_node < payload_node_count); |
payload_last_use_ip[sechalf_node] = use_ip; |
} |
} |
break; |
default: |
break; |
} |
ip++; |
} |
for (int i = 0; i < payload_node_count; i++) { |
/* Mark the payload node as interfering with any virtual grf that is |
* live between the start of the program and our last use of the payload |
* node. |
*/ |
for (int j = 0; j < this->virtual_grf_count; j++) { |
/* Note that we use a <= comparison, unlike virtual_grf_interferes(), |
* in order to not have to worry about the uniform issue described in |
* calculate_live_intervals(). |
*/ |
if (this->virtual_grf_start[j] <= payload_last_use_ip[i]) { |
ra_add_node_interference(g, first_payload_node + i, j); |
} |
} |
} |
for (int i = 0; i < payload_node_count; i++) { |
/* Mark each payload node as being allocated to its physical register. |
* |
* The alternative would be to have per-physical-register classes, which |
* would just be silly. |
*/ |
ra_set_node_reg(g, first_payload_node + i, i); |
} |
} |
/** |
* Sets interference between virtual GRFs and usage of the high GRFs for SEND |
* messages (treated as MRFs in code generation). |
*/ |
void |
fs_visitor::setup_mrf_hack_interference(struct ra_graph *g, int first_mrf_node) |
{ |
int mrf_count = BRW_MAX_GRF - GEN7_MRF_HACK_START; |
int reg_width = dispatch_width / 8; |
/* Identify all the MRFs used in the program. */ |
bool mrf_used[mrf_count]; |
memset(mrf_used, 0, sizeof(mrf_used)); |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
if (inst->dst.file == MRF) { |
int reg = inst->dst.reg & ~BRW_MRF_COMPR4; |
mrf_used[reg] = true; |
if (reg_width == 2) { |
if (inst->dst.reg & BRW_MRF_COMPR4) { |
mrf_used[reg + 4] = true; |
} else { |
mrf_used[reg + 1] = true; |
} |
} |
} |
if (inst->mlen > 0) { |
for (int i = 0; i < implied_mrf_writes(inst); i++) { |
mrf_used[inst->base_mrf + i] = true; |
} |
} |
} |
for (int i = 0; i < mrf_count; i++) { |
/* Mark each payload reg node as being allocated to its physical register. |
* |
* The alternative would be to have per-physical-register classes, which |
* would just be silly. |
*/ |
ra_set_node_reg(g, first_mrf_node + i, |
(GEN7_MRF_HACK_START + i) / reg_width); |
/* Since we don't have any live/dead analysis on the MRFs, just mark all |
* that are used as conflicting with all virtual GRFs. |
*/ |
if (mrf_used[i]) { |
for (int j = 0; j < this->virtual_grf_count; j++) { |
ra_add_node_interference(g, first_mrf_node + i, j); |
} |
} |
} |
} |
bool |
fs_visitor::assign_regs() |
{ |
/* Most of this allocation was written for a reg_width of 1 |
* (dispatch_width == 8). In extending to 16-wide, the code was |
* left in place and it was converted to have the hardware |
* registers it's allocating be contiguous physical pairs of regs |
* for reg_width == 2. |
*/ |
int reg_width = dispatch_width / 8; |
int hw_reg_mapping[this->virtual_grf_count]; |
int payload_node_count = (ALIGN(this->first_non_payload_grf, reg_width) / |
reg_width); |
int rsi = reg_width - 1; /* Which brw->wm.reg_sets[] to use */ |
calculate_live_intervals(); |
int node_count = this->virtual_grf_count; |
int first_payload_node = node_count; |
node_count += payload_node_count; |
int first_mrf_hack_node = node_count; |
if (brw->gen >= 7) |
node_count += BRW_MAX_GRF - GEN7_MRF_HACK_START; |
struct ra_graph *g = ra_alloc_interference_graph(brw->wm.reg_sets[rsi].regs, |
node_count); |
for (int i = 0; i < this->virtual_grf_count; i++) { |
int size = this->virtual_grf_sizes[i]; |
int c; |
if (size == 8) { |
c = 4; |
} else { |
assert(size >= 1 && |
size <= 4 && |
"Register allocation relies on split_virtual_grfs()"); |
c = brw->wm.reg_sets[rsi].classes[size - 1]; |
} |
/* Special case: on pre-GEN6 hardware that supports PLN, the |
* second operand of a PLN instruction needs to be an |
* even-numbered register, so we have a special register class |
* wm_aligned_pairs_class to handle this case. pre-GEN6 always |
* uses this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC] as the |
* second operand of a PLN instruction (since it doesn't support |
* any other interpolation modes). So all we need to do is find |
* that register and set it to the appropriate class. |
*/ |
if (brw->wm.reg_sets[rsi].aligned_pairs_class >= 0 && |
this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC].reg == i) { |
c = brw->wm.reg_sets[rsi].aligned_pairs_class; |
} |
ra_set_node_class(g, i, c); |
for (int j = 0; j < i; j++) { |
if (virtual_grf_interferes(i, j)) { |
ra_add_node_interference(g, i, j); |
} |
} |
} |
setup_payload_interference(g, payload_node_count, first_payload_node); |
if (brw->gen >= 7) |
setup_mrf_hack_interference(g, first_mrf_hack_node); |
if (!ra_allocate_no_spills(g)) { |
/* Failed to allocate registers. Spill a reg, and the caller will |
* loop back into here to try again. |
*/ |
int reg = choose_spill_reg(g); |
if (reg == -1) { |
fail("no register to spill:\n"); |
dump_instructions(); |
} else if (dispatch_width == 16) { |
fail("Failure to register allocate. Reduce number of live scalar " |
"values to avoid this."); |
} else { |
spill_reg(reg); |
} |
ralloc_free(g); |
return false; |
} |
/* Get the chosen virtual registers for each node, and map virtual |
* regs in the register classes back down to real hardware reg |
* numbers. |
*/ |
this->grf_used = payload_node_count * reg_width; |
for (int i = 0; i < this->virtual_grf_count; i++) { |
int reg = ra_get_node_reg(g, i); |
hw_reg_mapping[i] = brw->wm.reg_sets[rsi].ra_reg_to_grf[reg] * reg_width; |
this->grf_used = MAX2(this->grf_used, |
hw_reg_mapping[i] + this->virtual_grf_sizes[i] * |
reg_width); |
} |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
assign_reg(hw_reg_mapping, &inst->dst, reg_width); |
assign_reg(hw_reg_mapping, &inst->src[0], reg_width); |
assign_reg(hw_reg_mapping, &inst->src[1], reg_width); |
assign_reg(hw_reg_mapping, &inst->src[2], reg_width); |
} |
ralloc_free(g); |
return true; |
} |
void |
fs_visitor::emit_unspill(fs_inst *inst, fs_reg dst, uint32_t spill_offset) |
{ |
fs_inst *unspill_inst = new(mem_ctx) fs_inst(FS_OPCODE_UNSPILL, dst); |
unspill_inst->offset = spill_offset; |
unspill_inst->ir = inst->ir; |
unspill_inst->annotation = inst->annotation; |
/* Choose a MRF that won't conflict with an MRF that's live across the |
* spill. Nothing else will make it up to MRF 14/15. |
*/ |
unspill_inst->base_mrf = 14; |
unspill_inst->mlen = 1; /* header contains offset */ |
inst->insert_before(unspill_inst); |
} |
int |
fs_visitor::choose_spill_reg(struct ra_graph *g) |
{ |
float loop_scale = 1.0; |
float spill_costs[this->virtual_grf_count]; |
bool no_spill[this->virtual_grf_count]; |
for (int i = 0; i < this->virtual_grf_count; i++) { |
spill_costs[i] = 0.0; |
no_spill[i] = false; |
} |
/* Calculate costs for spilling nodes. Call it a cost of 1 per |
* spill/unspill we'll have to do, and guess that the insides of |
* loops run 10 times. |
*/ |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
for (unsigned int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
spill_costs[inst->src[i].reg] += loop_scale; |
/* Register spilling logic assumes full-width registers; smeared |
* registers have a width of 1 so if we try to spill them we'll |
* generate invalid assembly. This shouldn't be a problem because |
* smeared registers are only used as short-term temporaries when |
* loading pull constants, so spilling them is unlikely to reduce |
* register pressure anyhow. |
*/ |
if (inst->src[i].smear >= 0) { |
no_spill[inst->src[i].reg] = true; |
} |
} |
} |
if (inst->dst.file == GRF) { |
spill_costs[inst->dst.reg] += inst->regs_written * loop_scale; |
if (inst->dst.smear >= 0) { |
no_spill[inst->dst.reg] = true; |
} |
} |
switch (inst->opcode) { |
case BRW_OPCODE_DO: |
loop_scale *= 10; |
break; |
case BRW_OPCODE_WHILE: |
loop_scale /= 10; |
break; |
case FS_OPCODE_SPILL: |
if (inst->src[0].file == GRF) |
no_spill[inst->src[0].reg] = true; |
break; |
case FS_OPCODE_UNSPILL: |
if (inst->dst.file == GRF) |
no_spill[inst->dst.reg] = true; |
break; |
default: |
break; |
} |
} |
for (int i = 0; i < this->virtual_grf_count; i++) { |
if (!no_spill[i]) |
ra_set_node_spill_cost(g, i, spill_costs[i]); |
} |
return ra_get_best_spill_node(g); |
} |
void |
fs_visitor::spill_reg(int spill_reg) |
{ |
int size = virtual_grf_sizes[spill_reg]; |
unsigned int spill_offset = c->last_scratch; |
assert(ALIGN(spill_offset, 16) == spill_offset); /* oword read/write req. */ |
c->last_scratch += size * REG_SIZE; |
/* Generate spill/unspill instructions for the objects being |
* spilled. Right now, we spill or unspill the whole thing to a |
* virtual grf of the same size. For most instructions, though, we |
* could just spill/unspill the GRF being accessed. |
*/ |
foreach_list(node, &this->instructions) { |
fs_inst *inst = (fs_inst *)node; |
for (unsigned int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF && |
inst->src[i].reg == spill_reg) { |
inst->src[i].reg = virtual_grf_alloc(1); |
emit_unspill(inst, inst->src[i], |
spill_offset + REG_SIZE * inst->src[i].reg_offset); |
} |
} |
if (inst->dst.file == GRF && |
inst->dst.reg == spill_reg) { |
int subset_spill_offset = (spill_offset + |
REG_SIZE * inst->dst.reg_offset); |
inst->dst.reg = virtual_grf_alloc(inst->regs_written); |
inst->dst.reg_offset = 0; |
/* If our write is going to affect just part of the |
* inst->regs_written(), then we need to unspill the destination |
* since we write back out all of the regs_written(). |
*/ |
if (inst->predicate || inst->force_uncompressed || inst->force_sechalf) { |
fs_reg unspill_reg = inst->dst; |
for (int chan = 0; chan < inst->regs_written; chan++) { |
emit_unspill(inst, unspill_reg, |
subset_spill_offset + REG_SIZE * chan); |
unspill_reg.reg_offset++; |
} |
} |
fs_reg spill_src = inst->dst; |
spill_src.reg_offset = 0; |
spill_src.abs = false; |
spill_src.negate = false; |
spill_src.smear = -1; |
for (int chan = 0; chan < inst->regs_written; chan++) { |
fs_inst *spill_inst = new(mem_ctx) fs_inst(FS_OPCODE_SPILL, |
reg_null_f, spill_src); |
spill_src.reg_offset++; |
spill_inst->offset = subset_spill_offset + chan * REG_SIZE; |
spill_inst->ir = inst->ir; |
spill_inst->annotation = inst->annotation; |
spill_inst->base_mrf = 14; |
spill_inst->mlen = 2; /* header, value */ |
inst->insert_after(spill_inst); |
} |
} |
} |
this->live_intervals_valid = false; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs_vector_splitting.cpp |
---|
0,0 → 1,393 |
/* |
* Copyright © 2010 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. |
*/ |
/** |
* \file brw_wm_vector_splitting.cpp |
* |
* If a vector is only ever referenced by its components, then |
* split those components out to individual variables so they can be |
* handled normally by other optimization passes. |
* |
* This skips vectors in uniforms and varyings, which need to be |
* accessible as vectors for their access by the GL. Also, vector |
* results of non-variable-derefs in assignments aren't handled |
* because to do so we would have to store the vector result to a |
* temporary in order to unload each channel, and to do so would just |
* loop us back to where we started. For the 965, this is exactly the |
* behavior we want for the results of texture lookups, but probably not for |
*/ |
extern "C" { |
#include "main/core.h" |
#include "brw_context.h" |
} |
#include "glsl/ir.h" |
#include "glsl/ir_visitor.h" |
#include "glsl/ir_rvalue_visitor.h" |
#include "glsl/glsl_types.h" |
static bool debug = false; |
class variable_entry : public exec_node |
{ |
public: |
variable_entry(ir_variable *var) |
{ |
this->var = var; |
this->whole_vector_access = 0; |
this->declaration = false; |
this->mem_ctx = NULL; |
} |
ir_variable *var; /* The key: the variable's pointer. */ |
/** Number of times the variable is referenced, including assignments. */ |
unsigned whole_vector_access; |
bool declaration; /* If the variable had a decl in the instruction stream */ |
ir_variable *components[4]; |
/** ralloc_parent(this->var) -- the shader's ralloc context. */ |
void *mem_ctx; |
}; |
class ir_vector_reference_visitor : public ir_hierarchical_visitor { |
public: |
ir_vector_reference_visitor(void) |
{ |
this->mem_ctx = ralloc_context(NULL); |
this->variable_list.make_empty(); |
} |
~ir_vector_reference_visitor(void) |
{ |
ralloc_free(mem_ctx); |
} |
virtual ir_visitor_status visit(ir_variable *); |
virtual ir_visitor_status visit(ir_dereference_variable *); |
virtual ir_visitor_status visit_enter(ir_swizzle *); |
virtual ir_visitor_status visit_enter(ir_assignment *); |
virtual ir_visitor_status visit_enter(ir_function_signature *); |
variable_entry *get_variable_entry(ir_variable *var); |
/* List of variable_entry */ |
exec_list variable_list; |
void *mem_ctx; |
}; |
variable_entry * |
ir_vector_reference_visitor::get_variable_entry(ir_variable *var) |
{ |
assert(var); |
if (!var->type->is_vector()) |
return NULL; |
switch (var->mode) { |
case ir_var_uniform: |
case ir_var_shader_in: |
case ir_var_shader_out: |
case ir_var_function_in: |
case ir_var_function_out: |
case ir_var_function_inout: |
/* Can't split varyings or uniforms. Function in/outs won't get split |
* either. |
*/ |
return NULL; |
case ir_var_auto: |
case ir_var_temporary: |
break; |
} |
foreach_list(node, &this->variable_list) { |
variable_entry *entry = (variable_entry *)node; |
if (entry->var == var) |
return entry; |
} |
variable_entry *entry = new(mem_ctx) variable_entry(var); |
this->variable_list.push_tail(entry); |
return entry; |
} |
ir_visitor_status |
ir_vector_reference_visitor::visit(ir_variable *ir) |
{ |
variable_entry *entry = this->get_variable_entry(ir); |
if (entry) |
entry->declaration = true; |
return visit_continue; |
} |
ir_visitor_status |
ir_vector_reference_visitor::visit(ir_dereference_variable *ir) |
{ |
ir_variable *const var = ir->var; |
variable_entry *entry = this->get_variable_entry(var); |
if (entry) |
entry->whole_vector_access++; |
return visit_continue; |
} |
ir_visitor_status |
ir_vector_reference_visitor::visit_enter(ir_swizzle *ir) |
{ |
/* Don't descend into a vector ir_dereference_variable below. */ |
if (ir->val->as_dereference_variable() && ir->type->is_scalar()) |
return visit_continue_with_parent; |
return visit_continue; |
} |
ir_visitor_status |
ir_vector_reference_visitor::visit_enter(ir_assignment *ir) |
{ |
if (ir->lhs->as_dereference_variable() && |
ir->rhs->as_dereference_variable() && |
!ir->condition) { |
/* We'll split copies of a vector to copies of channels, so don't |
* descend to the ir_dereference_variables. |
*/ |
return visit_continue_with_parent; |
} |
if (ir->lhs->as_dereference_variable() && |
is_power_of_two(ir->write_mask) && |
!ir->condition) { |
/* If we're writing just a channel, then channel-splitting the LHS is OK. |
*/ |
ir->rhs->accept(this); |
return visit_continue_with_parent; |
} |
return visit_continue; |
} |
ir_visitor_status |
ir_vector_reference_visitor::visit_enter(ir_function_signature *ir) |
{ |
/* We don't want to descend into the function parameters and |
* split them, so just accept the body here. |
*/ |
visit_list_elements(this, &ir->body); |
return visit_continue_with_parent; |
} |
class ir_vector_splitting_visitor : public ir_rvalue_visitor { |
public: |
ir_vector_splitting_visitor(exec_list *vars) |
{ |
this->variable_list = vars; |
} |
virtual ir_visitor_status visit_leave(ir_assignment *); |
void handle_rvalue(ir_rvalue **rvalue); |
variable_entry *get_splitting_entry(ir_variable *var); |
exec_list *variable_list; |
}; |
variable_entry * |
ir_vector_splitting_visitor::get_splitting_entry(ir_variable *var) |
{ |
assert(var); |
if (!var->type->is_vector()) |
return NULL; |
foreach_list(node, &*this->variable_list) { |
variable_entry *entry = (variable_entry *)node; |
if (entry->var == var) { |
return entry; |
} |
} |
return NULL; |
} |
void |
ir_vector_splitting_visitor::handle_rvalue(ir_rvalue **rvalue) |
{ |
if (!*rvalue) |
return; |
ir_swizzle *swiz = (*rvalue)->as_swizzle(); |
if (!swiz || !swiz->type->is_scalar()) |
return; |
ir_dereference_variable *deref_var = swiz->val->as_dereference_variable(); |
if (!deref_var) |
return; |
variable_entry *entry = get_splitting_entry(deref_var->var); |
if (!entry) |
return; |
ir_variable *var = entry->components[swiz->mask.x]; |
*rvalue = new(entry->mem_ctx) ir_dereference_variable(var); |
} |
ir_visitor_status |
ir_vector_splitting_visitor::visit_leave(ir_assignment *ir) |
{ |
ir_dereference_variable *lhs_deref = ir->lhs->as_dereference_variable(); |
ir_dereference_variable *rhs_deref = ir->rhs->as_dereference_variable(); |
variable_entry *lhs = lhs_deref ? get_splitting_entry(lhs_deref->var) : NULL; |
variable_entry *rhs = rhs_deref ? get_splitting_entry(rhs_deref->var) : NULL; |
if (lhs_deref && rhs_deref && (lhs || rhs) && !ir->condition) { |
unsigned int rhs_chan = 0; |
/* Straight assignment of vector variables. */ |
for (unsigned int i = 0; i < ir->lhs->type->vector_elements; i++) { |
ir_dereference *new_lhs; |
ir_rvalue *new_rhs; |
void *mem_ctx = lhs ? lhs->mem_ctx : rhs->mem_ctx; |
unsigned int writemask; |
if (!(ir->write_mask & (1 << i))) |
continue; |
if (lhs) { |
new_lhs = new(mem_ctx) ir_dereference_variable(lhs->components[i]); |
writemask = 1; |
} else { |
new_lhs = ir->lhs->clone(mem_ctx, NULL); |
writemask = 1 << i; |
} |
if (rhs) { |
new_rhs = |
new(mem_ctx) ir_dereference_variable(rhs->components[rhs_chan]); |
} else { |
new_rhs = new(mem_ctx) ir_swizzle(ir->rhs->clone(mem_ctx, NULL), |
rhs_chan, 0, 0, 0, 1); |
} |
ir->insert_before(new(mem_ctx) ir_assignment(new_lhs, |
new_rhs, |
NULL, writemask)); |
rhs_chan++; |
} |
ir->remove(); |
} else if (lhs) { |
void *mem_ctx = lhs->mem_ctx; |
int elem = -1; |
switch (ir->write_mask) { |
case (1 << 0): |
elem = 0; |
break; |
case (1 << 1): |
elem = 1; |
break; |
case (1 << 2): |
elem = 2; |
break; |
case (1 << 3): |
elem = 3; |
break; |
default: |
ir->print(); |
assert(!"not reached: non-channelwise dereference of LHS."); |
} |
ir->lhs = new(mem_ctx) ir_dereference_variable(lhs->components[elem]); |
ir->write_mask = (1 << 0); |
handle_rvalue(&ir->rhs); |
} else { |
handle_rvalue(&ir->rhs); |
} |
handle_rvalue(&ir->condition); |
return visit_continue; |
} |
bool |
brw_do_vector_splitting(exec_list *instructions) |
{ |
ir_vector_reference_visitor refs; |
visit_list_elements(&refs, instructions); |
/* Trim out variables we can't split. */ |
foreach_list_safe(node, &refs.variable_list) { |
variable_entry *entry = (variable_entry *)node; |
if (debug) { |
printf("vector %s@%p: decl %d, whole_access %d\n", |
entry->var->name, (void *) entry->var, entry->declaration, |
entry->whole_vector_access); |
} |
if (!entry->declaration || entry->whole_vector_access) { |
entry->remove(); |
} |
} |
if (refs.variable_list.is_empty()) |
return false; |
void *mem_ctx = ralloc_context(NULL); |
/* Replace the decls of the vectors to be split with their split |
* components. |
*/ |
foreach_list(node, &refs.variable_list) { |
variable_entry *entry = (variable_entry *)node; |
const struct glsl_type *type; |
type = glsl_type::get_instance(entry->var->type->base_type, 1, 1); |
entry->mem_ctx = ralloc_parent(entry->var); |
for (unsigned int i = 0; i < entry->var->type->vector_elements; i++) { |
const char *name = ralloc_asprintf(mem_ctx, "%s_%c", |
entry->var->name, |
"xyzw"[i]); |
entry->components[i] = new(entry->mem_ctx) ir_variable(type, name, |
ir_var_temporary); |
entry->var->insert_before(entry->components[i]); |
} |
entry->var->remove(); |
} |
ir_vector_splitting_visitor split(&refs.variable_list); |
visit_list_elements(&split, instructions); |
ralloc_free(mem_ctx); |
return true; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp |
---|
0,0 → 1,2486 |
/* |
* Copyright © 2010 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. |
*/ |
/** @file brw_fs_visitor.cpp |
* |
* This file supports generating the FS LIR from the GLSL IR. The LIR |
* makes it easier to do backend-specific optimizations than doing so |
* in the GLSL IR or in the native code. |
*/ |
extern "C" { |
#include <sys/types.h> |
#include "main/macros.h" |
#include "main/shaderobj.h" |
#include "main/uniforms.h" |
#include "program/prog_parameter.h" |
#include "program/prog_print.h" |
#include "program/prog_optimize.h" |
#include "program/register_allocate.h" |
#include "program/sampler.h" |
#include "program/hash_table.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_wm.h" |
} |
#include "brw_fs.h" |
#include "glsl/glsl_types.h" |
#include "glsl/ir_optimization.h" |
void |
fs_visitor::visit(ir_variable *ir) |
{ |
fs_reg *reg = NULL; |
if (variable_storage(ir)) |
return; |
if (ir->mode == ir_var_shader_in) { |
if (!strcmp(ir->name, "gl_FragCoord")) { |
reg = emit_fragcoord_interpolation(ir); |
} else if (!strcmp(ir->name, "gl_FrontFacing")) { |
reg = emit_frontfacing_interpolation(ir); |
} else { |
reg = emit_general_interpolation(ir); |
} |
assert(reg); |
hash_table_insert(this->variable_ht, reg, ir); |
return; |
} else if (ir->mode == ir_var_shader_out) { |
reg = new(this->mem_ctx) fs_reg(this, ir->type); |
if (ir->index > 0) { |
assert(ir->location == FRAG_RESULT_DATA0); |
assert(ir->index == 1); |
this->dual_src_output = *reg; |
} else if (ir->location == FRAG_RESULT_COLOR) { |
/* Writing gl_FragColor outputs to all color regions. */ |
for (unsigned int i = 0; i < MAX2(c->key.nr_color_regions, 1); i++) { |
this->outputs[i] = *reg; |
this->output_components[i] = 4; |
} |
} else if (ir->location == FRAG_RESULT_DEPTH) { |
this->frag_depth = *reg; |
} else { |
/* gl_FragData or a user-defined FS output */ |
assert(ir->location >= FRAG_RESULT_DATA0 && |
ir->location < FRAG_RESULT_DATA0 + BRW_MAX_DRAW_BUFFERS); |
int vector_elements = |
ir->type->is_array() ? ir->type->fields.array->vector_elements |
: ir->type->vector_elements; |
/* General color output. */ |
for (unsigned int i = 0; i < MAX2(1, ir->type->length); i++) { |
int output = ir->location - FRAG_RESULT_DATA0 + i; |
this->outputs[output] = *reg; |
this->outputs[output].reg_offset += vector_elements * i; |
this->output_components[output] = vector_elements; |
} |
} |
} else if (ir->mode == ir_var_uniform) { |
int param_index = c->prog_data.nr_params; |
/* Thanks to the lower_ubo_reference pass, we will see only |
* ir_binop_ubo_load expressions and not ir_dereference_variable for UBO |
* variables, so no need for them to be in variable_ht. |
*/ |
if (ir->is_in_uniform_block()) |
return; |
if (dispatch_width == 16) { |
if (!variable_storage(ir)) { |
fail("Failed to find uniform '%s' in 16-wide\n", ir->name); |
} |
return; |
} |
param_size[param_index] = type_size(ir->type); |
if (!strncmp(ir->name, "gl_", 3)) { |
setup_builtin_uniform_values(ir); |
} else { |
setup_uniform_values(ir); |
} |
reg = new(this->mem_ctx) fs_reg(UNIFORM, param_index); |
reg->type = brw_type_for_base_type(ir->type); |
} |
if (!reg) |
reg = new(this->mem_ctx) fs_reg(this, ir->type); |
hash_table_insert(this->variable_ht, reg, ir); |
} |
void |
fs_visitor::visit(ir_dereference_variable *ir) |
{ |
fs_reg *reg = variable_storage(ir->var); |
this->result = *reg; |
} |
void |
fs_visitor::visit(ir_dereference_record *ir) |
{ |
const glsl_type *struct_type = ir->record->type; |
ir->record->accept(this); |
unsigned int offset = 0; |
for (unsigned int i = 0; i < struct_type->length; i++) { |
if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0) |
break; |
offset += type_size(struct_type->fields.structure[i].type); |
} |
this->result.reg_offset += offset; |
this->result.type = brw_type_for_base_type(ir->type); |
} |
void |
fs_visitor::visit(ir_dereference_array *ir) |
{ |
ir_constant *constant_index; |
fs_reg src; |
int element_size = type_size(ir->type); |
constant_index = ir->array_index->as_constant(); |
ir->array->accept(this); |
src = this->result; |
src.type = brw_type_for_base_type(ir->type); |
if (constant_index) { |
assert(src.file == UNIFORM || src.file == GRF); |
src.reg_offset += constant_index->value.i[0] * element_size; |
} else { |
/* Variable index array dereference. We attach the variable index |
* component to the reg as a pointer to a register containing the |
* offset. Currently only uniform arrays are supported in this patch, |
* and that reladdr pointer is resolved by |
* move_uniform_array_access_to_pull_constants(). All other array types |
* are lowered by lower_variable_index_to_cond_assign(). |
*/ |
ir->array_index->accept(this); |
fs_reg index_reg; |
index_reg = fs_reg(this, glsl_type::int_type); |
emit(BRW_OPCODE_MUL, index_reg, this->result, fs_reg(element_size)); |
if (src.reladdr) { |
emit(BRW_OPCODE_ADD, index_reg, *src.reladdr, index_reg); |
} |
src.reladdr = ralloc(mem_ctx, fs_reg); |
memcpy(src.reladdr, &index_reg, sizeof(index_reg)); |
} |
this->result = src; |
} |
void |
fs_visitor::emit_lrp(fs_reg dst, fs_reg x, fs_reg y, fs_reg a) |
{ |
if (brw->gen < 6 || |
!x.is_valid_3src() || |
!y.is_valid_3src() || |
!a.is_valid_3src()) { |
/* We can't use the LRP instruction. Emit x*(1-a) + y*a. */ |
fs_reg y_times_a = fs_reg(this, glsl_type::float_type); |
fs_reg one_minus_a = fs_reg(this, glsl_type::float_type); |
fs_reg x_times_one_minus_a = fs_reg(this, glsl_type::float_type); |
emit(MUL(y_times_a, y, a)); |
a.negate = !a.negate; |
emit(ADD(one_minus_a, a, fs_reg(1.0f))); |
emit(MUL(x_times_one_minus_a, x, one_minus_a)); |
emit(ADD(dst, x_times_one_minus_a, y_times_a)); |
} else { |
/* The LRP instruction actually does op1 * op0 + op2 * (1 - op0), so |
* we need to reorder the operands. |
*/ |
emit(LRP(dst, a, y, x)); |
} |
} |
void |
fs_visitor::emit_minmax(uint32_t conditionalmod, fs_reg dst, |
fs_reg src0, fs_reg src1) |
{ |
fs_inst *inst; |
if (brw->gen >= 6) { |
inst = emit(BRW_OPCODE_SEL, dst, src0, src1); |
inst->conditional_mod = conditionalmod; |
} else { |
emit(CMP(reg_null_d, src0, src1, conditionalmod)); |
inst = emit(BRW_OPCODE_SEL, dst, src0, src1); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
} |
/* Instruction selection: Produce a MOV.sat instead of |
* MIN(MAX(val, 0), 1) when possible. |
*/ |
bool |
fs_visitor::try_emit_saturate(ir_expression *ir) |
{ |
ir_rvalue *sat_val = ir->as_rvalue_to_saturate(); |
if (!sat_val) |
return false; |
fs_inst *pre_inst = (fs_inst *) this->instructions.get_tail(); |
sat_val->accept(this); |
fs_reg src = this->result; |
fs_inst *last_inst = (fs_inst *) this->instructions.get_tail(); |
/* If the last instruction from our accept() didn't generate our |
* src, generate a saturated MOV |
*/ |
fs_inst *modify = get_instruction_generating_reg(pre_inst, last_inst, src); |
if (!modify || modify->regs_written != 1) { |
this->result = fs_reg(this, ir->type); |
fs_inst *inst = emit(MOV(this->result, src)); |
inst->saturate = true; |
} else { |
modify->saturate = true; |
this->result = src; |
} |
return true; |
} |
bool |
fs_visitor::try_emit_mad(ir_expression *ir, int mul_arg) |
{ |
/* 3-src instructions were introduced in gen6. */ |
if (brw->gen < 6) |
return false; |
/* MAD can only handle floating-point data. */ |
if (ir->type != glsl_type::float_type) |
return false; |
ir_rvalue *nonmul = ir->operands[1 - mul_arg]; |
ir_expression *mul = ir->operands[mul_arg]->as_expression(); |
if (!mul || mul->operation != ir_binop_mul) |
return false; |
if (nonmul->as_constant() || |
mul->operands[0]->as_constant() || |
mul->operands[1]->as_constant()) |
return false; |
nonmul->accept(this); |
fs_reg src0 = this->result; |
mul->operands[0]->accept(this); |
fs_reg src1 = this->result; |
mul->operands[1]->accept(this); |
fs_reg src2 = this->result; |
this->result = fs_reg(this, ir->type); |
emit(BRW_OPCODE_MAD, this->result, src0, src1, src2); |
return true; |
} |
void |
fs_visitor::visit(ir_expression *ir) |
{ |
unsigned int operand; |
fs_reg op[3], temp; |
fs_inst *inst; |
assert(ir->get_num_operands() <= 3); |
if (try_emit_saturate(ir)) |
return; |
if (ir->operation == ir_binop_add) { |
if (try_emit_mad(ir, 0) || try_emit_mad(ir, 1)) |
return; |
} |
for (operand = 0; operand < ir->get_num_operands(); operand++) { |
ir->operands[operand]->accept(this); |
if (this->result.file == BAD_FILE) { |
fail("Failed to get tree for expression operand:\n"); |
ir->operands[operand]->print(); |
printf("\n"); |
} |
op[operand] = this->result; |
/* Matrix expression operands should have been broken down to vector |
* operations already. |
*/ |
assert(!ir->operands[operand]->type->is_matrix()); |
/* And then those vector operands should have been broken down to scalar. |
*/ |
assert(!ir->operands[operand]->type->is_vector()); |
} |
/* Storage for our result. If our result goes into an assignment, it will |
* just get copy-propagated out, so no worries. |
*/ |
this->result = fs_reg(this, ir->type); |
switch (ir->operation) { |
case ir_unop_logic_not: |
/* Note that BRW_OPCODE_NOT is not appropriate here, since it is |
* ones complement of the whole register, not just bit 0. |
*/ |
emit(XOR(this->result, op[0], fs_reg(1))); |
break; |
case ir_unop_neg: |
op[0].negate = !op[0].negate; |
emit(MOV(this->result, op[0])); |
break; |
case ir_unop_abs: |
op[0].abs = true; |
op[0].negate = false; |
emit(MOV(this->result, op[0])); |
break; |
case ir_unop_sign: |
temp = fs_reg(this, ir->type); |
emit(MOV(this->result, fs_reg(0.0f))); |
emit(CMP(reg_null_f, op[0], fs_reg(0.0f), BRW_CONDITIONAL_G)); |
inst = emit(MOV(this->result, fs_reg(1.0f))); |
inst->predicate = BRW_PREDICATE_NORMAL; |
emit(CMP(reg_null_f, op[0], fs_reg(0.0f), BRW_CONDITIONAL_L)); |
inst = emit(MOV(this->result, fs_reg(-1.0f))); |
inst->predicate = BRW_PREDICATE_NORMAL; |
break; |
case ir_unop_rcp: |
emit_math(SHADER_OPCODE_RCP, this->result, op[0]); |
break; |
case ir_unop_exp2: |
emit_math(SHADER_OPCODE_EXP2, this->result, op[0]); |
break; |
case ir_unop_log2: |
emit_math(SHADER_OPCODE_LOG2, this->result, op[0]); |
break; |
case ir_unop_exp: |
case ir_unop_log: |
assert(!"not reached: should be handled by ir_explog_to_explog2"); |
break; |
case ir_unop_sin: |
case ir_unop_sin_reduced: |
emit_math(SHADER_OPCODE_SIN, this->result, op[0]); |
break; |
case ir_unop_cos: |
case ir_unop_cos_reduced: |
emit_math(SHADER_OPCODE_COS, this->result, op[0]); |
break; |
case ir_unop_dFdx: |
emit(FS_OPCODE_DDX, this->result, op[0]); |
break; |
case ir_unop_dFdy: |
emit(FS_OPCODE_DDY, this->result, op[0]); |
break; |
case ir_binop_add: |
emit(ADD(this->result, op[0], op[1])); |
break; |
case ir_binop_sub: |
assert(!"not reached: should be handled by ir_sub_to_add_neg"); |
break; |
case ir_binop_mul: |
if (ir->type->is_integer()) { |
/* For integer multiplication, the MUL uses the low 16 bits |
* of one of the operands (src0 on gen6, src1 on gen7). The |
* MACH accumulates in the contribution of the upper 16 bits |
* of that operand. |
* |
* FINISHME: Emit just the MUL if we know an operand is small |
* enough. |
*/ |
if (brw->gen >= 7 && dispatch_width == 16) |
fail("16-wide explicit accumulator operands unsupported\n"); |
struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_D); |
emit(MUL(acc, op[0], op[1])); |
emit(MACH(reg_null_d, op[0], op[1])); |
emit(MOV(this->result, fs_reg(acc))); |
} else { |
emit(MUL(this->result, op[0], op[1])); |
} |
break; |
case ir_binop_div: |
/* Floating point should be lowered by DIV_TO_MUL_RCP in the compiler. */ |
assert(ir->type->is_integer()); |
emit_math(SHADER_OPCODE_INT_QUOTIENT, this->result, op[0], op[1]); |
break; |
case ir_binop_mod: |
/* Floating point should be lowered by MOD_TO_FRACT in the compiler. */ |
assert(ir->type->is_integer()); |
emit_math(SHADER_OPCODE_INT_REMAINDER, this->result, op[0], op[1]); |
break; |
case ir_binop_less: |
case ir_binop_greater: |
case ir_binop_lequal: |
case ir_binop_gequal: |
case ir_binop_equal: |
case ir_binop_all_equal: |
case ir_binop_nequal: |
case ir_binop_any_nequal: |
resolve_bool_comparison(ir->operands[0], &op[0]); |
resolve_bool_comparison(ir->operands[1], &op[1]); |
emit(CMP(this->result, op[0], op[1], |
brw_conditional_for_comparison(ir->operation))); |
break; |
case ir_binop_logic_xor: |
emit(XOR(this->result, op[0], op[1])); |
break; |
case ir_binop_logic_or: |
emit(OR(this->result, op[0], op[1])); |
break; |
case ir_binop_logic_and: |
emit(AND(this->result, op[0], op[1])); |
break; |
case ir_binop_dot: |
case ir_unop_any: |
assert(!"not reached: should be handled by brw_fs_channel_expressions"); |
break; |
case ir_unop_noise: |
assert(!"not reached: should be handled by lower_noise"); |
break; |
case ir_quadop_vector: |
assert(!"not reached: should be handled by lower_quadop_vector"); |
break; |
case ir_binop_vector_extract: |
assert(!"not reached: should be handled by lower_vec_index_to_cond_assign()"); |
break; |
case ir_triop_vector_insert: |
assert(!"not reached: should be handled by lower_vector_insert()"); |
break; |
case ir_unop_sqrt: |
emit_math(SHADER_OPCODE_SQRT, this->result, op[0]); |
break; |
case ir_unop_rsq: |
emit_math(SHADER_OPCODE_RSQ, this->result, op[0]); |
break; |
case ir_unop_bitcast_i2f: |
case ir_unop_bitcast_u2f: |
op[0].type = BRW_REGISTER_TYPE_F; |
this->result = op[0]; |
break; |
case ir_unop_i2u: |
case ir_unop_bitcast_f2u: |
op[0].type = BRW_REGISTER_TYPE_UD; |
this->result = op[0]; |
break; |
case ir_unop_u2i: |
case ir_unop_bitcast_f2i: |
op[0].type = BRW_REGISTER_TYPE_D; |
this->result = op[0]; |
break; |
case ir_unop_i2f: |
case ir_unop_u2f: |
case ir_unop_f2i: |
case ir_unop_f2u: |
emit(MOV(this->result, op[0])); |
break; |
case ir_unop_b2i: |
emit(AND(this->result, op[0], fs_reg(1))); |
break; |
case ir_unop_b2f: |
temp = fs_reg(this, glsl_type::int_type); |
emit(AND(temp, op[0], fs_reg(1))); |
emit(MOV(this->result, temp)); |
break; |
case ir_unop_f2b: |
emit(CMP(this->result, op[0], fs_reg(0.0f), BRW_CONDITIONAL_NZ)); |
break; |
case ir_unop_i2b: |
emit(CMP(this->result, op[0], fs_reg(0), BRW_CONDITIONAL_NZ)); |
break; |
case ir_unop_trunc: |
emit(RNDZ(this->result, op[0])); |
break; |
case ir_unop_ceil: |
op[0].negate = !op[0].negate; |
emit(RNDD(this->result, op[0])); |
this->result.negate = true; |
break; |
case ir_unop_floor: |
emit(RNDD(this->result, op[0])); |
break; |
case ir_unop_fract: |
emit(FRC(this->result, op[0])); |
break; |
case ir_unop_round_even: |
emit(RNDE(this->result, op[0])); |
break; |
case ir_binop_min: |
case ir_binop_max: |
resolve_ud_negate(&op[0]); |
resolve_ud_negate(&op[1]); |
emit_minmax(ir->operation == ir_binop_min ? |
BRW_CONDITIONAL_L : BRW_CONDITIONAL_GE, |
this->result, op[0], op[1]); |
break; |
case ir_unop_pack_snorm_2x16: |
case ir_unop_pack_snorm_4x8: |
case ir_unop_pack_unorm_2x16: |
case ir_unop_pack_unorm_4x8: |
case ir_unop_unpack_snorm_2x16: |
case ir_unop_unpack_snorm_4x8: |
case ir_unop_unpack_unorm_2x16: |
case ir_unop_unpack_unorm_4x8: |
case ir_unop_unpack_half_2x16: |
case ir_unop_pack_half_2x16: |
assert(!"not reached: should be handled by lower_packing_builtins"); |
break; |
case ir_unop_unpack_half_2x16_split_x: |
emit(FS_OPCODE_UNPACK_HALF_2x16_SPLIT_X, this->result, op[0]); |
break; |
case ir_unop_unpack_half_2x16_split_y: |
emit(FS_OPCODE_UNPACK_HALF_2x16_SPLIT_Y, this->result, op[0]); |
break; |
case ir_binop_pow: |
emit_math(SHADER_OPCODE_POW, this->result, op[0], op[1]); |
break; |
case ir_unop_bitfield_reverse: |
emit(BFREV(this->result, op[0])); |
break; |
case ir_unop_bit_count: |
emit(CBIT(this->result, op[0])); |
break; |
case ir_unop_find_msb: |
temp = fs_reg(this, glsl_type::uint_type); |
emit(FBH(temp, op[0])); |
/* FBH counts from the MSB side, while GLSL's findMSB() wants the count |
* from the LSB side. If FBH didn't return an error (0xFFFFFFFF), then |
* subtract the result from 31 to convert the MSB count into an LSB count. |
*/ |
/* FBH only supports UD type for dst, so use a MOV to convert UD to D. */ |
emit(MOV(this->result, temp)); |
emit(CMP(reg_null_d, this->result, fs_reg(-1), BRW_CONDITIONAL_NZ)); |
temp.negate = true; |
inst = emit(ADD(this->result, temp, fs_reg(31))); |
inst->predicate = BRW_PREDICATE_NORMAL; |
break; |
case ir_unop_find_lsb: |
emit(FBL(this->result, op[0])); |
break; |
case ir_triop_bitfield_extract: |
/* Note that the instruction's argument order is reversed from GLSL |
* and the IR. |
*/ |
emit(BFE(this->result, op[2], op[1], op[0])); |
break; |
case ir_binop_bfm: |
emit(BFI1(this->result, op[0], op[1])); |
break; |
case ir_triop_bfi: |
emit(BFI2(this->result, op[0], op[1], op[2])); |
break; |
case ir_quadop_bitfield_insert: |
assert(!"not reached: should be handled by " |
"lower_instructions::bitfield_insert_to_bfm_bfi"); |
break; |
case ir_unop_bit_not: |
emit(NOT(this->result, op[0])); |
break; |
case ir_binop_bit_and: |
emit(AND(this->result, op[0], op[1])); |
break; |
case ir_binop_bit_xor: |
emit(XOR(this->result, op[0], op[1])); |
break; |
case ir_binop_bit_or: |
emit(OR(this->result, op[0], op[1])); |
break; |
case ir_binop_lshift: |
emit(SHL(this->result, op[0], op[1])); |
break; |
case ir_binop_rshift: |
if (ir->type->base_type == GLSL_TYPE_INT) |
emit(ASR(this->result, op[0], op[1])); |
else |
emit(SHR(this->result, op[0], op[1])); |
break; |
case ir_binop_pack_half_2x16_split: |
emit(FS_OPCODE_PACK_HALF_2x16_SPLIT, this->result, op[0], op[1]); |
break; |
case ir_binop_ubo_load: { |
/* This IR node takes a constant uniform block and a constant or |
* variable byte offset within the block and loads a vector from that. |
*/ |
ir_constant *uniform_block = ir->operands[0]->as_constant(); |
ir_constant *const_offset = ir->operands[1]->as_constant(); |
fs_reg surf_index = fs_reg((unsigned)SURF_INDEX_WM_UBO(uniform_block->value.u[0])); |
if (const_offset) { |
fs_reg packed_consts = fs_reg(this, glsl_type::float_type); |
packed_consts.type = result.type; |
fs_reg const_offset_reg = fs_reg(const_offset->value.u[0] & ~15); |
emit(fs_inst(FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD, |
packed_consts, surf_index, const_offset_reg)); |
packed_consts.smear = const_offset->value.u[0] % 16 / 4; |
for (int i = 0; i < ir->type->vector_elements; i++) { |
/* UBO bools are any nonzero value. We consider bools to be |
* values with the low bit set to 1. Convert them using CMP. |
*/ |
if (ir->type->base_type == GLSL_TYPE_BOOL) { |
emit(CMP(result, packed_consts, fs_reg(0u), BRW_CONDITIONAL_NZ)); |
} else { |
emit(MOV(result, packed_consts)); |
} |
packed_consts.smear++; |
result.reg_offset++; |
/* The std140 packing rules don't allow vectors to cross 16-byte |
* boundaries, and a reg is 32 bytes. |
*/ |
assert(packed_consts.smear < 8); |
} |
} else { |
/* Turn the byte offset into a dword offset. */ |
fs_reg base_offset = fs_reg(this, glsl_type::int_type); |
emit(SHR(base_offset, op[1], fs_reg(2))); |
for (int i = 0; i < ir->type->vector_elements; i++) { |
emit(VARYING_PULL_CONSTANT_LOAD(result, surf_index, |
base_offset, i)); |
if (ir->type->base_type == GLSL_TYPE_BOOL) |
emit(CMP(result, result, fs_reg(0), BRW_CONDITIONAL_NZ)); |
result.reg_offset++; |
} |
} |
result.reg_offset = 0; |
break; |
} |
case ir_triop_lrp: |
emit_lrp(this->result, op[0], op[1], op[2]); |
break; |
} |
} |
void |
fs_visitor::emit_assignment_writes(fs_reg &l, fs_reg &r, |
const glsl_type *type, bool predicated) |
{ |
switch (type->base_type) { |
case GLSL_TYPE_FLOAT: |
case GLSL_TYPE_UINT: |
case GLSL_TYPE_INT: |
case GLSL_TYPE_BOOL: |
for (unsigned int i = 0; i < type->components(); i++) { |
l.type = brw_type_for_base_type(type); |
r.type = brw_type_for_base_type(type); |
if (predicated || !l.equals(r)) { |
fs_inst *inst = emit(MOV(l, r)); |
inst->predicate = predicated ? BRW_PREDICATE_NORMAL : BRW_PREDICATE_NONE; |
} |
l.reg_offset++; |
r.reg_offset++; |
} |
break; |
case GLSL_TYPE_ARRAY: |
for (unsigned int i = 0; i < type->length; i++) { |
emit_assignment_writes(l, r, type->fields.array, predicated); |
} |
break; |
case GLSL_TYPE_STRUCT: |
for (unsigned int i = 0; i < type->length; i++) { |
emit_assignment_writes(l, r, type->fields.structure[i].type, |
predicated); |
} |
break; |
case GLSL_TYPE_SAMPLER: |
break; |
case GLSL_TYPE_VOID: |
case GLSL_TYPE_ERROR: |
case GLSL_TYPE_INTERFACE: |
assert(!"not reached"); |
break; |
} |
} |
/* If the RHS processing resulted in an instruction generating a |
* temporary value, and it would be easy to rewrite the instruction to |
* generate its result right into the LHS instead, do so. This ends |
* up reliably removing instructions where it can be tricky to do so |
* later without real UD chain information. |
*/ |
bool |
fs_visitor::try_rewrite_rhs_to_dst(ir_assignment *ir, |
fs_reg dst, |
fs_reg src, |
fs_inst *pre_rhs_inst, |
fs_inst *last_rhs_inst) |
{ |
/* Only attempt if we're doing a direct assignment. */ |
if (ir->condition || |
!(ir->lhs->type->is_scalar() || |
(ir->lhs->type->is_vector() && |
ir->write_mask == (1 << ir->lhs->type->vector_elements) - 1))) |
return false; |
/* Make sure the last instruction generated our source reg. */ |
fs_inst *modify = get_instruction_generating_reg(pre_rhs_inst, |
last_rhs_inst, |
src); |
if (!modify) |
return false; |
/* If last_rhs_inst wrote a different number of components than our LHS, |
* we can't safely rewrite it. |
*/ |
if (virtual_grf_sizes[dst.reg] != modify->regs_written) |
return false; |
/* Success! Rewrite the instruction. */ |
modify->dst = dst; |
return true; |
} |
void |
fs_visitor::visit(ir_assignment *ir) |
{ |
fs_reg l, r; |
fs_inst *inst; |
/* FINISHME: arrays on the lhs */ |
ir->lhs->accept(this); |
l = this->result; |
fs_inst *pre_rhs_inst = (fs_inst *) this->instructions.get_tail(); |
ir->rhs->accept(this); |
r = this->result; |
fs_inst *last_rhs_inst = (fs_inst *) this->instructions.get_tail(); |
assert(l.file != BAD_FILE); |
assert(r.file != BAD_FILE); |
if (try_rewrite_rhs_to_dst(ir, l, r, pre_rhs_inst, last_rhs_inst)) |
return; |
if (ir->condition) { |
emit_bool_to_cond_code(ir->condition); |
} |
if (ir->lhs->type->is_scalar() || |
ir->lhs->type->is_vector()) { |
for (int i = 0; i < ir->lhs->type->vector_elements; i++) { |
if (ir->write_mask & (1 << i)) { |
inst = emit(MOV(l, r)); |
if (ir->condition) |
inst->predicate = BRW_PREDICATE_NORMAL; |
r.reg_offset++; |
} |
l.reg_offset++; |
} |
} else { |
emit_assignment_writes(l, r, ir->lhs->type, ir->condition != NULL); |
} |
} |
fs_inst * |
fs_visitor::emit_texture_gen4(ir_texture *ir, fs_reg dst, fs_reg coordinate, |
fs_reg shadow_c, fs_reg lod, fs_reg dPdy) |
{ |
int mlen; |
int base_mrf = 1; |
bool simd16 = false; |
fs_reg orig_dst; |
/* g0 header. */ |
mlen = 1; |
if (ir->shadow_comparitor) { |
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen + i), coordinate)); |
coordinate.reg_offset++; |
} |
/* gen4's SIMD8 sampler always has the slots for u,v,r present. |
* the unused slots must be zeroed. |
*/ |
for (int i = ir->coordinate->type->vector_elements; i < 3; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen + i), fs_reg(0.0f))); |
} |
mlen += 3; |
if (ir->op == ir_tex) { |
/* There's no plain shadow compare message, so we use shadow |
* compare with a bias of 0.0. |
*/ |
emit(MOV(fs_reg(MRF, base_mrf + mlen), fs_reg(0.0f))); |
mlen++; |
} else if (ir->op == ir_txb || ir->op == ir_txl) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen), lod)); |
mlen++; |
} else { |
assert(!"Should not get here."); |
} |
emit(MOV(fs_reg(MRF, base_mrf + mlen), shadow_c)); |
mlen++; |
} else if (ir->op == ir_tex) { |
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen + i), coordinate)); |
coordinate.reg_offset++; |
} |
/* zero the others. */ |
for (int i = ir->coordinate->type->vector_elements; i<3; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen + i), fs_reg(0.0f))); |
} |
/* gen4's SIMD8 sampler always has the slots for u,v,r present. */ |
mlen += 3; |
} else if (ir->op == ir_txd) { |
fs_reg &dPdx = lod; |
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen + i), coordinate)); |
coordinate.reg_offset++; |
} |
/* the slots for u and v are always present, but r is optional */ |
mlen += MAX2(ir->coordinate->type->vector_elements, 2); |
/* P = u, v, r |
* dPdx = dudx, dvdx, drdx |
* dPdy = dudy, dvdy, drdy |
* |
* 1-arg: Does not exist. |
* |
* 2-arg: dudx dvdx dudy dvdy |
* dPdx.x dPdx.y dPdy.x dPdy.y |
* m4 m5 m6 m7 |
* |
* 3-arg: dudx dvdx drdx dudy dvdy drdy |
* dPdx.x dPdx.y dPdx.z dPdy.x dPdy.y dPdy.z |
* m5 m6 m7 m8 m9 m10 |
*/ |
for (int i = 0; i < ir->lod_info.grad.dPdx->type->vector_elements; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen), dPdx)); |
dPdx.reg_offset++; |
} |
mlen += MAX2(ir->lod_info.grad.dPdx->type->vector_elements, 2); |
for (int i = 0; i < ir->lod_info.grad.dPdy->type->vector_elements; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen), dPdy)); |
dPdy.reg_offset++; |
} |
mlen += MAX2(ir->lod_info.grad.dPdy->type->vector_elements, 2); |
} else if (ir->op == ir_txs) { |
/* There's no SIMD8 resinfo message on Gen4. Use SIMD16 instead. */ |
simd16 = true; |
emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), lod)); |
mlen += 2; |
} else { |
/* Oh joy. gen4 doesn't have SIMD8 non-shadow-compare bias/lod |
* instructions. We'll need to do SIMD16 here. |
*/ |
simd16 = true; |
assert(ir->op == ir_txb || ir->op == ir_txl || ir->op == ir_txf); |
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen + i * 2, coordinate.type), |
coordinate)); |
coordinate.reg_offset++; |
} |
/* Initialize the rest of u/v/r with 0.0. Empirically, this seems to |
* be necessary for TXF (ld), but seems wise to do for all messages. |
*/ |
for (int i = ir->coordinate->type->vector_elements; i < 3; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen + i * 2), fs_reg(0.0f))); |
} |
/* lod/bias appears after u/v/r. */ |
mlen += 6; |
emit(MOV(fs_reg(MRF, base_mrf + mlen, lod.type), lod)); |
mlen++; |
/* The unused upper half. */ |
mlen++; |
} |
if (simd16) { |
/* Now, since we're doing simd16, the return is 2 interleaved |
* vec4s where the odd-indexed ones are junk. We'll need to move |
* this weirdness around to the expected layout. |
*/ |
orig_dst = dst; |
dst = fs_reg(GRF, virtual_grf_alloc(8), |
(brw->is_g4x ? |
brw_type_for_base_type(ir->type) : |
BRW_REGISTER_TYPE_F)); |
} |
fs_inst *inst = NULL; |
switch (ir->op) { |
case ir_tex: |
inst = emit(SHADER_OPCODE_TEX, dst); |
break; |
case ir_txb: |
inst = emit(FS_OPCODE_TXB, dst); |
break; |
case ir_txl: |
inst = emit(SHADER_OPCODE_TXL, dst); |
break; |
case ir_txd: |
inst = emit(SHADER_OPCODE_TXD, dst); |
break; |
case ir_txs: |
inst = emit(SHADER_OPCODE_TXS, dst); |
break; |
case ir_txf: |
inst = emit(SHADER_OPCODE_TXF, dst); |
break; |
default: |
fail("unrecognized texture opcode"); |
} |
inst->base_mrf = base_mrf; |
inst->mlen = mlen; |
inst->header_present = true; |
inst->regs_written = simd16 ? 8 : 4; |
if (simd16) { |
for (int i = 0; i < 4; i++) { |
emit(MOV(orig_dst, dst)); |
orig_dst.reg_offset++; |
dst.reg_offset += 2; |
} |
} |
return inst; |
} |
/* gen5's sampler has slots for u, v, r, array index, then optional |
* parameters like shadow comparitor or LOD bias. If optional |
* parameters aren't present, those base slots are optional and don't |
* need to be included in the message. |
* |
* We don't fill in the unnecessary slots regardless, which may look |
* surprising in the disassembly. |
*/ |
fs_inst * |
fs_visitor::emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate, |
fs_reg shadow_c, fs_reg lod, fs_reg lod2, |
fs_reg sample_index) |
{ |
int mlen = 0; |
int base_mrf = 2; |
int reg_width = dispatch_width / 8; |
bool header_present = false; |
const int vector_elements = |
ir->coordinate ? ir->coordinate->type->vector_elements : 0; |
if (ir->offset != NULL && ir->op == ir_txf) { |
/* It appears that the ld instruction used for txf does its |
* address bounds check before adding in the offset. To work |
* around this, just add the integer offset to the integer texel |
* coordinate, and don't put the offset in the header. |
*/ |
ir_constant *offset = ir->offset->as_constant(); |
for (int i = 0; i < vector_elements; i++) { |
emit(ADD(fs_reg(MRF, base_mrf + mlen + i * reg_width, coordinate.type), |
coordinate, |
offset->value.i[i])); |
coordinate.reg_offset++; |
} |
} else { |
if (ir->offset) { |
/* The offsets set up by the ir_texture visitor are in the |
* m1 header, so we can't go headerless. |
*/ |
header_present = true; |
mlen++; |
base_mrf--; |
} |
for (int i = 0; i < vector_elements; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen + i * reg_width, coordinate.type), |
coordinate)); |
coordinate.reg_offset++; |
} |
} |
mlen += vector_elements * reg_width; |
if (ir->shadow_comparitor) { |
mlen = MAX2(mlen, header_present + 4 * reg_width); |
emit(MOV(fs_reg(MRF, base_mrf + mlen), shadow_c)); |
mlen += reg_width; |
} |
fs_inst *inst = NULL; |
switch (ir->op) { |
case ir_tex: |
inst = emit(SHADER_OPCODE_TEX, dst); |
break; |
case ir_txb: |
mlen = MAX2(mlen, header_present + 4 * reg_width); |
emit(MOV(fs_reg(MRF, base_mrf + mlen), lod)); |
mlen += reg_width; |
inst = emit(FS_OPCODE_TXB, dst); |
break; |
case ir_txl: |
mlen = MAX2(mlen, header_present + 4 * reg_width); |
emit(MOV(fs_reg(MRF, base_mrf + mlen), lod)); |
mlen += reg_width; |
inst = emit(SHADER_OPCODE_TXL, dst); |
break; |
case ir_txd: { |
mlen = MAX2(mlen, header_present + 4 * reg_width); /* skip over 'ai' */ |
/** |
* P = u, v, r |
* dPdx = dudx, dvdx, drdx |
* dPdy = dudy, dvdy, drdy |
* |
* Load up these values: |
* - dudx dudy dvdx dvdy drdx drdy |
* - dPdx.x dPdy.x dPdx.y dPdy.y dPdx.z dPdy.z |
*/ |
for (int i = 0; i < ir->lod_info.grad.dPdx->type->vector_elements; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen), lod)); |
lod.reg_offset++; |
mlen += reg_width; |
emit(MOV(fs_reg(MRF, base_mrf + mlen), lod2)); |
lod2.reg_offset++; |
mlen += reg_width; |
} |
inst = emit(SHADER_OPCODE_TXD, dst); |
break; |
} |
case ir_txs: |
emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), lod)); |
mlen += reg_width; |
inst = emit(SHADER_OPCODE_TXS, dst); |
break; |
case ir_txf: |
mlen = header_present + 4 * reg_width; |
emit(MOV(fs_reg(MRF, base_mrf + mlen - reg_width, BRW_REGISTER_TYPE_UD), lod)); |
inst = emit(SHADER_OPCODE_TXF, dst); |
break; |
case ir_txf_ms: |
mlen = header_present + 4 * reg_width; |
/* lod */ |
emit(MOV(fs_reg(MRF, base_mrf + mlen - reg_width, BRW_REGISTER_TYPE_UD), fs_reg(0))); |
/* sample index */ |
emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), sample_index)); |
mlen += reg_width; |
inst = emit(SHADER_OPCODE_TXF_MS, dst); |
break; |
case ir_lod: |
inst = emit(SHADER_OPCODE_LOD, dst); |
break; |
} |
inst->base_mrf = base_mrf; |
inst->mlen = mlen; |
inst->header_present = header_present; |
inst->regs_written = 4; |
if (mlen > 11) { |
fail("Message length >11 disallowed by hardware\n"); |
} |
return inst; |
} |
fs_inst * |
fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate, |
fs_reg shadow_c, fs_reg lod, fs_reg lod2, |
fs_reg sample_index) |
{ |
int mlen = 0; |
int base_mrf = 2; |
int reg_width = dispatch_width / 8; |
bool header_present = false; |
int offsets[3]; |
if (ir->offset && ir->op != ir_txf) { |
/* The offsets set up by the ir_texture visitor are in the |
* m1 header, so we can't go headerless. |
*/ |
header_present = true; |
mlen++; |
base_mrf--; |
} |
if (ir->shadow_comparitor) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen), shadow_c)); |
mlen += reg_width; |
} |
/* Set up the LOD info */ |
switch (ir->op) { |
case ir_tex: |
case ir_lod: |
break; |
case ir_txb: |
emit(MOV(fs_reg(MRF, base_mrf + mlen), lod)); |
mlen += reg_width; |
break; |
case ir_txl: |
emit(MOV(fs_reg(MRF, base_mrf + mlen), lod)); |
mlen += reg_width; |
break; |
case ir_txd: { |
if (dispatch_width == 16) |
fail("Gen7 does not support sample_d/sample_d_c in SIMD16 mode."); |
/* Load dPdx and the coordinate together: |
* [hdr], [ref], x, dPdx.x, dPdy.x, y, dPdx.y, dPdy.y, z, dPdx.z, dPdy.z |
*/ |
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen), coordinate)); |
coordinate.reg_offset++; |
mlen += reg_width; |
/* For cube map array, the coordinate is (u,v,r,ai) but there are |
* only derivatives for (u, v, r). |
*/ |
if (i < ir->lod_info.grad.dPdx->type->vector_elements) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen), lod)); |
lod.reg_offset++; |
mlen += reg_width; |
emit(MOV(fs_reg(MRF, base_mrf + mlen), lod2)); |
lod2.reg_offset++; |
mlen += reg_width; |
} |
} |
break; |
} |
case ir_txs: |
emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), lod)); |
mlen += reg_width; |
break; |
case ir_txf: |
/* It appears that the ld instruction used for txf does its |
* address bounds check before adding in the offset. To work |
* around this, just add the integer offset to the integer texel |
* coordinate, and don't put the offset in the header. |
*/ |
if (ir->offset) { |
ir_constant *offset = ir->offset->as_constant(); |
offsets[0] = offset->value.i[0]; |
offsets[1] = offset->value.i[1]; |
offsets[2] = offset->value.i[2]; |
} else { |
memset(offsets, 0, sizeof(offsets)); |
} |
/* Unfortunately, the parameters for LD are intermixed: u, lod, v, r. */ |
emit(ADD(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D), |
coordinate, offsets[0])); |
coordinate.reg_offset++; |
mlen += reg_width; |
emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D), lod)); |
mlen += reg_width; |
for (int i = 1; i < ir->coordinate->type->vector_elements; i++) { |
emit(ADD(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D), |
coordinate, offsets[i])); |
coordinate.reg_offset++; |
mlen += reg_width; |
} |
break; |
case ir_txf_ms: |
emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), sample_index)); |
mlen += reg_width; |
/* constant zero MCS; we arrange to never actually have a compressed |
* multisample surface here for now. TODO: issue ld_mcs to get this first, |
* if we ever support texturing from compressed multisample surfaces |
*/ |
emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), fs_reg(0u))); |
mlen += reg_width; |
/* there is no offsetting for this message; just copy in the integer |
* texture coordinates |
*/ |
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_D), |
coordinate)); |
coordinate.reg_offset++; |
mlen += reg_width; |
} |
break; |
} |
/* Set up the coordinate (except for cases where it was done above) */ |
if (ir->op != ir_txd && ir->op != ir_txs && ir->op != ir_txf && ir->op != ir_txf_ms) { |
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) { |
emit(MOV(fs_reg(MRF, base_mrf + mlen), coordinate)); |
coordinate.reg_offset++; |
mlen += reg_width; |
} |
} |
/* Generate the SEND */ |
fs_inst *inst = NULL; |
switch (ir->op) { |
case ir_tex: inst = emit(SHADER_OPCODE_TEX, dst); break; |
case ir_txb: inst = emit(FS_OPCODE_TXB, dst); break; |
case ir_txl: inst = emit(SHADER_OPCODE_TXL, dst); break; |
case ir_txd: inst = emit(SHADER_OPCODE_TXD, dst); break; |
case ir_txf: inst = emit(SHADER_OPCODE_TXF, dst); break; |
case ir_txf_ms: inst = emit(SHADER_OPCODE_TXF_MS, dst); break; |
case ir_txs: inst = emit(SHADER_OPCODE_TXS, dst); break; |
case ir_lod: inst = emit(SHADER_OPCODE_LOD, dst); break; |
} |
inst->base_mrf = base_mrf; |
inst->mlen = mlen; |
inst->header_present = header_present; |
inst->regs_written = 4; |
if (mlen > 11) { |
fail("Message length >11 disallowed by hardware\n"); |
} |
return inst; |
} |
fs_reg |
fs_visitor::rescale_texcoord(ir_texture *ir, fs_reg coordinate, |
bool is_rect, int sampler, int texunit) |
{ |
fs_inst *inst = NULL; |
bool needs_gl_clamp = true; |
fs_reg scale_x, scale_y; |
/* The 965 requires the EU to do the normalization of GL rectangle |
* texture coordinates. We use the program parameter state |
* tracking to get the scaling factor. |
*/ |
if (is_rect && |
(brw->gen < 6 || |
(brw->gen >= 6 && (c->key.tex.gl_clamp_mask[0] & (1 << sampler) || |
c->key.tex.gl_clamp_mask[1] & (1 << sampler))))) { |
struct gl_program_parameter_list *params = fp->Base.Parameters; |
int tokens[STATE_LENGTH] = { |
STATE_INTERNAL, |
STATE_TEXRECT_SCALE, |
texunit, |
0, |
0 |
}; |
if (dispatch_width == 16) { |
fail("rectangle scale uniform setup not supported on 16-wide\n"); |
return coordinate; |
} |
scale_x = fs_reg(UNIFORM, c->prog_data.nr_params); |
scale_y = fs_reg(UNIFORM, c->prog_data.nr_params + 1); |
GLuint index = _mesa_add_state_reference(params, |
(gl_state_index *)tokens); |
c->prog_data.param[c->prog_data.nr_params++] = |
&fp->Base.Parameters->ParameterValues[index][0].f; |
c->prog_data.param[c->prog_data.nr_params++] = |
&fp->Base.Parameters->ParameterValues[index][1].f; |
} |
/* The 965 requires the EU to do the normalization of GL rectangle |
* texture coordinates. We use the program parameter state |
* tracking to get the scaling factor. |
*/ |
if (brw->gen < 6 && is_rect) { |
fs_reg dst = fs_reg(this, ir->coordinate->type); |
fs_reg src = coordinate; |
coordinate = dst; |
emit(MUL(dst, src, scale_x)); |
dst.reg_offset++; |
src.reg_offset++; |
emit(MUL(dst, src, scale_y)); |
} else if (is_rect) { |
/* On gen6+, the sampler handles the rectangle coordinates |
* natively, without needing rescaling. But that means we have |
* to do GL_CLAMP clamping at the [0, width], [0, height] scale, |
* not [0, 1] like the default case below. |
*/ |
needs_gl_clamp = false; |
for (int i = 0; i < 2; i++) { |
if (c->key.tex.gl_clamp_mask[i] & (1 << sampler)) { |
fs_reg chan = coordinate; |
chan.reg_offset += i; |
inst = emit(BRW_OPCODE_SEL, chan, chan, brw_imm_f(0.0)); |
inst->conditional_mod = BRW_CONDITIONAL_G; |
/* Our parameter comes in as 1.0/width or 1.0/height, |
* because that's what people normally want for doing |
* texture rectangle handling. We need width or height |
* for clamping, but we don't care enough to make a new |
* parameter type, so just invert back. |
*/ |
fs_reg limit = fs_reg(this, glsl_type::float_type); |
emit(MOV(limit, i == 0 ? scale_x : scale_y)); |
emit(SHADER_OPCODE_RCP, limit, limit); |
inst = emit(BRW_OPCODE_SEL, chan, chan, limit); |
inst->conditional_mod = BRW_CONDITIONAL_L; |
} |
} |
} |
if (ir->coordinate && needs_gl_clamp) { |
for (unsigned int i = 0; |
i < MIN2(ir->coordinate->type->vector_elements, 3); i++) { |
if (c->key.tex.gl_clamp_mask[i] & (1 << sampler)) { |
fs_reg chan = coordinate; |
chan.reg_offset += i; |
fs_inst *inst = emit(MOV(chan, chan)); |
inst->saturate = true; |
} |
} |
} |
return coordinate; |
} |
void |
fs_visitor::visit(ir_texture *ir) |
{ |
fs_inst *inst = NULL; |
int sampler = |
_mesa_get_sampler_uniform_value(ir->sampler, shader_prog, &fp->Base); |
/* FINISHME: We're failing to recompile our programs when the sampler is |
* updated. This only matters for the texture rectangle scale parameters |
* (pre-gen6, or gen6+ with GL_CLAMP). |
*/ |
int texunit = fp->Base.SamplerUnits[sampler]; |
/* Should be lowered by do_lower_texture_projection */ |
assert(!ir->projector); |
/* Generate code to compute all the subexpression trees. This has to be |
* done before loading any values into MRFs for the sampler message since |
* generating these values may involve SEND messages that need the MRFs. |
*/ |
fs_reg coordinate; |
if (ir->coordinate) { |
ir->coordinate->accept(this); |
coordinate = rescale_texcoord(ir, this->result, |
ir->sampler->type->sampler_dimensionality == |
GLSL_SAMPLER_DIM_RECT, |
sampler, texunit); |
} |
fs_reg shadow_comparitor; |
if (ir->shadow_comparitor) { |
ir->shadow_comparitor->accept(this); |
shadow_comparitor = this->result; |
} |
fs_reg lod, lod2, sample_index; |
switch (ir->op) { |
case ir_tex: |
case ir_lod: |
break; |
case ir_txb: |
ir->lod_info.bias->accept(this); |
lod = this->result; |
break; |
case ir_txd: |
ir->lod_info.grad.dPdx->accept(this); |
lod = this->result; |
ir->lod_info.grad.dPdy->accept(this); |
lod2 = this->result; |
break; |
case ir_txf: |
case ir_txl: |
case ir_txs: |
ir->lod_info.lod->accept(this); |
lod = this->result; |
break; |
case ir_txf_ms: |
ir->lod_info.sample_index->accept(this); |
sample_index = this->result; |
break; |
}; |
/* Writemasking doesn't eliminate channels on SIMD8 texture |
* samples, so don't worry about them. |
*/ |
fs_reg dst = fs_reg(this, glsl_type::get_instance(ir->type->base_type, 4, 1)); |
if (brw->gen >= 7) { |
inst = emit_texture_gen7(ir, dst, coordinate, shadow_comparitor, |
lod, lod2, sample_index); |
} else if (brw->gen >= 5) { |
inst = emit_texture_gen5(ir, dst, coordinate, shadow_comparitor, |
lod, lod2, sample_index); |
} else { |
inst = emit_texture_gen4(ir, dst, coordinate, shadow_comparitor, |
lod, lod2); |
} |
/* The header is set up by generate_tex() when necessary. */ |
inst->src[0] = reg_undef; |
if (ir->offset != NULL && ir->op != ir_txf) |
inst->texture_offset = brw_texture_offset(ir->offset->as_constant()); |
inst->sampler = sampler; |
if (ir->shadow_comparitor) |
inst->shadow_compare = true; |
/* fixup #layers for cube map arrays */ |
if (ir->op == ir_txs) { |
glsl_type const *type = ir->sampler->type; |
if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE && |
type->sampler_array) { |
fs_reg depth = dst; |
depth.reg_offset = 2; |
emit_math(SHADER_OPCODE_INT_QUOTIENT, depth, depth, fs_reg(6)); |
} |
} |
swizzle_result(ir, dst, sampler); |
} |
/** |
* Swizzle the result of a texture result. This is necessary for |
* EXT_texture_swizzle as well as DEPTH_TEXTURE_MODE for shadow comparisons. |
*/ |
void |
fs_visitor::swizzle_result(ir_texture *ir, fs_reg orig_val, int sampler) |
{ |
this->result = orig_val; |
if (ir->op == ir_txs || ir->op == ir_lod) |
return; |
if (ir->type == glsl_type::float_type) { |
/* Ignore DEPTH_TEXTURE_MODE swizzling. */ |
assert(ir->sampler->type->sampler_shadow); |
} else if (c->key.tex.swizzles[sampler] != SWIZZLE_NOOP) { |
fs_reg swizzled_result = fs_reg(this, glsl_type::vec4_type); |
for (int i = 0; i < 4; i++) { |
int swiz = GET_SWZ(c->key.tex.swizzles[sampler], i); |
fs_reg l = swizzled_result; |
l.reg_offset += i; |
if (swiz == SWIZZLE_ZERO) { |
emit(MOV(l, fs_reg(0.0f))); |
} else if (swiz == SWIZZLE_ONE) { |
emit(MOV(l, fs_reg(1.0f))); |
} else { |
fs_reg r = orig_val; |
r.reg_offset += GET_SWZ(c->key.tex.swizzles[sampler], i); |
emit(MOV(l, r)); |
} |
} |
this->result = swizzled_result; |
} |
} |
void |
fs_visitor::visit(ir_swizzle *ir) |
{ |
ir->val->accept(this); |
fs_reg val = this->result; |
if (ir->type->vector_elements == 1) { |
this->result.reg_offset += ir->mask.x; |
return; |
} |
fs_reg result = fs_reg(this, ir->type); |
this->result = result; |
for (unsigned int i = 0; i < ir->type->vector_elements; i++) { |
fs_reg channel = val; |
int swiz = 0; |
switch (i) { |
case 0: |
swiz = ir->mask.x; |
break; |
case 1: |
swiz = ir->mask.y; |
break; |
case 2: |
swiz = ir->mask.z; |
break; |
case 3: |
swiz = ir->mask.w; |
break; |
} |
channel.reg_offset += swiz; |
emit(MOV(result, channel)); |
result.reg_offset++; |
} |
} |
void |
fs_visitor::visit(ir_discard *ir) |
{ |
assert(ir->condition == NULL); /* FINISHME */ |
/* We track our discarded pixels in f0.1. By predicating on it, we can |
* update just the flag bits that aren't yet discarded. By emitting a |
* CMP of g0 != g0, all our currently executing channels will get turned |
* off. |
*/ |
fs_reg some_reg = fs_reg(retype(brw_vec8_grf(0, 0), |
BRW_REGISTER_TYPE_UW)); |
fs_inst *cmp = emit(CMP(reg_null_f, some_reg, some_reg, |
BRW_CONDITIONAL_NZ)); |
cmp->predicate = BRW_PREDICATE_NORMAL; |
cmp->flag_subreg = 1; |
if (brw->gen >= 6) { |
/* For performance, after a discard, jump to the end of the shader. |
* However, many people will do foliage by discarding based on a |
* texture's alpha mask, and then continue on to texture with the |
* remaining pixels. To avoid trashing the derivatives for those |
* texture samples, we'll only jump if all of the pixels in the subspan |
* have been discarded. |
*/ |
fs_inst *discard_jump = emit(FS_OPCODE_DISCARD_JUMP); |
discard_jump->flag_subreg = 1; |
discard_jump->predicate = BRW_PREDICATE_ALIGN1_ANY4H; |
discard_jump->predicate_inverse = true; |
} |
} |
void |
fs_visitor::visit(ir_constant *ir) |
{ |
/* Set this->result to reg at the bottom of the function because some code |
* paths will cause this visitor to be applied to other fields. This will |
* cause the value stored in this->result to be modified. |
* |
* Make reg constant so that it doesn't get accidentally modified along the |
* way. Yes, I actually had this problem. :( |
*/ |
const fs_reg reg(this, ir->type); |
fs_reg dst_reg = reg; |
if (ir->type->is_array()) { |
const unsigned size = type_size(ir->type->fields.array); |
for (unsigned i = 0; i < ir->type->length; i++) { |
ir->array_elements[i]->accept(this); |
fs_reg src_reg = this->result; |
dst_reg.type = src_reg.type; |
for (unsigned j = 0; j < size; j++) { |
emit(MOV(dst_reg, src_reg)); |
src_reg.reg_offset++; |
dst_reg.reg_offset++; |
} |
} |
} else if (ir->type->is_record()) { |
foreach_list(node, &ir->components) { |
ir_constant *const field = (ir_constant *) node; |
const unsigned size = type_size(field->type); |
field->accept(this); |
fs_reg src_reg = this->result; |
dst_reg.type = src_reg.type; |
for (unsigned j = 0; j < size; j++) { |
emit(MOV(dst_reg, src_reg)); |
src_reg.reg_offset++; |
dst_reg.reg_offset++; |
} |
} |
} else { |
const unsigned size = type_size(ir->type); |
for (unsigned i = 0; i < size; i++) { |
switch (ir->type->base_type) { |
case GLSL_TYPE_FLOAT: |
emit(MOV(dst_reg, fs_reg(ir->value.f[i]))); |
break; |
case GLSL_TYPE_UINT: |
emit(MOV(dst_reg, fs_reg(ir->value.u[i]))); |
break; |
case GLSL_TYPE_INT: |
emit(MOV(dst_reg, fs_reg(ir->value.i[i]))); |
break; |
case GLSL_TYPE_BOOL: |
emit(MOV(dst_reg, fs_reg((int)ir->value.b[i]))); |
break; |
default: |
assert(!"Non-float/uint/int/bool constant"); |
} |
dst_reg.reg_offset++; |
} |
} |
this->result = reg; |
} |
void |
fs_visitor::emit_bool_to_cond_code(ir_rvalue *ir) |
{ |
ir_expression *expr = ir->as_expression(); |
if (expr) { |
fs_reg op[2]; |
fs_inst *inst; |
assert(expr->get_num_operands() <= 2); |
for (unsigned int i = 0; i < expr->get_num_operands(); i++) { |
assert(expr->operands[i]->type->is_scalar()); |
expr->operands[i]->accept(this); |
op[i] = this->result; |
resolve_ud_negate(&op[i]); |
} |
switch (expr->operation) { |
case ir_unop_logic_not: |
inst = emit(AND(reg_null_d, op[0], fs_reg(1))); |
inst->conditional_mod = BRW_CONDITIONAL_Z; |
break; |
case ir_binop_logic_xor: |
case ir_binop_logic_or: |
case ir_binop_logic_and: |
goto out; |
case ir_unop_f2b: |
if (brw->gen >= 6) { |
emit(CMP(reg_null_d, op[0], fs_reg(0.0f), BRW_CONDITIONAL_NZ)); |
} else { |
inst = emit(MOV(reg_null_f, op[0])); |
inst->conditional_mod = BRW_CONDITIONAL_NZ; |
} |
break; |
case ir_unop_i2b: |
if (brw->gen >= 6) { |
emit(CMP(reg_null_d, op[0], fs_reg(0), BRW_CONDITIONAL_NZ)); |
} else { |
inst = emit(MOV(reg_null_d, op[0])); |
inst->conditional_mod = BRW_CONDITIONAL_NZ; |
} |
break; |
case ir_binop_greater: |
case ir_binop_gequal: |
case ir_binop_less: |
case ir_binop_lequal: |
case ir_binop_equal: |
case ir_binop_all_equal: |
case ir_binop_nequal: |
case ir_binop_any_nequal: |
resolve_bool_comparison(expr->operands[0], &op[0]); |
resolve_bool_comparison(expr->operands[1], &op[1]); |
emit(CMP(reg_null_d, op[0], op[1], |
brw_conditional_for_comparison(expr->operation))); |
break; |
default: |
assert(!"not reached"); |
fail("bad cond code\n"); |
break; |
} |
return; |
} |
out: |
ir->accept(this); |
fs_inst *inst = emit(AND(reg_null_d, this->result, fs_reg(1))); |
inst->conditional_mod = BRW_CONDITIONAL_NZ; |
} |
/** |
* Emit a gen6 IF statement with the comparison folded into the IF |
* instruction. |
*/ |
void |
fs_visitor::emit_if_gen6(ir_if *ir) |
{ |
ir_expression *expr = ir->condition->as_expression(); |
if (expr) { |
fs_reg op[2]; |
fs_inst *inst; |
fs_reg temp; |
assert(expr->get_num_operands() <= 2); |
for (unsigned int i = 0; i < expr->get_num_operands(); i++) { |
assert(expr->operands[i]->type->is_scalar()); |
expr->operands[i]->accept(this); |
op[i] = this->result; |
} |
switch (expr->operation) { |
case ir_unop_logic_not: |
case ir_binop_logic_xor: |
case ir_binop_logic_or: |
case ir_binop_logic_and: |
/* For operations on bool arguments, only the low bit of the bool is |
* valid, and the others are undefined. Fall back to the condition |
* code path. |
*/ |
break; |
case ir_unop_f2b: |
inst = emit(BRW_OPCODE_IF, reg_null_f, op[0], fs_reg(0)); |
inst->conditional_mod = BRW_CONDITIONAL_NZ; |
return; |
case ir_unop_i2b: |
emit(IF(op[0], fs_reg(0), BRW_CONDITIONAL_NZ)); |
return; |
case ir_binop_greater: |
case ir_binop_gequal: |
case ir_binop_less: |
case ir_binop_lequal: |
case ir_binop_equal: |
case ir_binop_all_equal: |
case ir_binop_nequal: |
case ir_binop_any_nequal: |
resolve_bool_comparison(expr->operands[0], &op[0]); |
resolve_bool_comparison(expr->operands[1], &op[1]); |
emit(IF(op[0], op[1], |
brw_conditional_for_comparison(expr->operation))); |
return; |
default: |
assert(!"not reached"); |
emit(IF(op[0], fs_reg(0), BRW_CONDITIONAL_NZ)); |
fail("bad condition\n"); |
return; |
} |
} |
emit_bool_to_cond_code(ir->condition); |
fs_inst *inst = emit(BRW_OPCODE_IF); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
void |
fs_visitor::visit(ir_if *ir) |
{ |
if (brw->gen < 6 && dispatch_width == 16) { |
fail("Can't support (non-uniform) control flow on 16-wide\n"); |
} |
/* Don't point the annotation at the if statement, because then it plus |
* the then and else blocks get printed. |
*/ |
this->base_ir = ir->condition; |
if (brw->gen == 6) { |
emit_if_gen6(ir); |
} else { |
emit_bool_to_cond_code(ir->condition); |
emit(IF(BRW_PREDICATE_NORMAL)); |
} |
foreach_list(node, &ir->then_instructions) { |
ir_instruction *ir = (ir_instruction *)node; |
this->base_ir = ir; |
ir->accept(this); |
} |
if (!ir->else_instructions.is_empty()) { |
emit(BRW_OPCODE_ELSE); |
foreach_list(node, &ir->else_instructions) { |
ir_instruction *ir = (ir_instruction *)node; |
this->base_ir = ir; |
ir->accept(this); |
} |
} |
emit(BRW_OPCODE_ENDIF); |
} |
void |
fs_visitor::visit(ir_loop *ir) |
{ |
fs_reg counter = reg_undef; |
if (brw->gen < 6 && dispatch_width == 16) { |
fail("Can't support (non-uniform) control flow on 16-wide\n"); |
} |
if (ir->counter) { |
this->base_ir = ir->counter; |
ir->counter->accept(this); |
counter = *(variable_storage(ir->counter)); |
if (ir->from) { |
this->base_ir = ir->from; |
ir->from->accept(this); |
emit(MOV(counter, this->result)); |
} |
} |
this->base_ir = NULL; |
emit(BRW_OPCODE_DO); |
if (ir->to) { |
this->base_ir = ir->to; |
ir->to->accept(this); |
emit(CMP(reg_null_d, counter, this->result, |
brw_conditional_for_comparison(ir->cmp))); |
fs_inst *inst = emit(BRW_OPCODE_BREAK); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
foreach_list(node, &ir->body_instructions) { |
ir_instruction *ir = (ir_instruction *)node; |
this->base_ir = ir; |
ir->accept(this); |
} |
if (ir->increment) { |
this->base_ir = ir->increment; |
ir->increment->accept(this); |
emit(ADD(counter, counter, this->result)); |
} |
this->base_ir = NULL; |
emit(BRW_OPCODE_WHILE); |
} |
void |
fs_visitor::visit(ir_loop_jump *ir) |
{ |
switch (ir->mode) { |
case ir_loop_jump::jump_break: |
emit(BRW_OPCODE_BREAK); |
break; |
case ir_loop_jump::jump_continue: |
emit(BRW_OPCODE_CONTINUE); |
break; |
} |
} |
void |
fs_visitor::visit(ir_call *ir) |
{ |
assert(!"FINISHME"); |
} |
void |
fs_visitor::visit(ir_return *ir) |
{ |
assert(!"FINISHME"); |
} |
void |
fs_visitor::visit(ir_function *ir) |
{ |
/* Ignore function bodies other than main() -- we shouldn't see calls to |
* them since they should all be inlined before we get to ir_to_mesa. |
*/ |
if (strcmp(ir->name, "main") == 0) { |
const ir_function_signature *sig; |
exec_list empty; |
sig = ir->matching_signature(&empty); |
assert(sig); |
foreach_list(node, &sig->body) { |
ir_instruction *ir = (ir_instruction *)node; |
this->base_ir = ir; |
ir->accept(this); |
} |
} |
} |
void |
fs_visitor::visit(ir_function_signature *ir) |
{ |
assert(!"not reached"); |
(void)ir; |
} |
fs_inst * |
fs_visitor::emit(fs_inst inst) |
{ |
fs_inst *list_inst = new(mem_ctx) fs_inst; |
*list_inst = inst; |
emit(list_inst); |
return list_inst; |
} |
fs_inst * |
fs_visitor::emit(fs_inst *inst) |
{ |
if (force_uncompressed_stack > 0) |
inst->force_uncompressed = true; |
else if (force_sechalf_stack > 0) |
inst->force_sechalf = true; |
inst->annotation = this->current_annotation; |
inst->ir = this->base_ir; |
this->instructions.push_tail(inst); |
return inst; |
} |
void |
fs_visitor::emit(exec_list list) |
{ |
foreach_list_safe(node, &list) { |
fs_inst *inst = (fs_inst *)node; |
inst->remove(); |
emit(inst); |
} |
} |
/** Emits a dummy fragment shader consisting of magenta for bringup purposes. */ |
void |
fs_visitor::emit_dummy_fs() |
{ |
int reg_width = dispatch_width / 8; |
/* Everyone's favorite color. */ |
emit(MOV(fs_reg(MRF, 2 + 0 * reg_width), fs_reg(1.0f))); |
emit(MOV(fs_reg(MRF, 2 + 1 * reg_width), fs_reg(0.0f))); |
emit(MOV(fs_reg(MRF, 2 + 2 * reg_width), fs_reg(1.0f))); |
emit(MOV(fs_reg(MRF, 2 + 3 * reg_width), fs_reg(0.0f))); |
fs_inst *write; |
write = emit(FS_OPCODE_FB_WRITE, fs_reg(0), fs_reg(0)); |
write->base_mrf = 2; |
write->mlen = 4 * reg_width; |
write->eot = true; |
} |
/* The register location here is relative to the start of the URB |
* data. It will get adjusted to be a real location before |
* generate_code() time. |
*/ |
struct brw_reg |
fs_visitor::interp_reg(int location, int channel) |
{ |
int regnr = urb_setup[location] * 2 + channel / 2; |
int stride = (channel & 1) * 4; |
assert(urb_setup[location] != -1); |
return brw_vec1_grf(regnr, stride); |
} |
/** Emits the interpolation for the varying inputs. */ |
void |
fs_visitor::emit_interpolation_setup_gen4() |
{ |
this->current_annotation = "compute pixel centers"; |
this->pixel_x = fs_reg(this, glsl_type::uint_type); |
this->pixel_y = fs_reg(this, glsl_type::uint_type); |
this->pixel_x.type = BRW_REGISTER_TYPE_UW; |
this->pixel_y.type = BRW_REGISTER_TYPE_UW; |
emit(FS_OPCODE_PIXEL_X, this->pixel_x); |
emit(FS_OPCODE_PIXEL_Y, this->pixel_y); |
this->current_annotation = "compute pixel deltas from v0"; |
if (brw->has_pln) { |
this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC] = |
fs_reg(this, glsl_type::vec2_type); |
this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC] = |
this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC]; |
this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC].reg_offset++; |
} else { |
this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC] = |
fs_reg(this, glsl_type::float_type); |
this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC] = |
fs_reg(this, glsl_type::float_type); |
} |
emit(ADD(this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], |
this->pixel_x, fs_reg(negate(brw_vec1_grf(1, 0))))); |
emit(ADD(this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], |
this->pixel_y, fs_reg(negate(brw_vec1_grf(1, 1))))); |
this->current_annotation = "compute pos.w and 1/pos.w"; |
/* Compute wpos.w. It's always in our setup, since it's needed to |
* interpolate the other attributes. |
*/ |
this->wpos_w = fs_reg(this, glsl_type::float_type); |
emit(FS_OPCODE_LINTERP, wpos_w, |
this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], |
this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], |
interp_reg(VARYING_SLOT_POS, 3)); |
/* Compute the pixel 1/W value from wpos.w. */ |
this->pixel_w = fs_reg(this, glsl_type::float_type); |
emit_math(SHADER_OPCODE_RCP, this->pixel_w, wpos_w); |
this->current_annotation = NULL; |
} |
/** Emits the interpolation for the varying inputs. */ |
void |
fs_visitor::emit_interpolation_setup_gen6() |
{ |
struct brw_reg g1_uw = retype(brw_vec1_grf(1, 0), BRW_REGISTER_TYPE_UW); |
/* If the pixel centers end up used, the setup is the same as for gen4. */ |
this->current_annotation = "compute pixel centers"; |
fs_reg int_pixel_x = fs_reg(this, glsl_type::uint_type); |
fs_reg int_pixel_y = fs_reg(this, glsl_type::uint_type); |
int_pixel_x.type = BRW_REGISTER_TYPE_UW; |
int_pixel_y.type = BRW_REGISTER_TYPE_UW; |
emit(ADD(int_pixel_x, |
fs_reg(stride(suboffset(g1_uw, 4), 2, 4, 0)), |
fs_reg(brw_imm_v(0x10101010)))); |
emit(ADD(int_pixel_y, |
fs_reg(stride(suboffset(g1_uw, 5), 2, 4, 0)), |
fs_reg(brw_imm_v(0x11001100)))); |
/* As of gen6, we can no longer mix float and int sources. We have |
* to turn the integer pixel centers into floats for their actual |
* use. |
*/ |
this->pixel_x = fs_reg(this, glsl_type::float_type); |
this->pixel_y = fs_reg(this, glsl_type::float_type); |
emit(MOV(this->pixel_x, int_pixel_x)); |
emit(MOV(this->pixel_y, int_pixel_y)); |
this->current_annotation = "compute pos.w"; |
this->pixel_w = fs_reg(brw_vec8_grf(c->source_w_reg, 0)); |
this->wpos_w = fs_reg(this, glsl_type::float_type); |
emit_math(SHADER_OPCODE_RCP, this->wpos_w, this->pixel_w); |
for (int i = 0; i < BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT; ++i) { |
uint8_t reg = c->barycentric_coord_reg[i]; |
this->delta_x[i] = fs_reg(brw_vec8_grf(reg, 0)); |
this->delta_y[i] = fs_reg(brw_vec8_grf(reg + 1, 0)); |
} |
this->current_annotation = NULL; |
} |
void |
fs_visitor::emit_color_write(int target, int index, int first_color_mrf) |
{ |
int reg_width = dispatch_width / 8; |
fs_inst *inst; |
fs_reg color = outputs[target]; |
fs_reg mrf; |
/* If there's no color data to be written, skip it. */ |
if (color.file == BAD_FILE) |
return; |
color.reg_offset += index; |
if (dispatch_width == 8 || brw->gen >= 6) { |
/* SIMD8 write looks like: |
* m + 0: r0 |
* m + 1: r1 |
* m + 2: g0 |
* m + 3: g1 |
* |
* gen6 SIMD16 DP write looks like: |
* m + 0: r0 |
* m + 1: r1 |
* m + 2: g0 |
* m + 3: g1 |
* m + 4: b0 |
* m + 5: b1 |
* m + 6: a0 |
* m + 7: a1 |
*/ |
inst = emit(MOV(fs_reg(MRF, first_color_mrf + index * reg_width, |
color.type), |
color)); |
inst->saturate = c->key.clamp_fragment_color; |
} else { |
/* pre-gen6 SIMD16 single source DP write looks like: |
* m + 0: r0 |
* m + 1: g0 |
* m + 2: b0 |
* m + 3: a0 |
* m + 4: r1 |
* m + 5: g1 |
* m + 6: b1 |
* m + 7: a1 |
*/ |
if (brw->has_compr4) { |
/* By setting the high bit of the MRF register number, we |
* indicate that we want COMPR4 mode - instead of doing the |
* usual destination + 1 for the second half we get |
* destination + 4. |
*/ |
inst = emit(MOV(fs_reg(MRF, BRW_MRF_COMPR4 + first_color_mrf + index, |
color.type), |
color)); |
inst->saturate = c->key.clamp_fragment_color; |
} else { |
push_force_uncompressed(); |
inst = emit(MOV(fs_reg(MRF, first_color_mrf + index, color.type), |
color)); |
inst->saturate = c->key.clamp_fragment_color; |
pop_force_uncompressed(); |
push_force_sechalf(); |
color.sechalf = true; |
inst = emit(MOV(fs_reg(MRF, first_color_mrf + index + 4, color.type), |
color)); |
inst->saturate = c->key.clamp_fragment_color; |
pop_force_sechalf(); |
color.sechalf = false; |
} |
} |
} |
void |
fs_visitor::emit_fb_writes() |
{ |
this->current_annotation = "FB write header"; |
bool header_present = true; |
/* We can potentially have a message length of up to 15, so we have to set |
* base_mrf to either 0 or 1 in order to fit in m0..m15. |
*/ |
int base_mrf = 1; |
int nr = base_mrf; |
int reg_width = dispatch_width / 8; |
bool do_dual_src = this->dual_src_output.file != BAD_FILE; |
bool src0_alpha_to_render_target = false; |
if (dispatch_width == 16 && do_dual_src) { |
fail("GL_ARB_blend_func_extended not yet supported in 16-wide."); |
do_dual_src = false; |
} |
/* From the Sandy Bridge PRM, volume 4, page 198: |
* |
* "Dispatched Pixel Enables. One bit per pixel indicating |
* which pixels were originally enabled when the thread was |
* dispatched. This field is only required for the end-of- |
* thread message and on all dual-source messages." |
*/ |
if (brw->gen >= 6 && |
!this->fp->UsesKill && |
!do_dual_src && |
c->key.nr_color_regions == 1) { |
header_present = false; |
} |
if (header_present) { |
src0_alpha_to_render_target = brw->gen >= 6 && |
!do_dual_src && |
c->key.replicate_alpha; |
/* m2, m3 header */ |
nr += 2; |
} |
if (c->aa_dest_stencil_reg) { |
push_force_uncompressed(); |
emit(MOV(fs_reg(MRF, nr++), |
fs_reg(brw_vec8_grf(c->aa_dest_stencil_reg, 0)))); |
pop_force_uncompressed(); |
} |
/* Reserve space for color. It'll be filled in per MRT below. */ |
int color_mrf = nr; |
nr += 4 * reg_width; |
if (do_dual_src) |
nr += 4; |
if (src0_alpha_to_render_target) |
nr += reg_width; |
if (c->source_depth_to_render_target) { |
if (brw->gen == 6 && dispatch_width == 16) { |
/* For outputting oDepth on gen6, SIMD8 writes have to be |
* used. This would require 8-wide moves of each half to |
* message regs, kind of like pre-gen5 SIMD16 FB writes. |
* Just bail on doing so for now. |
*/ |
fail("Missing support for simd16 depth writes on gen6\n"); |
} |
if (fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { |
/* Hand over gl_FragDepth. */ |
assert(this->frag_depth.file != BAD_FILE); |
emit(MOV(fs_reg(MRF, nr), this->frag_depth)); |
} else { |
/* Pass through the payload depth. */ |
emit(MOV(fs_reg(MRF, nr), |
fs_reg(brw_vec8_grf(c->source_depth_reg, 0)))); |
} |
nr += reg_width; |
} |
if (c->dest_depth_reg) { |
emit(MOV(fs_reg(MRF, nr), |
fs_reg(brw_vec8_grf(c->dest_depth_reg, 0)))); |
nr += reg_width; |
} |
if (do_dual_src) { |
fs_reg src0 = this->outputs[0]; |
fs_reg src1 = this->dual_src_output; |
this->current_annotation = ralloc_asprintf(this->mem_ctx, |
"FB write src0"); |
for (int i = 0; i < 4; i++) { |
fs_inst *inst = emit(MOV(fs_reg(MRF, color_mrf + i, src0.type), src0)); |
src0.reg_offset++; |
inst->saturate = c->key.clamp_fragment_color; |
} |
this->current_annotation = ralloc_asprintf(this->mem_ctx, |
"FB write src1"); |
for (int i = 0; i < 4; i++) { |
fs_inst *inst = emit(MOV(fs_reg(MRF, color_mrf + 4 + i, src1.type), |
src1)); |
src1.reg_offset++; |
inst->saturate = c->key.clamp_fragment_color; |
} |
if (INTEL_DEBUG & DEBUG_SHADER_TIME) |
emit_shader_time_end(); |
fs_inst *inst = emit(FS_OPCODE_FB_WRITE); |
inst->target = 0; |
inst->base_mrf = base_mrf; |
inst->mlen = nr - base_mrf; |
inst->eot = true; |
inst->header_present = header_present; |
c->prog_data.dual_src_blend = true; |
this->current_annotation = NULL; |
return; |
} |
for (int target = 0; target < c->key.nr_color_regions; target++) { |
this->current_annotation = ralloc_asprintf(this->mem_ctx, |
"FB write target %d", |
target); |
/* If src0_alpha_to_render_target is true, include source zero alpha |
* data in RenderTargetWrite message for targets > 0. |
*/ |
int write_color_mrf = color_mrf; |
if (src0_alpha_to_render_target && target != 0) { |
fs_inst *inst; |
fs_reg color = outputs[0]; |
color.reg_offset += 3; |
inst = emit(MOV(fs_reg(MRF, write_color_mrf, color.type), |
color)); |
inst->saturate = c->key.clamp_fragment_color; |
write_color_mrf = color_mrf + reg_width; |
} |
for (unsigned i = 0; i < this->output_components[target]; i++) |
emit_color_write(target, i, write_color_mrf); |
bool eot = false; |
if (target == c->key.nr_color_regions - 1) { |
eot = true; |
if (INTEL_DEBUG & DEBUG_SHADER_TIME) |
emit_shader_time_end(); |
} |
fs_inst *inst = emit(FS_OPCODE_FB_WRITE); |
inst->target = target; |
inst->base_mrf = base_mrf; |
if (src0_alpha_to_render_target && target == 0) |
inst->mlen = nr - base_mrf - reg_width; |
else |
inst->mlen = nr - base_mrf; |
inst->eot = eot; |
inst->header_present = header_present; |
} |
if (c->key.nr_color_regions == 0) { |
/* Even if there's no color buffers enabled, we still need to send |
* alpha out the pipeline to our null renderbuffer to support |
* alpha-testing, alpha-to-coverage, and so on. |
*/ |
emit_color_write(0, 3, color_mrf); |
if (INTEL_DEBUG & DEBUG_SHADER_TIME) |
emit_shader_time_end(); |
fs_inst *inst = emit(FS_OPCODE_FB_WRITE); |
inst->base_mrf = base_mrf; |
inst->mlen = nr - base_mrf; |
inst->eot = true; |
inst->header_present = header_present; |
} |
this->current_annotation = NULL; |
} |
void |
fs_visitor::resolve_ud_negate(fs_reg *reg) |
{ |
if (reg->type != BRW_REGISTER_TYPE_UD || |
!reg->negate) |
return; |
fs_reg temp = fs_reg(this, glsl_type::uint_type); |
emit(MOV(temp, *reg)); |
*reg = temp; |
} |
void |
fs_visitor::resolve_bool_comparison(ir_rvalue *rvalue, fs_reg *reg) |
{ |
if (rvalue->type != glsl_type::bool_type) |
return; |
fs_reg temp = fs_reg(this, glsl_type::bool_type); |
emit(AND(temp, *reg, fs_reg(1))); |
*reg = temp; |
} |
fs_visitor::fs_visitor(struct brw_context *brw, |
struct brw_wm_compile *c, |
struct gl_shader_program *shader_prog, |
struct gl_fragment_program *fp, |
unsigned dispatch_width) |
: dispatch_width(dispatch_width) |
{ |
this->c = c; |
this->brw = brw; |
this->fp = fp; |
this->shader_prog = shader_prog; |
this->ctx = &brw->ctx; |
this->mem_ctx = ralloc_context(NULL); |
if (shader_prog) |
shader = (struct brw_shader *) |
shader_prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; |
else |
shader = NULL; |
this->failed = false; |
this->variable_ht = hash_table_ctor(0, |
hash_table_pointer_hash, |
hash_table_pointer_compare); |
memset(this->outputs, 0, sizeof(this->outputs)); |
memset(this->output_components, 0, sizeof(this->output_components)); |
this->first_non_payload_grf = 0; |
this->max_grf = brw->gen >= 7 ? GEN7_MRF_HACK_START : BRW_MAX_GRF; |
this->current_annotation = NULL; |
this->base_ir = NULL; |
this->virtual_grf_sizes = NULL; |
this->virtual_grf_count = 0; |
this->virtual_grf_array_size = 0; |
this->virtual_grf_start = NULL; |
this->virtual_grf_end = NULL; |
this->live_intervals_valid = false; |
this->params_remap = NULL; |
this->nr_params_remap = 0; |
this->force_uncompressed_stack = 0; |
this->force_sechalf_stack = 0; |
memset(&this->param_size, 0, sizeof(this->param_size)); |
} |
fs_visitor::~fs_visitor() |
{ |
ralloc_free(this->mem_ctx); |
hash_table_dtor(this->variable_ht); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_gs.c |
---|
0,0 → 1,258 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "main/transformfeedback.h" |
#include "intel_batchbuffer.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_util.h" |
#include "brw_state.h" |
#include "brw_gs.h" |
#include "glsl/ralloc.h" |
static void compile_gs_prog( struct brw_context *brw, |
struct brw_gs_prog_key *key ) |
{ |
struct brw_gs_compile c; |
const GLuint *program; |
void *mem_ctx; |
GLuint program_size; |
memset(&c, 0, sizeof(c)); |
c.key = *key; |
c.vue_map = brw->vs.prog_data->base.vue_map; |
c.nr_regs = (c.vue_map.num_slots + 1)/2; |
mem_ctx = ralloc_context(NULL); |
/* Begin the compilation: |
*/ |
brw_init_compile(brw, &c.func, mem_ctx); |
c.func.single_program_flow = 1; |
/* For some reason the thread is spawned with only 4 channels |
* unmasked. |
*/ |
brw_set_mask_control(&c.func, BRW_MASK_DISABLE); |
if (brw->gen >= 6) { |
unsigned num_verts; |
bool check_edge_flag; |
/* On Sandybridge, we use the GS for implementing transform feedback |
* (called "Stream Out" in the PRM). |
*/ |
switch (key->primitive) { |
case _3DPRIM_POINTLIST: |
num_verts = 1; |
check_edge_flag = false; |
break; |
case _3DPRIM_LINELIST: |
case _3DPRIM_LINESTRIP: |
case _3DPRIM_LINELOOP: |
num_verts = 2; |
check_edge_flag = false; |
break; |
case _3DPRIM_TRILIST: |
case _3DPRIM_TRIFAN: |
case _3DPRIM_TRISTRIP: |
case _3DPRIM_RECTLIST: |
num_verts = 3; |
check_edge_flag = false; |
break; |
case _3DPRIM_QUADLIST: |
case _3DPRIM_QUADSTRIP: |
case _3DPRIM_POLYGON: |
num_verts = 3; |
check_edge_flag = true; |
break; |
default: |
assert(!"Unexpected primitive type in Gen6 SOL program."); |
return; |
} |
gen6_sol_program(&c, key, num_verts, check_edge_flag); |
} else { |
/* On Gen4-5, we use the GS to decompose certain types of primitives. |
* Note that primitives which don't require a GS program have already |
* been weeded out by now. |
*/ |
switch (key->primitive) { |
case _3DPRIM_QUADLIST: |
brw_gs_quads( &c, key ); |
break; |
case _3DPRIM_QUADSTRIP: |
brw_gs_quad_strip( &c, key ); |
break; |
case _3DPRIM_LINELOOP: |
brw_gs_lines( &c ); |
break; |
default: |
ralloc_free(mem_ctx); |
return; |
} |
} |
/* get the program |
*/ |
program = brw_get_program(&c.func, &program_size); |
if (unlikely(INTEL_DEBUG & DEBUG_GS)) { |
int i; |
printf("gs:\n"); |
for (i = 0; i < program_size / sizeof(struct brw_instruction); i++) |
brw_disasm(stdout, &((struct brw_instruction *)program)[i], |
brw->gen); |
printf("\n"); |
} |
brw_upload_cache(&brw->cache, BRW_GS_PROG, |
&c.key, sizeof(c.key), |
program, program_size, |
&c.prog_data, sizeof(c.prog_data), |
&brw->gs.prog_offset, &brw->gs.prog_data); |
ralloc_free(mem_ctx); |
} |
static void populate_key( struct brw_context *brw, |
struct brw_gs_prog_key *key ) |
{ |
static const unsigned swizzle_for_offset[4] = { |
BRW_SWIZZLE4(0, 1, 2, 3), |
BRW_SWIZZLE4(1, 2, 3, 3), |
BRW_SWIZZLE4(2, 3, 3, 3), |
BRW_SWIZZLE4(3, 3, 3, 3) |
}; |
struct gl_context *ctx = &brw->ctx; |
memset(key, 0, sizeof(*key)); |
/* CACHE_NEW_VS_PROG (part of VUE map) */ |
key->attrs = brw->vs.prog_data->base.vue_map.slots_valid; |
/* BRW_NEW_PRIMITIVE */ |
key->primitive = brw->primitive; |
/* _NEW_LIGHT */ |
key->pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION); |
if (key->primitive == _3DPRIM_QUADLIST && ctx->Light.ShadeModel != GL_FLAT) { |
/* Provide consistent primitive order with brw_set_prim's |
* optimization of single quads to trifans. |
*/ |
key->pv_first = true; |
} |
if (brw->gen >= 7) { |
/* On Gen7 and later, we don't use GS (yet). */ |
key->need_gs_prog = false; |
} else if (brw->gen == 6) { |
/* On Gen6, GS is used for transform feedback. */ |
/* BRW_NEW_TRANSFORM_FEEDBACK */ |
if (_mesa_is_xfb_active_and_unpaused(ctx)) { |
const struct gl_shader_program *shaderprog = |
ctx->Shader.CurrentVertexProgram; |
const struct gl_transform_feedback_info *linked_xfb_info = |
&shaderprog->LinkedTransformFeedback; |
int i; |
/* Make sure that the VUE slots won't overflow the unsigned chars in |
* key->transform_feedback_bindings[]. |
*/ |
STATIC_ASSERT(BRW_VARYING_SLOT_COUNT <= 256); |
/* Make sure that we don't need more binding table entries than we've |
* set aside for use in transform feedback. (We shouldn't, since we |
* set aside enough binding table entries to have one per component). |
*/ |
assert(linked_xfb_info->NumOutputs <= BRW_MAX_SOL_BINDINGS); |
key->need_gs_prog = true; |
key->num_transform_feedback_bindings = linked_xfb_info->NumOutputs; |
for (i = 0; i < key->num_transform_feedback_bindings; ++i) { |
key->transform_feedback_bindings[i] = |
linked_xfb_info->Outputs[i].OutputRegister; |
key->transform_feedback_swizzles[i] = |
swizzle_for_offset[linked_xfb_info->Outputs[i].ComponentOffset]; |
} |
} |
} else { |
/* Pre-gen6, GS is used to transform QUADLIST, QUADSTRIP, and LINELOOP |
* into simpler primitives. |
*/ |
key->need_gs_prog = (brw->primitive == _3DPRIM_QUADLIST || |
brw->primitive == _3DPRIM_QUADSTRIP || |
brw->primitive == _3DPRIM_LINELOOP); |
} |
} |
/* Calculate interpolants for triangle and line rasterization. |
*/ |
static void |
brw_upload_gs_prog(struct brw_context *brw) |
{ |
struct brw_gs_prog_key key; |
/* Populate the key: |
*/ |
populate_key(brw, &key); |
if (brw->gs.prog_active != key.need_gs_prog) { |
brw->state.dirty.cache |= CACHE_NEW_GS_PROG; |
brw->gs.prog_active = key.need_gs_prog; |
} |
if (brw->gs.prog_active) { |
if (!brw_search_cache(&brw->cache, BRW_GS_PROG, |
&key, sizeof(key), |
&brw->gs.prog_offset, &brw->gs.prog_data)) { |
compile_gs_prog( brw, &key ); |
} |
} |
} |
const struct brw_tracked_state brw_gs_prog = { |
.dirty = { |
.mesa = (_NEW_LIGHT), |
.brw = (BRW_NEW_PRIMITIVE | |
BRW_NEW_TRANSFORM_FEEDBACK), |
.cache = CACHE_NEW_VS_PROG |
}, |
.emit = brw_upload_gs_prog |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_gs.h |
---|
0,0 → 1,111 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 BRW_GS_H |
#define BRW_GS_H |
#include "brw_context.h" |
#include "brw_eu.h" |
#define MAX_GS_VERTS (4) |
struct brw_gs_prog_key { |
GLbitfield64 attrs; |
/** |
* Hardware primitive type being drawn, e.g. _3DPRIM_TRILIST. |
*/ |
GLuint primitive:8; |
GLuint pv_first:1; |
GLuint need_gs_prog:1; |
/** |
* Number of varyings that are output to transform feedback. |
*/ |
GLuint num_transform_feedback_bindings:7; /* 0-BRW_MAX_SOL_BINDINGS */ |
/** |
* Map from the index of a transform feedback binding table entry to the |
* gl_varying_slot that should be streamed out through that binding table |
* entry. |
*/ |
unsigned char transform_feedback_bindings[BRW_MAX_SOL_BINDINGS]; |
/** |
* Map from the index of a transform feedback binding table entry to the |
* swizzles that should be used when streaming out data through that |
* binding table entry. |
*/ |
unsigned char transform_feedback_swizzles[BRW_MAX_SOL_BINDINGS]; |
}; |
struct brw_gs_compile { |
struct brw_compile func; |
struct brw_gs_prog_key key; |
struct brw_gs_prog_data prog_data; |
struct { |
struct brw_reg R0; |
/** |
* Register holding streamed vertex buffer pointers -- see the Sandy |
* Bridge PRM, volume 2 part 1, section 4.4.2 (GS Thread Payload |
* [DevSNB]). These pointers are delivered in GRF 1. |
*/ |
struct brw_reg SVBI; |
struct brw_reg vertex[MAX_GS_VERTS]; |
struct brw_reg header; |
struct brw_reg temp; |
/** |
* Register holding destination indices for streamed buffer writes. |
* Only used for SOL programs. |
*/ |
struct brw_reg destination_indices; |
} reg; |
/* Number of registers used to store vertex data */ |
GLuint nr_regs; |
struct brw_vue_map vue_map; |
}; |
void brw_gs_quads( struct brw_gs_compile *c, struct brw_gs_prog_key *key ); |
void brw_gs_quad_strip( struct brw_gs_compile *c, struct brw_gs_prog_key *key ); |
void brw_gs_lines( struct brw_gs_compile *c ); |
void gen6_sol_program(struct brw_gs_compile *c, struct brw_gs_prog_key *key, |
unsigned num_verts, bool check_edge_flag); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_gs_emit.c |
---|
0,0 → 1,508 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "program/program.h" |
#include "intel_batchbuffer.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_gs.h" |
/** |
* Allocate registers for GS. |
* |
* If sol_program is true, then: |
* |
* - The thread will be spawned with the "SVBI Payload Enable" bit set, so GRF |
* 1 needs to be set aside to hold the streamed vertex buffer indices. |
* |
* - The thread will need to use the destination_indices register. |
*/ |
static void brw_gs_alloc_regs( struct brw_gs_compile *c, |
GLuint nr_verts, |
bool sol_program ) |
{ |
GLuint i = 0,j; |
/* Register usage is static, precompute here: |
*/ |
c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++; |
/* Streamed vertex buffer indices */ |
if (sol_program) |
c->reg.SVBI = retype(brw_vec8_grf(i++, 0), BRW_REGISTER_TYPE_UD); |
/* Payload vertices plus space for more generated vertices: |
*/ |
for (j = 0; j < nr_verts; j++) { |
c->reg.vertex[j] = brw_vec4_grf(i, 0); |
i += c->nr_regs; |
} |
c->reg.header = retype(brw_vec8_grf(i++, 0), BRW_REGISTER_TYPE_UD); |
c->reg.temp = retype(brw_vec8_grf(i++, 0), BRW_REGISTER_TYPE_UD); |
if (sol_program) { |
c->reg.destination_indices = |
retype(brw_vec4_grf(i++, 0), BRW_REGISTER_TYPE_UD); |
} |
c->prog_data.urb_read_length = c->nr_regs; |
c->prog_data.total_grf = i; |
} |
/** |
* Set up the initial value of c->reg.header register based on c->reg.R0. |
* |
* The following information is passed to the GS thread in R0, and needs to be |
* included in the first URB_WRITE or FF_SYNC message sent by the GS: |
* |
* - DWORD 0 [31:0] handle info (Gen4 only) |
* - DWORD 5 [7:0] FFTID |
* - DWORD 6 [31:0] Debug info |
* - DWORD 7 [31:0] Debug info |
* |
* This function sets up the above data by copying by copying the contents of |
* R0 to the header register. |
*/ |
static void brw_gs_initialize_header(struct brw_gs_compile *c) |
{ |
struct brw_compile *p = &c->func; |
brw_MOV(p, c->reg.header, c->reg.R0); |
} |
/** |
* Overwrite DWORD 2 of c->reg.header with the given immediate unsigned value. |
* |
* In URB_WRITE messages, DWORD 2 contains the fields PrimType, PrimStart, |
* PrimEnd, Increment CL_INVOCATIONS, and SONumPrimsWritten, many of which we |
* need to be able to update on a per-vertex basis. |
*/ |
static void brw_gs_overwrite_header_dw2(struct brw_gs_compile *c, |
unsigned dw2) |
{ |
struct brw_compile *p = &c->func; |
brw_MOV(p, get_element_ud(c->reg.header, 2), brw_imm_ud(dw2)); |
} |
/** |
* Overwrite DWORD 2 of c->reg.header with the primitive type from c->reg.R0. |
* |
* When the thread is spawned, GRF 0 contains the primitive type in bits 4:0 |
* of DWORD 2. URB_WRITE messages need the primitive type in bits 6:2 of |
* DWORD 2. So this function extracts the primitive type field, bitshifts it |
* appropriately, and stores it in c->reg.header. |
*/ |
static void brw_gs_overwrite_header_dw2_from_r0(struct brw_gs_compile *c) |
{ |
struct brw_compile *p = &c->func; |
brw_AND(p, get_element_ud(c->reg.header, 2), get_element_ud(c->reg.R0, 2), |
brw_imm_ud(0x1f)); |
brw_SHL(p, get_element_ud(c->reg.header, 2), |
get_element_ud(c->reg.header, 2), brw_imm_ud(2)); |
} |
/** |
* Apply an additive offset to DWORD 2 of c->reg.header. |
* |
* This is used to set/unset the "PrimStart" and "PrimEnd" flags appropriately |
* for each vertex. |
*/ |
static void brw_gs_offset_header_dw2(struct brw_gs_compile *c, int offset) |
{ |
struct brw_compile *p = &c->func; |
brw_ADD(p, get_element_d(c->reg.header, 2), get_element_d(c->reg.header, 2), |
brw_imm_d(offset)); |
} |
/** |
* Emit a vertex using the URB_WRITE message. Use the contents of |
* c->reg.header for the message header, and the registers starting at \c vert |
* for the vertex data. |
* |
* If \c last is true, then this is the last vertex, so no further URB space |
* should be allocated, and this message should end the thread. |
* |
* If \c last is false, then a new URB entry will be allocated, and its handle |
* will be stored in DWORD 0 of c->reg.header for use in the next URB_WRITE |
* message. |
*/ |
static void brw_gs_emit_vue(struct brw_gs_compile *c, |
struct brw_reg vert, |
bool last) |
{ |
struct brw_compile *p = &c->func; |
bool allocate = !last; |
/* Copy the vertex from vertn into m1..mN+1: |
*/ |
brw_copy8(p, brw_message_reg(1), vert, c->nr_regs); |
/* Send each vertex as a seperate write to the urb. This is |
* different to the concept in brw_sf_emit.c, where subsequent |
* writes are used to build up a single urb entry. Each of these |
* writes instantiates a seperate urb entry, and a new one must be |
* allocated each time. |
*/ |
brw_urb_WRITE(p, |
allocate ? c->reg.temp |
: retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), |
0, |
c->reg.header, |
allocate, |
1, /* used */ |
c->nr_regs + 1, /* msg length */ |
allocate ? 1 : 0, /* response length */ |
allocate ? 0 : 1, /* eot */ |
1, /* writes_complete */ |
0, /* urb offset */ |
BRW_URB_SWIZZLE_NONE); |
if (allocate) { |
brw_MOV(p, get_element_ud(c->reg.header, 0), |
get_element_ud(c->reg.temp, 0)); |
} |
} |
/** |
* Send an FF_SYNC message to ensure that all previously spawned GS threads |
* have finished sending primitives down the pipeline, and to allocate a URB |
* entry for the first output vertex. Only needed on Ironlake+. |
* |
* This function modifies c->reg.header: in DWORD 1, it stores num_prim (which |
* is needed by the FF_SYNC message), and in DWORD 0, it stores the handle to |
* the allocated URB entry (which will be needed by the URB_WRITE meesage that |
* follows). |
*/ |
static void brw_gs_ff_sync(struct brw_gs_compile *c, int num_prim) |
{ |
struct brw_compile *p = &c->func; |
brw_MOV(p, get_element_ud(c->reg.header, 1), brw_imm_ud(num_prim)); |
brw_ff_sync(p, |
c->reg.temp, |
0, |
c->reg.header, |
1, /* allocate */ |
1, /* response length */ |
0 /* eot */); |
brw_MOV(p, get_element_ud(c->reg.header, 0), |
get_element_ud(c->reg.temp, 0)); |
} |
void brw_gs_quads( struct brw_gs_compile *c, struct brw_gs_prog_key *key ) |
{ |
struct brw_context *brw = c->func.brw; |
brw_gs_alloc_regs(c, 4, false); |
brw_gs_initialize_header(c); |
/* Use polygons for correct edgeflag behaviour. Note that vertex 3 |
* is the PV for quads, but vertex 0 for polygons: |
*/ |
if (brw->gen == 5) |
brw_gs_ff_sync(c, 1); |
brw_gs_overwrite_header_dw2( |
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_START)); |
if (key->pv_first) { |
brw_gs_emit_vue(c, c->reg.vertex[0], 0); |
brw_gs_overwrite_header_dw2( |
c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT); |
brw_gs_emit_vue(c, c->reg.vertex[1], 0); |
brw_gs_emit_vue(c, c->reg.vertex[2], 0); |
brw_gs_overwrite_header_dw2( |
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_END)); |
brw_gs_emit_vue(c, c->reg.vertex[3], 1); |
} |
else { |
brw_gs_emit_vue(c, c->reg.vertex[3], 0); |
brw_gs_overwrite_header_dw2( |
c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT); |
brw_gs_emit_vue(c, c->reg.vertex[0], 0); |
brw_gs_emit_vue(c, c->reg.vertex[1], 0); |
brw_gs_overwrite_header_dw2( |
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_END)); |
brw_gs_emit_vue(c, c->reg.vertex[2], 1); |
} |
} |
void brw_gs_quad_strip( struct brw_gs_compile *c, struct brw_gs_prog_key *key ) |
{ |
struct brw_context *brw = c->func.brw; |
brw_gs_alloc_regs(c, 4, false); |
brw_gs_initialize_header(c); |
if (brw->gen == 5) |
brw_gs_ff_sync(c, 1); |
brw_gs_overwrite_header_dw2( |
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_START)); |
if (key->pv_first) { |
brw_gs_emit_vue(c, c->reg.vertex[0], 0); |
brw_gs_overwrite_header_dw2( |
c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT); |
brw_gs_emit_vue(c, c->reg.vertex[1], 0); |
brw_gs_emit_vue(c, c->reg.vertex[2], 0); |
brw_gs_overwrite_header_dw2( |
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_END)); |
brw_gs_emit_vue(c, c->reg.vertex[3], 1); |
} |
else { |
brw_gs_emit_vue(c, c->reg.vertex[2], 0); |
brw_gs_overwrite_header_dw2( |
c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT); |
brw_gs_emit_vue(c, c->reg.vertex[3], 0); |
brw_gs_emit_vue(c, c->reg.vertex[0], 0); |
brw_gs_overwrite_header_dw2( |
c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_END)); |
brw_gs_emit_vue(c, c->reg.vertex[1], 1); |
} |
} |
void brw_gs_lines( struct brw_gs_compile *c ) |
{ |
struct brw_context *brw = c->func.brw; |
brw_gs_alloc_regs(c, 2, false); |
brw_gs_initialize_header(c); |
if (brw->gen == 5) |
brw_gs_ff_sync(c, 1); |
brw_gs_overwrite_header_dw2( |
c, ((_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_START)); |
brw_gs_emit_vue(c, c->reg.vertex[0], 0); |
brw_gs_overwrite_header_dw2( |
c, ((_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT) |
| URB_WRITE_PRIM_END)); |
brw_gs_emit_vue(c, c->reg.vertex[1], 1); |
} |
/** |
* Generate the geometry shader program used on Gen6 to perform stream output |
* (transform feedback). |
*/ |
void |
gen6_sol_program(struct brw_gs_compile *c, struct brw_gs_prog_key *key, |
unsigned num_verts, bool check_edge_flags) |
{ |
struct brw_compile *p = &c->func; |
c->prog_data.svbi_postincrement_value = num_verts; |
brw_gs_alloc_regs(c, num_verts, true); |
brw_gs_initialize_header(c); |
if (key->num_transform_feedback_bindings > 0) { |
unsigned vertex, binding; |
struct brw_reg destination_indices_uw = |
vec8(retype(c->reg.destination_indices, BRW_REGISTER_TYPE_UW)); |
/* Note: since we use the binding table to keep track of buffer offsets |
* and stride, the GS doesn't need to keep track of a separate pointer |
* into each buffer; it uses a single pointer which increments by 1 for |
* each vertex. So we use SVBI0 for this pointer, regardless of whether |
* transform feedback is in interleaved or separate attribs mode. |
* |
* Make sure that the buffers have enough room for all the vertices. |
*/ |
brw_ADD(p, get_element_ud(c->reg.temp, 0), |
get_element_ud(c->reg.SVBI, 0), brw_imm_ud(num_verts)); |
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, |
get_element_ud(c->reg.temp, 0), |
get_element_ud(c->reg.SVBI, 4)); |
brw_IF(p, BRW_EXECUTE_1); |
/* Compute the destination indices to write to. Usually we use SVBI[0] |
* + (0, 1, 2). However, for odd-numbered triangles in tristrips, the |
* vertices come down the pipeline in reversed winding order, so we need |
* to flip the order when writing to the transform feedback buffer. To |
* ensure that flatshading accuracy is preserved, we need to write them |
* in order SVBI[0] + (0, 2, 1) if we're using the first provoking |
* vertex convention, and in order SVBI[0] + (1, 0, 2) if we're using |
* the last provoking vertex convention. |
* |
* Note: since brw_imm_v can only be used in instructions in |
* packed-word execution mode, and SVBI is a double-word, we need to |
* first move the appropriate immediate constant ((0, 1, 2), (0, 2, 1), |
* or (1, 0, 2)) to the destination_indices register, and then add SVBI |
* using a separate instruction. Also, since the immediate constant is |
* expressed as packed words, and we need to load double-words into |
* destination_indices, we need to intersperse zeros to fill the upper |
* halves of each double-word. |
*/ |
brw_MOV(p, destination_indices_uw, |
brw_imm_v(0x00020100)); /* (0, 1, 2) */ |
if (num_verts == 3) { |
/* Get primitive type into temp register. */ |
brw_AND(p, get_element_ud(c->reg.temp, 0), |
get_element_ud(c->reg.R0, 2), brw_imm_ud(0x1f)); |
/* Test if primitive type is TRISTRIP_REVERSE. We need to do this as |
* an 8-wide comparison so that the conditional MOV that follows |
* moves all 8 words correctly. |
*/ |
brw_CMP(p, vec8(brw_null_reg()), BRW_CONDITIONAL_EQ, |
get_element_ud(c->reg.temp, 0), |
brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE)); |
/* If so, then overwrite destination_indices_uw with the appropriate |
* reordering. |
*/ |
brw_MOV(p, destination_indices_uw, |
brw_imm_v(key->pv_first ? 0x00010200 /* (0, 2, 1) */ |
: 0x00020001)); /* (1, 0, 2) */ |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
} |
brw_ADD(p, c->reg.destination_indices, |
c->reg.destination_indices, get_element_ud(c->reg.SVBI, 0)); |
/* For each vertex, generate code to output each varying using the |
* appropriate binding table entry. |
*/ |
for (vertex = 0; vertex < num_verts; ++vertex) { |
/* Set up the correct destination index for this vertex */ |
brw_MOV(p, get_element_ud(c->reg.header, 5), |
get_element_ud(c->reg.destination_indices, vertex)); |
for (binding = 0; binding < key->num_transform_feedback_bindings; |
++binding) { |
unsigned char varying = |
key->transform_feedback_bindings[binding]; |
unsigned char slot = c->vue_map.varying_to_slot[varying]; |
/* From the Sandybridge PRM, Volume 2, Part 1, Section 4.5.1: |
* |
* "Prior to End of Thread with a URB_WRITE, the kernel must |
* ensure that all writes are complete by sending the final |
* write as a committed write." |
*/ |
bool final_write = |
binding == key->num_transform_feedback_bindings - 1 && |
vertex == num_verts - 1; |
struct brw_reg vertex_slot = c->reg.vertex[vertex]; |
vertex_slot.nr += slot / 2; |
vertex_slot.subnr = (slot % 2) * 16; |
/* gl_PointSize is stored in VARYING_SLOT_PSIZ.w. */ |
vertex_slot.dw1.bits.swizzle = varying == VARYING_SLOT_PSIZ |
? BRW_SWIZZLE_WWWW : key->transform_feedback_swizzles[binding]; |
brw_set_access_mode(p, BRW_ALIGN_16); |
brw_MOV(p, stride(c->reg.header, 4, 4, 1), |
retype(vertex_slot, BRW_REGISTER_TYPE_UD)); |
brw_set_access_mode(p, BRW_ALIGN_1); |
brw_svb_write(p, |
final_write ? c->reg.temp : brw_null_reg(), /* dest */ |
1, /* msg_reg_nr */ |
c->reg.header, /* src0 */ |
SURF_INDEX_SOL_BINDING(binding), /* binding_table_index */ |
final_write); /* send_commit_msg */ |
} |
} |
brw_ENDIF(p); |
/* Now, reinitialize the header register from R0 to restore the parts of |
* the register that we overwrote while streaming out transform feedback |
* data. |
*/ |
brw_gs_initialize_header(c); |
/* Finally, wait for the write commit to occur so that we can proceed to |
* other things safely. |
* |
* From the Sandybridge PRM, Volume 4, Part 1, Section 3.3: |
* |
* The write commit does not modify the destination register, but |
* merely clears the dependency associated with the destination |
* register. Thus, a simple “mov” instruction using the register as a |
* source is sufficient to wait for the write commit to occur. |
*/ |
brw_MOV(p, c->reg.temp, c->reg.temp); |
} |
brw_gs_ff_sync(c, 1); |
brw_gs_overwrite_header_dw2_from_r0(c); |
switch (num_verts) { |
case 1: |
brw_gs_offset_header_dw2(c, URB_WRITE_PRIM_START | URB_WRITE_PRIM_END); |
brw_gs_emit_vue(c, c->reg.vertex[0], true); |
break; |
case 2: |
brw_gs_offset_header_dw2(c, URB_WRITE_PRIM_START); |
brw_gs_emit_vue(c, c->reg.vertex[0], false); |
brw_gs_offset_header_dw2(c, URB_WRITE_PRIM_END - URB_WRITE_PRIM_START); |
brw_gs_emit_vue(c, c->reg.vertex[1], true); |
break; |
case 3: |
if (check_edge_flags) { |
/* Only emit vertices 0 and 1 if this is the first triangle of the |
* polygon. Otherwise they are redundant. |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_AND(p, retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), |
get_element_ud(c->reg.R0, 2), |
brw_imm_ud(BRW_GS_EDGE_INDICATOR_0)); |
brw_IF(p, BRW_EXECUTE_1); |
} |
brw_gs_offset_header_dw2(c, URB_WRITE_PRIM_START); |
brw_gs_emit_vue(c, c->reg.vertex[0], false); |
brw_gs_offset_header_dw2(c, -URB_WRITE_PRIM_START); |
brw_gs_emit_vue(c, c->reg.vertex[1], false); |
if (check_edge_flags) { |
brw_ENDIF(p); |
/* Only emit vertex 2 in PRIM_END mode if this is the last triangle |
* of the polygon. Otherwise leave the primitive incomplete because |
* there are more polygon vertices coming. |
*/ |
brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); |
brw_AND(p, retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), |
get_element_ud(c->reg.R0, 2), |
brw_imm_ud(BRW_GS_EDGE_INDICATOR_1)); |
brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); |
} |
brw_gs_offset_header_dw2(c, URB_WRITE_PRIM_END); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_gs_emit_vue(c, c->reg.vertex[2], true); |
break; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_gs_state.c |
---|
0,0 → 1,98 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
static void |
brw_upload_gs_unit(struct brw_context *brw) |
{ |
struct brw_gs_unit_state *gs; |
gs = brw_state_batch(brw, AUB_TRACE_GS_STATE, |
sizeof(*gs), 32, &brw->gs.state_offset); |
memset(gs, 0, sizeof(*gs)); |
/* BRW_NEW_PROGRAM_CACHE | CACHE_NEW_GS_PROG */ |
if (brw->gs.prog_active) { |
gs->thread0.grf_reg_count = (ALIGN(brw->gs.prog_data->total_grf, 16) / |
16 - 1); |
gs->thread0.kernel_start_pointer = |
brw_program_reloc(brw, |
brw->gs.state_offset + |
offsetof(struct brw_gs_unit_state, thread0), |
brw->gs.prog_offset + |
(gs->thread0.grf_reg_count << 1)) >> 6; |
gs->thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754; |
gs->thread1.single_program_flow = 1; |
gs->thread3.dispatch_grf_start_reg = 1; |
gs->thread3.const_urb_entry_read_offset = 0; |
gs->thread3.const_urb_entry_read_length = 0; |
gs->thread3.urb_entry_read_offset = 0; |
gs->thread3.urb_entry_read_length = brw->gs.prog_data->urb_read_length; |
/* BRW_NEW_URB_FENCE */ |
gs->thread4.nr_urb_entries = brw->urb.nr_gs_entries; |
gs->thread4.urb_entry_allocation_size = brw->urb.vsize - 1; |
if (brw->urb.nr_gs_entries >= 8) |
gs->thread4.max_threads = 1; |
else |
gs->thread4.max_threads = 0; |
} |
if (brw->gen == 5) |
gs->thread4.rendering_enable = 1; |
if (unlikely(INTEL_DEBUG & DEBUG_STATS)) |
gs->thread4.stats_enable = 1; |
brw->state.dirty.cache |= CACHE_NEW_GS_UNIT; |
} |
const struct brw_tracked_state brw_gs_unit = { |
.dirty = { |
.mesa = 0, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_PROGRAM_CACHE | |
BRW_NEW_CURBE_OFFSETS | |
BRW_NEW_URB_FENCE), |
.cache = CACHE_NEW_GS_PROG |
}, |
.emit = brw_upload_gs_unit, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_lower_texture_gradients.cpp |
---|
0,0 → 1,179 |
/* |
* 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. |
*/ |
/** |
* \file brw_lower_texture_gradients.cpp |
*/ |
#include "glsl/ir.h" |
#include "glsl/ir_builder.h" |
#include "program/prog_instruction.h" |
#include "brw_context.h" |
using namespace ir_builder; |
class lower_texture_grad_visitor : public ir_hierarchical_visitor { |
public: |
lower_texture_grad_visitor(bool has_sample_d_c) |
: has_sample_d_c(has_sample_d_c) |
{ |
progress = false; |
} |
ir_visitor_status visit_leave(ir_texture *ir); |
bool progress; |
bool has_sample_d_c; |
private: |
void emit(ir_variable *, ir_rvalue *); |
}; |
/** |
* Emit a variable declaration and an assignment to initialize it. |
*/ |
void |
lower_texture_grad_visitor::emit(ir_variable *var, ir_rvalue *value) |
{ |
base_ir->insert_before(var); |
base_ir->insert_before(assign(var, value)); |
} |
static const glsl_type * |
txs_type(const glsl_type *type) |
{ |
unsigned dims; |
switch (type->sampler_dimensionality) { |
case GLSL_SAMPLER_DIM_1D: |
dims = 1; |
break; |
case GLSL_SAMPLER_DIM_2D: |
case GLSL_SAMPLER_DIM_RECT: |
case GLSL_SAMPLER_DIM_CUBE: |
dims = 2; |
break; |
case GLSL_SAMPLER_DIM_3D: |
dims = 3; |
break; |
default: |
assert(!"Should not get here: invalid sampler dimensionality"); |
dims = 2; |
} |
if (type->sampler_array) |
dims++; |
return glsl_type::get_instance(GLSL_TYPE_INT, dims, 1); |
} |
ir_visitor_status |
lower_texture_grad_visitor::visit_leave(ir_texture *ir) |
{ |
/* Only lower textureGrad with shadow samplers */ |
if (ir->op != ir_txd || !ir->shadow_comparitor) |
return visit_continue; |
/* Lower textureGrad() with samplerCubeShadow even if we have the sample_d_c |
* message. GLSL provides gradients for the 'r' coordinate. Unfortunately: |
* |
* From the Ivybridge PRM, Volume 4, Part 1, sample_d message description: |
* "The r coordinate contains the faceid, and the r gradients are ignored |
* by hardware." |
* |
* We likely need to do a similar treatment for samplerCube and |
* samplerCubeArray, but we have insufficient testing for that at the moment. |
*/ |
bool need_lowering = !has_sample_d_c || |
ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE; |
if (!need_lowering) |
return visit_continue; |
void *mem_ctx = ralloc_parent(ir); |
const glsl_type *grad_type = ir->lod_info.grad.dPdx->type; |
/* Use textureSize() to get the width and height of LOD 0; swizzle away |
* the depth/number of array slices. |
*/ |
ir_texture *txs = new(mem_ctx) ir_texture(ir_txs); |
txs->set_sampler(ir->sampler->clone(mem_ctx, NULL), |
txs_type(ir->sampler->type)); |
txs->lod_info.lod = new(mem_ctx) ir_constant(0); |
ir_variable *size = |
new(mem_ctx) ir_variable(grad_type, "size", ir_var_temporary); |
if (ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE) { |
base_ir->insert_before(size); |
base_ir->insert_before(assign(size, expr(ir_unop_i2f, txs), WRITEMASK_XY)); |
base_ir->insert_before(assign(size, new(mem_ctx) ir_constant(1.0f), WRITEMASK_Z)); |
} else { |
emit(size, expr(ir_unop_i2f, |
swizzle_for_size(txs, grad_type->vector_elements))); |
} |
/* Scale the gradients by width and height. Effectively, the incoming |
* gradients are s'(x,y), t'(x,y), and r'(x,y) from equation 3.19 in the |
* GL 3.0 spec; we want u'(x,y), which is w_t * s'(x,y). |
*/ |
ir_variable *dPdx = |
new(mem_ctx) ir_variable(grad_type, "dPdx", ir_var_temporary); |
emit(dPdx, mul(size, ir->lod_info.grad.dPdx)); |
ir_variable *dPdy = |
new(mem_ctx) ir_variable(grad_type, "dPdy", ir_var_temporary); |
emit(dPdy, mul(size, ir->lod_info.grad.dPdy)); |
/* Calculate rho from equation 3.20 of the GL 3.0 specification. */ |
ir_rvalue *rho; |
if (dPdx->type->is_scalar()) { |
rho = expr(ir_binop_max, expr(ir_unop_abs, dPdx), |
expr(ir_unop_abs, dPdy)); |
} else { |
rho = expr(ir_binop_max, expr(ir_unop_sqrt, dot(dPdx, dPdx)), |
expr(ir_unop_sqrt, dot(dPdy, dPdy))); |
} |
/* lambda_base = log2(rho). We're ignoring GL state biases for now. */ |
ir->op = ir_txl; |
ir->lod_info.lod = expr(ir_unop_log2, rho); |
progress = true; |
return visit_continue; |
} |
extern "C" { |
bool |
brw_lower_texture_gradients(struct brw_context *brw, |
struct exec_list *instructions) |
{ |
bool has_sample_d_c = brw->gen >= 8 || brw->is_haswell; |
lower_texture_grad_visitor v(has_sample_d_c); |
visit_list_elements(&v, instructions); |
return v.progress; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_misc_state.c |
---|
0,0 → 1,1123 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "intel_batchbuffer.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "main/fbobject.h" |
#include "main/glformats.h" |
/* Constant single cliprect for framebuffer object or DRI2 drawing */ |
static void upload_drawing_rect(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_DRAWING_RECTANGLE << 16 | (4 - 2)); |
OUT_BATCH(0); /* xmin, ymin */ |
OUT_BATCH(((ctx->DrawBuffer->Width - 1) & 0xffff) | |
((ctx->DrawBuffer->Height - 1) << 16)); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state brw_drawing_rect = { |
.dirty = { |
.mesa = _NEW_BUFFERS, |
.brw = BRW_NEW_CONTEXT, |
.cache = 0 |
}, |
.emit = upload_drawing_rect |
}; |
/** |
* Upload the binding table pointers, which point each stage's array of surface |
* state pointers. |
* |
* The binding table pointers are relative to the surface state base address, |
* which points at the batchbuffer containing the streamed batch state. |
*/ |
static void upload_binding_table_pointers(struct brw_context *brw) |
{ |
BEGIN_BATCH(6); |
OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS << 16 | (6 - 2)); |
OUT_BATCH(brw->vs.bind_bo_offset); |
OUT_BATCH(0); /* gs */ |
OUT_BATCH(0); /* clip */ |
OUT_BATCH(0); /* sf */ |
OUT_BATCH(brw->wm.bind_bo_offset); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state brw_binding_table_pointers = { |
.dirty = { |
.mesa = 0, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_STATE_BASE_ADDRESS | |
BRW_NEW_VS_BINDING_TABLE | |
BRW_NEW_GS_BINDING_TABLE | |
BRW_NEW_PS_BINDING_TABLE), |
.cache = 0, |
}, |
.emit = upload_binding_table_pointers, |
}; |
/** |
* Upload the binding table pointers, which point each stage's array of surface |
* state pointers. |
* |
* The binding table pointers are relative to the surface state base address, |
* which points at the batchbuffer containing the streamed batch state. |
*/ |
static void upload_gen6_binding_table_pointers(struct brw_context *brw) |
{ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS << 16 | |
GEN6_BINDING_TABLE_MODIFY_VS | |
GEN6_BINDING_TABLE_MODIFY_GS | |
GEN6_BINDING_TABLE_MODIFY_PS | |
(4 - 2)); |
OUT_BATCH(brw->vs.bind_bo_offset); /* vs */ |
OUT_BATCH(brw->gs.bind_bo_offset); /* gs */ |
OUT_BATCH(brw->wm.bind_bo_offset); /* wm/ps */ |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen6_binding_table_pointers = { |
.dirty = { |
.mesa = 0, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_STATE_BASE_ADDRESS | |
BRW_NEW_VS_BINDING_TABLE | |
BRW_NEW_GS_BINDING_TABLE | |
BRW_NEW_PS_BINDING_TABLE), |
.cache = 0, |
}, |
.emit = upload_gen6_binding_table_pointers, |
}; |
/** |
* Upload pointers to the per-stage state. |
* |
* The state pointers in this packet are all relative to the general state |
* base address set by CMD_STATE_BASE_ADDRESS, which is 0. |
*/ |
static void upload_pipelined_state_pointers(struct brw_context *brw ) |
{ |
if (brw->gen == 5) { |
/* Need to flush before changing clip max threads for errata. */ |
BEGIN_BATCH(1); |
OUT_BATCH(MI_FLUSH); |
ADVANCE_BATCH(); |
} |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_PIPELINED_POINTERS << 16 | (7 - 2)); |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, |
brw->vs.state_offset); |
if (brw->gs.prog_active) |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, |
brw->gs.state_offset | 1); |
else |
OUT_BATCH(0); |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, |
brw->clip.state_offset | 1); |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, |
brw->sf.state_offset); |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, |
brw->wm.state_offset); |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, |
brw->cc.state_offset); |
ADVANCE_BATCH(); |
brw->state.dirty.brw |= BRW_NEW_PSP; |
} |
static void upload_psp_urb_cbs(struct brw_context *brw ) |
{ |
upload_pipelined_state_pointers(brw); |
brw_upload_urb_fence(brw); |
brw_upload_cs_urb_state(brw); |
} |
const struct brw_tracked_state brw_psp_urb_cbs = { |
.dirty = { |
.mesa = 0, |
.brw = (BRW_NEW_URB_FENCE | |
BRW_NEW_BATCH | |
BRW_NEW_STATE_BASE_ADDRESS), |
.cache = (CACHE_NEW_VS_UNIT | |
CACHE_NEW_GS_UNIT | |
CACHE_NEW_GS_PROG | |
CACHE_NEW_CLIP_UNIT | |
CACHE_NEW_SF_UNIT | |
CACHE_NEW_WM_UNIT | |
CACHE_NEW_CC_UNIT) |
}, |
.emit = upload_psp_urb_cbs, |
}; |
uint32_t |
brw_depthbuffer_format(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct intel_renderbuffer *drb = intel_get_renderbuffer(fb, BUFFER_DEPTH); |
struct intel_renderbuffer *srb; |
if (!drb && |
(srb = intel_get_renderbuffer(fb, BUFFER_STENCIL)) && |
!srb->mt->stencil_mt && |
(intel_rb_format(srb) == MESA_FORMAT_S8_Z24 || |
intel_rb_format(srb) == MESA_FORMAT_Z32_FLOAT_X24S8)) { |
drb = srb; |
} |
if (!drb) |
return BRW_DEPTHFORMAT_D32_FLOAT; |
switch (drb->mt->format) { |
case MESA_FORMAT_Z16: |
return BRW_DEPTHFORMAT_D16_UNORM; |
case MESA_FORMAT_Z32_FLOAT: |
return BRW_DEPTHFORMAT_D32_FLOAT; |
case MESA_FORMAT_X8_Z24: |
if (brw->gen >= 6) { |
return BRW_DEPTHFORMAT_D24_UNORM_X8_UINT; |
} else { |
/* Use D24_UNORM_S8, not D24_UNORM_X8. |
* |
* D24_UNORM_X8 was not introduced until Gen5. (See the Ironlake PRM, |
* Volume 2, Part 1, Section 8.4.6 "Depth/Stencil Buffer State", Bits |
* 3DSTATE_DEPTH_BUFFER.Surface_Format). |
* |
* However, on Gen5, D24_UNORM_X8 may be used only if separate |
* stencil is enabled, and we never enable it. From the Ironlake PRM, |
* same section as above, Bit 3DSTATE_DEPTH_BUFFER.Separate_Stencil_Buffer_Enable: |
* If this field is disabled, the Surface Format of the depth |
* buffer cannot be D24_UNORM_X8_UINT. |
*/ |
return BRW_DEPTHFORMAT_D24_UNORM_S8_UINT; |
} |
case MESA_FORMAT_S8_Z24: |
return BRW_DEPTHFORMAT_D24_UNORM_S8_UINT; |
case MESA_FORMAT_Z32_FLOAT_X24S8: |
return BRW_DEPTHFORMAT_D32_FLOAT_S8X24_UINT; |
default: |
_mesa_problem(ctx, "Unexpected depth format %s\n", |
_mesa_get_format_name(intel_rb_format(drb))); |
return BRW_DEPTHFORMAT_D16_UNORM; |
} |
} |
/** |
* Returns the mask of how many bits of x and y must be handled through the |
* depthbuffer's draw offset x and y fields. |
* |
* The draw offset x/y field of the depthbuffer packet is unfortunately shared |
* between the depth, hiz, and stencil buffers. Because it can be hard to get |
* all 3 to agree on this value, we want to do as much drawing offset |
* adjustment as possible by moving the base offset of the 3 buffers, which is |
* restricted to tile boundaries. |
* |
* For each buffer, the remainder must be applied through the x/y draw offset. |
* This returns the worst-case mask of the low bits that have to go into the |
* packet. If the 3 buffers don't agree on the drawing offset ANDed with this |
* mask, then we're in trouble. |
*/ |
void |
brw_get_depthstencil_tile_masks(struct intel_mipmap_tree *depth_mt, |
uint32_t depth_level, |
uint32_t depth_layer, |
struct intel_mipmap_tree *stencil_mt, |
uint32_t *out_tile_mask_x, |
uint32_t *out_tile_mask_y) |
{ |
uint32_t tile_mask_x = 0, tile_mask_y = 0; |
if (depth_mt) { |
intel_region_get_tile_masks(depth_mt->region, |
&tile_mask_x, &tile_mask_y, false); |
if (intel_miptree_slice_has_hiz(depth_mt, depth_level, depth_layer)) { |
uint32_t hiz_tile_mask_x, hiz_tile_mask_y; |
intel_region_get_tile_masks(depth_mt->hiz_mt->region, |
&hiz_tile_mask_x, &hiz_tile_mask_y, false); |
/* Each HiZ row represents 2 rows of pixels */ |
hiz_tile_mask_y = hiz_tile_mask_y << 1 | 1; |
tile_mask_x |= hiz_tile_mask_x; |
tile_mask_y |= hiz_tile_mask_y; |
} |
} |
if (stencil_mt) { |
if (stencil_mt->stencil_mt) |
stencil_mt = stencil_mt->stencil_mt; |
if (stencil_mt->format == MESA_FORMAT_S8) { |
/* Separate stencil buffer uses 64x64 tiles. */ |
tile_mask_x |= 63; |
tile_mask_y |= 63; |
} else { |
uint32_t stencil_tile_mask_x, stencil_tile_mask_y; |
intel_region_get_tile_masks(stencil_mt->region, |
&stencil_tile_mask_x, |
&stencil_tile_mask_y, false); |
tile_mask_x |= stencil_tile_mask_x; |
tile_mask_y |= stencil_tile_mask_y; |
} |
} |
*out_tile_mask_x = tile_mask_x; |
*out_tile_mask_y = tile_mask_y; |
} |
static struct intel_mipmap_tree * |
get_stencil_miptree(struct intel_renderbuffer *irb) |
{ |
if (!irb) |
return NULL; |
if (irb->mt->stencil_mt) |
return irb->mt->stencil_mt; |
return irb->mt; |
} |
void |
brw_workaround_depthstencil_alignment(struct brw_context *brw, |
GLbitfield clear_mask) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
bool rebase_depth = false; |
bool rebase_stencil = false; |
struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(fb, BUFFER_DEPTH); |
struct intel_renderbuffer *stencil_irb = intel_get_renderbuffer(fb, BUFFER_STENCIL); |
struct intel_mipmap_tree *depth_mt = NULL; |
struct intel_mipmap_tree *stencil_mt = get_stencil_miptree(stencil_irb); |
uint32_t tile_x = 0, tile_y = 0, stencil_tile_x = 0, stencil_tile_y = 0; |
uint32_t stencil_draw_x = 0, stencil_draw_y = 0; |
bool invalidate_depth = clear_mask & BUFFER_BIT_DEPTH; |
bool invalidate_stencil = clear_mask & BUFFER_BIT_STENCIL; |
if (depth_irb) |
depth_mt = depth_irb->mt; |
/* Check if depth buffer is in depth/stencil format. If so, then it's only |
* safe to invalidate it if we're also clearing stencil, and both depth_irb |
* and stencil_irb point to the same miptree. |
* |
* Note: it's not sufficient to check for the case where |
* _mesa_get_format_base_format(depth_mt->format) == GL_DEPTH_STENCIL, |
* because this fails to catch depth/stencil buffers on hardware that uses |
* separate stencil. To catch that case, we check whether |
* depth_mt->stencil_mt is non-NULL. |
*/ |
if (depth_irb && invalidate_depth && |
(_mesa_get_format_base_format(depth_mt->format) == GL_DEPTH_STENCIL || |
depth_mt->stencil_mt)) { |
invalidate_depth = invalidate_stencil && depth_irb && stencil_irb |
&& depth_irb->mt == stencil_irb->mt; |
} |
uint32_t tile_mask_x, tile_mask_y; |
brw_get_depthstencil_tile_masks(depth_mt, |
depth_mt ? depth_irb->mt_level : 0, |
depth_mt ? depth_irb->mt_layer : 0, |
stencil_mt, |
&tile_mask_x, &tile_mask_y); |
if (depth_irb) { |
tile_x = depth_irb->draw_x & tile_mask_x; |
tile_y = depth_irb->draw_y & tile_mask_y; |
/* According to the Sandy Bridge PRM, volume 2 part 1, pp326-327 |
* (3DSTATE_DEPTH_BUFFER dw5), in the documentation for "Depth |
* Coordinate Offset X/Y": |
* |
* "The 3 LSBs of both offsets must be zero to ensure correct |
* alignment" |
*/ |
if (tile_x & 7 || tile_y & 7) |
rebase_depth = true; |
/* We didn't even have intra-tile offsets before g45. */ |
if (brw->gen == 4 && !brw->is_g4x) { |
if (tile_x || tile_y) |
rebase_depth = true; |
} |
if (rebase_depth) { |
perf_debug("HW workaround: blitting depth level %d to a temporary " |
"to fix alignment (depth tile offset %d,%d)\n", |
depth_irb->mt_level, tile_x, tile_y); |
intel_renderbuffer_move_to_temp(brw, depth_irb, invalidate_depth); |
/* In the case of stencil_irb being the same packed depth/stencil |
* texture but not the same rb, make it point at our rebased mt, too. |
*/ |
if (stencil_irb && |
stencil_irb != depth_irb && |
stencil_irb->mt == depth_mt) { |
intel_miptree_reference(&stencil_irb->mt, depth_irb->mt); |
intel_renderbuffer_set_draw_offset(stencil_irb); |
} |
stencil_mt = get_stencil_miptree(stencil_irb); |
tile_x = depth_irb->draw_x & tile_mask_x; |
tile_y = depth_irb->draw_y & tile_mask_y; |
} |
if (stencil_irb) { |
stencil_mt = get_stencil_miptree(stencil_irb); |
intel_miptree_get_image_offset(stencil_mt, |
stencil_irb->mt_level, |
stencil_irb->mt_layer, |
&stencil_draw_x, &stencil_draw_y); |
int stencil_tile_x = stencil_draw_x & tile_mask_x; |
int stencil_tile_y = stencil_draw_y & tile_mask_y; |
/* If stencil doesn't match depth, then we'll need to rebase stencil |
* as well. (if we hadn't decided to rebase stencil before, the |
* post-stencil depth test will also rebase depth to try to match it |
* up). |
*/ |
if (tile_x != stencil_tile_x || |
tile_y != stencil_tile_y) { |
rebase_stencil = true; |
} |
} |
} |
/* If we have (just) stencil, check it for ignored low bits as well */ |
if (stencil_irb) { |
intel_miptree_get_image_offset(stencil_mt, |
stencil_irb->mt_level, |
stencil_irb->mt_layer, |
&stencil_draw_x, &stencil_draw_y); |
stencil_tile_x = stencil_draw_x & tile_mask_x; |
stencil_tile_y = stencil_draw_y & tile_mask_y; |
if (stencil_tile_x & 7 || stencil_tile_y & 7) |
rebase_stencil = true; |
if (brw->gen == 4 && !brw->is_g4x) { |
if (stencil_tile_x || stencil_tile_y) |
rebase_stencil = true; |
} |
} |
if (rebase_stencil) { |
perf_debug("HW workaround: blitting stencil level %d to a temporary " |
"to fix alignment (stencil tile offset %d,%d)\n", |
stencil_irb->mt_level, stencil_tile_x, stencil_tile_y); |
intel_renderbuffer_move_to_temp(brw, stencil_irb, invalidate_stencil); |
stencil_mt = get_stencil_miptree(stencil_irb); |
intel_miptree_get_image_offset(stencil_mt, |
stencil_irb->mt_level, |
stencil_irb->mt_layer, |
&stencil_draw_x, &stencil_draw_y); |
stencil_tile_x = stencil_draw_x & tile_mask_x; |
stencil_tile_y = stencil_draw_y & tile_mask_y; |
if (depth_irb && depth_irb->mt == stencil_irb->mt) { |
intel_miptree_reference(&depth_irb->mt, stencil_irb->mt); |
intel_renderbuffer_set_draw_offset(depth_irb); |
} else if (depth_irb && !rebase_depth) { |
if (tile_x != stencil_tile_x || |
tile_y != stencil_tile_y) { |
perf_debug("HW workaround: blitting depth level %d to a temporary " |
"to match stencil level %d alignment (depth tile offset " |
"%d,%d, stencil offset %d,%d)\n", |
depth_irb->mt_level, |
stencil_irb->mt_level, |
tile_x, tile_y, |
stencil_tile_x, stencil_tile_y); |
intel_renderbuffer_move_to_temp(brw, depth_irb, invalidate_depth); |
tile_x = depth_irb->draw_x & tile_mask_x; |
tile_y = depth_irb->draw_y & tile_mask_y; |
if (stencil_irb && stencil_irb->mt == depth_mt) { |
intel_miptree_reference(&stencil_irb->mt, depth_irb->mt); |
intel_renderbuffer_set_draw_offset(stencil_irb); |
} |
WARN_ONCE(stencil_tile_x != tile_x || |
stencil_tile_y != tile_y, |
"Rebased stencil tile offset (%d,%d) doesn't match depth " |
"tile offset (%d,%d).\n", |
stencil_tile_x, stencil_tile_y, |
tile_x, tile_y); |
} |
} |
} |
if (!depth_irb) { |
tile_x = stencil_tile_x; |
tile_y = stencil_tile_y; |
} |
/* While we just tried to get everything aligned, we may have failed to do |
* so in the case of rendering to array or 3D textures, where nonzero faces |
* will still have an offset post-rebase. At least give an informative |
* warning. |
*/ |
WARN_ONCE((tile_x & 7) || (tile_y & 7), |
"Depth/stencil buffer needs alignment to 8-pixel boundaries.\n" |
"Truncating offset, bad rendering may occur.\n"); |
tile_x &= ~7; |
tile_y &= ~7; |
/* Now, after rebasing, save off the new dephtstencil state so the hardware |
* packets can just dereference that without re-calculating tile offsets. |
*/ |
brw->depthstencil.tile_x = tile_x; |
brw->depthstencil.tile_y = tile_y; |
brw->depthstencil.depth_offset = 0; |
brw->depthstencil.stencil_offset = 0; |
brw->depthstencil.hiz_offset = 0; |
brw->depthstencil.depth_mt = NULL; |
brw->depthstencil.stencil_mt = NULL; |
if (depth_irb) { |
depth_mt = depth_irb->mt; |
brw->depthstencil.depth_mt = depth_mt; |
brw->depthstencil.depth_offset = |
intel_region_get_aligned_offset(depth_mt->region, |
depth_irb->draw_x & ~tile_mask_x, |
depth_irb->draw_y & ~tile_mask_y, |
false); |
if (intel_renderbuffer_has_hiz(depth_irb)) { |
brw->depthstencil.hiz_offset = |
intel_region_get_aligned_offset(depth_mt->region, |
depth_irb->draw_x & ~tile_mask_x, |
(depth_irb->draw_y & ~tile_mask_y) / |
2, |
false); |
} |
} |
if (stencil_irb) { |
stencil_mt = get_stencil_miptree(stencil_irb); |
brw->depthstencil.stencil_mt = stencil_mt; |
if (stencil_mt->format == MESA_FORMAT_S8) { |
/* Note: we can't compute the stencil offset using |
* intel_region_get_aligned_offset(), because stencil_region claims |
* that the region is untiled even though it's W tiled. |
*/ |
brw->depthstencil.stencil_offset = |
(stencil_draw_y & ~tile_mask_y) * stencil_mt->region->pitch + |
(stencil_draw_x & ~tile_mask_x) * 64; |
} |
} |
} |
void |
brw_emit_depthbuffer(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
/* _NEW_BUFFERS */ |
struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(fb, BUFFER_DEPTH); |
struct intel_renderbuffer *stencil_irb = intel_get_renderbuffer(fb, BUFFER_STENCIL); |
struct intel_mipmap_tree *depth_mt = brw->depthstencil.depth_mt; |
struct intel_mipmap_tree *stencil_mt = brw->depthstencil.stencil_mt; |
uint32_t tile_x = brw->depthstencil.tile_x; |
uint32_t tile_y = brw->depthstencil.tile_y; |
bool hiz = depth_irb && intel_renderbuffer_has_hiz(depth_irb); |
bool separate_stencil = false; |
uint32_t depth_surface_type = BRW_SURFACE_NULL; |
uint32_t depthbuffer_format = BRW_DEPTHFORMAT_D32_FLOAT; |
uint32_t depth_offset = 0; |
uint32_t width = 1, height = 1; |
if (stencil_mt) { |
separate_stencil = stencil_mt->format == MESA_FORMAT_S8; |
/* Gen7 supports only separate stencil */ |
assert(separate_stencil || brw->gen < 7); |
} |
/* If there's a packed depth/stencil bound to stencil only, we need to |
* emit the packed depth/stencil buffer packet. |
*/ |
if (!depth_irb && stencil_irb && !separate_stencil) { |
depth_irb = stencil_irb; |
depth_mt = stencil_mt; |
} |
if (depth_irb && depth_mt) { |
/* When 3DSTATE_DEPTH_BUFFER.Separate_Stencil_Enable is set, then |
* 3DSTATE_DEPTH_BUFFER.Surface_Format is not permitted to be a packed |
* depthstencil format. |
* |
* Gens prior to 7 require that HiZ_Enable and Separate_Stencil_Enable be |
* set to the same value. Gens after 7 implicitly always set |
* Separate_Stencil_Enable; software cannot disable it. |
*/ |
if ((brw->gen < 7 && hiz) || brw->gen >= 7) { |
assert(!_mesa_is_format_packed_depth_stencil(depth_mt->format)); |
} |
/* Prior to Gen7, if using separate stencil, hiz must be enabled. */ |
assert(brw->gen >= 7 || !separate_stencil || hiz); |
assert(brw->gen < 6 || depth_mt->region->tiling == I915_TILING_Y); |
assert(!hiz || depth_mt->region->tiling == I915_TILING_Y); |
depthbuffer_format = brw_depthbuffer_format(brw); |
depth_surface_type = BRW_SURFACE_2D; |
depth_offset = brw->depthstencil.depth_offset; |
width = depth_irb->Base.Base.Width; |
height = depth_irb->Base.Base.Height; |
} else if (separate_stencil) { |
/* |
* There exists a separate stencil buffer but no depth buffer. |
* |
* The stencil buffer inherits most of its fields from |
* 3DSTATE_DEPTH_BUFFER: namely the tile walk, surface type, width, and |
* height. |
* |
* The tiled bit must be set. From the Sandybridge PRM, Volume 2, Part 1, |
* Section 7.5.5.1.1 3DSTATE_DEPTH_BUFFER, Bit 1.27 Tiled Surface: |
* [DevGT+]: This field must be set to TRUE. |
*/ |
assert(brw->has_separate_stencil); |
depth_surface_type = BRW_SURFACE_2D; |
width = stencil_irb->Base.Base.Width; |
height = stencil_irb->Base.Base.Height; |
} |
brw->vtbl.emit_depth_stencil_hiz(brw, depth_mt, depth_offset, |
depthbuffer_format, depth_surface_type, |
stencil_mt, hiz, separate_stencil, |
width, height, tile_x, tile_y); |
} |
void |
brw_emit_depth_stencil_hiz(struct brw_context *brw, |
struct intel_mipmap_tree *depth_mt, |
uint32_t depth_offset, uint32_t depthbuffer_format, |
uint32_t depth_surface_type, |
struct intel_mipmap_tree *stencil_mt, |
bool hiz, bool separate_stencil, |
uint32_t width, uint32_t height, |
uint32_t tile_x, uint32_t tile_y) |
{ |
/* Enable the hiz bit if we're doing separate stencil, because it and the |
* separate stencil bit must have the same value. From Section 2.11.5.6.1.1 |
* 3DSTATE_DEPTH_BUFFER, Bit 1.21 "Separate Stencil Enable": |
* [DevIL]: If this field is enabled, Hierarchical Depth Buffer |
* Enable must also be enabled. |
* |
* [DevGT]: This field must be set to the same value (enabled or |
* disabled) as Hierarchical Depth Buffer Enable |
*/ |
bool enable_hiz_ss = hiz || separate_stencil; |
/* 3DSTATE_DEPTH_BUFFER, 3DSTATE_STENCIL_BUFFER are both |
* non-pipelined state that will need the PIPE_CONTROL workaround. |
*/ |
if (brw->gen == 6) { |
intel_emit_post_sync_nonzero_flush(brw); |
intel_emit_depth_stall_flushes(brw); |
} |
unsigned int len; |
if (brw->gen >= 6) |
len = 7; |
else if (brw->is_g4x || brw->gen == 5) |
len = 6; |
else |
len = 5; |
BEGIN_BATCH(len); |
OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2)); |
OUT_BATCH((depth_mt ? depth_mt->region->pitch - 1 : 0) | |
(depthbuffer_format << 18) | |
((enable_hiz_ss ? 1 : 0) << 21) | /* separate stencil enable */ |
((enable_hiz_ss ? 1 : 0) << 22) | /* hiz enable */ |
(BRW_TILEWALK_YMAJOR << 26) | |
((depth_mt ? depth_mt->region->tiling != I915_TILING_NONE : 1) |
<< 27) | |
(depth_surface_type << 29)); |
if (depth_mt) { |
OUT_RELOC(depth_mt->region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
depth_offset); |
} else { |
OUT_BATCH(0); |
} |
OUT_BATCH(((width + tile_x - 1) << 6) | |
((height + tile_y - 1) << 19)); |
OUT_BATCH(0); |
if (brw->is_g4x || brw->gen >= 5) |
OUT_BATCH(tile_x | (tile_y << 16)); |
else |
assert(tile_x == 0 && tile_y == 0); |
if (brw->gen >= 6) |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
if (hiz || separate_stencil) { |
/* |
* In the 3DSTATE_DEPTH_BUFFER batch emitted above, the 'separate |
* stencil enable' and 'hiz enable' bits were set. Therefore we must |
* emit 3DSTATE_HIER_DEPTH_BUFFER and 3DSTATE_STENCIL_BUFFER. Even if |
* there is no stencil buffer, 3DSTATE_STENCIL_BUFFER must be emitted; |
* failure to do so causes hangs on gen5 and a stall on gen6. |
*/ |
/* Emit hiz buffer. */ |
if (hiz) { |
struct intel_mipmap_tree *hiz_mt = depth_mt->hiz_mt; |
BEGIN_BATCH(3); |
OUT_BATCH((_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2)); |
OUT_BATCH(hiz_mt->region->pitch - 1); |
OUT_RELOC(hiz_mt->region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
brw->depthstencil.hiz_offset); |
ADVANCE_BATCH(); |
} else { |
BEGIN_BATCH(3); |
OUT_BATCH((_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* Emit stencil buffer. */ |
if (separate_stencil) { |
struct intel_region *region = stencil_mt->region; |
BEGIN_BATCH(3); |
OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2)); |
/* The stencil buffer has quirky pitch requirements. From Vol 2a, |
* 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch": |
* The pitch must be set to 2x the value computed based on width, as |
* the stencil buffer is stored with two rows interleaved. |
*/ |
OUT_BATCH(2 * region->pitch - 1); |
OUT_RELOC(region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
brw->depthstencil.stencil_offset); |
ADVANCE_BATCH(); |
} else { |
BEGIN_BATCH(3); |
OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
} |
/* |
* On Gen >= 6, emit clear params for safety. If using hiz, then clear |
* params must be emitted. |
* |
* From Section 2.11.5.6.4.1 3DSTATE_CLEAR_PARAMS: |
* 3DSTATE_CLEAR_PARAMS packet must follow the DEPTH_BUFFER_STATE packet |
* when HiZ is enabled and the DEPTH_BUFFER_STATE changes. |
*/ |
if (brw->gen >= 6 || hiz) { |
if (brw->gen == 6) |
intel_emit_post_sync_nonzero_flush(brw); |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_CLEAR_PARAMS << 16 | |
GEN5_DEPTH_CLEAR_VALID | |
(2 - 2)); |
OUT_BATCH(depth_mt ? depth_mt->depth_clear_value : 0); |
ADVANCE_BATCH(); |
} |
} |
const struct brw_tracked_state brw_depthbuffer = { |
.dirty = { |
.mesa = _NEW_BUFFERS, |
.brw = BRW_NEW_BATCH, |
.cache = 0, |
}, |
.emit = brw_emit_depthbuffer, |
}; |
/*********************************************************************** |
* Polygon stipple packet |
*/ |
static void upload_polygon_stipple(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
GLuint i; |
/* _NEW_POLYGON */ |
if (!ctx->Polygon.StippleFlag) |
return; |
if (brw->gen == 6) |
intel_emit_post_sync_nonzero_flush(brw); |
BEGIN_BATCH(33); |
OUT_BATCH(_3DSTATE_POLY_STIPPLE_PATTERN << 16 | (33 - 2)); |
/* Polygon stipple is provided in OpenGL order, i.e. bottom |
* row first. If we're rendering to a window (i.e. the |
* default frame buffer object, 0), then we need to invert |
* it to match our pixel layout. But if we're rendering |
* to a FBO (i.e. any named frame buffer object), we *don't* |
* need to invert - we already match the layout. |
*/ |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
for (i = 0; i < 32; i++) |
OUT_BATCH(ctx->PolygonStipple[31 - i]); /* invert */ |
} |
else { |
for (i = 0; i < 32; i++) |
OUT_BATCH(ctx->PolygonStipple[i]); |
} |
CACHED_BATCH(); |
} |
const struct brw_tracked_state brw_polygon_stipple = { |
.dirty = { |
.mesa = (_NEW_POLYGONSTIPPLE | |
_NEW_POLYGON), |
.brw = BRW_NEW_CONTEXT, |
.cache = 0 |
}, |
.emit = upload_polygon_stipple |
}; |
/*********************************************************************** |
* Polygon stipple offset packet |
*/ |
static void upload_polygon_stipple_offset(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* _NEW_POLYGON */ |
if (!ctx->Polygon.StippleFlag) |
return; |
if (brw->gen == 6) |
intel_emit_post_sync_nonzero_flush(brw); |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_POLY_STIPPLE_OFFSET << 16 | (2-2)); |
/* _NEW_BUFFERS |
* |
* If we're drawing to a system window we have to invert the Y axis |
* in order to match the OpenGL pixel coordinate system, and our |
* offset must be matched to the window position. If we're drawing |
* to a user-created FBO then our native pixel coordinate system |
* works just fine, and there's no window system to worry about. |
*/ |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) |
OUT_BATCH((32 - (ctx->DrawBuffer->Height & 31)) & 31); |
else |
OUT_BATCH(0); |
CACHED_BATCH(); |
} |
const struct brw_tracked_state brw_polygon_stipple_offset = { |
.dirty = { |
.mesa = (_NEW_BUFFERS | |
_NEW_POLYGON), |
.brw = BRW_NEW_CONTEXT, |
.cache = 0 |
}, |
.emit = upload_polygon_stipple_offset |
}; |
/********************************************************************** |
* AA Line parameters |
*/ |
static void upload_aa_line_parameters(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
if (!ctx->Line.SmoothFlag || !brw->has_aa_line_parameters) |
return; |
if (brw->gen == 6) |
intel_emit_post_sync_nonzero_flush(brw); |
OUT_BATCH(_3DSTATE_AA_LINE_PARAMETERS << 16 | (3 - 2)); |
/* use legacy aa line coverage computation */ |
OUT_BATCH(0); |
OUT_BATCH(0); |
CACHED_BATCH(); |
} |
const struct brw_tracked_state brw_aa_line_parameters = { |
.dirty = { |
.mesa = _NEW_LINE, |
.brw = BRW_NEW_CONTEXT, |
.cache = 0 |
}, |
.emit = upload_aa_line_parameters |
}; |
/*********************************************************************** |
* Line stipple packet |
*/ |
static void upload_line_stipple(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
GLfloat tmp; |
GLint tmpi; |
if (!ctx->Line.StippleFlag) |
return; |
if (brw->gen == 6) |
intel_emit_post_sync_nonzero_flush(brw); |
BEGIN_BATCH(3); |
OUT_BATCH(_3DSTATE_LINE_STIPPLE_PATTERN << 16 | (3 - 2)); |
OUT_BATCH(ctx->Line.StipplePattern); |
if (brw->gen >= 7) { |
/* in U1.16 */ |
tmp = 1.0 / (GLfloat) ctx->Line.StippleFactor; |
tmpi = tmp * (1<<16); |
OUT_BATCH(tmpi << 15 | ctx->Line.StippleFactor); |
} |
else { |
/* in U1.13 */ |
tmp = 1.0 / (GLfloat) ctx->Line.StippleFactor; |
tmpi = tmp * (1<<13); |
OUT_BATCH(tmpi << 16 | ctx->Line.StippleFactor); |
} |
CACHED_BATCH(); |
} |
const struct brw_tracked_state brw_line_stipple = { |
.dirty = { |
.mesa = _NEW_LINE, |
.brw = BRW_NEW_CONTEXT, |
.cache = 0 |
}, |
.emit = upload_line_stipple |
}; |
/*********************************************************************** |
* Misc invariant state packets |
*/ |
void |
brw_upload_invariant_state(struct brw_context *brw) |
{ |
/* 3DSTATE_SIP, 3DSTATE_MULTISAMPLE, etc. are nonpipelined. */ |
if (brw->gen == 6) |
intel_emit_post_sync_nonzero_flush(brw); |
/* Select the 3D pipeline (as opposed to media) */ |
BEGIN_BATCH(1); |
OUT_BATCH(brw->CMD_PIPELINE_SELECT << 16 | 0); |
ADVANCE_BATCH(); |
if (brw->gen < 6) { |
/* Disable depth offset clamping. */ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP << 16 | (2 - 2)); |
OUT_BATCH_F(0.0); |
ADVANCE_BATCH(); |
} |
BEGIN_BATCH(2); |
OUT_BATCH(CMD_STATE_SIP << 16 | (2 - 2)); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(1); |
OUT_BATCH(brw->CMD_VF_STATISTICS << 16 | |
(unlikely(INTEL_DEBUG & DEBUG_STATS) ? 1 : 0)); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state brw_invariant_state = { |
.dirty = { |
.mesa = 0, |
.brw = BRW_NEW_CONTEXT, |
.cache = 0 |
}, |
.emit = brw_upload_invariant_state |
}; |
/** |
* Define the base addresses which some state is referenced from. |
* |
* This allows us to avoid having to emit relocations for the objects, |
* and is actually required for binding table pointers on gen6. |
* |
* Surface state base address covers binding table pointers and |
* surface state objects, but not the surfaces that the surface state |
* objects point to. |
*/ |
static void upload_state_base_address( struct brw_context *brw ) |
{ |
/* FINISHME: According to section 3.6.1 "STATE_BASE_ADDRESS" of |
* vol1a of the G45 PRM, MI_FLUSH with the ISC invalidate should be |
* programmed prior to STATE_BASE_ADDRESS. |
* |
* However, given that the instruction SBA (general state base |
* address) on this chipset is always set to 0 across X and GL, |
* maybe this isn't required for us in particular. |
*/ |
if (brw->gen >= 6) { |
if (brw->gen == 6) |
intel_emit_post_sync_nonzero_flush(brw); |
BEGIN_BATCH(10); |
OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (10 - 2)); |
/* General state base address: stateless DP read/write requests */ |
OUT_BATCH(1); |
/* Surface state base address: |
* BINDING_TABLE_STATE |
* SURFACE_STATE |
*/ |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0, 1); |
/* Dynamic state base address: |
* SAMPLER_STATE |
* SAMPLER_BORDER_COLOR_STATE |
* CLIP, SF, WM/CC viewport state |
* COLOR_CALC_STATE |
* DEPTH_STENCIL_STATE |
* BLEND_STATE |
* Push constants (when INSTPM: CONSTANT_BUFFER Address Offset |
* Disable is clear, which we rely on) |
*/ |
OUT_RELOC(brw->batch.bo, (I915_GEM_DOMAIN_RENDER | |
I915_GEM_DOMAIN_INSTRUCTION), 0, 1); |
OUT_BATCH(1); /* Indirect object base address: MEDIA_OBJECT data */ |
OUT_RELOC(brw->cache.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, |
1); /* Instruction base address: shader kernels (incl. SIP) */ |
OUT_BATCH(1); /* General state upper bound */ |
/* Dynamic state upper bound. Although the documentation says that |
* programming it to zero will cause it to be ignored, that is a lie. |
* If this isn't programmed to a real bound, the sampler border color |
* pointer is rejected, causing border color to mysteriously fail. |
*/ |
OUT_BATCH(0xfffff001); |
OUT_BATCH(1); /* Indirect object upper bound */ |
OUT_BATCH(1); /* Instruction access upper bound */ |
ADVANCE_BATCH(); |
} else if (brw->gen == 5) { |
BEGIN_BATCH(8); |
OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (8 - 2)); |
OUT_BATCH(1); /* General state base address */ |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0, |
1); /* Surface state base address */ |
OUT_BATCH(1); /* Indirect object base address */ |
OUT_RELOC(brw->cache.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, |
1); /* Instruction base address */ |
OUT_BATCH(0xfffff001); /* General state upper bound */ |
OUT_BATCH(1); /* Indirect object upper bound */ |
OUT_BATCH(1); /* Instruction access upper bound */ |
ADVANCE_BATCH(); |
} else { |
BEGIN_BATCH(6); |
OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (6 - 2)); |
OUT_BATCH(1); /* General state base address */ |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0, |
1); /* Surface state base address */ |
OUT_BATCH(1); /* Indirect object base address */ |
OUT_BATCH(1); /* General state upper bound */ |
OUT_BATCH(1); /* Indirect object upper bound */ |
ADVANCE_BATCH(); |
} |
/* According to section 3.6.1 of VOL1 of the 965 PRM, |
* STATE_BASE_ADDRESS updates require a reissue of: |
* |
* 3DSTATE_PIPELINE_POINTERS |
* 3DSTATE_BINDING_TABLE_POINTERS |
* MEDIA_STATE_POINTERS |
* |
* and this continues through Ironlake. The Sandy Bridge PRM, vol |
* 1 part 1 says that the folowing packets must be reissued: |
* |
* 3DSTATE_CC_POINTERS |
* 3DSTATE_BINDING_TABLE_POINTERS |
* 3DSTATE_SAMPLER_STATE_POINTERS |
* 3DSTATE_VIEWPORT_STATE_POINTERS |
* MEDIA_STATE_POINTERS |
* |
* Those are always reissued following SBA updates anyway (new |
* batch time), except in the case of the program cache BO |
* changing. Having a separate state flag makes the sequence more |
* obvious. |
*/ |
brw->state.dirty.brw |= BRW_NEW_STATE_BASE_ADDRESS; |
} |
const struct brw_tracked_state brw_state_base_address = { |
.dirty = { |
.mesa = 0, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_PROGRAM_CACHE), |
.cache = 0, |
}, |
.emit = upload_state_base_address |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_primitive_restart.c |
---|
0,0 → 1,221 |
/* |
* 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. |
* |
* Authors: |
* Jordan Justen <jordan.l.justen@intel.com> |
* |
*/ |
#include "main/imports.h" |
#include "main/bufferobj.h" |
#include "main/varray.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
#include "brw_draw.h" |
#include "intel_batchbuffer.h" |
/** |
* Check if the hardware's cut index support can handle the primitive |
* restart index value (pre-Haswell only). |
*/ |
static bool |
can_cut_index_handle_restart_index(struct gl_context *ctx, |
const struct _mesa_index_buffer *ib) |
{ |
/* The FixedIndex variant means 0xFF, 0xFFFF, or 0xFFFFFFFF based on |
* the index buffer type, which corresponds exactly to the hardware. |
*/ |
if (ctx->Array.PrimitiveRestartFixedIndex) |
return true; |
bool cut_index_will_work; |
switch (ib->type) { |
case GL_UNSIGNED_BYTE: |
cut_index_will_work = ctx->Array.RestartIndex == 0xff; |
break; |
case GL_UNSIGNED_SHORT: |
cut_index_will_work = ctx->Array.RestartIndex == 0xffff; |
break; |
case GL_UNSIGNED_INT: |
cut_index_will_work = ctx->Array.RestartIndex == 0xffffffff; |
break; |
default: |
cut_index_will_work = false; |
assert(0); |
} |
return cut_index_will_work; |
} |
/** |
* Check if the hardware's cut index support can handle the primitive |
* restart case. |
*/ |
static bool |
can_cut_index_handle_prims(struct gl_context *ctx, |
const struct _mesa_prim *prim, |
GLuint nr_prims, |
const struct _mesa_index_buffer *ib) |
{ |
struct brw_context *brw = brw_context(ctx); |
/* Otherwise Haswell can do it all. */ |
if (brw->gen >= 8 || brw->is_haswell) |
return true; |
if (!can_cut_index_handle_restart_index(ctx, ib)) { |
/* The primitive restart index can't be handled, so take |
* the software path |
*/ |
return false; |
} |
for ( ; nr_prims > 0; nr_prims--) { |
switch(prim->mode) { |
case GL_POINTS: |
case GL_LINES: |
case GL_LINE_STRIP: |
case GL_TRIANGLES: |
case GL_TRIANGLE_STRIP: |
/* Cut index supports these primitive types */ |
break; |
default: |
/* Cut index does not support these primitive types */ |
//case GL_LINE_LOOP: |
//case GL_TRIANGLE_FAN: |
//case GL_QUADS: |
//case GL_QUAD_STRIP: |
//case GL_POLYGON: |
return false; |
} |
} |
return true; |
} |
/** |
* Check if primitive restart is enabled, and if so, handle it properly. |
* |
* In some cases the support will be handled in software. When available |
* hardware will handle primitive restart. |
*/ |
GLboolean |
brw_handle_primitive_restart(struct gl_context *ctx, |
const struct _mesa_prim *prim, |
GLuint nr_prims, |
const struct _mesa_index_buffer *ib) |
{ |
struct brw_context *brw = brw_context(ctx); |
/* We only need to handle cases where there is an index buffer. */ |
if (ib == NULL) { |
return GL_FALSE; |
} |
/* If the driver has requested software handling of primitive restarts, |
* then the VBO module has already taken care of things, and we can |
* just draw as normal. |
*/ |
if (ctx->Const.PrimitiveRestartInSoftware) { |
return GL_FALSE; |
} |
/* If we have set the in_progress flag, then we are in the middle |
* of handling the primitive restart draw. |
*/ |
if (brw->prim_restart.in_progress) { |
return GL_FALSE; |
} |
/* If PrimitiveRestart is not enabled, then we aren't concerned about |
* handling this draw. |
*/ |
if (!(ctx->Array._PrimitiveRestart)) { |
return GL_FALSE; |
} |
/* Signal that we are in the process of handling the |
* primitive restart draw |
*/ |
brw->prim_restart.in_progress = true; |
if (can_cut_index_handle_prims(ctx, prim, nr_prims, ib)) { |
/* Cut index should work for primitive restart, so use it |
*/ |
brw->prim_restart.enable_cut_index = true; |
brw_draw_prims(ctx, prim, nr_prims, ib, GL_FALSE, -1, -1, NULL); |
brw->prim_restart.enable_cut_index = false; |
} else { |
/* Not all the primitive draw modes are supported by the cut index, |
* so take the software path |
*/ |
vbo_sw_primitive_restart(ctx, prim, nr_prims, ib); |
} |
brw->prim_restart.in_progress = false; |
/* The primitive restart draw was completed, so return true. */ |
return GL_TRUE; |
} |
static void |
haswell_upload_cut_index(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* Don't trigger on Ivybridge */ |
if (!brw->is_haswell) |
return; |
const unsigned cut_index_setting = |
ctx->Array._PrimitiveRestart ? HSW_CUT_INDEX_ENABLE : 0; |
/* BRW_NEW_INDEX_BUFFER */ |
unsigned cut_index; |
if (brw->ib.ib) { |
cut_index = _mesa_primitive_restart_index(ctx, brw->ib.type); |
} else { |
/* There's no index buffer, but primitive restart may still apply |
* to glDrawArrays and such. FIXED_INDEX mode only applies to drawing |
* operations that use an index buffer, so we can ignore it and use |
* the GL restart index directly. |
*/ |
cut_index = ctx->Array.RestartIndex; |
} |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_VF << 16 | cut_index_setting | (2 - 2)); |
OUT_BATCH(cut_index); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state haswell_cut_index = { |
.dirty = { |
.mesa = _NEW_TRANSFORM, |
.brw = BRW_NEW_INDEX_BUFFER, |
.cache = 0, |
}, |
.emit = haswell_upload_cut_index, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_program.c |
---|
0,0 → 1,512 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 <pthread.h> |
#include "main/imports.h" |
#include "main/enums.h" |
#include "main/shaderobj.h" |
#include "program/prog_parameter.h" |
#include "program/program.h" |
#include "program/programopt.h" |
#include "tnl/tnl.h" |
#include "glsl/ralloc.h" |
#include "brw_context.h" |
#include "brw_wm.h" |
static unsigned |
get_new_program_id(struct intel_screen *screen) |
{ |
// static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; |
// pthread_mutex_lock(&m); |
unsigned id = screen->program_id++; |
// pthread_mutex_unlock(&m); |
return id; |
} |
static void brwBindProgram( struct gl_context *ctx, |
GLenum target, |
struct gl_program *prog ) |
{ |
struct brw_context *brw = brw_context(ctx); |
switch (target) { |
case GL_VERTEX_PROGRAM_ARB: |
brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM; |
break; |
case GL_FRAGMENT_PROGRAM_ARB: |
brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM; |
break; |
} |
} |
static struct gl_program *brwNewProgram( struct gl_context *ctx, |
GLenum target, |
GLuint id ) |
{ |
struct brw_context *brw = brw_context(ctx); |
switch (target) { |
case GL_VERTEX_PROGRAM_ARB: { |
struct brw_vertex_program *prog = CALLOC_STRUCT(brw_vertex_program); |
if (prog) { |
prog->id = get_new_program_id(brw->intelScreen); |
return _mesa_init_vertex_program( ctx, &prog->program, |
target, id ); |
} |
else |
return NULL; |
} |
case GL_FRAGMENT_PROGRAM_ARB: { |
struct brw_fragment_program *prog = CALLOC_STRUCT(brw_fragment_program); |
if (prog) { |
prog->id = get_new_program_id(brw->intelScreen); |
return _mesa_init_fragment_program( ctx, &prog->program, |
target, id ); |
} |
else |
return NULL; |
} |
default: |
return _mesa_new_program(ctx, target, id); |
} |
} |
static void brwDeleteProgram( struct gl_context *ctx, |
struct gl_program *prog ) |
{ |
_mesa_delete_program( ctx, prog ); |
} |
static GLboolean |
brwIsProgramNative(struct gl_context *ctx, |
GLenum target, |
struct gl_program *prog) |
{ |
return true; |
} |
static GLboolean |
brwProgramStringNotify(struct gl_context *ctx, |
GLenum target, |
struct gl_program *prog) |
{ |
struct brw_context *brw = brw_context(ctx); |
switch (target) { |
case GL_FRAGMENT_PROGRAM_ARB: { |
struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog; |
struct brw_fragment_program *newFP = brw_fragment_program(fprog); |
const struct brw_fragment_program *curFP = |
brw_fragment_program_const(brw->fragment_program); |
if (newFP == curFP) |
brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM; |
newFP->id = get_new_program_id(brw->intelScreen); |
break; |
} |
case GL_VERTEX_PROGRAM_ARB: { |
struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog; |
struct brw_vertex_program *newVP = brw_vertex_program(vprog); |
const struct brw_vertex_program *curVP = |
brw_vertex_program_const(brw->vertex_program); |
if (newVP == curVP) |
brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM; |
if (newVP->program.IsPositionInvariant) { |
_mesa_insert_mvp_code(ctx, &newVP->program); |
} |
newVP->id = get_new_program_id(brw->intelScreen); |
/* Also tell tnl about it: |
*/ |
_tnl_program_string(ctx, target, prog); |
break; |
} |
default: |
/* |
* driver->ProgramStringNotify is only called for ARB programs, fixed |
* function vertex programs, and ir_to_mesa (which isn't used by the |
* i965 back-end). Therefore, even after geometry shaders are added, |
* this function should only ever be called with a target of |
* GL_VERTEX_PROGRAM_ARB or GL_FRAGMENT_PROGRAM_ARB. |
*/ |
assert(!"Unexpected target in brwProgramStringNotify"); |
break; |
} |
brw_add_texrect_params(prog); |
return true; |
} |
void |
brw_add_texrect_params(struct gl_program *prog) |
{ |
for (int texunit = 0; texunit < BRW_MAX_TEX_UNIT; texunit++) { |
if (!(prog->TexturesUsed[texunit] & (1 << TEXTURE_RECT_INDEX))) |
continue; |
int tokens[STATE_LENGTH] = { |
STATE_INTERNAL, |
STATE_TEXRECT_SCALE, |
texunit, |
0, |
0 |
}; |
_mesa_add_state_reference(prog->Parameters, (gl_state_index *)tokens); |
} |
} |
/* Per-thread scratch space is a power-of-two multiple of 1KB. */ |
int |
brw_get_scratch_size(int size) |
{ |
int i; |
for (i = 1024; i < size; i *= 2) |
; |
return i; |
} |
void |
brw_get_scratch_bo(struct brw_context *brw, |
drm_intel_bo **scratch_bo, int size) |
{ |
drm_intel_bo *old_bo = *scratch_bo; |
if (old_bo && old_bo->size < size) { |
drm_intel_bo_unreference(old_bo); |
old_bo = NULL; |
} |
if (!old_bo) { |
*scratch_bo = drm_intel_bo_alloc(brw->bufmgr, "scratch bo", size, 4096); |
} |
} |
void brwInitFragProgFuncs( struct dd_function_table *functions ) |
{ |
assert(functions->ProgramStringNotify == _tnl_program_string); |
functions->BindProgram = brwBindProgram; |
functions->NewProgram = brwNewProgram; |
functions->DeleteProgram = brwDeleteProgram; |
functions->IsProgramNative = brwIsProgramNative; |
functions->ProgramStringNotify = brwProgramStringNotify; |
functions->NewShader = brw_new_shader; |
functions->NewShaderProgram = brw_new_shader_program; |
functions->LinkShader = brw_link_shader; |
} |
void |
brw_init_shader_time(struct brw_context *brw) |
{ |
const int max_entries = 4096; |
brw->shader_time.bo = drm_intel_bo_alloc(brw->bufmgr, "shader time", |
max_entries * SHADER_TIME_STRIDE, |
4096); |
brw->shader_time.shader_programs = rzalloc_array(brw, struct gl_shader_program *, |
max_entries); |
brw->shader_time.programs = rzalloc_array(brw, struct gl_program *, |
max_entries); |
brw->shader_time.types = rzalloc_array(brw, enum shader_time_shader_type, |
max_entries); |
brw->shader_time.cumulative = rzalloc_array(brw, uint64_t, |
max_entries); |
brw->shader_time.max_entries = max_entries; |
} |
static int |
compare_time(const void *a, const void *b) |
{ |
uint64_t * const *a_val = a; |
uint64_t * const *b_val = b; |
/* We don't just subtract because we're turning the value to an int. */ |
if (**a_val < **b_val) |
return -1; |
else if (**a_val == **b_val) |
return 0; |
else |
return 1; |
} |
static void |
get_written_and_reset(struct brw_context *brw, int i, |
uint64_t *written, uint64_t *reset) |
{ |
enum shader_time_shader_type type = brw->shader_time.types[i]; |
assert(type == ST_VS || type == ST_FS8 || type == ST_FS16); |
/* Find where we recorded written and reset. */ |
int wi, ri; |
for (wi = i; brw->shader_time.types[wi] != type + 1; wi++) |
; |
for (ri = i; brw->shader_time.types[ri] != type + 2; ri++) |
; |
*written = brw->shader_time.cumulative[wi]; |
*reset = brw->shader_time.cumulative[ri]; |
} |
static void |
print_shader_time_line(const char *stage, const char *name, |
int shader_num, uint64_t time, uint64_t total) |
{ |
printf("%-6s%-6s", stage, name); |
if (shader_num != -1) |
printf("%4d: ", shader_num); |
else |
printf(" : "); |
printf("%16lld (%7.2f Gcycles) %4.1f%%\n", |
(long long)time, |
(double)time / 1000000000.0, |
(double)time / total * 100.0); |
} |
static void |
brw_report_shader_time(struct brw_context *brw) |
{ |
if (!brw->shader_time.bo || !brw->shader_time.num_entries) |
return; |
uint64_t scaled[brw->shader_time.num_entries]; |
uint64_t *sorted[brw->shader_time.num_entries]; |
uint64_t total_by_type[ST_FS16 + 1]; |
memset(total_by_type, 0, sizeof(total_by_type)); |
double total = 0; |
for (int i = 0; i < brw->shader_time.num_entries; i++) { |
uint64_t written = 0, reset = 0; |
enum shader_time_shader_type type = brw->shader_time.types[i]; |
sorted[i] = &scaled[i]; |
switch (type) { |
case ST_VS_WRITTEN: |
case ST_VS_RESET: |
case ST_FS8_WRITTEN: |
case ST_FS8_RESET: |
case ST_FS16_WRITTEN: |
case ST_FS16_RESET: |
/* We'll handle these when along with the time. */ |
scaled[i] = 0; |
continue; |
case ST_VS: |
case ST_FS8: |
case ST_FS16: |
get_written_and_reset(brw, i, &written, &reset); |
break; |
default: |
/* I sometimes want to print things that aren't the 3 shader times. |
* Just print the sum in that case. |
*/ |
written = 1; |
reset = 0; |
break; |
} |
uint64_t time = brw->shader_time.cumulative[i]; |
if (written) { |
scaled[i] = time / written * (written + reset); |
} else { |
scaled[i] = time; |
} |
switch (type) { |
case ST_VS: |
case ST_FS8: |
case ST_FS16: |
total_by_type[type] += scaled[i]; |
break; |
default: |
break; |
} |
total += scaled[i]; |
} |
if (total == 0) { |
printf("No shader time collected yet\n"); |
return; |
} |
qsort(sorted, brw->shader_time.num_entries, sizeof(sorted[0]), compare_time); |
printf("\n"); |
printf("type ID cycles spent %% of total\n"); |
for (int s = 0; s < brw->shader_time.num_entries; s++) { |
const char *shader_name; |
const char *stage; |
/* Work back from the sorted pointers times to a time to print. */ |
int i = sorted[s] - scaled; |
if (scaled[i] == 0) |
continue; |
int shader_num = -1; |
if (brw->shader_time.shader_programs[i]) { |
shader_num = brw->shader_time.shader_programs[i]->Name; |
/* The fixed function fragment shader generates GLSL IR with a Name |
* of 0, and nothing else does. |
*/ |
if (shader_num == 0 && |
(brw->shader_time.types[i] == ST_FS8 || |
brw->shader_time.types[i] == ST_FS16)) { |
shader_name = "ff"; |
shader_num = -1; |
} else { |
shader_name = "glsl"; |
} |
} else if (brw->shader_time.programs[i]) { |
shader_num = brw->shader_time.programs[i]->Id; |
if (shader_num == 0) { |
shader_name = "ff"; |
shader_num = -1; |
} else { |
shader_name = "prog"; |
} |
} else { |
shader_name = "other"; |
} |
switch (brw->shader_time.types[i]) { |
case ST_VS: |
stage = "vs"; |
break; |
case ST_FS8: |
stage = "fs8"; |
break; |
case ST_FS16: |
stage = "fs16"; |
break; |
default: |
stage = "other"; |
break; |
} |
print_shader_time_line(stage, shader_name, shader_num, |
scaled[i], total); |
} |
printf("\n"); |
print_shader_time_line("total", "vs", -1, total_by_type[ST_VS], total); |
print_shader_time_line("total", "fs8", -1, total_by_type[ST_FS8], total); |
print_shader_time_line("total", "fs16", -1, total_by_type[ST_FS16], total); |
} |
static void |
brw_collect_shader_time(struct brw_context *brw) |
{ |
if (!brw->shader_time.bo) |
return; |
/* This probably stalls on the last rendering. We could fix that by |
* delaying reading the reports, but it doesn't look like it's a big |
* overhead compared to the cost of tracking the time in the first place. |
*/ |
drm_intel_bo_map(brw->shader_time.bo, true); |
uint32_t *times = brw->shader_time.bo->virtual; |
for (int i = 0; i < brw->shader_time.num_entries; i++) { |
brw->shader_time.cumulative[i] += times[i * SHADER_TIME_STRIDE / 4]; |
} |
/* Zero the BO out to clear it out for our next collection. |
*/ |
memset(times, 0, brw->shader_time.bo->size); |
drm_intel_bo_unmap(brw->shader_time.bo); |
} |
void |
brw_collect_and_report_shader_time(struct brw_context *brw) |
{ |
brw_collect_shader_time(brw); |
if (brw->shader_time.report_time == 0 || |
get_time() - brw->shader_time.report_time >= 1.0) { |
brw_report_shader_time(brw); |
brw->shader_time.report_time = get_time(); |
} |
} |
/** |
* Chooses an index in the shader_time buffer and sets up tracking information |
* for our printouts. |
* |
* Note that this holds on to references to the underlying programs, which may |
* change their lifetimes compared to normal operation. |
*/ |
int |
brw_get_shader_time_index(struct brw_context *brw, |
struct gl_shader_program *shader_prog, |
struct gl_program *prog, |
enum shader_time_shader_type type) |
{ |
struct gl_context *ctx = &brw->ctx; |
int shader_time_index = brw->shader_time.num_entries++; |
assert(shader_time_index < brw->shader_time.max_entries); |
brw->shader_time.types[shader_time_index] = type; |
_mesa_reference_shader_program(ctx, |
&brw->shader_time.shader_programs[shader_time_index], |
shader_prog); |
_mesa_reference_program(ctx, |
&brw->shader_time.programs[shader_time_index], |
prog); |
return shader_time_index; |
} |
void |
brw_destroy_shader_time(struct brw_context *brw) |
{ |
drm_intel_bo_unreference(brw->shader_time.bo); |
brw->shader_time.bo = NULL; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_program.h |
---|
0,0 → 1,53 |
/* |
* Copyright © 2011 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. |
*/ |
#ifndef BRW_PROGRAM_H |
#define BRW_PROGRAM_H |
/** |
* Sampler information needed by VS, WM, and GS program cache keys. |
*/ |
struct brw_sampler_prog_key_data { |
/** |
* EXT_texture_swizzle and DEPTH_TEXTURE_MODE swizzles. |
*/ |
uint16_t swizzles[MAX_SAMPLERS]; |
uint16_t gl_clamp_mask[3]; |
/** |
* YUV conversions, needed for the GL_MESA_ycbcr extension. |
*/ |
uint16_t yuvtex_mask; |
uint16_t yuvtex_swap_mask; /**< UV swaped */ |
}; |
void brw_populate_sampler_prog_key_data(struct gl_context *ctx, |
const struct gl_program *prog, |
struct brw_sampler_prog_key_data *key); |
bool brw_debug_recompile_sampler_key(struct brw_context *brw, |
const struct brw_sampler_prog_key_data *old_key, |
const struct brw_sampler_prog_key_data *key); |
void brw_add_texrect_params(struct gl_program *prog); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_queryobj.c |
---|
0,0 → 1,558 |
/* |
* Copyright © 2008 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
/** @file brw_queryobj.c |
* |
* Support for query objects (GL_ARB_occlusion_query, GL_ARB_timer_query, |
* GL_EXT_transform_feedback, and friends). |
* |
* The hardware provides a PIPE_CONTROL command that can report the number of |
* fragments that passed the depth test, or the hardware timer. They are |
* appropriately synced with the stage of the pipeline for our extensions' |
* needs. |
*/ |
#include "main/imports.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
#include "brw_state.h" |
#include "intel_batchbuffer.h" |
#include "intel_reg.h" |
/** |
* Emit PIPE_CONTROLs to write the current GPU timestamp into a buffer. |
*/ |
static void |
write_timestamp(struct brw_context *brw, drm_intel_bo *query_bo, int idx) |
{ |
if (brw->gen >= 6) { |
/* Emit workaround flushes: */ |
if (brw->gen == 6) { |
/* The timestamp write below is a non-zero post-sync op, which on |
* Gen6 necessitates a CS stall. CS stalls need stall at scoreboard |
* set. See the comments for intel_emit_post_sync_nonzero_flush(). |
*/ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2)); |
OUT_BATCH(PIPE_CONTROL_CS_STALL | PIPE_CONTROL_STALL_AT_SCOREBOARD); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (5 - 2)); |
OUT_BATCH(PIPE_CONTROL_WRITE_TIMESTAMP); |
OUT_RELOC(query_bo, |
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, |
PIPE_CONTROL_GLOBAL_GTT_WRITE | |
idx * sizeof(uint64_t)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} else { |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2) | |
PIPE_CONTROL_WRITE_TIMESTAMP); |
OUT_RELOC(query_bo, |
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, |
PIPE_CONTROL_GLOBAL_GTT_WRITE | |
idx * sizeof(uint64_t)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
} |
/** |
* Emit PIPE_CONTROLs to write the PS_DEPTH_COUNT register into a buffer. |
*/ |
static void |
write_depth_count(struct brw_context *brw, drm_intel_bo *query_bo, int idx) |
{ |
assert(brw->gen < 6); |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2) | |
PIPE_CONTROL_DEPTH_STALL | PIPE_CONTROL_WRITE_DEPTH_COUNT); |
/* This object could be mapped cacheable, but we don't have an exposed |
* mechanism to support that. Since it's going uncached, tell GEM that |
* we're writing to it. The usual clflush should be all that's required |
* to pick up the results. |
*/ |
OUT_RELOC(query_bo, |
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, |
PIPE_CONTROL_GLOBAL_GTT_WRITE | |
(idx * sizeof(uint64_t))); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/** |
* Wait on the query object's BO and calculate the final result. |
*/ |
static void |
brw_queryobj_get_results(struct gl_context *ctx, |
struct brw_query_object *query) |
{ |
struct brw_context *brw = brw_context(ctx); |
int i; |
uint64_t *results; |
assert(brw->gen < 6); |
if (query->bo == NULL) |
return; |
/* If the application has requested the query result, but this batch is |
* still contributing to it, flush it now so the results will be present |
* when mapped. |
*/ |
if (drm_intel_bo_references(brw->batch.bo, query->bo)) |
intel_batchbuffer_flush(brw); |
if (unlikely(brw->perf_debug)) { |
if (drm_intel_bo_busy(query->bo)) { |
perf_debug("Stalling on the GPU waiting for a query object.\n"); |
} |
} |
drm_intel_bo_map(query->bo, false); |
results = query->bo->virtual; |
switch (query->Base.Target) { |
case GL_TIME_ELAPSED_EXT: |
/* The query BO contains the starting and ending timestamps. |
* Subtract the two and convert to nanoseconds. |
*/ |
query->Base.Result += 1000 * ((results[1] >> 32) - (results[0] >> 32)); |
break; |
case GL_TIMESTAMP: |
/* The query BO contains a single timestamp value in results[0]. */ |
query->Base.Result = 1000 * (results[0] >> 32); |
break; |
case GL_SAMPLES_PASSED_ARB: |
/* Loop over pairs of values from the BO, which are the PS_DEPTH_COUNT |
* value at the start and end of the batchbuffer. Subtract them to |
* get the number of fragments which passed the depth test in each |
* individual batch, and add those differences up to get the number |
* of fragments for the entire query. |
* |
* Note that query->Base.Result may already be non-zero. We may have |
* run out of space in the query's BO and allocated a new one. If so, |
* this function was already called to accumulate the results so far. |
*/ |
for (i = 0; i < query->last_index; i++) { |
query->Base.Result += results[i * 2 + 1] - results[i * 2]; |
} |
break; |
case GL_ANY_SAMPLES_PASSED: |
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: |
/* If the starting and ending PS_DEPTH_COUNT from any of the batches |
* differ, then some fragments passed the depth test. |
*/ |
for (i = 0; i < query->last_index; i++) { |
if (results[i * 2 + 1] != results[i * 2]) { |
query->Base.Result = GL_TRUE; |
break; |
} |
} |
break; |
default: |
assert(!"Unrecognized query target in brw_queryobj_get_results()"); |
break; |
} |
drm_intel_bo_unmap(query->bo); |
/* Now that we've processed the data stored in the query's buffer object, |
* we can release it. |
*/ |
drm_intel_bo_unreference(query->bo); |
query->bo = NULL; |
} |
/** |
* The NewQueryObject() driver hook. |
* |
* Allocates and initializes a new query object. |
*/ |
static struct gl_query_object * |
brw_new_query_object(struct gl_context *ctx, GLuint id) |
{ |
struct brw_query_object *query; |
query = calloc(1, sizeof(struct brw_query_object)); |
query->Base.Id = id; |
query->Base.Result = 0; |
query->Base.Active = false; |
query->Base.Ready = true; |
return &query->Base; |
} |
/** |
* The DeleteQuery() driver hook. |
*/ |
static void |
brw_delete_query(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct brw_query_object *query = (struct brw_query_object *)q; |
drm_intel_bo_unreference(query->bo); |
free(query); |
} |
/** |
* Gen4-5 driver hook for glBeginQuery(). |
* |
* Initializes driver structures and emits any GPU commands required to begin |
* recording data for the query. |
*/ |
static void |
brw_begin_query(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct brw_query_object *query = (struct brw_query_object *)q; |
assert(brw->gen < 6); |
switch (query->Base.Target) { |
case GL_TIME_ELAPSED_EXT: |
/* For timestamp queries, we record the starting time right away so that |
* we measure the full time between BeginQuery and EndQuery. There's |
* some debate about whether this is the right thing to do. Our decision |
* is based on the following text from the ARB_timer_query extension: |
* |
* "(5) Should the extension measure total time elapsed between the full |
* completion of the BeginQuery and EndQuery commands, or just time |
* spent in the graphics library? |
* |
* RESOLVED: This extension will measure the total time elapsed |
* between the full completion of these commands. Future extensions |
* may implement a query to determine time elapsed at different stages |
* of the graphics pipeline." |
* |
* We write a starting timestamp now (at index 0). At EndQuery() time, |
* we'll write a second timestamp (at index 1), and subtract the two to |
* obtain the time elapsed. Notably, this includes time elapsed while |
* the system was doing other work, such as running other applications. |
*/ |
drm_intel_bo_unreference(query->bo); |
query->bo = drm_intel_bo_alloc(brw->bufmgr, "timer query", 4096, 4096); |
write_timestamp(brw, query->bo, 0); |
break; |
case GL_ANY_SAMPLES_PASSED: |
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: |
case GL_SAMPLES_PASSED_ARB: |
/* For occlusion queries, we delay taking an initial sample until the |
* first drawing occurs in this batch. See the reasoning in the comments |
* for brw_emit_query_begin() below. |
* |
* Since we're starting a new query, we need to be sure to throw away |
* any previous occlusion query results. |
*/ |
drm_intel_bo_unreference(query->bo); |
query->bo = NULL; |
query->last_index = -1; |
brw->query.obj = query; |
/* Depth statistics on Gen4 require strange workarounds, so we try to |
* avoid them when necessary. They're required for occlusion queries, |
* so turn them on now. |
*/ |
brw->stats_wm++; |
brw->state.dirty.brw |= BRW_NEW_STATS_WM; |
break; |
default: |
assert(!"Unrecognized query target in brw_begin_query()"); |
break; |
} |
} |
/** |
* Gen4-5 driver hook for glEndQuery(). |
* |
* Emits GPU commands to record a final query value, ending any data capturing. |
* However, the final result isn't necessarily available until the GPU processes |
* those commands. brw_queryobj_get_results() processes the captured data to |
* produce the final result. |
*/ |
static void |
brw_end_query(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct brw_query_object *query = (struct brw_query_object *)q; |
assert(brw->gen < 6); |
switch (query->Base.Target) { |
case GL_TIME_ELAPSED_EXT: |
/* Write the final timestamp. */ |
write_timestamp(brw, query->bo, 1); |
break; |
case GL_ANY_SAMPLES_PASSED: |
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: |
case GL_SAMPLES_PASSED_ARB: |
/* No query->bo means that EndQuery was called after BeginQuery with no |
* intervening drawing. Rather than doing nothing at all here in this |
* case, we emit the query_begin and query_end state to the |
* hardware. This is to guarantee that waiting on the result of this |
* empty state will cause all previous queries to complete at all, as |
* required by the specification: |
* |
* It must always be true that if any query object |
* returns a result available of TRUE, all queries of the |
* same type issued prior to that query must also return |
* TRUE. [Open GL 4.3 (Core Profile) Section 4.2.1] |
*/ |
if (!query->bo) { |
brw_emit_query_begin(brw); |
} |
assert(query->bo); |
brw_emit_query_end(brw); |
brw->query.obj = NULL; |
brw->stats_wm--; |
brw->state.dirty.brw |= BRW_NEW_STATS_WM; |
break; |
default: |
assert(!"Unrecognized query target in brw_end_query()"); |
break; |
} |
} |
/** |
* The Gen4-5 WaitQuery() driver hook. |
* |
* Wait for a query result to become available and return it. This is the |
* backing for glGetQueryObjectiv() with the GL_QUERY_RESULT pname. |
*/ |
static void brw_wait_query(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct brw_query_object *query = (struct brw_query_object *)q; |
assert(brw_context(ctx)->gen < 6); |
brw_queryobj_get_results(ctx, query); |
query->Base.Ready = true; |
} |
/** |
* The Gen4-5 CheckQuery() driver hook. |
* |
* Checks whether a query result is ready yet. If not, flushes. |
* This is the backing for glGetQueryObjectiv()'s QUERY_RESULT_AVAILABLE pname. |
*/ |
static void brw_check_query(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct brw_query_object *query = (struct brw_query_object *)q; |
assert(brw->gen < 6); |
/* From the GL_ARB_occlusion_query spec: |
* |
* "Instead of allowing for an infinite loop, performing a |
* QUERY_RESULT_AVAILABLE_ARB will perform a flush if the result is |
* not ready yet on the first time it is queried. This ensures that |
* the async query will return true in finite time. |
*/ |
if (query->bo && drm_intel_bo_references(brw->batch.bo, query->bo)) |
intel_batchbuffer_flush(brw); |
if (query->bo == NULL || !drm_intel_bo_busy(query->bo)) { |
brw_queryobj_get_results(ctx, query); |
query->Base.Ready = true; |
} |
} |
/** |
* Ensure there query's BO has enough space to store a new pair of values. |
* |
* If not, gather the existing BO's results and create a new buffer of the |
* same size. |
*/ |
static void |
ensure_bo_has_space(struct gl_context *ctx, struct brw_query_object *query) |
{ |
struct brw_context *brw = brw_context(ctx); |
assert(brw->gen < 6); |
if (!query->bo || query->last_index * 2 + 1 >= 4096 / sizeof(uint64_t)) { |
if (query->bo != NULL) { |
/* The old query BO did not have enough space, so we allocated a new |
* one. Gather the results so far (adding up the differences) and |
* release the old BO. |
*/ |
brw_queryobj_get_results(ctx, query); |
} |
query->bo = drm_intel_bo_alloc(brw->bufmgr, "query", 4096, 1); |
query->last_index = 0; |
} |
} |
/** |
* Record the PS_DEPTH_COUNT value (for occlusion queries) just before |
* primitive drawing. |
* |
* In a pre-hardware context world, the single PS_DEPTH_COUNT register is |
* shared among all applications using the GPU. However, our query value |
* needs to only include fragments generated by our application/GL context. |
* |
* To accommodate this, we record PS_DEPTH_COUNT at the start and end of |
* each batchbuffer (technically, the first primitive drawn and flush time). |
* Subtracting each pair of values calculates the change in PS_DEPTH_COUNT |
* caused by a batchbuffer. Since there is no preemption inside batches, |
* this is guaranteed to only measure the effects of our current application. |
* |
* Adding each of these differences (in case drawing is done over many batches) |
* produces the final expected value. |
* |
* In a world with hardware contexts, PS_DEPTH_COUNT is saved and restored |
* as part of the context state, so this is unnecessary, and skipped. |
*/ |
void |
brw_emit_query_begin(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_query_object *query = brw->query.obj; |
if (brw->hw_ctx) |
return; |
/* Skip if we're not doing any queries, or we've already recorded the |
* initial query value for this batchbuffer. |
*/ |
if (!query || brw->query.begin_emitted) |
return; |
ensure_bo_has_space(ctx, query); |
write_depth_count(brw, query->bo, query->last_index * 2); |
brw->query.begin_emitted = true; |
} |
/** |
* Called at batchbuffer flush to get an ending PS_DEPTH_COUNT |
* (for non-hardware context platforms). |
* |
* See the explanation in brw_emit_query_begin(). |
*/ |
void |
brw_emit_query_end(struct brw_context *brw) |
{ |
struct brw_query_object *query = brw->query.obj; |
if (brw->hw_ctx) |
return; |
if (!brw->query.begin_emitted) |
return; |
write_depth_count(brw, query->bo, query->last_index * 2 + 1); |
brw->query.begin_emitted = false; |
query->last_index++; |
} |
/** |
* Driver hook for glQueryCounter(). |
* |
* This handles GL_TIMESTAMP queries, which perform a pipelined read of the |
* current GPU time. This is unlike GL_TIME_ELAPSED, which measures the |
* time while the query is active. |
*/ |
static void |
brw_query_counter(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct brw_query_object *query = (struct brw_query_object *) q; |
assert(q->Target == GL_TIMESTAMP); |
drm_intel_bo_unreference(query->bo); |
query->bo = drm_intel_bo_alloc(brw->bufmgr, "timestamp query", 4096, 4096); |
write_timestamp(brw, query->bo, 0); |
} |
/** |
* Read the TIMESTAMP register immediately (in a non-pipelined fashion). |
* |
* This is used to implement the GetTimestamp() driver hook. |
*/ |
static uint64_t |
brw_get_timestamp(struct gl_context *ctx) |
{ |
struct brw_context *brw = brw_context(ctx); |
uint64_t result = 0; |
drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &result); |
/* See logic in brw_queryobj_get_results() */ |
result = result >> 32; |
result *= 80; |
result &= (1ull << 36) - 1; |
return result; |
} |
/* Initialize query object functions used on all generations. */ |
void brw_init_common_queryobj_functions(struct dd_function_table *functions) |
{ |
functions->NewQueryObject = brw_new_query_object; |
functions->DeleteQuery = brw_delete_query; |
functions->QueryCounter = brw_query_counter; |
functions->GetTimestamp = brw_get_timestamp; |
} |
/* Initialize Gen4/5-specific query object functions. */ |
void gen4_init_queryobj_functions(struct dd_function_table *functions) |
{ |
functions->BeginQuery = brw_begin_query; |
functions->EndQuery = brw_end_query; |
functions->CheckQuery = brw_check_query; |
functions->WaitQuery = brw_wait_query; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_reg.h |
---|
0,0 → 1,785 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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> |
*/ |
/** @file brw_reg.h |
* |
* This file defines struct brw_reg, which is our representation for EU |
* registers. They're not a hardware specific format, just an abstraction |
* that intends to capture the full flexibility of the hardware registers. |
* |
* The brw_eu_emit.c layer's brw_set_dest/brw_set_src[01] functions encode |
* the abstract brw_reg type into the actual hardware instruction encoding. |
*/ |
#ifndef BRW_REG_H |
#define BRW_REG_H |
#include <stdbool.h> |
#include "program/prog_instruction.h" |
#include "brw_defines.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
/** Number of general purpose registers (VS, WM, etc) */ |
#define BRW_MAX_GRF 128 |
/** |
* First GRF used for the MRF hack. |
* |
* On gen7, MRFs are no longer used, and contiguous GRFs are used instead. We |
* haven't converted our compiler to be aware of this, so it asks for MRFs and |
* brw_eu_emit.c quietly converts them to be accesses of the top GRFs. The |
* register allocators have to be careful of this to avoid corrupting the "MRF"s |
* with actual GRF allocations. |
*/ |
#define GEN7_MRF_HACK_START 112 |
/** Number of message register file registers */ |
#define BRW_MAX_MRF 16 |
#define BRW_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6)) |
#define BRW_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3) |
#define BRW_SWIZZLE_NOOP BRW_SWIZZLE4(0,1,2,3) |
#define BRW_SWIZZLE_XYZW BRW_SWIZZLE4(0,1,2,3) |
#define BRW_SWIZZLE_XXXX BRW_SWIZZLE4(0,0,0,0) |
#define BRW_SWIZZLE_YYYY BRW_SWIZZLE4(1,1,1,1) |
#define BRW_SWIZZLE_ZZZZ BRW_SWIZZLE4(2,2,2,2) |
#define BRW_SWIZZLE_WWWW BRW_SWIZZLE4(3,3,3,3) |
#define BRW_SWIZZLE_XYXY BRW_SWIZZLE4(0,1,0,1) |
static inline bool |
brw_is_single_value_swizzle(int swiz) |
{ |
return (swiz == BRW_SWIZZLE_XXXX || |
swiz == BRW_SWIZZLE_YYYY || |
swiz == BRW_SWIZZLE_ZZZZ || |
swiz == BRW_SWIZZLE_WWWW); |
} |
#define REG_SIZE (8*4) |
/* These aren't hardware structs, just something useful for us to pass around: |
* |
* Align1 operation has a lot of control over input ranges. Used in |
* WM programs to implement shaders decomposed into "channel serial" |
* or "structure of array" form: |
*/ |
struct brw_reg { |
unsigned type:4; |
unsigned file:2; |
unsigned nr:8; |
unsigned subnr:5; /* :1 in align16 */ |
unsigned negate:1; /* source only */ |
unsigned abs:1; /* source only */ |
unsigned vstride:4; /* source only */ |
unsigned width:3; /* src only, align1 only */ |
unsigned hstride:2; /* align1 only */ |
unsigned address_mode:1; /* relative addressing, hopefully! */ |
unsigned pad0:1; |
union { |
struct { |
unsigned swizzle:8; /* src only, align16 only */ |
unsigned writemask:4; /* dest only, align16 only */ |
int indirect_offset:10; /* relative addressing offset */ |
unsigned pad1:10; /* two dwords total */ |
} bits; |
float f; |
int d; |
unsigned ud; |
} dw1; |
}; |
struct brw_indirect { |
unsigned addr_subnr:4; |
int addr_offset:10; |
unsigned pad:18; |
}; |
static inline int |
type_sz(unsigned type) |
{ |
switch(type) { |
case BRW_REGISTER_TYPE_UD: |
case BRW_REGISTER_TYPE_D: |
case BRW_REGISTER_TYPE_F: |
return 4; |
case BRW_REGISTER_TYPE_HF: |
case BRW_REGISTER_TYPE_UW: |
case BRW_REGISTER_TYPE_W: |
return 2; |
case BRW_REGISTER_TYPE_UB: |
case BRW_REGISTER_TYPE_B: |
return 1; |
default: |
return 0; |
} |
} |
/** |
* Construct a brw_reg. |
* \param file one of the BRW_x_REGISTER_FILE values |
* \param nr register number/index |
* \param subnr register sub number |
* \param type one of BRW_REGISTER_TYPE_x |
* \param vstride one of BRW_VERTICAL_STRIDE_x |
* \param width one of BRW_WIDTH_x |
* \param hstride one of BRW_HORIZONTAL_STRIDE_x |
* \param swizzle one of BRW_SWIZZLE_x |
* \param writemask WRITEMASK_X/Y/Z/W bitfield |
*/ |
static inline struct brw_reg |
brw_reg(unsigned file, |
unsigned nr, |
unsigned subnr, |
unsigned type, |
unsigned vstride, |
unsigned width, |
unsigned hstride, |
unsigned swizzle, |
unsigned writemask) |
{ |
struct brw_reg reg; |
if (file == BRW_GENERAL_REGISTER_FILE) |
assert(nr < BRW_MAX_GRF); |
else if (file == BRW_MESSAGE_REGISTER_FILE) |
assert((nr & ~(1 << 7)) < BRW_MAX_MRF); |
else if (file == BRW_ARCHITECTURE_REGISTER_FILE) |
assert(nr <= BRW_ARF_TIMESTAMP); |
reg.type = type; |
reg.file = file; |
reg.nr = nr; |
reg.subnr = subnr * type_sz(type); |
reg.negate = 0; |
reg.abs = 0; |
reg.vstride = vstride; |
reg.width = width; |
reg.hstride = hstride; |
reg.address_mode = BRW_ADDRESS_DIRECT; |
reg.pad0 = 0; |
/* Could do better: If the reg is r5.3<0;1,0>, we probably want to |
* set swizzle and writemask to W, as the lower bits of subnr will |
* be lost when converted to align16. This is probably too much to |
* keep track of as you'd want it adjusted by suboffset(), etc. |
* Perhaps fix up when converting to align16? |
*/ |
reg.dw1.bits.swizzle = swizzle; |
reg.dw1.bits.writemask = writemask; |
reg.dw1.bits.indirect_offset = 0; |
reg.dw1.bits.pad1 = 0; |
return reg; |
} |
/** Construct float[16] register */ |
static inline struct brw_reg |
brw_vec16_reg(unsigned file, unsigned nr, unsigned subnr) |
{ |
return brw_reg(file, |
nr, |
subnr, |
BRW_REGISTER_TYPE_F, |
BRW_VERTICAL_STRIDE_16, |
BRW_WIDTH_16, |
BRW_HORIZONTAL_STRIDE_1, |
BRW_SWIZZLE_XYZW, |
WRITEMASK_XYZW); |
} |
/** Construct float[8] register */ |
static inline struct brw_reg |
brw_vec8_reg(unsigned file, unsigned nr, unsigned subnr) |
{ |
return brw_reg(file, |
nr, |
subnr, |
BRW_REGISTER_TYPE_F, |
BRW_VERTICAL_STRIDE_8, |
BRW_WIDTH_8, |
BRW_HORIZONTAL_STRIDE_1, |
BRW_SWIZZLE_XYZW, |
WRITEMASK_XYZW); |
} |
/** Construct float[4] register */ |
static inline struct brw_reg |
brw_vec4_reg(unsigned file, unsigned nr, unsigned subnr) |
{ |
return brw_reg(file, |
nr, |
subnr, |
BRW_REGISTER_TYPE_F, |
BRW_VERTICAL_STRIDE_4, |
BRW_WIDTH_4, |
BRW_HORIZONTAL_STRIDE_1, |
BRW_SWIZZLE_XYZW, |
WRITEMASK_XYZW); |
} |
/** Construct float[2] register */ |
static inline struct brw_reg |
brw_vec2_reg(unsigned file, unsigned nr, unsigned subnr) |
{ |
return brw_reg(file, |
nr, |
subnr, |
BRW_REGISTER_TYPE_F, |
BRW_VERTICAL_STRIDE_2, |
BRW_WIDTH_2, |
BRW_HORIZONTAL_STRIDE_1, |
BRW_SWIZZLE_XYXY, |
WRITEMASK_XY); |
} |
/** Construct float[1] register */ |
static inline struct brw_reg |
brw_vec1_reg(unsigned file, unsigned nr, unsigned subnr) |
{ |
return brw_reg(file, |
nr, |
subnr, |
BRW_REGISTER_TYPE_F, |
BRW_VERTICAL_STRIDE_0, |
BRW_WIDTH_1, |
BRW_HORIZONTAL_STRIDE_0, |
BRW_SWIZZLE_XXXX, |
WRITEMASK_X); |
} |
static inline struct brw_reg |
retype(struct brw_reg reg, unsigned type) |
{ |
reg.type = type; |
return reg; |
} |
static inline struct brw_reg |
sechalf(struct brw_reg reg) |
{ |
if (reg.vstride) |
reg.nr++; |
return reg; |
} |
static inline struct brw_reg |
suboffset(struct brw_reg reg, unsigned delta) |
{ |
reg.subnr += delta * type_sz(reg.type); |
return reg; |
} |
static inline struct brw_reg |
offset(struct brw_reg reg, unsigned delta) |
{ |
reg.nr += delta; |
return reg; |
} |
static inline struct brw_reg |
byte_offset(struct brw_reg reg, unsigned bytes) |
{ |
unsigned newoffset = reg.nr * REG_SIZE + reg.subnr + bytes; |
reg.nr = newoffset / REG_SIZE; |
reg.subnr = newoffset % REG_SIZE; |
return reg; |
} |
/** Construct unsigned word[16] register */ |
static inline struct brw_reg |
brw_uw16_reg(unsigned file, unsigned nr, unsigned subnr) |
{ |
return suboffset(retype(brw_vec16_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr); |
} |
/** Construct unsigned word[8] register */ |
static inline struct brw_reg |
brw_uw8_reg(unsigned file, unsigned nr, unsigned subnr) |
{ |
return suboffset(retype(brw_vec8_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr); |
} |
/** Construct unsigned word[1] register */ |
static inline struct brw_reg |
brw_uw1_reg(unsigned file, unsigned nr, unsigned subnr) |
{ |
return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr); |
} |
static inline struct brw_reg |
brw_imm_reg(unsigned type) |
{ |
return brw_reg(BRW_IMMEDIATE_VALUE, |
0, |
0, |
type, |
BRW_VERTICAL_STRIDE_0, |
BRW_WIDTH_1, |
BRW_HORIZONTAL_STRIDE_0, |
0, |
0); |
} |
/** Construct float immediate register */ |
static inline struct brw_reg |
brw_imm_f(float f) |
{ |
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F); |
imm.dw1.f = f; |
return imm; |
} |
/** Construct integer immediate register */ |
static inline struct brw_reg |
brw_imm_d(int d) |
{ |
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D); |
imm.dw1.d = d; |
return imm; |
} |
/** Construct uint immediate register */ |
static inline struct brw_reg |
brw_imm_ud(unsigned ud) |
{ |
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD); |
imm.dw1.ud = ud; |
return imm; |
} |
/** Construct ushort immediate register */ |
static inline struct brw_reg |
brw_imm_uw(uint16_t uw) |
{ |
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW); |
imm.dw1.ud = uw | (uw << 16); |
return imm; |
} |
/** Construct short immediate register */ |
static inline struct brw_reg |
brw_imm_w(int16_t w) |
{ |
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W); |
imm.dw1.d = w | (w << 16); |
return imm; |
} |
/* brw_imm_b and brw_imm_ub aren't supported by hardware - the type |
* numbers alias with _V and _VF below: |
*/ |
/** Construct vector of eight signed half-byte values */ |
static inline struct brw_reg |
brw_imm_v(unsigned v) |
{ |
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V); |
imm.vstride = BRW_VERTICAL_STRIDE_0; |
imm.width = BRW_WIDTH_8; |
imm.hstride = BRW_HORIZONTAL_STRIDE_1; |
imm.dw1.ud = v; |
return imm; |
} |
/** Construct vector of four 8-bit float values */ |
static inline struct brw_reg |
brw_imm_vf(unsigned v) |
{ |
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF); |
imm.vstride = BRW_VERTICAL_STRIDE_0; |
imm.width = BRW_WIDTH_4; |
imm.hstride = BRW_HORIZONTAL_STRIDE_1; |
imm.dw1.ud = v; |
return imm; |
} |
#define VF_ZERO 0x0 |
#define VF_ONE 0x30 |
#define VF_NEG (1<<7) |
static inline struct brw_reg |
brw_imm_vf4(unsigned v0, unsigned v1, unsigned v2, unsigned v3) |
{ |
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF); |
imm.vstride = BRW_VERTICAL_STRIDE_0; |
imm.width = BRW_WIDTH_4; |
imm.hstride = BRW_HORIZONTAL_STRIDE_1; |
imm.dw1.ud = ((v0 << 0) | (v1 << 8) | (v2 << 16) | (v3 << 24)); |
return imm; |
} |
static inline struct brw_reg |
brw_address(struct brw_reg reg) |
{ |
return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr); |
} |
/** Construct float[1] general-purpose register */ |
static inline struct brw_reg |
brw_vec1_grf(unsigned nr, unsigned subnr) |
{ |
return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); |
} |
/** Construct float[2] general-purpose register */ |
static inline struct brw_reg |
brw_vec2_grf(unsigned nr, unsigned subnr) |
{ |
return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); |
} |
/** Construct float[4] general-purpose register */ |
static inline struct brw_reg |
brw_vec4_grf(unsigned nr, unsigned subnr) |
{ |
return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); |
} |
/** Construct float[8] general-purpose register */ |
static inline struct brw_reg |
brw_vec8_grf(unsigned nr, unsigned subnr) |
{ |
return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); |
} |
static inline struct brw_reg |
brw_uw8_grf(unsigned nr, unsigned subnr) |
{ |
return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); |
} |
static inline struct brw_reg |
brw_uw16_grf(unsigned nr, unsigned subnr) |
{ |
return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); |
} |
/** Construct null register (usually used for setting condition codes) */ |
static inline struct brw_reg |
brw_null_reg(void) |
{ |
return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0); |
} |
static inline struct brw_reg |
brw_address_reg(unsigned subnr) |
{ |
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_ADDRESS, subnr); |
} |
/* If/else instructions break in align16 mode if writemask & swizzle |
* aren't xyzw. This goes against the convention for other scalar |
* regs: |
*/ |
static inline struct brw_reg |
brw_ip_reg(void) |
{ |
return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE, |
BRW_ARF_IP, |
0, |
BRW_REGISTER_TYPE_UD, |
BRW_VERTICAL_STRIDE_4, /* ? */ |
BRW_WIDTH_1, |
BRW_HORIZONTAL_STRIDE_0, |
BRW_SWIZZLE_XYZW, /* NOTE! */ |
WRITEMASK_XYZW); /* NOTE! */ |
} |
static inline struct brw_reg |
brw_acc_reg(void) |
{ |
return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_ACCUMULATOR, 0); |
} |
static inline struct brw_reg |
brw_notification_1_reg(void) |
{ |
return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE, |
BRW_ARF_NOTIFICATION_COUNT, |
1, |
BRW_REGISTER_TYPE_UD, |
BRW_VERTICAL_STRIDE_0, |
BRW_WIDTH_1, |
BRW_HORIZONTAL_STRIDE_0, |
BRW_SWIZZLE_XXXX, |
WRITEMASK_X); |
} |
static inline struct brw_reg |
brw_flag_reg(int reg, int subreg) |
{ |
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, |
BRW_ARF_FLAG + reg, subreg); |
} |
static inline struct brw_reg |
brw_mask_reg(unsigned subnr) |
{ |
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_MASK, subnr); |
} |
static inline struct brw_reg |
brw_message_reg(unsigned nr) |
{ |
assert((nr & ~(1 << 7)) < BRW_MAX_MRF); |
return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, nr, 0); |
} |
/* This is almost always called with a numeric constant argument, so |
* make things easy to evaluate at compile time: |
*/ |
static inline unsigned cvt(unsigned val) |
{ |
switch (val) { |
case 0: return 0; |
case 1: return 1; |
case 2: return 2; |
case 4: return 3; |
case 8: return 4; |
case 16: return 5; |
case 32: return 6; |
} |
return 0; |
} |
static inline struct brw_reg |
stride(struct brw_reg reg, unsigned vstride, unsigned width, unsigned hstride) |
{ |
reg.vstride = cvt(vstride); |
reg.width = cvt(width) - 1; |
reg.hstride = cvt(hstride); |
return reg; |
} |
static inline struct brw_reg |
vec16(struct brw_reg reg) |
{ |
return stride(reg, 16,16,1); |
} |
static inline struct brw_reg |
vec8(struct brw_reg reg) |
{ |
return stride(reg, 8,8,1); |
} |
static inline struct brw_reg |
vec4(struct brw_reg reg) |
{ |
return stride(reg, 4,4,1); |
} |
static inline struct brw_reg |
vec2(struct brw_reg reg) |
{ |
return stride(reg, 2,2,1); |
} |
static inline struct brw_reg |
vec1(struct brw_reg reg) |
{ |
return stride(reg, 0,1,0); |
} |
static inline struct brw_reg |
get_element(struct brw_reg reg, unsigned elt) |
{ |
return vec1(suboffset(reg, elt)); |
} |
static inline struct brw_reg |
get_element_ud(struct brw_reg reg, unsigned elt) |
{ |
return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_UD), elt)); |
} |
static inline struct brw_reg |
get_element_d(struct brw_reg reg, unsigned elt) |
{ |
return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_D), elt)); |
} |
static inline struct brw_reg |
brw_swizzle(struct brw_reg reg, unsigned x, unsigned y, unsigned z, unsigned w) |
{ |
assert(reg.file != BRW_IMMEDIATE_VALUE); |
reg.dw1.bits.swizzle = BRW_SWIZZLE4(BRW_GET_SWZ(reg.dw1.bits.swizzle, x), |
BRW_GET_SWZ(reg.dw1.bits.swizzle, y), |
BRW_GET_SWZ(reg.dw1.bits.swizzle, z), |
BRW_GET_SWZ(reg.dw1.bits.swizzle, w)); |
return reg; |
} |
static inline struct brw_reg |
brw_swizzle1(struct brw_reg reg, unsigned x) |
{ |
return brw_swizzle(reg, x, x, x, x); |
} |
static inline struct brw_reg |
brw_writemask(struct brw_reg reg, unsigned mask) |
{ |
assert(reg.file != BRW_IMMEDIATE_VALUE); |
reg.dw1.bits.writemask &= mask; |
return reg; |
} |
static inline struct brw_reg |
brw_set_writemask(struct brw_reg reg, unsigned mask) |
{ |
assert(reg.file != BRW_IMMEDIATE_VALUE); |
reg.dw1.bits.writemask = mask; |
return reg; |
} |
static inline struct brw_reg |
negate(struct brw_reg reg) |
{ |
reg.negate ^= 1; |
return reg; |
} |
static inline struct brw_reg |
brw_abs(struct brw_reg reg) |
{ |
reg.abs = 1; |
reg.negate = 0; |
return reg; |
} |
/************************************************************************/ |
static inline struct brw_reg |
brw_vec4_indirect(unsigned subnr, int offset) |
{ |
struct brw_reg reg = brw_vec4_grf(0, 0); |
reg.subnr = subnr; |
reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; |
reg.dw1.bits.indirect_offset = offset; |
return reg; |
} |
static inline struct brw_reg |
brw_vec1_indirect(unsigned subnr, int offset) |
{ |
struct brw_reg reg = brw_vec1_grf(0, 0); |
reg.subnr = subnr; |
reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; |
reg.dw1.bits.indirect_offset = offset; |
return reg; |
} |
static inline struct brw_reg |
deref_4f(struct brw_indirect ptr, int offset) |
{ |
return brw_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset); |
} |
static inline struct brw_reg |
deref_1f(struct brw_indirect ptr, int offset) |
{ |
return brw_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset); |
} |
static inline struct brw_reg |
deref_4b(struct brw_indirect ptr, int offset) |
{ |
return retype(deref_4f(ptr, offset), BRW_REGISTER_TYPE_B); |
} |
static inline struct brw_reg |
deref_1uw(struct brw_indirect ptr, int offset) |
{ |
return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UW); |
} |
static inline struct brw_reg |
deref_1d(struct brw_indirect ptr, int offset) |
{ |
return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_D); |
} |
static inline struct brw_reg |
deref_1ud(struct brw_indirect ptr, int offset) |
{ |
return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UD); |
} |
static inline struct brw_reg |
get_addr_reg(struct brw_indirect ptr) |
{ |
return brw_address_reg(ptr.addr_subnr); |
} |
static inline struct brw_indirect |
brw_indirect_offset(struct brw_indirect ptr, int offset) |
{ |
ptr.addr_offset += offset; |
return ptr; |
} |
static inline struct brw_indirect |
brw_indirect(unsigned addr_subnr, int offset) |
{ |
struct brw_indirect ptr; |
ptr.addr_subnr = addr_subnr; |
ptr.addr_offset = offset; |
ptr.pad = 0; |
return ptr; |
} |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_schedule_instructions.cpp |
---|
0,0 → 1,1155 |
/* |
* Copyright © 2010 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_fs.h" |
#include "brw_vec4.h" |
#include "glsl/glsl_types.h" |
#include "glsl/ir_optimization.h" |
using namespace brw; |
/** @file brw_fs_schedule_instructions.cpp |
* |
* List scheduling of FS instructions. |
* |
* The basic model of the list scheduler is to take a basic block, |
* compute a DAG of the dependencies (RAW ordering with latency, WAW |
* ordering with latency, WAR ordering), and make a list of the DAG heads. |
* Heuristically pick a DAG head, then put all the children that are |
* now DAG heads into the list of things to schedule. |
* |
* The heuristic is the important part. We're trying to be cheap, |
* since actually computing the optimal scheduling is NP complete. |
* What we do is track a "current clock". When we schedule a node, we |
* update the earliest-unblocked clock time of its children, and |
* increment the clock. Then, when trying to schedule, we just pick |
* the earliest-unblocked instruction to schedule. |
* |
* Note that often there will be many things which could execute |
* immediately, and there are a range of heuristic options to choose |
* from in picking among those. |
*/ |
static bool debug = false; |
class schedule_node : public exec_node |
{ |
public: |
schedule_node(backend_instruction *inst, const struct brw_context *brw) |
{ |
this->inst = inst; |
this->child_array_size = 0; |
this->children = NULL; |
this->child_latency = NULL; |
this->child_count = 0; |
this->parent_count = 0; |
this->unblocked_time = 0; |
/* We can't measure Gen6 timings directly but expect them to be much |
* closer to Gen7 than Gen4. |
*/ |
if (brw->gen >= 6) |
set_latency_gen7(brw->is_haswell); |
else |
set_latency_gen4(); |
} |
void set_latency_gen4(); |
void set_latency_gen7(bool is_haswell); |
backend_instruction *inst; |
schedule_node **children; |
int *child_latency; |
int child_count; |
int parent_count; |
int child_array_size; |
int unblocked_time; |
int latency; |
}; |
void |
schedule_node::set_latency_gen4() |
{ |
int chans = 8; |
int math_latency = 22; |
switch (inst->opcode) { |
case SHADER_OPCODE_RCP: |
this->latency = 1 * chans * math_latency; |
break; |
case SHADER_OPCODE_RSQ: |
this->latency = 2 * chans * math_latency; |
break; |
case SHADER_OPCODE_INT_QUOTIENT: |
case SHADER_OPCODE_SQRT: |
case SHADER_OPCODE_LOG2: |
/* full precision log. partial is 2. */ |
this->latency = 3 * chans * math_latency; |
break; |
case SHADER_OPCODE_INT_REMAINDER: |
case SHADER_OPCODE_EXP2: |
/* full precision. partial is 3, same throughput. */ |
this->latency = 4 * chans * math_latency; |
break; |
case SHADER_OPCODE_POW: |
this->latency = 8 * chans * math_latency; |
break; |
case SHADER_OPCODE_SIN: |
case SHADER_OPCODE_COS: |
/* minimum latency, max is 12 rounds. */ |
this->latency = 5 * chans * math_latency; |
break; |
default: |
this->latency = 2; |
break; |
} |
} |
void |
schedule_node::set_latency_gen7(bool is_haswell) |
{ |
switch (inst->opcode) { |
case BRW_OPCODE_MAD: |
/* 2 cycles |
* (since the last two src operands are in different register banks): |
* mad(8) g4<1>F g2.2<4,1,1>F.x g2<4,1,1>F.x g3.1<4,1,1>F.x { align16 WE_normal 1Q }; |
* |
* 3 cycles on IVB, 4 on HSW |
* (since the last two src operands are in the same register bank): |
* mad(8) g4<1>F g2.2<4,1,1>F.x g2<4,1,1>F.x g2.1<4,1,1>F.x { align16 WE_normal 1Q }; |
* |
* 18 cycles on IVB, 16 on HSW |
* (since the last two src operands are in different register banks): |
* mad(8) g4<1>F g2.2<4,1,1>F.x g2<4,1,1>F.x g3.1<4,1,1>F.x { align16 WE_normal 1Q }; |
* mov(8) null g4<4,5,1>F { align16 WE_normal 1Q }; |
* |
* 20 cycles on IVB, 18 on HSW |
* (since the last two src operands are in the same register bank): |
* mad(8) g4<1>F g2.2<4,1,1>F.x g2<4,1,1>F.x g2.1<4,1,1>F.x { align16 WE_normal 1Q }; |
* mov(8) null g4<4,4,1>F { align16 WE_normal 1Q }; |
*/ |
/* Our register allocator doesn't know about register banks, so use the |
* higher latency. |
*/ |
latency = is_haswell ? 16 : 18; |
break; |
case BRW_OPCODE_LRP: |
/* 2 cycles |
* (since the last two src operands are in different register banks): |
* lrp(8) g4<1>F g2.2<4,1,1>F.x g2<4,1,1>F.x g3.1<4,1,1>F.x { align16 WE_normal 1Q }; |
* |
* 3 cycles on IVB, 4 on HSW |
* (since the last two src operands are in the same register bank): |
* lrp(8) g4<1>F g2.2<4,1,1>F.x g2<4,1,1>F.x g2.1<4,1,1>F.x { align16 WE_normal 1Q }; |
* |
* 16 cycles on IVB, 14 on HSW |
* (since the last two src operands are in different register banks): |
* lrp(8) g4<1>F g2.2<4,1,1>F.x g2<4,1,1>F.x g3.1<4,1,1>F.x { align16 WE_normal 1Q }; |
* mov(8) null g4<4,4,1>F { align16 WE_normal 1Q }; |
* |
* 16 cycles |
* (since the last two src operands are in the same register bank): |
* lrp(8) g4<1>F g2.2<4,1,1>F.x g2<4,1,1>F.x g2.1<4,1,1>F.x { align16 WE_normal 1Q }; |
* mov(8) null g4<4,4,1>F { align16 WE_normal 1Q }; |
*/ |
/* Our register allocator doesn't know about register banks, so use the |
* higher latency. |
*/ |
latency = 14; |
break; |
case SHADER_OPCODE_RCP: |
case SHADER_OPCODE_RSQ: |
case SHADER_OPCODE_SQRT: |
case SHADER_OPCODE_LOG2: |
case SHADER_OPCODE_EXP2: |
case SHADER_OPCODE_SIN: |
case SHADER_OPCODE_COS: |
/* 2 cycles: |
* math inv(8) g4<1>F g2<0,1,0>F null { align1 WE_normal 1Q }; |
* |
* 18 cycles: |
* math inv(8) g4<1>F g2<0,1,0>F null { align1 WE_normal 1Q }; |
* mov(8) null g4<8,8,1>F { align1 WE_normal 1Q }; |
* |
* Same for exp2, log2, rsq, sqrt, sin, cos. |
*/ |
latency = is_haswell ? 14 : 16; |
break; |
case SHADER_OPCODE_POW: |
/* 2 cycles: |
* math pow(8) g4<1>F g2<0,1,0>F g2.1<0,1,0>F { align1 WE_normal 1Q }; |
* |
* 26 cycles: |
* math pow(8) g4<1>F g2<0,1,0>F g2.1<0,1,0>F { align1 WE_normal 1Q }; |
* mov(8) null g4<8,8,1>F { align1 WE_normal 1Q }; |
*/ |
latency = is_haswell ? 22 : 24; |
break; |
case SHADER_OPCODE_TEX: |
case SHADER_OPCODE_TXD: |
case SHADER_OPCODE_TXF: |
case SHADER_OPCODE_TXL: |
/* 18 cycles: |
* mov(8) g115<1>F 0F { align1 WE_normal 1Q }; |
* mov(8) g114<1>F 0F { align1 WE_normal 1Q }; |
* send(8) g4<1>UW g114<8,8,1>F |
* sampler (10, 0, 0, 1) mlen 2 rlen 4 { align1 WE_normal 1Q }; |
* |
* 697 +/-49 cycles (min 610, n=26): |
* mov(8) g115<1>F 0F { align1 WE_normal 1Q }; |
* mov(8) g114<1>F 0F { align1 WE_normal 1Q }; |
* send(8) g4<1>UW g114<8,8,1>F |
* sampler (10, 0, 0, 1) mlen 2 rlen 4 { align1 WE_normal 1Q }; |
* mov(8) null g4<8,8,1>F { align1 WE_normal 1Q }; |
* |
* So the latency on our first texture load of the batchbuffer takes |
* ~700 cycles, since the caches are cold at that point. |
* |
* 840 +/- 92 cycles (min 720, n=25): |
* mov(8) g115<1>F 0F { align1 WE_normal 1Q }; |
* mov(8) g114<1>F 0F { align1 WE_normal 1Q }; |
* send(8) g4<1>UW g114<8,8,1>F |
* sampler (10, 0, 0, 1) mlen 2 rlen 4 { align1 WE_normal 1Q }; |
* mov(8) null g4<8,8,1>F { align1 WE_normal 1Q }; |
* send(8) g4<1>UW g114<8,8,1>F |
* sampler (10, 0, 0, 1) mlen 2 rlen 4 { align1 WE_normal 1Q }; |
* mov(8) null g4<8,8,1>F { align1 WE_normal 1Q }; |
* |
* On the second load, it takes just an extra ~140 cycles, and after |
* accounting for the 14 cycles of the MOV's latency, that makes ~130. |
* |
* 683 +/- 49 cycles (min = 602, n=47): |
* mov(8) g115<1>F 0F { align1 WE_normal 1Q }; |
* mov(8) g114<1>F 0F { align1 WE_normal 1Q }; |
* send(8) g4<1>UW g114<8,8,1>F |
* sampler (10, 0, 0, 1) mlen 2 rlen 4 { align1 WE_normal 1Q }; |
* send(8) g50<1>UW g114<8,8,1>F |
* sampler (10, 0, 0, 1) mlen 2 rlen 4 { align1 WE_normal 1Q }; |
* mov(8) null g4<8,8,1>F { align1 WE_normal 1Q }; |
* |
* The unit appears to be pipelined, since this matches up with the |
* cache-cold case, despite there being two loads here. If you replace |
* the g4 in the MOV to null with g50, it's still 693 +/- 52 (n=39). |
* |
* So, take some number between the cache-hot 140 cycles and the |
* cache-cold 700 cycles. No particular tuning was done on this. |
* |
* I haven't done significant testing of the non-TEX opcodes. TXL at |
* least looked about the same as TEX. |
*/ |
latency = 200; |
break; |
case SHADER_OPCODE_TXS: |
/* Testing textureSize(sampler2D, 0), one load was 420 +/- 41 |
* cycles (n=15): |
* mov(8) g114<1>UD 0D { align1 WE_normal 1Q }; |
* send(8) g6<1>UW g114<8,8,1>F |
* sampler (10, 0, 10, 1) mlen 1 rlen 4 { align1 WE_normal 1Q }; |
* mov(16) g6<1>F g6<8,8,1>D { align1 WE_normal 1Q }; |
* |
* |
* Two loads was 535 +/- 30 cycles (n=19): |
* mov(16) g114<1>UD 0D { align1 WE_normal 1H }; |
* send(16) g6<1>UW g114<8,8,1>F |
* sampler (10, 0, 10, 2) mlen 2 rlen 8 { align1 WE_normal 1H }; |
* mov(16) g114<1>UD 0D { align1 WE_normal 1H }; |
* mov(16) g6<1>F g6<8,8,1>D { align1 WE_normal 1H }; |
* send(16) g8<1>UW g114<8,8,1>F |
* sampler (10, 0, 10, 2) mlen 2 rlen 8 { align1 WE_normal 1H }; |
* mov(16) g8<1>F g8<8,8,1>D { align1 WE_normal 1H }; |
* add(16) g6<1>F g6<8,8,1>F g8<8,8,1>F { align1 WE_normal 1H }; |
* |
* Since the only caches that should matter are just the |
* instruction/state cache containing the surface state, assume that we |
* always have hot caches. |
*/ |
latency = 100; |
break; |
case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD: |
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD: |
case VS_OPCODE_PULL_CONSTANT_LOAD: |
/* testing using varying-index pull constants: |
* |
* 16 cycles: |
* mov(8) g4<1>D g2.1<0,1,0>F { align1 WE_normal 1Q }; |
* send(8) g4<1>F g4<8,8,1>D |
* data (9, 2, 3) mlen 1 rlen 1 { align1 WE_normal 1Q }; |
* |
* ~480 cycles: |
* mov(8) g4<1>D g2.1<0,1,0>F { align1 WE_normal 1Q }; |
* send(8) g4<1>F g4<8,8,1>D |
* data (9, 2, 3) mlen 1 rlen 1 { align1 WE_normal 1Q }; |
* mov(8) null g4<8,8,1>F { align1 WE_normal 1Q }; |
* |
* ~620 cycles: |
* mov(8) g4<1>D g2.1<0,1,0>F { align1 WE_normal 1Q }; |
* send(8) g4<1>F g4<8,8,1>D |
* data (9, 2, 3) mlen 1 rlen 1 { align1 WE_normal 1Q }; |
* mov(8) null g4<8,8,1>F { align1 WE_normal 1Q }; |
* send(8) g4<1>F g4<8,8,1>D |
* data (9, 2, 3) mlen 1 rlen 1 { align1 WE_normal 1Q }; |
* mov(8) null g4<8,8,1>F { align1 WE_normal 1Q }; |
* |
* So, if it's cache-hot, it's about 140. If it's cache cold, it's |
* about 460. We expect to mostly be cache hot, so pick something more |
* in that direction. |
*/ |
latency = 200; |
break; |
default: |
/* 2 cycles: |
* mul(8) g4<1>F g2<0,1,0>F 0.5F { align1 WE_normal 1Q }; |
* |
* 16 cycles: |
* mul(8) g4<1>F g2<0,1,0>F 0.5F { align1 WE_normal 1Q }; |
* mov(8) null g4<8,8,1>F { align1 WE_normal 1Q }; |
*/ |
latency = 14; |
break; |
} |
} |
class instruction_scheduler { |
public: |
instruction_scheduler(backend_visitor *v, int grf_count, bool post_reg_alloc) |
{ |
this->bv = v; |
this->mem_ctx = ralloc_context(v->mem_ctx); |
this->grf_count = grf_count; |
this->instructions.make_empty(); |
this->instructions_to_schedule = 0; |
this->post_reg_alloc = post_reg_alloc; |
this->time = 0; |
} |
~instruction_scheduler() |
{ |
ralloc_free(this->mem_ctx); |
} |
void add_barrier_deps(schedule_node *n); |
void add_dep(schedule_node *before, schedule_node *after, int latency); |
void add_dep(schedule_node *before, schedule_node *after); |
void run(exec_list *instructions); |
void add_inst(backend_instruction *inst); |
virtual void calculate_deps() = 0; |
virtual schedule_node *choose_instruction_to_schedule() = 0; |
/** |
* Returns how many cycles it takes the instruction to issue. |
* |
* Instructions in gen hardware are handled one simd4 vector at a time, |
* with 1 cycle per vector dispatched. Thus 8-wide pixel shaders take 2 |
* cycles to dispatch and 16-wide (compressed) instructions take 4. |
*/ |
virtual int issue_time(backend_instruction *inst) = 0; |
void schedule_instructions(backend_instruction *next_block_header); |
void *mem_ctx; |
bool post_reg_alloc; |
int instructions_to_schedule; |
int grf_count; |
int time; |
exec_list instructions; |
backend_visitor *bv; |
}; |
class fs_instruction_scheduler : public instruction_scheduler |
{ |
public: |
fs_instruction_scheduler(fs_visitor *v, int grf_count, bool post_reg_alloc); |
void calculate_deps(); |
bool is_compressed(fs_inst *inst); |
schedule_node *choose_instruction_to_schedule(); |
int issue_time(backend_instruction *inst); |
fs_visitor *v; |
}; |
fs_instruction_scheduler::fs_instruction_scheduler(fs_visitor *v, |
int grf_count, |
bool post_reg_alloc) |
: instruction_scheduler(v, grf_count, post_reg_alloc), |
v(v) |
{ |
} |
class vec4_instruction_scheduler : public instruction_scheduler |
{ |
public: |
vec4_instruction_scheduler(vec4_visitor *v, int grf_count); |
void calculate_deps(); |
schedule_node *choose_instruction_to_schedule(); |
int issue_time(backend_instruction *inst); |
vec4_visitor *v; |
}; |
vec4_instruction_scheduler::vec4_instruction_scheduler(vec4_visitor *v, |
int grf_count) |
: instruction_scheduler(v, grf_count, true), |
v(v) |
{ |
} |
void |
instruction_scheduler::add_inst(backend_instruction *inst) |
{ |
schedule_node *n = new(mem_ctx) schedule_node(inst, bv->brw); |
assert(!inst->is_head_sentinel()); |
assert(!inst->is_tail_sentinel()); |
this->instructions_to_schedule++; |
inst->remove(); |
instructions.push_tail(n); |
} |
/** |
* Add a dependency between two instruction nodes. |
* |
* The @after node will be scheduled after @before. We will try to |
* schedule it @latency cycles after @before, but no guarantees there. |
*/ |
void |
instruction_scheduler::add_dep(schedule_node *before, schedule_node *after, |
int latency) |
{ |
if (!before || !after) |
return; |
assert(before != after); |
for (int i = 0; i < before->child_count; i++) { |
if (before->children[i] == after) { |
before->child_latency[i] = MAX2(before->child_latency[i], latency); |
return; |
} |
} |
if (before->child_array_size <= before->child_count) { |
if (before->child_array_size < 16) |
before->child_array_size = 16; |
else |
before->child_array_size *= 2; |
before->children = reralloc(mem_ctx, before->children, |
schedule_node *, |
before->child_array_size); |
before->child_latency = reralloc(mem_ctx, before->child_latency, |
int, before->child_array_size); |
} |
before->children[before->child_count] = after; |
before->child_latency[before->child_count] = latency; |
before->child_count++; |
after->parent_count++; |
} |
void |
instruction_scheduler::add_dep(schedule_node *before, schedule_node *after) |
{ |
if (!before) |
return; |
add_dep(before, after, before->latency); |
} |
/** |
* Sometimes we really want this node to execute after everything that |
* was before it and before everything that followed it. This adds |
* the deps to do so. |
*/ |
void |
instruction_scheduler::add_barrier_deps(schedule_node *n) |
{ |
schedule_node *prev = (schedule_node *)n->prev; |
schedule_node *next = (schedule_node *)n->next; |
if (prev) { |
while (!prev->is_head_sentinel()) { |
add_dep(prev, n, 0); |
prev = (schedule_node *)prev->prev; |
} |
} |
if (next) { |
while (!next->is_tail_sentinel()) { |
add_dep(n, next, 0); |
next = (schedule_node *)next->next; |
} |
} |
} |
/* instruction scheduling needs to be aware of when an MRF write |
* actually writes 2 MRFs. |
*/ |
bool |
fs_instruction_scheduler::is_compressed(fs_inst *inst) |
{ |
return (v->dispatch_width == 16 && |
!inst->force_uncompressed && |
!inst->force_sechalf); |
} |
void |
fs_instruction_scheduler::calculate_deps() |
{ |
/* Pre-register-allocation, this tracks the last write per VGRF (so |
* different reg_offsets within it can interfere when they shouldn't). |
* After register allocation, reg_offsets are gone and we track individual |
* GRF registers. |
*/ |
schedule_node *last_grf_write[grf_count]; |
schedule_node *last_mrf_write[BRW_MAX_MRF]; |
schedule_node *last_conditional_mod[2] = { NULL, NULL }; |
/* Fixed HW registers are assumed to be separate from the virtual |
* GRFs, so they can be tracked separately. We don't really write |
* to fixed GRFs much, so don't bother tracking them on a more |
* granular level. |
*/ |
schedule_node *last_fixed_grf_write = NULL; |
int reg_width = v->dispatch_width / 8; |
/* The last instruction always needs to still be the last |
* instruction. Either it's flow control (IF, ELSE, ENDIF, DO, |
* WHILE) and scheduling other things after it would disturb the |
* basic block, or it's FB_WRITE and we should do a better job at |
* dead code elimination anyway. |
*/ |
schedule_node *last = (schedule_node *)instructions.get_tail(); |
add_barrier_deps(last); |
memset(last_grf_write, 0, sizeof(last_grf_write)); |
memset(last_mrf_write, 0, sizeof(last_mrf_write)); |
/* top-to-bottom dependencies: RAW and WAW. */ |
foreach_list(node, &instructions) { |
schedule_node *n = (schedule_node *)node; |
fs_inst *inst = (fs_inst *)n->inst; |
if (inst->opcode == FS_OPCODE_PLACEHOLDER_HALT) |
add_barrier_deps(n); |
/* read-after-write deps. */ |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
if (post_reg_alloc) { |
for (int r = 0; r < reg_width; r++) |
add_dep(last_grf_write[inst->src[i].reg + r], n); |
} else { |
add_dep(last_grf_write[inst->src[i].reg], n); |
} |
} else if (inst->src[i].file == HW_REG && |
(inst->src[i].fixed_hw_reg.file == |
BRW_GENERAL_REGISTER_FILE)) { |
if (post_reg_alloc) { |
int size = reg_width; |
if (inst->src[i].fixed_hw_reg.vstride == BRW_VERTICAL_STRIDE_0) |
size = 1; |
for (int r = 0; r < size; r++) |
add_dep(last_grf_write[inst->src[i].fixed_hw_reg.nr + r], n); |
} else { |
add_dep(last_fixed_grf_write, n); |
} |
} else if (inst->src[i].file != BAD_FILE && |
inst->src[i].file != IMM && |
inst->src[i].file != UNIFORM) { |
assert(inst->src[i].file != MRF); |
add_barrier_deps(n); |
} |
} |
for (int i = 0; i < inst->mlen; i++) { |
/* It looks like the MRF regs are released in the send |
* instruction once it's sent, not when the result comes |
* back. |
*/ |
add_dep(last_mrf_write[inst->base_mrf + i], n); |
} |
if (inst->predicate) { |
add_dep(last_conditional_mod[inst->flag_subreg], n); |
} |
/* write-after-write deps. */ |
if (inst->dst.file == GRF) { |
if (post_reg_alloc) { |
for (int r = 0; r < inst->regs_written * reg_width; r++) { |
add_dep(last_grf_write[inst->dst.reg + r], n); |
last_grf_write[inst->dst.reg + r] = n; |
} |
} else { |
add_dep(last_grf_write[inst->dst.reg], n); |
last_grf_write[inst->dst.reg] = n; |
} |
} else if (inst->dst.file == MRF) { |
int reg = inst->dst.reg & ~BRW_MRF_COMPR4; |
add_dep(last_mrf_write[reg], n); |
last_mrf_write[reg] = n; |
if (is_compressed(inst)) { |
if (inst->dst.reg & BRW_MRF_COMPR4) |
reg += 4; |
else |
reg++; |
add_dep(last_mrf_write[reg], n); |
last_mrf_write[reg] = n; |
} |
} else if (inst->dst.file == HW_REG && |
inst->dst.fixed_hw_reg.file == BRW_GENERAL_REGISTER_FILE) { |
if (post_reg_alloc) { |
for (int r = 0; r < reg_width; r++) |
last_grf_write[inst->dst.fixed_hw_reg.nr + r] = n; |
} else { |
last_fixed_grf_write = n; |
} |
} else if (inst->dst.file != BAD_FILE) { |
add_barrier_deps(n); |
} |
if (inst->mlen > 0) { |
for (int i = 0; i < v->implied_mrf_writes(inst); i++) { |
add_dep(last_mrf_write[inst->base_mrf + i], n); |
last_mrf_write[inst->base_mrf + i] = n; |
} |
} |
/* Treat FS_OPCODE_MOV_DISPATCH_TO_FLAGS as though it had a |
* conditional_mod, because it sets the flag register. |
*/ |
if (inst->conditional_mod || |
inst->opcode == FS_OPCODE_MOV_DISPATCH_TO_FLAGS) { |
add_dep(last_conditional_mod[inst->flag_subreg], n, 0); |
last_conditional_mod[inst->flag_subreg] = n; |
} |
} |
/* bottom-to-top dependencies: WAR */ |
memset(last_grf_write, 0, sizeof(last_grf_write)); |
memset(last_mrf_write, 0, sizeof(last_mrf_write)); |
memset(last_conditional_mod, 0, sizeof(last_conditional_mod)); |
last_fixed_grf_write = NULL; |
exec_node *node; |
exec_node *prev; |
for (node = instructions.get_tail(), prev = node->prev; |
!node->is_head_sentinel(); |
node = prev, prev = node->prev) { |
schedule_node *n = (schedule_node *)node; |
fs_inst *inst = (fs_inst *)n->inst; |
/* write-after-read deps. */ |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
if (post_reg_alloc) { |
for (int r = 0; r < reg_width; r++) |
add_dep(n, last_grf_write[inst->src[i].reg + r]); |
} else { |
add_dep(n, last_grf_write[inst->src[i].reg]); |
} |
} else if (inst->src[i].file == HW_REG && |
(inst->src[i].fixed_hw_reg.file == |
BRW_GENERAL_REGISTER_FILE)) { |
if (post_reg_alloc) { |
int size = reg_width; |
if (inst->src[i].fixed_hw_reg.vstride == BRW_VERTICAL_STRIDE_0) |
size = 1; |
for (int r = 0; r < size; r++) |
add_dep(n, last_grf_write[inst->src[i].fixed_hw_reg.nr + r]); |
} else { |
add_dep(n, last_fixed_grf_write); |
} |
} else if (inst->src[i].file != BAD_FILE && |
inst->src[i].file != IMM && |
inst->src[i].file != UNIFORM) { |
assert(inst->src[i].file != MRF); |
add_barrier_deps(n); |
} |
} |
for (int i = 0; i < inst->mlen; i++) { |
/* It looks like the MRF regs are released in the send |
* instruction once it's sent, not when the result comes |
* back. |
*/ |
add_dep(n, last_mrf_write[inst->base_mrf + i], 2); |
} |
if (inst->predicate) { |
add_dep(n, last_conditional_mod[inst->flag_subreg]); |
} |
/* Update the things this instruction wrote, so earlier reads |
* can mark this as WAR dependency. |
*/ |
if (inst->dst.file == GRF) { |
if (post_reg_alloc) { |
for (int r = 0; r < inst->regs_written * reg_width; r++) |
last_grf_write[inst->dst.reg + r] = n; |
} else { |
last_grf_write[inst->dst.reg] = n; |
} |
} else if (inst->dst.file == MRF) { |
int reg = inst->dst.reg & ~BRW_MRF_COMPR4; |
last_mrf_write[reg] = n; |
if (is_compressed(inst)) { |
if (inst->dst.reg & BRW_MRF_COMPR4) |
reg += 4; |
else |
reg++; |
last_mrf_write[reg] = n; |
} |
} else if (inst->dst.file == HW_REG && |
inst->dst.fixed_hw_reg.file == BRW_GENERAL_REGISTER_FILE) { |
if (post_reg_alloc) { |
for (int r = 0; r < reg_width; r++) |
last_grf_write[inst->dst.fixed_hw_reg.nr + r] = n; |
} else { |
last_fixed_grf_write = n; |
} |
} else if (inst->dst.file != BAD_FILE) { |
add_barrier_deps(n); |
} |
if (inst->mlen > 0) { |
for (int i = 0; i < v->implied_mrf_writes(inst); i++) { |
last_mrf_write[inst->base_mrf + i] = n; |
} |
} |
/* Treat FS_OPCODE_MOV_DISPATCH_TO_FLAGS as though it had a |
* conditional_mod, because it sets the flag register. |
*/ |
if (inst->conditional_mod || |
inst->opcode == FS_OPCODE_MOV_DISPATCH_TO_FLAGS) { |
last_conditional_mod[inst->flag_subreg] = n; |
} |
} |
} |
void |
vec4_instruction_scheduler::calculate_deps() |
{ |
schedule_node *last_grf_write[grf_count]; |
schedule_node *last_mrf_write[BRW_MAX_MRF]; |
schedule_node *last_conditional_mod = NULL; |
/* Fixed HW registers are assumed to be separate from the virtual |
* GRFs, so they can be tracked separately. We don't really write |
* to fixed GRFs much, so don't bother tracking them on a more |
* granular level. |
*/ |
schedule_node *last_fixed_grf_write = NULL; |
/* The last instruction always needs to still be the last instruction. |
* Either it's flow control (IF, ELSE, ENDIF, DO, WHILE) and scheduling |
* other things after it would disturb the basic block, or it's the EOT |
* URB_WRITE and we should do a better job at dead code eliminating |
* anything that could have been scheduled after it. |
*/ |
schedule_node *last = (schedule_node *)instructions.get_tail(); |
add_barrier_deps(last); |
memset(last_grf_write, 0, sizeof(last_grf_write)); |
memset(last_mrf_write, 0, sizeof(last_mrf_write)); |
/* top-to-bottom dependencies: RAW and WAW. */ |
foreach_list(node, &instructions) { |
schedule_node *n = (schedule_node *)node; |
vec4_instruction *inst = (vec4_instruction *)n->inst; |
/* read-after-write deps. */ |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
add_dep(last_grf_write[inst->src[i].reg], n); |
} else if (inst->src[i].file == HW_REG && |
(inst->src[i].fixed_hw_reg.file == |
BRW_GENERAL_REGISTER_FILE)) { |
add_dep(last_fixed_grf_write, n); |
} else if (inst->src[i].file != BAD_FILE && |
inst->src[i].file != IMM && |
inst->src[i].file != UNIFORM) { |
/* No reads from MRF, and ATTR is already translated away */ |
assert(inst->src[i].file != MRF && |
inst->src[i].file != ATTR); |
add_barrier_deps(n); |
} |
} |
for (int i = 0; i < inst->mlen; i++) { |
/* It looks like the MRF regs are released in the send |
* instruction once it's sent, not when the result comes |
* back. |
*/ |
add_dep(last_mrf_write[inst->base_mrf + i], n); |
} |
if (inst->predicate) { |
assert(last_conditional_mod); |
add_dep(last_conditional_mod, n); |
} |
/* write-after-write deps. */ |
if (inst->dst.file == GRF) { |
add_dep(last_grf_write[inst->dst.reg], n); |
last_grf_write[inst->dst.reg] = n; |
} else if (inst->dst.file == MRF) { |
add_dep(last_mrf_write[inst->dst.reg], n); |
last_mrf_write[inst->dst.reg] = n; |
} else if (inst->dst.file == HW_REG && |
inst->dst.fixed_hw_reg.file == BRW_GENERAL_REGISTER_FILE) { |
last_fixed_grf_write = n; |
} else if (inst->dst.file != BAD_FILE) { |
add_barrier_deps(n); |
} |
if (inst->mlen > 0) { |
for (int i = 0; i < v->implied_mrf_writes(inst); i++) { |
add_dep(last_mrf_write[inst->base_mrf + i], n); |
last_mrf_write[inst->base_mrf + i] = n; |
} |
} |
if (inst->conditional_mod) { |
add_dep(last_conditional_mod, n, 0); |
last_conditional_mod = n; |
} |
} |
/* bottom-to-top dependencies: WAR */ |
memset(last_grf_write, 0, sizeof(last_grf_write)); |
memset(last_mrf_write, 0, sizeof(last_mrf_write)); |
last_conditional_mod = NULL; |
last_fixed_grf_write = NULL; |
exec_node *node; |
exec_node *prev; |
for (node = instructions.get_tail(), prev = node->prev; |
!node->is_head_sentinel(); |
node = prev, prev = node->prev) { |
schedule_node *n = (schedule_node *)node; |
vec4_instruction *inst = (vec4_instruction *)n->inst; |
/* write-after-read deps. */ |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
add_dep(n, last_grf_write[inst->src[i].reg]); |
} else if (inst->src[i].file == HW_REG && |
(inst->src[i].fixed_hw_reg.file == |
BRW_GENERAL_REGISTER_FILE)) { |
add_dep(n, last_fixed_grf_write); |
} else if (inst->src[i].file != BAD_FILE && |
inst->src[i].file != IMM && |
inst->src[i].file != UNIFORM) { |
assert(inst->src[i].file != MRF && |
inst->src[i].file != ATTR); |
add_barrier_deps(n); |
} |
} |
for (int i = 0; i < inst->mlen; i++) { |
/* It looks like the MRF regs are released in the send |
* instruction once it's sent, not when the result comes |
* back. |
*/ |
add_dep(n, last_mrf_write[inst->base_mrf + i], 2); |
} |
if (inst->predicate) { |
add_dep(n, last_conditional_mod); |
} |
/* Update the things this instruction wrote, so earlier reads |
* can mark this as WAR dependency. |
*/ |
if (inst->dst.file == GRF) { |
last_grf_write[inst->dst.reg] = n; |
} else if (inst->dst.file == MRF) { |
last_mrf_write[inst->dst.reg] = n; |
} else if (inst->dst.file == HW_REG && |
inst->dst.fixed_hw_reg.file == BRW_GENERAL_REGISTER_FILE) { |
last_fixed_grf_write = n; |
} else if (inst->dst.file != BAD_FILE) { |
add_barrier_deps(n); |
} |
if (inst->mlen > 0) { |
for (int i = 0; i < v->implied_mrf_writes(inst); i++) { |
last_mrf_write[inst->base_mrf + i] = n; |
} |
} |
if (inst->conditional_mod) { |
last_conditional_mod = n; |
} |
} |
} |
schedule_node * |
fs_instruction_scheduler::choose_instruction_to_schedule() |
{ |
schedule_node *chosen = NULL; |
if (post_reg_alloc) { |
int chosen_time = 0; |
/* Of the instructions closest ready to execute or the closest to |
* being ready, choose the oldest one. |
*/ |
foreach_list(node, &instructions) { |
schedule_node *n = (schedule_node *)node; |
if (!chosen || n->unblocked_time < chosen_time) { |
chosen = n; |
chosen_time = n->unblocked_time; |
} |
} |
} else { |
/* Before register allocation, we don't care about the latencies of |
* instructions. All we care about is reducing live intervals of |
* variables so that we can avoid register spilling, or get 16-wide |
* shaders which naturally do a better job of hiding instruction |
* latency. |
* |
* To do so, schedule our instructions in a roughly LIFO/depth-first |
* order: when new instructions become available as a result of |
* scheduling something, choose those first so that our result |
* hopefully is consumed quickly. |
* |
* The exception is messages that generate more than one result |
* register (AKA texturing). In those cases, the LIFO search would |
* normally tend to choose them quickly (because scheduling the |
* previous message not only unblocked the children using its result, |
* but also the MRF setup for the next sampler message, which in turn |
* unblocks the next sampler message). |
*/ |
for (schedule_node *node = (schedule_node *)instructions.get_tail(); |
node != instructions.get_head()->prev; |
node = (schedule_node *)node->prev) { |
schedule_node *n = (schedule_node *)node; |
fs_inst *inst = (fs_inst *)n->inst; |
chosen = n; |
if (inst->regs_written <= 1) |
break; |
} |
} |
return chosen; |
} |
schedule_node * |
vec4_instruction_scheduler::choose_instruction_to_schedule() |
{ |
schedule_node *chosen = NULL; |
int chosen_time = 0; |
/* Of the instructions ready to execute or the closest to being ready, |
* choose the oldest one. |
*/ |
foreach_list(node, &instructions) { |
schedule_node *n = (schedule_node *)node; |
if (!chosen || n->unblocked_time < chosen_time) { |
chosen = n; |
chosen_time = n->unblocked_time; |
} |
} |
return chosen; |
} |
int |
fs_instruction_scheduler::issue_time(backend_instruction *inst) |
{ |
if (is_compressed((fs_inst *)inst)) |
return 4; |
else |
return 2; |
} |
int |
vec4_instruction_scheduler::issue_time(backend_instruction *inst) |
{ |
/* We always execute as two vec4s in parallel. */ |
return 2; |
} |
void |
instruction_scheduler::schedule_instructions(backend_instruction *next_block_header) |
{ |
time = 0; |
/* Remove non-DAG heads from the list. */ |
foreach_list_safe(node, &instructions) { |
schedule_node *n = (schedule_node *)node; |
if (n->parent_count != 0) |
n->remove(); |
} |
while (!instructions.is_empty()) { |
schedule_node *chosen = choose_instruction_to_schedule(); |
/* Schedule this instruction. */ |
assert(chosen); |
chosen->remove(); |
next_block_header->insert_before(chosen->inst); |
instructions_to_schedule--; |
/* Update the clock for how soon an instruction could start after the |
* chosen one. |
*/ |
time += issue_time(chosen->inst); |
/* If we expected a delay for scheduling, then bump the clock to reflect |
* that as well. In reality, the hardware will switch to another |
* hyperthread and may not return to dispatching our thread for a while |
* even after we're unblocked. |
*/ |
time = MAX2(time, chosen->unblocked_time); |
if (debug) { |
printf("clock %4d, scheduled: ", time); |
bv->dump_instruction(chosen->inst); |
} |
/* Now that we've scheduled a new instruction, some of its |
* children can be promoted to the list of instructions ready to |
* be scheduled. Update the children's unblocked time for this |
* DAG edge as we do so. |
*/ |
for (int i = 0; i < chosen->child_count; i++) { |
schedule_node *child = chosen->children[i]; |
child->unblocked_time = MAX2(child->unblocked_time, |
time + chosen->child_latency[i]); |
child->parent_count--; |
if (child->parent_count == 0) { |
if (debug) { |
printf("now available: "); |
bv->dump_instruction(child->inst); |
} |
instructions.push_tail(child); |
} |
} |
/* Shared resource: the mathbox. There's one mathbox per EU on Gen6+ |
* but it's more limited pre-gen6, so if we send something off to it then |
* the next math instruction isn't going to make progress until the first |
* is done. |
*/ |
if (chosen->inst->is_math()) { |
foreach_list(node, &instructions) { |
schedule_node *n = (schedule_node *)node; |
if (n->inst->is_math()) |
n->unblocked_time = MAX2(n->unblocked_time, |
time + chosen->latency); |
} |
} |
} |
assert(instructions_to_schedule == 0); |
} |
void |
instruction_scheduler::run(exec_list *all_instructions) |
{ |
backend_instruction *next_block_header = |
(backend_instruction *)all_instructions->head; |
if (debug) { |
printf("\nInstructions before scheduling (reg_alloc %d)\n", post_reg_alloc); |
bv->dump_instructions(); |
} |
while (!next_block_header->is_tail_sentinel()) { |
/* Add things to be scheduled until we get to a new BB. */ |
while (!next_block_header->is_tail_sentinel()) { |
backend_instruction *inst = next_block_header; |
next_block_header = (backend_instruction *)next_block_header->next; |
add_inst(inst); |
if (inst->is_control_flow()) |
break; |
} |
calculate_deps(); |
schedule_instructions(next_block_header); |
} |
if (debug) { |
printf("\nInstructions after scheduling (reg_alloc %d)\n", post_reg_alloc); |
bv->dump_instructions(); |
} |
} |
void |
fs_visitor::schedule_instructions(bool post_reg_alloc) |
{ |
int grf_count; |
if (post_reg_alloc) |
grf_count = grf_used; |
else |
grf_count = virtual_grf_count; |
fs_instruction_scheduler sched(this, grf_count, post_reg_alloc); |
sched.run(&instructions); |
if (unlikely(INTEL_DEBUG & DEBUG_WM) && post_reg_alloc) { |
printf("fs%d estimated execution time: %d cycles\n", |
dispatch_width, sched.time); |
} |
this->live_intervals_valid = false; |
} |
void |
vec4_visitor::opt_schedule_instructions() |
{ |
vec4_instruction_scheduler sched(this, prog_data->total_grf); |
sched.run(&instructions); |
if (unlikely(debug_flag)) { |
printf("vec4 estimated execution time: %d cycles\n", sched.time); |
} |
this->live_intervals_valid = false; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_sf.c |
---|
0,0 → 1,222 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/enums.h" |
#include "main/fbobject.h" |
#include "intel_batchbuffer.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_util.h" |
#include "brw_sf.h" |
#include "brw_state.h" |
#include "glsl/ralloc.h" |
static void compile_sf_prog( struct brw_context *brw, |
struct brw_sf_prog_key *key ) |
{ |
struct brw_sf_compile c; |
const GLuint *program; |
void *mem_ctx; |
GLuint program_size; |
GLuint i; |
memset(&c, 0, sizeof(c)); |
mem_ctx = ralloc_context(NULL); |
/* Begin the compilation: |
*/ |
brw_init_compile(brw, &c.func, mem_ctx); |
c.key = *key; |
c.vue_map = brw->vue_map_geom_out; |
if (c.key.do_point_coord) { |
/* |
* gl_PointCoord is a FS instead of VS builtin variable, thus it's |
* not included in c.vue_map generated in VS stage. Here we add |
* it manually to let SF shader generate the needed interpolation |
* coefficient for FS shader. |
*/ |
c.vue_map.varying_to_slot[BRW_VARYING_SLOT_PNTC] = c.vue_map.num_slots; |
c.vue_map.slot_to_varying[c.vue_map.num_slots++] = BRW_VARYING_SLOT_PNTC; |
} |
c.urb_entry_read_offset = BRW_SF_URB_ENTRY_READ_OFFSET; |
c.nr_attr_regs = (c.vue_map.num_slots + 1)/2 - c.urb_entry_read_offset; |
c.nr_setup_regs = c.nr_attr_regs; |
c.prog_data.urb_read_length = c.nr_attr_regs; |
c.prog_data.urb_entry_size = c.nr_setup_regs * 2; |
/* Which primitive? Or all three? |
*/ |
switch (key->primitive) { |
case SF_TRIANGLES: |
c.nr_verts = 3; |
brw_emit_tri_setup( &c, true ); |
break; |
case SF_LINES: |
c.nr_verts = 2; |
brw_emit_line_setup( &c, true ); |
break; |
case SF_POINTS: |
c.nr_verts = 1; |
if (key->do_point_sprite) |
brw_emit_point_sprite_setup( &c, true ); |
else |
brw_emit_point_setup( &c, true ); |
break; |
case SF_UNFILLED_TRIS: |
c.nr_verts = 3; |
brw_emit_anyprim_setup( &c ); |
break; |
default: |
assert(0); |
return; |
} |
/* get the program |
*/ |
program = brw_get_program(&c.func, &program_size); |
if (unlikely(INTEL_DEBUG & DEBUG_SF)) { |
printf("sf:\n"); |
for (i = 0; i < program_size / sizeof(struct brw_instruction); i++) |
brw_disasm(stdout, &((struct brw_instruction *)program)[i], |
brw->gen); |
printf("\n"); |
} |
brw_upload_cache(&brw->cache, BRW_SF_PROG, |
&c.key, sizeof(c.key), |
program, program_size, |
&c.prog_data, sizeof(c.prog_data), |
&brw->sf.prog_offset, &brw->sf.prog_data); |
ralloc_free(mem_ctx); |
} |
/* Calculate interpolants for triangle and line rasterization. |
*/ |
static void |
brw_upload_sf_prog(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_sf_prog_key key; |
/* _NEW_BUFFERS */ |
bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
memset(&key, 0, sizeof(key)); |
/* Populate the key, noting state dependencies: |
*/ |
/* BRW_NEW_VUE_MAP_GEOM_OUT */ |
key.attrs = brw->vue_map_geom_out.slots_valid; |
/* BRW_NEW_REDUCED_PRIMITIVE */ |
switch (brw->reduced_primitive) { |
case GL_TRIANGLES: |
/* NOTE: We just use the edgeflag attribute as an indicator that |
* unfilled triangles are active. We don't actually do the |
* edgeflag testing here, it is already done in the clip |
* program. |
*/ |
if (key.attrs & BITFIELD64_BIT(VARYING_SLOT_EDGE)) |
key.primitive = SF_UNFILLED_TRIS; |
else |
key.primitive = SF_TRIANGLES; |
break; |
case GL_LINES: |
key.primitive = SF_LINES; |
break; |
case GL_POINTS: |
key.primitive = SF_POINTS; |
break; |
} |
/* _NEW_TRANSFORM */ |
key.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); |
/* _NEW_POINT */ |
key.do_point_sprite = ctx->Point.PointSprite; |
if (key.do_point_sprite) { |
int i; |
for (i = 0; i < 8; i++) { |
if (ctx->Point.CoordReplace[i]) |
key.point_sprite_coord_replace |= (1 << i); |
} |
} |
if (brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(VARYING_SLOT_PNTC)) |
key.do_point_coord = 1; |
/* |
* Window coordinates in a FBO are inverted, which means point |
* sprite origin must be inverted, too. |
*/ |
if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) |
key.sprite_origin_lower_left = true; |
/* _NEW_LIGHT | _NEW_PROGRAM */ |
key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT); |
key.do_twoside_color = ((ctx->Light.Enabled && ctx->Light.Model.TwoSide) || |
ctx->VertexProgram._TwoSideEnabled); |
/* _NEW_POLYGON */ |
if (key.do_twoside_color) { |
/* If we're rendering to a FBO, we have to invert the polygon |
* face orientation, just as we invert the viewport in |
* sf_unit_create_from_key(). |
*/ |
key.frontface_ccw = (ctx->Polygon.FrontFace == GL_CCW) != render_to_fbo; |
} |
if (!brw_search_cache(&brw->cache, BRW_SF_PROG, |
&key, sizeof(key), |
&brw->sf.prog_offset, &brw->sf.prog_data)) { |
compile_sf_prog( brw, &key ); |
} |
} |
const struct brw_tracked_state brw_sf_prog = { |
.dirty = { |
.mesa = (_NEW_HINT | _NEW_LIGHT | _NEW_POLYGON | _NEW_POINT | |
_NEW_TRANSFORM | _NEW_BUFFERS | _NEW_PROGRAM), |
.brw = (BRW_NEW_REDUCED_PRIMITIVE | BRW_NEW_VUE_MAP_GEOM_OUT) |
}, |
.emit = brw_upload_sf_prog |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_sf.h |
---|
0,0 → 1,109 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 BRW_SF_H |
#define BRW_SF_H |
#include "program/program.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#define SF_POINTS 0 |
#define SF_LINES 1 |
#define SF_TRIANGLES 2 |
#define SF_UNFILLED_TRIS 3 |
struct brw_sf_prog_key { |
GLbitfield64 attrs; |
uint8_t point_sprite_coord_replace; |
GLuint primitive:2; |
GLuint do_twoside_color:1; |
GLuint do_flat_shading:1; |
GLuint frontface_ccw:1; |
GLuint do_point_sprite:1; |
GLuint do_point_coord:1; |
GLuint sprite_origin_lower_left:1; |
GLuint userclip_active:1; |
}; |
struct brw_sf_compile { |
struct brw_compile func; |
struct brw_sf_prog_key key; |
struct brw_sf_prog_data prog_data; |
struct brw_reg pv; |
struct brw_reg det; |
struct brw_reg dx0; |
struct brw_reg dx2; |
struct brw_reg dy0; |
struct brw_reg dy2; |
/* z and 1/w passed in seperately: |
*/ |
struct brw_reg z[3]; |
struct brw_reg inv_w[3]; |
/* The vertices: |
*/ |
struct brw_reg vert[3]; |
/* Temporaries, allocated after last vertex reg. |
*/ |
struct brw_reg inv_det; |
struct brw_reg a1_sub_a0; |
struct brw_reg a2_sub_a0; |
struct brw_reg tmp; |
struct brw_reg m1Cx; |
struct brw_reg m2Cy; |
struct brw_reg m3C0; |
GLuint nr_verts; |
GLuint nr_attr_regs; |
GLuint nr_setup_regs; |
int urb_entry_read_offset; |
struct brw_vue_map vue_map; |
}; |
void brw_emit_tri_setup( struct brw_sf_compile *c, bool allocate ); |
void brw_emit_line_setup( struct brw_sf_compile *c, bool allocate ); |
void brw_emit_point_setup( struct brw_sf_compile *c, bool allocate ); |
void brw_emit_point_sprite_setup( struct brw_sf_compile *c, bool allocate ); |
void brw_emit_anyprim_setup( struct brw_sf_compile *c ); |
#define BRW_SF_URB_ENTRY_READ_OFFSET 1 |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_sf_emit.c |
---|
0,0 → 1,792 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "intel_batchbuffer.h" |
#include "brw_defines.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_util.h" |
#include "brw_sf.h" |
/** |
* Determine the varying corresponding to the given half of the given |
* register. half=0 means the first half of a register, half=1 means the |
* second half. |
*/ |
static inline int vert_reg_to_varying(struct brw_sf_compile *c, GLuint reg, |
int half) |
{ |
int vue_slot = (reg + c->urb_entry_read_offset) * 2 + half; |
return c->vue_map.slot_to_varying[vue_slot]; |
} |
/** |
* Determine the register corresponding to the given varying. |
*/ |
static struct brw_reg get_varying(struct brw_sf_compile *c, |
struct brw_reg vert, |
GLuint varying) |
{ |
int vue_slot = c->vue_map.varying_to_slot[varying]; |
assert (vue_slot >= c->urb_entry_read_offset); |
GLuint off = vue_slot / 2 - c->urb_entry_read_offset; |
GLuint sub = vue_slot % 2; |
return brw_vec4_grf(vert.nr + off, sub * 4); |
} |
static bool |
have_attr(struct brw_sf_compile *c, GLuint attr) |
{ |
return (c->key.attrs & BITFIELD64_BIT(attr)) ? 1 : 0; |
} |
/*********************************************************************** |
* Twoside lighting |
*/ |
static void copy_bfc( struct brw_sf_compile *c, |
struct brw_reg vert ) |
{ |
struct brw_compile *p = &c->func; |
GLuint i; |
for (i = 0; i < 2; i++) { |
if (have_attr(c, VARYING_SLOT_COL0+i) && |
have_attr(c, VARYING_SLOT_BFC0+i)) |
brw_MOV(p, |
get_varying(c, vert, VARYING_SLOT_COL0+i), |
get_varying(c, vert, VARYING_SLOT_BFC0+i)); |
} |
} |
static void do_twoside_color( struct brw_sf_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
GLuint backface_conditional = c->key.frontface_ccw ? BRW_CONDITIONAL_G : BRW_CONDITIONAL_L; |
/* Already done in clip program: |
*/ |
if (c->key.primitive == SF_UNFILLED_TRIS) |
return; |
/* XXX: What happens if BFC isn't present? This could only happen |
* for user-supplied vertex programs, as t_vp_build.c always does |
* the right thing. |
*/ |
if (!(have_attr(c, VARYING_SLOT_COL0) && have_attr(c, VARYING_SLOT_BFC0)) && |
!(have_attr(c, VARYING_SLOT_COL1) && have_attr(c, VARYING_SLOT_BFC1))) |
return; |
/* Need to use BRW_EXECUTE_4 and also do an 4-wide compare in order |
* to get all channels active inside the IF. In the clipping code |
* we run with NoMask, so it's not an option and we can use |
* BRW_EXECUTE_1 for all comparisions. |
*/ |
brw_push_insn_state(p); |
brw_CMP(p, vec4(brw_null_reg()), backface_conditional, c->det, brw_imm_f(0)); |
brw_IF(p, BRW_EXECUTE_4); |
{ |
switch (c->nr_verts) { |
case 3: copy_bfc(c, c->vert[2]); |
case 2: copy_bfc(c, c->vert[1]); |
case 1: copy_bfc(c, c->vert[0]); |
} |
} |
brw_ENDIF(p); |
brw_pop_insn_state(p); |
} |
/*********************************************************************** |
* Flat shading |
*/ |
#define VARYING_SLOT_COLOR_BITS (BITFIELD64_BIT(VARYING_SLOT_COL0) | \ |
BITFIELD64_BIT(VARYING_SLOT_COL1)) |
static void copy_colors( struct brw_sf_compile *c, |
struct brw_reg dst, |
struct brw_reg src) |
{ |
struct brw_compile *p = &c->func; |
GLuint i; |
for (i = VARYING_SLOT_COL0; i <= VARYING_SLOT_COL1; i++) { |
if (have_attr(c,i)) |
brw_MOV(p, |
get_varying(c, dst, i), |
get_varying(c, src, i)); |
} |
} |
/* Need to use a computed jump to copy flatshaded attributes as the |
* vertices are ordered according to y-coordinate before reaching this |
* point, so the PV could be anywhere. |
*/ |
static void do_flatshade_triangle( struct brw_sf_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_context *brw = p->brw; |
struct brw_reg ip = brw_ip_reg(); |
GLuint nr = _mesa_bitcount_64(c->key.attrs & VARYING_SLOT_COLOR_BITS); |
GLuint jmpi = 1; |
if (!nr) |
return; |
/* Already done in clip program: |
*/ |
if (c->key.primitive == SF_UNFILLED_TRIS) |
return; |
if (brw->gen == 5) |
jmpi = 2; |
brw_push_insn_state(p); |
brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr*2+1))); |
brw_JMPI(p, ip, ip, c->pv); |
copy_colors(c, c->vert[1], c->vert[0]); |
copy_colors(c, c->vert[2], c->vert[0]); |
brw_JMPI(p, ip, ip, brw_imm_d(jmpi*(nr*4+1))); |
copy_colors(c, c->vert[0], c->vert[1]); |
copy_colors(c, c->vert[2], c->vert[1]); |
brw_JMPI(p, ip, ip, brw_imm_d(jmpi*nr*2)); |
copy_colors(c, c->vert[0], c->vert[2]); |
copy_colors(c, c->vert[1], c->vert[2]); |
brw_pop_insn_state(p); |
} |
static void do_flatshade_line( struct brw_sf_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_context *brw = p->brw; |
struct brw_reg ip = brw_ip_reg(); |
GLuint nr = _mesa_bitcount_64(c->key.attrs & VARYING_SLOT_COLOR_BITS); |
GLuint jmpi = 1; |
if (!nr) |
return; |
/* Already done in clip program: |
*/ |
if (c->key.primitive == SF_UNFILLED_TRIS) |
return; |
if (brw->gen == 5) |
jmpi = 2; |
brw_push_insn_state(p); |
brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr+1))); |
brw_JMPI(p, ip, ip, c->pv); |
copy_colors(c, c->vert[1], c->vert[0]); |
brw_JMPI(p, ip, ip, brw_imm_ud(jmpi*nr)); |
copy_colors(c, c->vert[0], c->vert[1]); |
brw_pop_insn_state(p); |
} |
/*********************************************************************** |
* Triangle setup. |
*/ |
static void alloc_regs( struct brw_sf_compile *c ) |
{ |
GLuint reg, i; |
/* Values computed by fixed function unit: |
*/ |
c->pv = retype(brw_vec1_grf(1, 1), BRW_REGISTER_TYPE_D); |
c->det = brw_vec1_grf(1, 2); |
c->dx0 = brw_vec1_grf(1, 3); |
c->dx2 = brw_vec1_grf(1, 4); |
c->dy0 = brw_vec1_grf(1, 5); |
c->dy2 = brw_vec1_grf(1, 6); |
/* z and 1/w passed in seperately: |
*/ |
c->z[0] = brw_vec1_grf(2, 0); |
c->inv_w[0] = brw_vec1_grf(2, 1); |
c->z[1] = brw_vec1_grf(2, 2); |
c->inv_w[1] = brw_vec1_grf(2, 3); |
c->z[2] = brw_vec1_grf(2, 4); |
c->inv_w[2] = brw_vec1_grf(2, 5); |
/* The vertices: |
*/ |
reg = 3; |
for (i = 0; i < c->nr_verts; i++) { |
c->vert[i] = brw_vec8_grf(reg, 0); |
reg += c->nr_attr_regs; |
} |
/* Temporaries, allocated after last vertex reg. |
*/ |
c->inv_det = brw_vec1_grf(reg, 0); reg++; |
c->a1_sub_a0 = brw_vec8_grf(reg, 0); reg++; |
c->a2_sub_a0 = brw_vec8_grf(reg, 0); reg++; |
c->tmp = brw_vec8_grf(reg, 0); reg++; |
/* Note grf allocation: |
*/ |
c->prog_data.total_grf = reg; |
/* Outputs of this program - interpolation coefficients for |
* rasterization: |
*/ |
c->m1Cx = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 1, 0); |
c->m2Cy = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 2, 0); |
c->m3C0 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 3, 0); |
} |
static void copy_z_inv_w( struct brw_sf_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
GLuint i; |
brw_push_insn_state(p); |
/* Copy both scalars with a single MOV: |
*/ |
for (i = 0; i < c->nr_verts; i++) |
brw_MOV(p, vec2(suboffset(c->vert[i], 2)), vec2(c->z[i])); |
brw_pop_insn_state(p); |
} |
static void invert_det( struct brw_sf_compile *c) |
{ |
/* Looks like we invert all 8 elements just to get 1/det in |
* position 2 !?! |
*/ |
brw_math(&c->func, |
c->inv_det, |
BRW_MATH_FUNCTION_INV, |
0, |
c->det, |
BRW_MATH_DATA_SCALAR, |
BRW_MATH_PRECISION_FULL); |
} |
static bool |
calculate_masks(struct brw_sf_compile *c, |
GLuint reg, |
GLushort *pc, |
GLushort *pc_persp, |
GLushort *pc_linear) |
{ |
bool is_last_attr = (reg == c->nr_setup_regs - 1); |
GLbitfield64 persp_mask; |
GLbitfield64 linear_mask; |
if (c->key.do_flat_shading) |
persp_mask = c->key.attrs & ~(BITFIELD64_BIT(VARYING_SLOT_POS) | |
BITFIELD64_BIT(VARYING_SLOT_COL0) | |
BITFIELD64_BIT(VARYING_SLOT_COL1)); |
else |
persp_mask = c->key.attrs & ~(BITFIELD64_BIT(VARYING_SLOT_POS)); |
if (c->key.do_flat_shading) |
linear_mask = c->key.attrs & ~(BITFIELD64_BIT(VARYING_SLOT_COL0) | |
BITFIELD64_BIT(VARYING_SLOT_COL1)); |
else |
linear_mask = c->key.attrs; |
*pc_persp = 0; |
*pc_linear = 0; |
*pc = 0xf; |
if (persp_mask & BITFIELD64_BIT(vert_reg_to_varying(c, reg, 0))) |
*pc_persp = 0xf; |
if (linear_mask & BITFIELD64_BIT(vert_reg_to_varying(c, reg, 0))) |
*pc_linear = 0xf; |
/* Maybe only processs one attribute on the final round: |
*/ |
if (vert_reg_to_varying(c, reg, 1) != BRW_VARYING_SLOT_COUNT) { |
*pc |= 0xf0; |
if (persp_mask & BITFIELD64_BIT(vert_reg_to_varying(c, reg, 1))) |
*pc_persp |= 0xf0; |
if (linear_mask & BITFIELD64_BIT(vert_reg_to_varying(c, reg, 1))) |
*pc_linear |= 0xf0; |
} |
return is_last_attr; |
} |
/* Calculates the predicate control for which channels of a reg |
* (containing 2 attrs) to do point sprite coordinate replacement on. |
*/ |
static uint16_t |
calculate_point_sprite_mask(struct brw_sf_compile *c, GLuint reg) |
{ |
int varying1, varying2; |
uint16_t pc = 0; |
varying1 = vert_reg_to_varying(c, reg, 0); |
if (varying1 >= VARYING_SLOT_TEX0 && varying1 <= VARYING_SLOT_TEX7) { |
if (c->key.point_sprite_coord_replace & (1 << (varying1 - VARYING_SLOT_TEX0))) |
pc |= 0x0f; |
} |
if (varying1 == BRW_VARYING_SLOT_PNTC) |
pc |= 0x0f; |
varying2 = vert_reg_to_varying(c, reg, 1); |
if (varying2 >= VARYING_SLOT_TEX0 && varying2 <= VARYING_SLOT_TEX7) { |
if (c->key.point_sprite_coord_replace & (1 << (varying2 - |
VARYING_SLOT_TEX0))) |
pc |= 0xf0; |
} |
if (varying2 == BRW_VARYING_SLOT_PNTC) |
pc |= 0xf0; |
return pc; |
} |
void brw_emit_tri_setup(struct brw_sf_compile *c, bool allocate) |
{ |
struct brw_compile *p = &c->func; |
GLuint i; |
c->nr_verts = 3; |
if (allocate) |
alloc_regs(c); |
invert_det(c); |
copy_z_inv_w(c); |
if (c->key.do_twoside_color) |
do_twoside_color(c); |
if (c->key.do_flat_shading) |
do_flatshade_triangle(c); |
for (i = 0; i < c->nr_setup_regs; i++) |
{ |
/* Pair of incoming attributes: |
*/ |
struct brw_reg a0 = offset(c->vert[0], i); |
struct brw_reg a1 = offset(c->vert[1], i); |
struct brw_reg a2 = offset(c->vert[2], i); |
GLushort pc, pc_persp, pc_linear; |
bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear); |
if (pc_persp) |
{ |
brw_set_predicate_control_flag_value(p, pc_persp); |
brw_MUL(p, a0, a0, c->inv_w[0]); |
brw_MUL(p, a1, a1, c->inv_w[1]); |
brw_MUL(p, a2, a2, c->inv_w[2]); |
} |
/* Calculate coefficients for interpolated values: |
*/ |
if (pc_linear) |
{ |
brw_set_predicate_control_flag_value(p, pc_linear); |
brw_ADD(p, c->a1_sub_a0, a1, negate(a0)); |
brw_ADD(p, c->a2_sub_a0, a2, negate(a0)); |
/* calculate dA/dx |
*/ |
brw_MUL(p, brw_null_reg(), c->a1_sub_a0, c->dy2); |
brw_MAC(p, c->tmp, c->a2_sub_a0, negate(c->dy0)); |
brw_MUL(p, c->m1Cx, c->tmp, c->inv_det); |
/* calculate dA/dy |
*/ |
brw_MUL(p, brw_null_reg(), c->a2_sub_a0, c->dx0); |
brw_MAC(p, c->tmp, c->a1_sub_a0, negate(c->dx2)); |
brw_MUL(p, c->m2Cy, c->tmp, c->inv_det); |
} |
{ |
brw_set_predicate_control_flag_value(p, pc); |
/* start point for interpolation |
*/ |
brw_MOV(p, c->m3C0, a0); |
/* Copy m0..m3 to URB. m0 is implicitly copied from r0 in |
* the send instruction: |
*/ |
brw_urb_WRITE(p, |
brw_null_reg(), |
0, |
brw_vec8_grf(0, 0), /* r0, will be copied to m0 */ |
0, /* allocate */ |
1, /* used */ |
4, /* msg len */ |
0, /* response len */ |
last, /* eot */ |
last, /* writes complete */ |
i*4, /* offset */ |
BRW_URB_SWIZZLE_TRANSPOSE); /* XXX: Swizzle control "SF to windower" */ |
} |
} |
} |
void brw_emit_line_setup(struct brw_sf_compile *c, bool allocate) |
{ |
struct brw_compile *p = &c->func; |
GLuint i; |
c->nr_verts = 2; |
if (allocate) |
alloc_regs(c); |
invert_det(c); |
copy_z_inv_w(c); |
if (c->key.do_flat_shading) |
do_flatshade_line(c); |
for (i = 0; i < c->nr_setup_regs; i++) |
{ |
/* Pair of incoming attributes: |
*/ |
struct brw_reg a0 = offset(c->vert[0], i); |
struct brw_reg a1 = offset(c->vert[1], i); |
GLushort pc, pc_persp, pc_linear; |
bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear); |
if (pc_persp) |
{ |
brw_set_predicate_control_flag_value(p, pc_persp); |
brw_MUL(p, a0, a0, c->inv_w[0]); |
brw_MUL(p, a1, a1, c->inv_w[1]); |
} |
/* Calculate coefficients for position, color: |
*/ |
if (pc_linear) { |
brw_set_predicate_control_flag_value(p, pc_linear); |
brw_ADD(p, c->a1_sub_a0, a1, negate(a0)); |
brw_MUL(p, c->tmp, c->a1_sub_a0, c->dx0); |
brw_MUL(p, c->m1Cx, c->tmp, c->inv_det); |
brw_MUL(p, c->tmp, c->a1_sub_a0, c->dy0); |
brw_MUL(p, c->m2Cy, c->tmp, c->inv_det); |
} |
{ |
brw_set_predicate_control_flag_value(p, pc); |
/* start point for interpolation |
*/ |
brw_MOV(p, c->m3C0, a0); |
/* Copy m0..m3 to URB. |
*/ |
brw_urb_WRITE(p, |
brw_null_reg(), |
0, |
brw_vec8_grf(0, 0), |
0, /* allocate */ |
1, /* used */ |
4, /* msg len */ |
0, /* response len */ |
last, /* eot */ |
last, /* writes complete */ |
i*4, /* urb destination offset */ |
BRW_URB_SWIZZLE_TRANSPOSE); |
} |
} |
} |
void brw_emit_point_sprite_setup(struct brw_sf_compile *c, bool allocate) |
{ |
struct brw_compile *p = &c->func; |
GLuint i; |
c->nr_verts = 1; |
if (allocate) |
alloc_regs(c); |
copy_z_inv_w(c); |
for (i = 0; i < c->nr_setup_regs; i++) |
{ |
struct brw_reg a0 = offset(c->vert[0], i); |
GLushort pc, pc_persp, pc_linear, pc_coord_replace; |
bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear); |
pc_coord_replace = calculate_point_sprite_mask(c, i); |
pc_persp &= ~pc_coord_replace; |
if (pc_persp) { |
brw_set_predicate_control_flag_value(p, pc_persp); |
brw_MUL(p, a0, a0, c->inv_w[0]); |
} |
/* Point sprite coordinate replacement: A texcoord with this |
* enabled gets replaced with the value (x, y, 0, 1) where x and |
* y vary from 0 to 1 across the horizontal and vertical of the |
* point. |
*/ |
if (pc_coord_replace) { |
brw_set_predicate_control_flag_value(p, pc_coord_replace); |
/* Caculate 1.0/PointWidth */ |
brw_math(&c->func, |
c->tmp, |
BRW_MATH_FUNCTION_INV, |
0, |
c->dx0, |
BRW_MATH_DATA_SCALAR, |
BRW_MATH_PRECISION_FULL); |
brw_set_access_mode(p, BRW_ALIGN_16); |
/* dA/dx, dA/dy */ |
brw_MOV(p, c->m1Cx, brw_imm_f(0.0)); |
brw_MOV(p, c->m2Cy, brw_imm_f(0.0)); |
brw_MOV(p, brw_writemask(c->m1Cx, WRITEMASK_X), c->tmp); |
if (c->key.sprite_origin_lower_left) { |
brw_MOV(p, brw_writemask(c->m2Cy, WRITEMASK_Y), negate(c->tmp)); |
} else { |
brw_MOV(p, brw_writemask(c->m2Cy, WRITEMASK_Y), c->tmp); |
} |
/* attribute constant offset */ |
brw_MOV(p, c->m3C0, brw_imm_f(0.0)); |
if (c->key.sprite_origin_lower_left) { |
brw_MOV(p, brw_writemask(c->m3C0, WRITEMASK_YW), brw_imm_f(1.0)); |
} else { |
brw_MOV(p, brw_writemask(c->m3C0, WRITEMASK_W), brw_imm_f(1.0)); |
} |
brw_set_access_mode(p, BRW_ALIGN_1); |
} |
if (pc & ~pc_coord_replace) { |
brw_set_predicate_control_flag_value(p, pc & ~pc_coord_replace); |
brw_MOV(p, c->m1Cx, brw_imm_ud(0)); |
brw_MOV(p, c->m2Cy, brw_imm_ud(0)); |
brw_MOV(p, c->m3C0, a0); /* constant value */ |
} |
brw_set_predicate_control_flag_value(p, pc); |
/* Copy m0..m3 to URB. */ |
brw_urb_WRITE(p, |
brw_null_reg(), |
0, |
brw_vec8_grf(0, 0), |
0, /* allocate */ |
1, /* used */ |
4, /* msg len */ |
0, /* response len */ |
last, /* eot */ |
last, /* writes complete */ |
i*4, /* urb destination offset */ |
BRW_URB_SWIZZLE_TRANSPOSE); |
} |
} |
/* Points setup - several simplifications as all attributes are |
* constant across the face of the point (point sprites excluded!) |
*/ |
void brw_emit_point_setup(struct brw_sf_compile *c, bool allocate) |
{ |
struct brw_compile *p = &c->func; |
GLuint i; |
c->nr_verts = 1; |
if (allocate) |
alloc_regs(c); |
copy_z_inv_w(c); |
brw_MOV(p, c->m1Cx, brw_imm_ud(0)); /* zero - move out of loop */ |
brw_MOV(p, c->m2Cy, brw_imm_ud(0)); /* zero - move out of loop */ |
for (i = 0; i < c->nr_setup_regs; i++) |
{ |
struct brw_reg a0 = offset(c->vert[0], i); |
GLushort pc, pc_persp, pc_linear; |
bool last = calculate_masks(c, i, &pc, &pc_persp, &pc_linear); |
if (pc_persp) |
{ |
/* This seems odd as the values are all constant, but the |
* fragment shader will be expecting it: |
*/ |
brw_set_predicate_control_flag_value(p, pc_persp); |
brw_MUL(p, a0, a0, c->inv_w[0]); |
} |
/* The delta values are always zero, just send the starting |
* coordinate. Again, this is to fit in with the interpolation |
* code in the fragment shader. |
*/ |
{ |
brw_set_predicate_control_flag_value(p, pc); |
brw_MOV(p, c->m3C0, a0); /* constant value */ |
/* Copy m0..m3 to URB. |
*/ |
brw_urb_WRITE(p, |
brw_null_reg(), |
0, |
brw_vec8_grf(0, 0), |
0, /* allocate */ |
1, /* used */ |
4, /* msg len */ |
0, /* response len */ |
last, /* eot */ |
last, /* writes complete */ |
i*4, /* urb destination offset */ |
BRW_URB_SWIZZLE_TRANSPOSE); |
} |
} |
} |
void brw_emit_anyprim_setup( struct brw_sf_compile *c ) |
{ |
struct brw_compile *p = &c->func; |
struct brw_reg ip = brw_ip_reg(); |
struct brw_reg payload_prim = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, 1, 0); |
struct brw_reg payload_attr = get_element_ud(brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, 1, 0), 0); |
struct brw_reg primmask; |
int jmp; |
struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD)); |
GLuint saveflag; |
c->nr_verts = 3; |
alloc_regs(c); |
primmask = retype(get_element(c->tmp, 0), BRW_REGISTER_TYPE_UD); |
brw_MOV(p, primmask, brw_imm_ud(1)); |
brw_SHL(p, primmask, primmask, payload_prim); |
brw_set_conditionalmod(p, BRW_CONDITIONAL_Z); |
brw_AND(p, v1_null_ud, primmask, brw_imm_ud((1<<_3DPRIM_TRILIST) | |
(1<<_3DPRIM_TRISTRIP) | |
(1<<_3DPRIM_TRIFAN) | |
(1<<_3DPRIM_TRISTRIP_REVERSE) | |
(1<<_3DPRIM_POLYGON) | |
(1<<_3DPRIM_RECTLIST) | |
(1<<_3DPRIM_TRIFAN_NOSTIPPLE))); |
jmp = brw_JMPI(p, ip, ip, brw_imm_d(0)) - p->store; |
{ |
saveflag = p->flag_value; |
brw_push_insn_state(p); |
brw_emit_tri_setup( c, false ); |
brw_pop_insn_state(p); |
p->flag_value = saveflag; |
/* note - thread killed in subroutine, so must |
* restore the flag which is changed when building |
* the subroutine. fix #13240 |
*/ |
} |
brw_land_fwd_jump(p, jmp); |
brw_set_conditionalmod(p, BRW_CONDITIONAL_Z); |
brw_AND(p, v1_null_ud, primmask, brw_imm_ud((1<<_3DPRIM_LINELIST) | |
(1<<_3DPRIM_LINESTRIP) | |
(1<<_3DPRIM_LINELOOP) | |
(1<<_3DPRIM_LINESTRIP_CONT) | |
(1<<_3DPRIM_LINESTRIP_BF) | |
(1<<_3DPRIM_LINESTRIP_CONT_BF))); |
jmp = brw_JMPI(p, ip, ip, brw_imm_d(0)) - p->store; |
{ |
saveflag = p->flag_value; |
brw_push_insn_state(p); |
brw_emit_line_setup( c, false ); |
brw_pop_insn_state(p); |
p->flag_value = saveflag; |
/* note - thread killed in subroutine */ |
} |
brw_land_fwd_jump(p, jmp); |
brw_set_conditionalmod(p, BRW_CONDITIONAL_Z); |
brw_AND(p, v1_null_ud, payload_attr, brw_imm_ud(1<<BRW_SPRITE_POINT_ENABLE)); |
jmp = brw_JMPI(p, ip, ip, brw_imm_d(0)) - p->store; |
{ |
saveflag = p->flag_value; |
brw_push_insn_state(p); |
brw_emit_point_sprite_setup( c, false ); |
brw_pop_insn_state(p); |
p->flag_value = saveflag; |
} |
brw_land_fwd_jump(p, jmp); |
brw_emit_point_setup( c, false ); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_sf_state.c |
---|
0,0 → 1,315 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/mtypes.h" |
#include "main/macros.h" |
#include "main/fbobject.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_sf.h" |
static void upload_sf_vp(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
const GLfloat depth_scale = 1.0F / ctx->DrawBuffer->_DepthMaxF; |
struct brw_sf_viewport *sfv; |
GLfloat y_scale, y_bias; |
const bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
const GLfloat *v = ctx->Viewport._WindowMap.m; |
sfv = brw_state_batch(brw, AUB_TRACE_SF_VP_STATE, |
sizeof(*sfv), 32, &brw->sf.vp_offset); |
memset(sfv, 0, sizeof(*sfv)); |
if (render_to_fbo) { |
y_scale = 1.0; |
y_bias = 0; |
} |
else { |
y_scale = -1.0; |
y_bias = ctx->DrawBuffer->Height; |
} |
/* _NEW_VIEWPORT */ |
sfv->viewport.m00 = v[MAT_SX]; |
sfv->viewport.m11 = v[MAT_SY] * y_scale; |
sfv->viewport.m22 = v[MAT_SZ] * depth_scale; |
sfv->viewport.m30 = v[MAT_TX]; |
sfv->viewport.m31 = v[MAT_TY] * y_scale + y_bias; |
sfv->viewport.m32 = v[MAT_TZ] * depth_scale; |
/* _NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT |
* for DrawBuffer->_[XY]{min,max} |
*/ |
/* The scissor only needs to handle the intersection of drawable |
* and scissor rect, since there are no longer cliprects for shared |
* buffers with DRI2. |
* |
* Note that the hardware's coordinates are inclusive, while Mesa's min is |
* inclusive but max is exclusive. |
*/ |
if (ctx->DrawBuffer->_Xmin == ctx->DrawBuffer->_Xmax || |
ctx->DrawBuffer->_Ymin == ctx->DrawBuffer->_Ymax) { |
/* If the scissor was out of bounds and got clamped to 0 |
* width/height at the bounds, the subtraction of 1 from |
* maximums could produce a negative number and thus not clip |
* anything. Instead, just provide a min > max scissor inside |
* the bounds, which produces the expected no rendering. |
*/ |
sfv->scissor.xmin = 1; |
sfv->scissor.xmax = 0; |
sfv->scissor.ymin = 1; |
sfv->scissor.ymax = 0; |
} else if (render_to_fbo) { |
/* texmemory: Y=0=bottom */ |
sfv->scissor.xmin = ctx->DrawBuffer->_Xmin; |
sfv->scissor.xmax = ctx->DrawBuffer->_Xmax - 1; |
sfv->scissor.ymin = ctx->DrawBuffer->_Ymin; |
sfv->scissor.ymax = ctx->DrawBuffer->_Ymax - 1; |
} |
else { |
/* memory: Y=0=top */ |
sfv->scissor.xmin = ctx->DrawBuffer->_Xmin; |
sfv->scissor.xmax = ctx->DrawBuffer->_Xmax - 1; |
sfv->scissor.ymin = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax; |
sfv->scissor.ymax = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin - 1; |
} |
brw->state.dirty.cache |= CACHE_NEW_SF_VP; |
} |
const struct brw_tracked_state brw_sf_vp = { |
.dirty = { |
.mesa = (_NEW_VIEWPORT | |
_NEW_SCISSOR | |
_NEW_BUFFERS), |
.brw = BRW_NEW_BATCH, |
.cache = 0 |
}, |
.emit = upload_sf_vp |
}; |
static void upload_sf_unit( struct brw_context *brw ) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_sf_unit_state *sf; |
drm_intel_bo *bo = brw->batch.bo; |
int chipset_max_threads; |
bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
sf = brw_state_batch(brw, AUB_TRACE_SF_STATE, |
sizeof(*sf), 64, &brw->sf.state_offset); |
memset(sf, 0, sizeof(*sf)); |
/* BRW_NEW_PROGRAM_CACHE | CACHE_NEW_SF_PROG */ |
sf->thread0.grf_reg_count = ALIGN(brw->sf.prog_data->total_grf, 16) / 16 - 1; |
sf->thread0.kernel_start_pointer = |
brw_program_reloc(brw, |
brw->sf.state_offset + |
offsetof(struct brw_sf_unit_state, thread0), |
brw->sf.prog_offset + |
(sf->thread0.grf_reg_count << 1)) >> 6; |
sf->thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754; |
sf->thread3.dispatch_grf_start_reg = 3; |
sf->thread3.urb_entry_read_offset = BRW_SF_URB_ENTRY_READ_OFFSET; |
/* CACHE_NEW_SF_PROG */ |
sf->thread3.urb_entry_read_length = brw->sf.prog_data->urb_read_length; |
/* BRW_NEW_URB_FENCE */ |
sf->thread4.nr_urb_entries = brw->urb.nr_sf_entries; |
sf->thread4.urb_entry_allocation_size = brw->urb.sfsize - 1; |
/* Each SF thread produces 1 PUE, and there can be up to 24 (Pre-Ironlake) or |
* 48 (Ironlake) threads. |
*/ |
if (brw->gen == 5) |
chipset_max_threads = 48; |
else |
chipset_max_threads = 24; |
/* BRW_NEW_URB_FENCE */ |
sf->thread4.max_threads = MIN2(chipset_max_threads, |
brw->urb.nr_sf_entries) - 1; |
if (unlikely(INTEL_DEBUG & DEBUG_STATS)) |
sf->thread4.stats_enable = 1; |
/* CACHE_NEW_SF_VP */ |
sf->sf5.sf_viewport_state_offset = (brw->batch.bo->offset + |
brw->sf.vp_offset) >> 5; /* reloc */ |
sf->sf5.viewport_transform = 1; |
/* _NEW_SCISSOR */ |
if (ctx->Scissor.Enabled) |
sf->sf6.scissor = 1; |
/* _NEW_POLYGON */ |
if (ctx->Polygon.FrontFace == GL_CCW) |
sf->sf5.front_winding = BRW_FRONTWINDING_CCW; |
else |
sf->sf5.front_winding = BRW_FRONTWINDING_CW; |
/* _NEW_BUFFERS |
* The viewport is inverted for rendering to a FBO, and that inverts |
* polygon front/back orientation. |
*/ |
sf->sf5.front_winding ^= render_to_fbo; |
/* _NEW_POLYGON */ |
switch (ctx->Polygon.CullFlag ? ctx->Polygon.CullFaceMode : GL_NONE) { |
case GL_FRONT: |
sf->sf6.cull_mode = BRW_CULLMODE_FRONT; |
break; |
case GL_BACK: |
sf->sf6.cull_mode = BRW_CULLMODE_BACK; |
break; |
case GL_FRONT_AND_BACK: |
sf->sf6.cull_mode = BRW_CULLMODE_BOTH; |
break; |
case GL_NONE: |
sf->sf6.cull_mode = BRW_CULLMODE_NONE; |
break; |
default: |
assert(0); |
break; |
} |
/* _NEW_LINE */ |
/* XXX use ctx->Const.Min/MaxLineWidth here */ |
sf->sf6.line_width = CLAMP(ctx->Line.Width, 1.0, 5.0) * (1<<1); |
sf->sf6.line_endcap_aa_region_width = 1; |
if (ctx->Line.SmoothFlag) |
sf->sf6.aa_enable = 1; |
else if (sf->sf6.line_width <= 0x2) |
sf->sf6.line_width = 0; |
/* _NEW_BUFFERS */ |
if (!render_to_fbo) { |
/* Rendering to an OpenGL window */ |
sf->sf6.point_rast_rule = BRW_RASTRULE_UPPER_RIGHT; |
} |
else { |
/* If rendering to an FBO, the pixel coordinate system is |
* inverted with respect to the normal OpenGL coordinate |
* system, so BRW_RASTRULE_LOWER_RIGHT is correct. |
* But this value is listed as "Reserved, but not seen as useful" |
* in Intel documentation (page 212, "Point Rasterization Rule", |
* section 7.4 "SF Pipeline State Summary", of document |
* "Intel® 965 Express Chipset Family and Intel® G35 Express |
* Chipset Graphics Controller Programmer's Reference Manual, |
* Volume 2: 3D/Media", Revision 1.0b as of January 2008, |
* available at |
* http://intellinuxgraphics.org/documentation.html |
* at the time of this writing). |
* |
* It does work on at least some devices, if not all; |
* if devices that don't support it can be identified, |
* the likely failure case is that points are rasterized |
* incorrectly, which is no worse than occurs without |
* the value, so we're using it here. |
*/ |
sf->sf6.point_rast_rule = BRW_RASTRULE_LOWER_RIGHT; |
} |
/* XXX clamp max depends on AA vs. non-AA */ |
/* _NEW_POINT */ |
sf->sf7.sprite_point = ctx->Point.PointSprite; |
sf->sf7.point_size = CLAMP(rint(CLAMP(ctx->Point.Size, |
ctx->Point.MinSize, |
ctx->Point.MaxSize)), 1, 255) * (1<<3); |
/* _NEW_PROGRAM | _NEW_POINT */ |
sf->sf7.use_point_size_state = !(ctx->VertexProgram.PointSizeEnabled || |
ctx->Point._Attenuated); |
sf->sf7.aa_line_distance_mode = 0; |
/* might be BRW_NEW_PRIMITIVE if we have to adjust pv for polygons: |
* _NEW_LIGHT |
*/ |
if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { |
sf->sf7.trifan_pv = 2; |
sf->sf7.linestrip_pv = 1; |
sf->sf7.tristrip_pv = 2; |
} else { |
sf->sf7.trifan_pv = 1; |
sf->sf7.linestrip_pv = 0; |
sf->sf7.tristrip_pv = 0; |
} |
sf->sf7.line_last_pixel_enable = 0; |
/* Set bias for OpenGL rasterization rules: |
*/ |
sf->sf6.dest_org_vbias = 0x8; |
sf->sf6.dest_org_hbias = 0x8; |
/* STATE_PREFETCH command description describes this state as being |
* something loaded through the GPE (L2 ISC), so it's INSTRUCTION domain. |
*/ |
/* Emit SF viewport relocation */ |
drm_intel_bo_emit_reloc(bo, (brw->sf.state_offset + |
offsetof(struct brw_sf_unit_state, sf5)), |
brw->batch.bo, (brw->sf.vp_offset | |
sf->sf5.front_winding | |
(sf->sf5.viewport_transform << 1)), |
I915_GEM_DOMAIN_INSTRUCTION, 0); |
brw->state.dirty.cache |= CACHE_NEW_SF_UNIT; |
} |
const struct brw_tracked_state brw_sf_unit = { |
.dirty = { |
.mesa = (_NEW_POLYGON | |
_NEW_PROGRAM | |
_NEW_LIGHT | |
_NEW_LINE | |
_NEW_POINT | |
_NEW_SCISSOR | |
_NEW_BUFFERS), |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_PROGRAM_CACHE | |
BRW_NEW_URB_FENCE), |
.cache = (CACHE_NEW_SF_VP | |
CACHE_NEW_SF_PROG) |
}, |
.emit = upload_sf_unit, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_shader.cpp |
---|
0,0 → 1,564 |
/* |
* Copyright © 2010 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. |
*/ |
extern "C" { |
#include "main/macros.h" |
#include "brw_context.h" |
#include "brw_vs.h" |
} |
#include "brw_fs.h" |
#include "glsl/ir_optimization.h" |
#include "glsl/glsl_parser_extras.h" |
struct gl_shader * |
brw_new_shader(struct gl_context *ctx, GLuint name, GLuint type) |
{ |
struct brw_shader *shader; |
shader = rzalloc(NULL, struct brw_shader); |
if (shader) { |
shader->base.Type = type; |
shader->base.Name = name; |
_mesa_init_shader(ctx, &shader->base); |
} |
return &shader->base; |
} |
struct gl_shader_program * |
brw_new_shader_program(struct gl_context *ctx, GLuint name) |
{ |
struct gl_shader_program *prog = rzalloc(NULL, struct gl_shader_program); |
if (prog) { |
prog->Name = name; |
_mesa_init_shader_program(ctx, prog); |
} |
return prog; |
} |
/** |
* Performs a compile of the shader stages even when we don't know |
* what non-orthogonal state will be set, in the hope that it reflects |
* the eventual NOS used, and thus allows us to produce link failures. |
*/ |
static bool |
brw_shader_precompile(struct gl_context *ctx, struct gl_shader_program *prog) |
{ |
struct brw_context *brw = brw_context(ctx); |
if (brw->precompile && !brw_fs_precompile(ctx, prog)) |
return false; |
if (brw->precompile && !brw_vs_precompile(ctx, prog)) |
return false; |
return true; |
} |
static void |
brw_lower_packing_builtins(struct brw_context *brw, |
gl_shader_type shader_type, |
exec_list *ir) |
{ |
int ops = LOWER_PACK_SNORM_2x16 |
| LOWER_UNPACK_SNORM_2x16 |
| LOWER_PACK_UNORM_2x16 |
| LOWER_UNPACK_UNORM_2x16 |
| LOWER_PACK_SNORM_4x8 |
| LOWER_UNPACK_SNORM_4x8 |
| LOWER_PACK_UNORM_4x8 |
| LOWER_UNPACK_UNORM_4x8; |
if (brw->gen >= 7) { |
/* Gen7 introduced the f32to16 and f16to32 instructions, which can be |
* used to execute packHalf2x16 and unpackHalf2x16. For AOS code, no |
* lowering is needed. For SOA code, the Half2x16 ops must be |
* scalarized. |
*/ |
if (shader_type == MESA_SHADER_FRAGMENT) { |
ops |= LOWER_PACK_HALF_2x16_TO_SPLIT |
| LOWER_UNPACK_HALF_2x16_TO_SPLIT; |
} |
} else { |
ops |= LOWER_PACK_HALF_2x16 |
| LOWER_UNPACK_HALF_2x16; |
} |
lower_packing_builtins(ir, ops); |
} |
GLboolean |
brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg) |
{ |
struct brw_context *brw = brw_context(ctx); |
unsigned int stage; |
for (stage = 0; stage < ARRAY_SIZE(shProg->_LinkedShaders); stage++) { |
struct brw_shader *shader = |
(struct brw_shader *)shProg->_LinkedShaders[stage]; |
if (!shader) |
continue; |
struct gl_program *prog = |
ctx->Driver.NewProgram(ctx, _mesa_program_index_to_target(stage), |
shader->base.Name); |
if (!prog) |
return false; |
prog->Parameters = _mesa_new_parameter_list(); |
if (stage == 0) { |
struct gl_vertex_program *vp = (struct gl_vertex_program *) prog; |
vp->UsesClipDistance = shProg->Vert.UsesClipDistance; |
} |
void *mem_ctx = ralloc_context(NULL); |
bool progress; |
if (shader->ir) |
ralloc_free(shader->ir); |
shader->ir = new(shader) exec_list; |
clone_ir_list(mem_ctx, shader->ir, shader->base.ir); |
/* lower_packing_builtins() inserts arithmetic instructions, so it |
* must precede lower_instructions(). |
*/ |
brw_lower_packing_builtins(brw, (gl_shader_type) stage, shader->ir); |
do_mat_op_to_vec(shader->ir); |
const int bitfield_insert = brw->gen >= 7 |
? BITFIELD_INSERT_TO_BFM_BFI |
: 0; |
const int lrp_to_arith = brw->gen < 6 ? LRP_TO_ARITH : 0; |
lower_instructions(shader->ir, |
MOD_TO_FRACT | |
DIV_TO_MUL_RCP | |
SUB_TO_ADD_NEG | |
EXP_TO_EXP2 | |
LOG_TO_LOG2 | |
bitfield_insert | |
lrp_to_arith); |
/* Pre-gen6 HW can only nest if-statements 16 deep. Beyond this, |
* if-statements need to be flattened. |
*/ |
if (brw->gen < 6) |
lower_if_to_cond_assign(shader->ir, 16); |
do_lower_texture_projection(shader->ir); |
brw_lower_texture_gradients(brw, shader->ir); |
do_vec_index_to_cond_assign(shader->ir); |
lower_vector_insert(shader->ir, true); |
brw_do_cubemap_normalize(shader->ir); |
lower_noise(shader->ir); |
lower_quadop_vector(shader->ir, false); |
bool input = true; |
bool output = stage == MESA_SHADER_FRAGMENT; |
bool temp = stage == MESA_SHADER_FRAGMENT; |
bool uniform = false; |
bool lowered_variable_indexing = |
lower_variable_index_to_cond_assign(shader->ir, |
input, output, temp, uniform); |
if (unlikely(brw->perf_debug && lowered_variable_indexing)) { |
perf_debug("Unsupported form of variable indexing in FS; falling " |
"back to very inefficient code generation\n"); |
} |
/* FINISHME: Do this before the variable index lowering. */ |
lower_ubo_reference(&shader->base, shader->ir); |
do { |
progress = false; |
if (stage == MESA_SHADER_FRAGMENT) { |
brw_do_channel_expressions(shader->ir); |
brw_do_vector_splitting(shader->ir); |
} |
progress = do_lower_jumps(shader->ir, true, true, |
true, /* main return */ |
false, /* continue */ |
false /* loops */ |
) || progress; |
progress = do_common_optimization(shader->ir, true, true, 32, |
&ctx->ShaderCompilerOptions[stage]) |
|| progress; |
} while (progress); |
/* Make a pass over the IR to add state references for any built-in |
* uniforms that are used. This has to be done now (during linking). |
* Code generation doesn't happen until the first time this shader is |
* used for rendering. Waiting until then to generate the parameters is |
* too late. At that point, the values for the built-in uniforms won't |
* get sent to the shader. |
*/ |
foreach_list(node, shader->ir) { |
ir_variable *var = ((ir_instruction *) node)->as_variable(); |
if ((var == NULL) || (var->mode != ir_var_uniform) |
|| (strncmp(var->name, "gl_", 3) != 0)) |
continue; |
const ir_state_slot *const slots = var->state_slots; |
assert(var->state_slots != NULL); |
for (unsigned int i = 0; i < var->num_state_slots; i++) { |
_mesa_add_state_reference(prog->Parameters, |
(gl_state_index *) slots[i].tokens); |
} |
} |
validate_ir_tree(shader->ir); |
reparent_ir(shader->ir, shader->ir); |
ralloc_free(mem_ctx); |
do_set_program_inouts(shader->ir, prog, |
shader->base.Type == GL_FRAGMENT_SHADER); |
prog->SamplersUsed = shader->base.active_samplers; |
_mesa_update_shader_textures_used(shProg, prog); |
_mesa_reference_program(ctx, &shader->base.Program, prog); |
brw_add_texrect_params(prog); |
/* This has to be done last. Any operation that can cause |
* prog->ParameterValues to get reallocated (e.g., anything that adds a |
* program constant) has to happen before creating this linkage. |
*/ |
_mesa_associate_uniform_storage(ctx, shProg, prog->Parameters); |
_mesa_reference_program(ctx, &prog, NULL); |
if (ctx->Shader.Flags & GLSL_DUMP) { |
printf("\n"); |
printf("GLSL IR for linked %s program %d:\n", |
_mesa_glsl_shader_target_name(shader->base.Type), shProg->Name); |
_mesa_print_ir(shader->base.ir, NULL); |
printf("\n"); |
} |
} |
if (ctx->Shader.Flags & GLSL_DUMP) { |
for (unsigned i = 0; i < shProg->NumShaders; i++) { |
const struct gl_shader *sh = shProg->Shaders[i]; |
if (!sh) |
continue; |
printf("GLSL %s shader %d source for linked program %d:\n", |
_mesa_glsl_shader_target_name(sh->Type), |
i, |
shProg->Name); |
printf("%s", sh->Source); |
printf("\n"); |
} |
} |
if (!brw_shader_precompile(ctx, shProg)) |
return false; |
return true; |
} |
int |
brw_type_for_base_type(const struct glsl_type *type) |
{ |
switch (type->base_type) { |
case GLSL_TYPE_FLOAT: |
return BRW_REGISTER_TYPE_F; |
case GLSL_TYPE_INT: |
case GLSL_TYPE_BOOL: |
return BRW_REGISTER_TYPE_D; |
case GLSL_TYPE_UINT: |
return BRW_REGISTER_TYPE_UD; |
case GLSL_TYPE_ARRAY: |
return brw_type_for_base_type(type->fields.array); |
case GLSL_TYPE_STRUCT: |
case GLSL_TYPE_SAMPLER: |
/* These should be overridden with the type of the member when |
* dereferenced into. BRW_REGISTER_TYPE_UD seems like a likely |
* way to trip up if we don't. |
*/ |
return BRW_REGISTER_TYPE_UD; |
case GLSL_TYPE_VOID: |
case GLSL_TYPE_ERROR: |
case GLSL_TYPE_INTERFACE: |
assert(!"not reached"); |
break; |
} |
return BRW_REGISTER_TYPE_F; |
} |
uint32_t |
brw_conditional_for_comparison(unsigned int op) |
{ |
switch (op) { |
case ir_binop_less: |
return BRW_CONDITIONAL_L; |
case ir_binop_greater: |
return BRW_CONDITIONAL_G; |
case ir_binop_lequal: |
return BRW_CONDITIONAL_LE; |
case ir_binop_gequal: |
return BRW_CONDITIONAL_GE; |
case ir_binop_equal: |
case ir_binop_all_equal: /* same as equal for scalars */ |
return BRW_CONDITIONAL_Z; |
case ir_binop_nequal: |
case ir_binop_any_nequal: /* same as nequal for scalars */ |
return BRW_CONDITIONAL_NZ; |
default: |
assert(!"not reached: bad operation for comparison"); |
return BRW_CONDITIONAL_NZ; |
} |
} |
uint32_t |
brw_math_function(enum opcode op) |
{ |
switch (op) { |
case SHADER_OPCODE_RCP: |
return BRW_MATH_FUNCTION_INV; |
case SHADER_OPCODE_RSQ: |
return BRW_MATH_FUNCTION_RSQ; |
case SHADER_OPCODE_SQRT: |
return BRW_MATH_FUNCTION_SQRT; |
case SHADER_OPCODE_EXP2: |
return BRW_MATH_FUNCTION_EXP; |
case SHADER_OPCODE_LOG2: |
return BRW_MATH_FUNCTION_LOG; |
case SHADER_OPCODE_POW: |
return BRW_MATH_FUNCTION_POW; |
case SHADER_OPCODE_SIN: |
return BRW_MATH_FUNCTION_SIN; |
case SHADER_OPCODE_COS: |
return BRW_MATH_FUNCTION_COS; |
case SHADER_OPCODE_INT_QUOTIENT: |
return BRW_MATH_FUNCTION_INT_DIV_QUOTIENT; |
case SHADER_OPCODE_INT_REMAINDER: |
return BRW_MATH_FUNCTION_INT_DIV_REMAINDER; |
default: |
assert(!"not reached: unknown math function"); |
return 0; |
} |
} |
uint32_t |
brw_texture_offset(ir_constant *offset) |
{ |
assert(offset != NULL); |
signed char offsets[3]; |
for (unsigned i = 0; i < offset->type->vector_elements; i++) |
offsets[i] = (signed char) offset->value.i[i]; |
/* Combine all three offsets into a single unsigned dword: |
* |
* bits 11:8 - U Offset (X component) |
* bits 7:4 - V Offset (Y component) |
* bits 3:0 - R Offset (Z component) |
*/ |
unsigned offset_bits = 0; |
for (unsigned i = 0; i < offset->type->vector_elements; i++) { |
const unsigned shift = 4 * (2 - i); |
offset_bits |= (offsets[i] << shift) & (0xF << shift); |
} |
return offset_bits; |
} |
const char * |
brw_instruction_name(enum opcode op) |
{ |
char *fallback; |
if (op < ARRAY_SIZE(opcode_descs) && opcode_descs[op].name) |
return opcode_descs[op].name; |
switch (op) { |
case FS_OPCODE_FB_WRITE: |
return "fb_write"; |
case SHADER_OPCODE_RCP: |
return "rcp"; |
case SHADER_OPCODE_RSQ: |
return "rsq"; |
case SHADER_OPCODE_SQRT: |
return "sqrt"; |
case SHADER_OPCODE_EXP2: |
return "exp2"; |
case SHADER_OPCODE_LOG2: |
return "log2"; |
case SHADER_OPCODE_POW: |
return "pow"; |
case SHADER_OPCODE_INT_QUOTIENT: |
return "int_quot"; |
case SHADER_OPCODE_INT_REMAINDER: |
return "int_rem"; |
case SHADER_OPCODE_SIN: |
return "sin"; |
case SHADER_OPCODE_COS: |
return "cos"; |
case SHADER_OPCODE_TEX: |
return "tex"; |
case SHADER_OPCODE_TXD: |
return "txd"; |
case SHADER_OPCODE_TXF: |
return "txf"; |
case SHADER_OPCODE_TXL: |
return "txl"; |
case SHADER_OPCODE_TXS: |
return "txs"; |
case FS_OPCODE_TXB: |
return "txb"; |
case SHADER_OPCODE_TXF_MS: |
return "txf_ms"; |
case FS_OPCODE_DDX: |
return "ddx"; |
case FS_OPCODE_DDY: |
return "ddy"; |
case FS_OPCODE_PIXEL_X: |
return "pixel_x"; |
case FS_OPCODE_PIXEL_Y: |
return "pixel_y"; |
case FS_OPCODE_CINTERP: |
return "cinterp"; |
case FS_OPCODE_LINTERP: |
return "linterp"; |
case FS_OPCODE_SPILL: |
return "spill"; |
case FS_OPCODE_UNSPILL: |
return "unspill"; |
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD: |
return "uniform_pull_const"; |
case FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD_GEN7: |
return "uniform_pull_const_gen7"; |
case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD: |
return "varying_pull_const"; |
case FS_OPCODE_VARYING_PULL_CONSTANT_LOAD_GEN7: |
return "varying_pull_const_gen7"; |
case FS_OPCODE_MOV_DISPATCH_TO_FLAGS: |
return "mov_dispatch_to_flags"; |
case FS_OPCODE_DISCARD_JUMP: |
return "discard_jump"; |
case FS_OPCODE_SET_SIMD4X2_OFFSET: |
return "set_simd4x2_offset"; |
case FS_OPCODE_PACK_HALF_2x16_SPLIT: |
return "pack_half_2x16_split"; |
case FS_OPCODE_UNPACK_HALF_2x16_SPLIT_X: |
return "unpack_half_2x16_split_x"; |
case FS_OPCODE_UNPACK_HALF_2x16_SPLIT_Y: |
return "unpack_half_2x16_split_y"; |
case FS_OPCODE_PLACEHOLDER_HALT: |
return "placeholder_halt"; |
case VS_OPCODE_URB_WRITE: |
return "urb_write"; |
case VS_OPCODE_SCRATCH_READ: |
return "scratch_read"; |
case VS_OPCODE_SCRATCH_WRITE: |
return "scratch_write"; |
case VS_OPCODE_PULL_CONSTANT_LOAD: |
return "pull_constant_load"; |
case VS_OPCODE_PULL_CONSTANT_LOAD_GEN7: |
return "pull_constant_load_gen7"; |
default: |
/* Yes, this leaks. It's in debug code, it should never occur, and if |
* it does, you should just add the case to the list above. |
*/ |
// asprintf(&fallback, "op%d", op); |
return fallback; |
} |
} |
bool |
backend_instruction::is_tex() |
{ |
return (opcode == SHADER_OPCODE_TEX || |
opcode == FS_OPCODE_TXB || |
opcode == SHADER_OPCODE_TXD || |
opcode == SHADER_OPCODE_TXF || |
opcode == SHADER_OPCODE_TXF_MS || |
opcode == SHADER_OPCODE_TXL || |
opcode == SHADER_OPCODE_TXS || |
opcode == SHADER_OPCODE_LOD); |
} |
bool |
backend_instruction::is_math() |
{ |
return (opcode == SHADER_OPCODE_RCP || |
opcode == SHADER_OPCODE_RSQ || |
opcode == SHADER_OPCODE_SQRT || |
opcode == SHADER_OPCODE_EXP2 || |
opcode == SHADER_OPCODE_LOG2 || |
opcode == SHADER_OPCODE_SIN || |
opcode == SHADER_OPCODE_COS || |
opcode == SHADER_OPCODE_INT_QUOTIENT || |
opcode == SHADER_OPCODE_INT_REMAINDER || |
opcode == SHADER_OPCODE_POW); |
} |
bool |
backend_instruction::is_control_flow() |
{ |
switch (opcode) { |
case BRW_OPCODE_DO: |
case BRW_OPCODE_WHILE: |
case BRW_OPCODE_IF: |
case BRW_OPCODE_ELSE: |
case BRW_OPCODE_ENDIF: |
case BRW_OPCODE_BREAK: |
case BRW_OPCODE_CONTINUE: |
return true; |
default: |
return false; |
} |
} |
void |
backend_visitor::dump_instructions() |
{ |
int ip = 0; |
foreach_list(node, &this->instructions) { |
backend_instruction *inst = (backend_instruction *)node; |
printf("%d: ", ip++); |
dump_instruction(inst); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_shader.h |
---|
0,0 → 1,78 |
/* |
* Copyright © 2010 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 <stdint.h> |
#include "brw_defines.h" |
#include "glsl/ir.h" |
#pragma once |
enum register_file { |
BAD_FILE, |
ARF, |
GRF, |
MRF, |
IMM, |
HW_REG, /* a struct brw_reg */ |
ATTR, |
UNIFORM, /* prog_data->params[reg] */ |
}; |
class backend_instruction : public exec_node { |
public: |
bool is_tex(); |
bool is_math(); |
bool is_control_flow(); |
enum opcode opcode; /* BRW_OPCODE_* or FS_OPCODE_* */ |
uint32_t predicate; |
bool predicate_inverse; |
}; |
class backend_visitor : public ir_visitor { |
public: |
struct brw_context *brw; |
struct gl_context *ctx; |
struct brw_shader *shader; |
struct gl_shader_program *shader_prog; |
/** ralloc context for temporary data used during compile */ |
void *mem_ctx; |
/** |
* List of either fs_inst or vec4_instruction (inheriting from |
* backend_instruction) |
*/ |
exec_list instructions; |
virtual void dump_instruction(backend_instruction *inst) = 0; |
void dump_instructions(); |
}; |
int brw_type_for_base_type(const struct glsl_type *type); |
uint32_t brw_conditional_for_comparison(unsigned int op); |
uint32_t brw_math_function(enum opcode op); |
uint32_t brw_texture_offset(ir_constant *offset); |
const char *brw_instruction_name(enum opcode op); |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_state.h |
---|
0,0 → 1,220 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 BRW_STATE_H |
#define BRW_STATE_H |
#include "brw_context.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
enum intel_msaa_layout; |
extern const struct brw_tracked_state brw_blend_constant_color; |
extern const struct brw_tracked_state brw_cc_vp; |
extern const struct brw_tracked_state brw_cc_unit; |
extern const struct brw_tracked_state brw_clip_prog; |
extern const struct brw_tracked_state brw_clip_unit; |
extern const struct brw_tracked_state brw_vs_pull_constants; |
extern const struct brw_tracked_state brw_wm_pull_constants; |
extern const struct brw_tracked_state brw_constant_buffer; |
extern const struct brw_tracked_state brw_curbe_offsets; |
extern const struct brw_tracked_state brw_invariant_state; |
extern const struct brw_tracked_state brw_gs_prog; |
extern const struct brw_tracked_state brw_gs_unit; |
extern const struct brw_tracked_state brw_line_stipple; |
extern const struct brw_tracked_state brw_aa_line_parameters; |
extern const struct brw_tracked_state brw_binding_table_pointers; |
extern const struct brw_tracked_state brw_depthbuffer; |
extern const struct brw_tracked_state brw_polygon_stipple_offset; |
extern const struct brw_tracked_state brw_polygon_stipple; |
extern const struct brw_tracked_state brw_recalculate_urb_fence; |
extern const struct brw_tracked_state brw_samplers; |
extern const struct brw_tracked_state brw_sf_prog; |
extern const struct brw_tracked_state brw_sf_unit; |
extern const struct brw_tracked_state brw_sf_vp; |
extern const struct brw_tracked_state brw_state_base_address; |
extern const struct brw_tracked_state brw_urb_fence; |
extern const struct brw_tracked_state brw_vs_prog; |
extern const struct brw_tracked_state brw_vs_ubo_surfaces; |
extern const struct brw_tracked_state brw_vs_unit; |
extern const struct brw_tracked_state brw_wm_prog; |
extern const struct brw_tracked_state brw_renderbuffer_surfaces; |
extern const struct brw_tracked_state brw_texture_surfaces; |
extern const struct brw_tracked_state brw_wm_binding_table; |
extern const struct brw_tracked_state brw_vs_binding_table; |
extern const struct brw_tracked_state brw_wm_ubo_surfaces; |
extern const struct brw_tracked_state brw_wm_unit; |
extern const struct brw_tracked_state brw_psp_urb_cbs; |
extern const struct brw_tracked_state brw_drawing_rect; |
extern const struct brw_tracked_state brw_indices; |
extern const struct brw_tracked_state brw_vertices; |
extern const struct brw_tracked_state brw_index_buffer; |
extern const struct brw_tracked_state gen6_binding_table_pointers; |
extern const struct brw_tracked_state gen6_blend_state; |
extern const struct brw_tracked_state gen6_cc_state_pointers; |
extern const struct brw_tracked_state gen6_clip_state; |
extern const struct brw_tracked_state gen6_clip_vp; |
extern const struct brw_tracked_state gen6_color_calc_state; |
extern const struct brw_tracked_state gen6_depth_stencil_state; |
extern const struct brw_tracked_state gen6_gs_state; |
extern const struct brw_tracked_state gen6_gs_binding_table; |
extern const struct brw_tracked_state gen6_multisample_state; |
extern const struct brw_tracked_state gen6_renderbuffer_surfaces; |
extern const struct brw_tracked_state gen6_sampler_state; |
extern const struct brw_tracked_state gen6_scissor_state; |
extern const struct brw_tracked_state gen6_sol_surface; |
extern const struct brw_tracked_state gen6_sf_state; |
extern const struct brw_tracked_state gen6_sf_vp; |
extern const struct brw_tracked_state gen6_urb; |
extern const struct brw_tracked_state gen6_viewport_state; |
extern const struct brw_tracked_state gen6_vs_push_constants; |
extern const struct brw_tracked_state gen6_vs_state; |
extern const struct brw_tracked_state gen6_wm_push_constants; |
extern const struct brw_tracked_state gen6_wm_state; |
extern const struct brw_tracked_state gen7_depthbuffer; |
extern const struct brw_tracked_state gen7_cc_viewport_state_pointer; |
extern const struct brw_tracked_state gen7_clip_state; |
extern const struct brw_tracked_state gen7_disable_stages; |
extern const struct brw_tracked_state gen7_ps_state; |
extern const struct brw_tracked_state gen7_samplers; |
extern const struct brw_tracked_state gen7_sbe_state; |
extern const struct brw_tracked_state gen7_sf_clip_viewport; |
extern const struct brw_tracked_state gen7_sf_state; |
extern const struct brw_tracked_state gen7_sol_state; |
extern const struct brw_tracked_state gen7_urb; |
extern const struct brw_tracked_state gen7_vs_state; |
extern const struct brw_tracked_state gen7_wm_state; |
extern const struct brw_tracked_state haswell_cut_index; |
/* brw_misc_state.c */ |
void brw_upload_invariant_state(struct brw_context *brw); |
uint32_t |
brw_depthbuffer_format(struct brw_context *brw); |
/*********************************************************************** |
* brw_state.c |
*/ |
void brw_upload_state(struct brw_context *brw); |
void brw_init_state(struct brw_context *brw); |
void brw_destroy_state(struct brw_context *brw); |
/*********************************************************************** |
* brw_state_cache.c |
*/ |
void brw_upload_cache(struct brw_cache *cache, |
enum brw_cache_id cache_id, |
const void *key, |
GLuint key_sz, |
const void *data, |
GLuint data_sz, |
const void *aux, |
GLuint aux_sz, |
uint32_t *out_offset, void *out_aux); |
bool brw_search_cache(struct brw_cache *cache, |
enum brw_cache_id cache_id, |
const void *key, |
GLuint key_size, |
uint32_t *inout_offset, void *out_aux); |
void brw_state_cache_check_size( struct brw_context *brw ); |
void brw_init_caches( struct brw_context *brw ); |
void brw_destroy_caches( struct brw_context *brw ); |
/*********************************************************************** |
* brw_state_batch.c |
*/ |
#define BRW_BATCH_STRUCT(brw, s) intel_batchbuffer_data(brw, (s), \ |
sizeof(*(s)), false) |
void *brw_state_batch(struct brw_context *brw, |
enum state_struct_type type, |
int size, |
int alignment, |
uint32_t *out_offset); |
/* brw_wm_surface_state.c */ |
void gen4_init_vtable_surface_functions(struct brw_context *brw); |
uint32_t brw_get_surface_tiling_bits(uint32_t tiling); |
uint32_t brw_get_surface_num_multisamples(unsigned num_samples); |
uint32_t brw_format_for_mesa_format(gl_format mesa_format); |
GLuint translate_tex_target(GLenum target); |
GLuint translate_tex_format(struct brw_context *brw, |
gl_format mesa_format, |
GLenum depth_mode, |
GLenum srgb_decode); |
int brw_get_texture_swizzle(const struct gl_context *ctx, |
const struct gl_texture_object *t); |
/* gen7_wm_surface_state.c */ |
uint32_t gen7_surface_tiling_mode(uint32_t tiling); |
uint32_t gen7_surface_msaa_bits(unsigned num_samples, enum intel_msaa_layout l); |
void gen7_set_surface_mcs_info(struct brw_context *brw, |
uint32_t *surf, |
uint32_t surf_offset, |
const struct intel_mipmap_tree *mcs_mt, |
bool is_render_target); |
void gen7_check_surface_setup(uint32_t *surf, bool is_render_target); |
void gen7_init_vtable_surface_functions(struct brw_context *brw); |
void gen7_create_shader_time_surface(struct brw_context *brw, |
uint32_t *out_offset); |
/* brw_wm_sampler_state.c */ |
uint32_t translate_wrap_mode(GLenum wrap, bool using_nearest); |
void upload_default_color(struct brw_context *brw, |
struct gl_sampler_object *sampler, |
int unit, int ss_index); |
/* gen6_sf_state.c */ |
uint32_t |
get_attr_override(const struct brw_vue_map *vue_map, int urb_entry_read_offset, |
int fs_attr, bool two_side_color, uint32_t *max_source_attr); |
/* gen7_urb.c */ |
void gen7_allocate_push_constants(struct brw_context *brw); |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_state_batch.c |
---|
0,0 → 1,147 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "brw_state.h" |
#include "intel_batchbuffer.h" |
#include "main/imports.h" |
#include "glsl/ralloc.h" |
static void |
brw_track_state_batch(struct brw_context *brw, |
enum state_struct_type type, |
uint32_t offset, |
int size) |
{ |
struct intel_batchbuffer *batch = &brw->batch; |
if (!brw->state_batch_list) { |
/* Our structs are always aligned to at least 32 bytes, so |
* our array doesn't need to be any larger |
*/ |
brw->state_batch_list = ralloc_size(brw, sizeof(*brw->state_batch_list) * |
batch->bo->size / 32); |
} |
brw->state_batch_list[brw->state_batch_count].offset = offset; |
brw->state_batch_list[brw->state_batch_count].size = size; |
brw->state_batch_list[brw->state_batch_count].type = type; |
brw->state_batch_count++; |
} |
/** |
* Convenience function to populate a single drm_intel_aub_annotation data |
* structure. |
*/ |
static inline void |
make_annotation(drm_intel_aub_annotation *annotation, uint32_t type, |
uint32_t subtype, uint32_t ending_offset) |
{ |
annotation->type = type; |
annotation->subtype = subtype; |
annotation->ending_offset = ending_offset; |
} |
/** |
* Generate a set of aub file annotations for the current batch buffer, and |
* deliver them to DRM. |
* |
* The "used" section of the batch buffer (the portion containing batch |
* commands) is annotated with AUB_TRACE_TYPE_BATCH. The remainder of the |
* batch buffer (which contains data structures pointed to by batch commands) |
* is annotated according to the type of each data structure. |
*/ |
void |
brw_annotate_aub(struct brw_context *brw) |
{ |
unsigned annotation_count = 2 * brw->state_batch_count + 1; |
drm_intel_aub_annotation annotations[annotation_count]; |
int a = 0; |
make_annotation(&annotations[a++], AUB_TRACE_TYPE_BATCH, 0, |
4*brw->batch.used); |
for (int i = brw->state_batch_count; i-- > 0; ) { |
uint32_t type = brw->state_batch_list[i].type; |
uint32_t start_offset = brw->state_batch_list[i].offset; |
uint32_t end_offset = start_offset + brw->state_batch_list[i].size; |
make_annotation(&annotations[a++], AUB_TRACE_TYPE_NOTYPE, 0, |
start_offset); |
make_annotation(&annotations[a++], AUB_TRACE_TYPE(type), |
AUB_TRACE_SUBTYPE(type), end_offset); |
} |
assert(a == annotation_count); |
drm_intel_bufmgr_gem_set_aub_annotations(brw->batch.bo, annotations, |
annotation_count); |
} |
/** |
* Allocates a block of space in the batchbuffer for indirect state. |
* |
* We don't want to allocate separate BOs for every bit of indirect |
* state in the driver. It means overallocating by a significant |
* margin (4096 bytes, even if the object is just a 20-byte surface |
* state), and more buffers to walk and count for aperture size checking. |
* |
* However, due to the restrictions inposed by the aperture size |
* checking performance hacks, we can't have the batch point at a |
* separate indirect state buffer, because once the batch points at |
* it, no more relocations can be added to it. So, we sneak these |
* buffers in at the top of the batchbuffer. |
*/ |
void * |
brw_state_batch(struct brw_context *brw, |
enum state_struct_type type, |
int size, |
int alignment, |
uint32_t *out_offset) |
{ |
struct intel_batchbuffer *batch = &brw->batch; |
uint32_t offset; |
assert(size < batch->bo->size); |
offset = ROUND_DOWN_TO(batch->state_batch_offset - size, alignment); |
/* If allocating from the top would wrap below the batchbuffer, or |
* if the batch's used space (plus the reserved pad) collides with our |
* space, then flush and try again. |
*/ |
if (batch->state_batch_offset < size || |
offset < 4*batch->used + batch->reserved_space) { |
intel_batchbuffer_flush(brw); |
offset = ROUND_DOWN_TO(batch->state_batch_offset - size, alignment); |
} |
batch->state_batch_offset = offset; |
if (unlikely(INTEL_DEBUG & (DEBUG_BATCH | DEBUG_AUB))) |
brw_track_state_batch(brw, type, offset, size); |
*out_offset = offset; |
return batch->map + (offset>>2); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_state_cache.c |
---|
0,0 → 1,419 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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> |
*/ |
/** @file brw_state_cache.c |
* |
* This file implements a simple static state cache for 965. The |
* consumers can query the hash table of state using a cache_id, |
* opaque key data, and receive the corresponding state buffer object |
* of state (plus associated auxiliary data) in return. Objects in |
* the cache may not have relocations (pointers to other BOs) in them. |
* |
* The inner workings are a simple hash table based on a CRC of the |
* key data. |
* |
* Replacement is not implemented. Instead, when the cache gets too |
* big we throw out all of the cache data and let it get regenerated. |
*/ |
#include "main/imports.h" |
#include "intel_batchbuffer.h" |
#include "brw_state.h" |
#include "brw_vs.h" |
#include "brw_wm.h" |
#include "brw_vs.h" |
#define FILE_DEBUG_FLAG DEBUG_STATE |
static GLuint |
hash_key(struct brw_cache_item *item) |
{ |
GLuint *ikey = (GLuint *)item->key; |
GLuint hash = item->cache_id, i; |
assert(item->key_size % 4 == 0); |
/* I'm sure this can be improved on: |
*/ |
for (i = 0; i < item->key_size/4; i++) { |
hash ^= ikey[i]; |
hash = (hash << 5) | (hash >> 27); |
} |
return hash; |
} |
static int |
brw_cache_item_equals(const struct brw_cache_item *a, |
const struct brw_cache_item *b) |
{ |
return a->cache_id == b->cache_id && |
a->hash == b->hash && |
a->key_size == b->key_size && |
(memcmp(a->key, b->key, a->key_size) == 0); |
} |
static struct brw_cache_item * |
search_cache(struct brw_cache *cache, GLuint hash, |
struct brw_cache_item *lookup) |
{ |
struct brw_cache_item *c; |
#if 0 |
int bucketcount = 0; |
for (c = cache->items[hash % cache->size]; c; c = c->next) |
bucketcount++; |
fprintf(stderr, "bucket %d/%d = %d/%d items\n", hash % cache->size, |
cache->size, bucketcount, cache->n_items); |
#endif |
for (c = cache->items[hash % cache->size]; c; c = c->next) { |
if (brw_cache_item_equals(lookup, c)) |
return c; |
} |
return NULL; |
} |
static void |
rehash(struct brw_cache *cache) |
{ |
struct brw_cache_item **items; |
struct brw_cache_item *c, *next; |
GLuint size, i; |
size = cache->size * 3; |
items = calloc(1, size * sizeof(*items)); |
for (i = 0; i < cache->size; i++) |
for (c = cache->items[i]; c; c = next) { |
next = c->next; |
c->next = items[c->hash % size]; |
items[c->hash % size] = c; |
} |
free(cache->items); |
cache->items = items; |
cache->size = size; |
} |
/** |
* Returns the buffer object matching cache_id and key, or NULL. |
*/ |
bool |
brw_search_cache(struct brw_cache *cache, |
enum brw_cache_id cache_id, |
const void *key, GLuint key_size, |
uint32_t *inout_offset, void *out_aux) |
{ |
struct brw_context *brw = cache->brw; |
struct brw_cache_item *item; |
struct brw_cache_item lookup; |
GLuint hash; |
lookup.cache_id = cache_id; |
lookup.key = key; |
lookup.key_size = key_size; |
hash = hash_key(&lookup); |
lookup.hash = hash; |
item = search_cache(cache, hash, &lookup); |
if (item == NULL) |
return false; |
*(void **)out_aux = ((char *)item->key + item->key_size); |
if (item->offset != *inout_offset) { |
brw->state.dirty.cache |= (1 << cache_id); |
*inout_offset = item->offset; |
} |
return true; |
} |
static void |
brw_cache_new_bo(struct brw_cache *cache, uint32_t new_size) |
{ |
struct brw_context *brw = cache->brw; |
drm_intel_bo *new_bo; |
new_bo = drm_intel_bo_alloc(brw->bufmgr, "program cache", new_size, 64); |
/* Copy any existing data that needs to be saved. */ |
if (cache->next_offset != 0) { |
drm_intel_bo_map(cache->bo, false); |
drm_intel_bo_subdata(new_bo, 0, cache->next_offset, cache->bo->virtual); |
drm_intel_bo_unmap(cache->bo); |
} |
drm_intel_bo_unreference(cache->bo); |
cache->bo = new_bo; |
cache->bo_used_by_gpu = false; |
/* Since we have a new BO in place, we need to signal the units |
* that depend on it (state base address on gen5+, or unit state before). |
*/ |
brw->state.dirty.brw |= BRW_NEW_PROGRAM_CACHE; |
} |
/** |
* Attempts to find an item in the cache with identical data and aux |
* data to use |
*/ |
static bool |
brw_try_upload_using_copy(struct brw_cache *cache, |
struct brw_cache_item *result_item, |
const void *data, |
const void *aux) |
{ |
int i; |
struct brw_cache_item *item; |
for (i = 0; i < cache->size; i++) { |
for (item = cache->items[i]; item; item = item->next) { |
const void *item_aux = item->key + item->key_size; |
int ret; |
if (item->cache_id != result_item->cache_id || |
item->size != result_item->size || |
item->aux_size != result_item->aux_size) { |
continue; |
} |
if (cache->aux_compare[result_item->cache_id]) { |
if (!cache->aux_compare[result_item->cache_id](item_aux, aux, |
item->aux_size, |
item->key)) |
continue; |
} else if (memcmp(item_aux, aux, item->aux_size) != 0) { |
continue; |
} |
drm_intel_bo_map(cache->bo, false); |
ret = memcmp(cache->bo->virtual + item->offset, data, item->size); |
drm_intel_bo_unmap(cache->bo); |
if (ret) |
continue; |
result_item->offset = item->offset; |
return true; |
} |
} |
return false; |
} |
static void |
brw_upload_item_data(struct brw_cache *cache, |
struct brw_cache_item *item, |
const void *data) |
{ |
/* Allocate space in the cache BO for our new program. */ |
if (cache->next_offset + item->size > cache->bo->size) { |
uint32_t new_size = cache->bo->size * 2; |
while (cache->next_offset + item->size > new_size) |
new_size *= 2; |
brw_cache_new_bo(cache, new_size); |
} |
/* If we would block on writing to an in-use program BO, just |
* recreate it. |
*/ |
if (cache->bo_used_by_gpu) { |
brw_cache_new_bo(cache, cache->bo->size); |
} |
item->offset = cache->next_offset; |
/* Programs are always 64-byte aligned, so set up the next one now */ |
cache->next_offset = ALIGN(item->offset + item->size, 64); |
} |
void |
brw_upload_cache(struct brw_cache *cache, |
enum brw_cache_id cache_id, |
const void *key, |
GLuint key_size, |
const void *data, |
GLuint data_size, |
const void *aux, |
GLuint aux_size, |
uint32_t *out_offset, |
void *out_aux) |
{ |
struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item); |
GLuint hash; |
void *tmp; |
item->cache_id = cache_id; |
item->size = data_size; |
item->key = key; |
item->key_size = key_size; |
item->aux_size = aux_size; |
hash = hash_key(item); |
item->hash = hash; |
/* If we can find a matching prog/prog_data combo in the cache |
* already, then reuse the existing stuff. This will mean not |
* flagging CACHE_NEW_* when transitioning between the two |
* equivalent hash keys. This is notably useful for programs |
* generating shaders at runtime, where multiple shaders may |
* compile to the thing in our backend. |
*/ |
if (!brw_try_upload_using_copy(cache, item, data, aux)) { |
brw_upload_item_data(cache, item, data); |
} |
/* Set up the memory containing the key and aux_data */ |
tmp = malloc(key_size + aux_size); |
memcpy(tmp, key, key_size); |
memcpy(tmp + key_size, aux, aux_size); |
item->key = tmp; |
if (cache->n_items > cache->size * 1.5) |
rehash(cache); |
hash %= cache->size; |
item->next = cache->items[hash]; |
cache->items[hash] = item; |
cache->n_items++; |
/* Copy data to the buffer */ |
drm_intel_bo_subdata(cache->bo, item->offset, data_size, data); |
*out_offset = item->offset; |
*(void **)out_aux = (void *)((char *)item->key + item->key_size); |
cache->brw->state.dirty.cache |= 1 << cache_id; |
} |
void |
brw_init_caches(struct brw_context *brw) |
{ |
struct brw_cache *cache = &brw->cache; |
cache->brw = brw; |
cache->size = 7; |
cache->n_items = 0; |
cache->items = |
calloc(1, cache->size * sizeof(struct brw_cache_item *)); |
cache->bo = drm_intel_bo_alloc(brw->bufmgr, |
"program cache", |
4096, 64); |
cache->aux_compare[BRW_VS_PROG] = brw_vs_prog_data_compare; |
cache->aux_compare[BRW_WM_PROG] = brw_wm_prog_data_compare; |
cache->aux_free[BRW_VS_PROG] = brw_vs_prog_data_free; |
cache->aux_free[BRW_WM_PROG] = brw_wm_prog_data_free; |
} |
static void |
brw_clear_cache(struct brw_context *brw, struct brw_cache *cache) |
{ |
struct brw_cache_item *c, *next; |
GLuint i; |
DBG("%s\n", __FUNCTION__); |
for (i = 0; i < cache->size; i++) { |
for (c = cache->items[i]; c; c = next) { |
next = c->next; |
if (cache->aux_free[c->cache_id]) { |
const void *item_aux = c->key + c->key_size; |
cache->aux_free[c->cache_id](item_aux); |
} |
free((void *)c->key); |
free(c); |
} |
cache->items[i] = NULL; |
} |
cache->n_items = 0; |
/* Start putting programs into the start of the BO again, since |
* we'll never find the old results. |
*/ |
cache->next_offset = 0; |
/* We need to make sure that the programs get regenerated, since |
* any offsets leftover in brw_context will no longer be valid. |
*/ |
brw->state.dirty.mesa |= ~0; |
brw->state.dirty.brw |= ~0; |
brw->state.dirty.cache |= ~0; |
intel_batchbuffer_flush(brw); |
} |
void |
brw_state_cache_check_size(struct brw_context *brw) |
{ |
/* un-tuned guess. Each object is generally a page, so 2000 of them is 8 MB of |
* state cache. |
*/ |
if (brw->cache.n_items > 2000) { |
perf_debug("Exceeded state cache size limit. Clearing the set " |
"of compiled programs, which will trigger recompiles\n"); |
brw_clear_cache(brw, &brw->cache); |
} |
} |
static void |
brw_destroy_cache(struct brw_context *brw, struct brw_cache *cache) |
{ |
DBG("%s\n", __FUNCTION__); |
drm_intel_bo_unreference(cache->bo); |
cache->bo = NULL; |
brw_clear_cache(brw, cache); |
free(cache->items); |
cache->items = NULL; |
cache->size = 0; |
} |
void |
brw_destroy_caches(struct brw_context *brw) |
{ |
brw_destroy_cache(brw, &brw->cache); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_state_dump.c |
---|
0,0 → 1,635 |
/* |
* Copyright © 2007 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "main/mtypes.h" |
#include "intel_batchbuffer.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
static void |
batch_out(struct brw_context *brw, const char *name, uint32_t offset, |
int index, char *fmt, ...) PRINTFLIKE(5, 6); |
static void |
batch_out(struct brw_context *brw, const char *name, uint32_t offset, |
int index, char *fmt, ...) |
{ |
uint32_t *data = brw->batch.bo->virtual + offset; |
va_list va; |
fprintf(stderr, "0x%08x: 0x%08x: %8s: ", |
offset + index * 4, data[index], name); |
va_start(va, fmt); |
vfprintf(stderr, fmt, va); |
va_end(va); |
} |
static const char * |
get_965_surfacetype(unsigned int surfacetype) |
{ |
switch (surfacetype) { |
case 0: return "1D"; |
case 1: return "2D"; |
case 2: return "3D"; |
case 3: return "CUBE"; |
case 4: return "BUFFER"; |
case 7: return "NULL"; |
default: return "unknown"; |
} |
} |
static const char * |
get_965_surface_format(unsigned int surface_format) |
{ |
switch (surface_format) { |
case 0x000: return "r32g32b32a32_float"; |
case 0x0c1: return "b8g8r8a8_unorm"; |
case 0x100: return "b5g6r5_unorm"; |
case 0x102: return "b5g5r5a1_unorm"; |
case 0x104: return "b4g4r4a4_unorm"; |
default: return "unknown"; |
} |
} |
static void dump_vs_state(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "VS_STATE"; |
struct brw_vs_unit_state *vs = brw->batch.bo->virtual + offset; |
batch_out(brw, name, offset, 0, "thread0\n"); |
batch_out(brw, name, offset, 1, "thread1\n"); |
batch_out(brw, name, offset, 2, "thread2\n"); |
batch_out(brw, name, offset, 3, "thread3\n"); |
batch_out(brw, name, offset, 4, "thread4: %d threads\n", |
vs->thread4.max_threads + 1); |
batch_out(brw, name, offset, 5, "vs5\n"); |
batch_out(brw, name, offset, 6, "vs6\n"); |
} |
static void dump_gs_state(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "GS_STATE"; |
struct brw_gs_unit_state *gs = brw->batch.bo->virtual + offset; |
batch_out(brw, name, offset, 0, "thread0\n"); |
batch_out(brw, name, offset, 1, "thread1\n"); |
batch_out(brw, name, offset, 2, "thread2\n"); |
batch_out(brw, name, offset, 3, "thread3\n"); |
batch_out(brw, name, offset, 4, "thread4: %d threads\n", |
gs->thread4.max_threads + 1); |
batch_out(brw, name, offset, 5, "vs5\n"); |
batch_out(brw, name, offset, 6, "vs6\n"); |
} |
static void dump_clip_state(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "CLIP_STATE"; |
struct brw_clip_unit_state *clip = brw->batch.bo->virtual + offset; |
batch_out(brw, name, offset, 0, "thread0\n"); |
batch_out(brw, name, offset, 1, "thread1\n"); |
batch_out(brw, name, offset, 2, "thread2\n"); |
batch_out(brw, name, offset, 3, "thread3\n"); |
batch_out(brw, name, offset, 4, "thread4: %d threads\n", |
clip->thread4.max_threads + 1); |
batch_out(brw, name, offset, 5, "clip5\n"); |
batch_out(brw, name, offset, 6, "clip6\n"); |
batch_out(brw, name, offset, 7, "vp xmin %f\n", clip->viewport_xmin); |
batch_out(brw, name, offset, 8, "vp xmax %f\n", clip->viewport_xmax); |
batch_out(brw, name, offset, 9, "vp ymin %f\n", clip->viewport_ymin); |
batch_out(brw, name, offset, 10, "vp ymax %f\n", clip->viewport_ymax); |
} |
static void dump_sf_state(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "SF_STATE"; |
struct brw_sf_unit_state *sf = brw->batch.bo->virtual + offset; |
batch_out(brw, name, offset, 0, "thread0\n"); |
batch_out(brw, name, offset, 1, "thread1\n"); |
batch_out(brw, name, offset, 2, "thread2\n"); |
batch_out(brw, name, offset, 3, "thread3\n"); |
batch_out(brw, name, offset, 4, "thread4: %d threads\n", |
sf->thread4.max_threads + 1); |
batch_out(brw, name, offset, 5, "sf5: viewport offset\n"); |
batch_out(brw, name, offset, 6, "sf6\n"); |
batch_out(brw, name, offset, 7, "sf7\n"); |
} |
static void dump_wm_state(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "WM_STATE"; |
struct brw_wm_unit_state *wm = brw->batch.bo->virtual + offset; |
batch_out(brw, name, offset, 0, "thread0\n"); |
batch_out(brw, name, offset, 1, "thread1\n"); |
batch_out(brw, name, offset, 2, "thread2\n"); |
batch_out(brw, name, offset, 3, "thread3\n"); |
batch_out(brw, name, offset, 4, "wm4\n"); |
batch_out(brw, name, offset, 5, "wm5: %s%s%s%s%s%s, %d threads\n", |
wm->wm5.enable_8_pix ? "8pix" : "", |
wm->wm5.enable_16_pix ? "16pix" : "", |
wm->wm5.program_uses_depth ? ", uses depth" : "", |
wm->wm5.program_computes_depth ? ", computes depth" : "", |
wm->wm5.program_uses_killpixel ? ", kills" : "", |
wm->wm5.thread_dispatch_enable ? "" : ", no dispatch", |
wm->wm5.max_threads + 1); |
batch_out(brw, name, offset, 6, "depth offset constant %f\n", |
wm->global_depth_offset_constant); |
batch_out(brw, name, offset, 7, "depth offset scale %f\n", |
wm->global_depth_offset_scale); |
batch_out(brw, name, offset, 8, "wm8: kernel 1 (gen5+)\n"); |
batch_out(brw, name, offset, 9, "wm9: kernel 2 (gen5+)\n"); |
batch_out(brw, name, offset, 10, "wm10: kernel 3 (gen5+)\n"); |
} |
static void dump_surface_state(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "SURF"; |
uint32_t *surf = brw->batch.bo->virtual + offset; |
batch_out(brw, name, offset, 0, "%s %s\n", |
get_965_surfacetype(GET_FIELD(surf[0], BRW_SURFACE_TYPE)), |
get_965_surface_format(GET_FIELD(surf[0], BRW_SURFACE_FORMAT))); |
batch_out(brw, name, offset, 1, "offset\n"); |
batch_out(brw, name, offset, 2, "%dx%d size, %d mips\n", |
GET_FIELD(surf[2], BRW_SURFACE_WIDTH) + 1, |
GET_FIELD(surf[2], BRW_SURFACE_HEIGHT) + 1, |
GET_FIELD(surf[2], BRW_SURFACE_LOD)); |
batch_out(brw, name, offset, 3, "pitch %d, %s tiled\n", |
GET_FIELD(surf[3], BRW_SURFACE_PITCH) + 1, |
(surf[3] & BRW_SURFACE_TILED) ? |
((surf[3] & BRW_SURFACE_TILED_Y) ? "Y" : "X") : "not"); |
batch_out(brw, name, offset, 4, "mip base %d\n", |
GET_FIELD(surf[4], BRW_SURFACE_MIN_LOD)); |
batch_out(brw, name, offset, 5, "x,y offset: %d,%d\n", |
GET_FIELD(surf[5], BRW_SURFACE_X_OFFSET), |
GET_FIELD(surf[5], BRW_SURFACE_Y_OFFSET)); |
} |
static void dump_gen7_surface_state(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "SURF"; |
uint32_t *surf = brw->batch.bo->virtual + offset; |
batch_out(brw, name, offset, 0, "%s %s\n", |
get_965_surfacetype(GET_FIELD(surf[0], BRW_SURFACE_TYPE)), |
get_965_surface_format(GET_FIELD(surf[0], BRW_SURFACE_FORMAT))); |
batch_out(brw, name, offset, 1, "offset\n"); |
batch_out(brw, name, offset, 2, "%dx%d size, %d mips\n", |
GET_FIELD(surf[2], GEN7_SURFACE_WIDTH) + 1, |
GET_FIELD(surf[2], GEN7_SURFACE_HEIGHT) + 1, |
surf[5] & INTEL_MASK(3, 0)); |
batch_out(brw, name, offset, 3, "pitch %d, %stiled\n", |
(surf[3] & INTEL_MASK(17, 0)) + 1, |
(surf[0] & (1 << 14)) ? "" : "not "); |
batch_out(brw, name, offset, 4, "mip base %d\n", |
GET_FIELD(surf[5], GEN7_SURFACE_MIN_LOD)); |
batch_out(brw, name, offset, 5, "x,y offset: %d,%d\n", |
GET_FIELD(surf[5], BRW_SURFACE_X_OFFSET), |
GET_FIELD(surf[5], BRW_SURFACE_Y_OFFSET)); |
} |
static void |
dump_sdc(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "SDC"; |
if (brw->gen >= 5 && brw->gen <= 6) { |
struct gen5_sampler_default_color *sdc = (brw->batch.bo->virtual + |
offset); |
batch_out(brw, name, offset, 0, "unorm rgba\n"); |
batch_out(brw, name, offset, 1, "r %f\n", sdc->f[0]); |
batch_out(brw, name, offset, 2, "b %f\n", sdc->f[1]); |
batch_out(brw, name, offset, 3, "g %f\n", sdc->f[2]); |
batch_out(brw, name, offset, 4, "a %f\n", sdc->f[3]); |
batch_out(brw, name, offset, 5, "half float rg\n"); |
batch_out(brw, name, offset, 6, "half float ba\n"); |
batch_out(brw, name, offset, 7, "u16 rg\n"); |
batch_out(brw, name, offset, 8, "u16 ba\n"); |
batch_out(brw, name, offset, 9, "s16 rg\n"); |
batch_out(brw, name, offset, 10, "s16 ba\n"); |
batch_out(brw, name, offset, 11, "s8 rgba\n"); |
} else { |
struct brw_sampler_default_color *sdc = (brw->batch.bo->virtual + |
offset); |
batch_out(brw, name, offset, 0, "r %f\n", sdc->color[0]); |
batch_out(brw, name, offset, 1, "g %f\n", sdc->color[1]); |
batch_out(brw, name, offset, 2, "b %f\n", sdc->color[2]); |
batch_out(brw, name, offset, 3, "a %f\n", sdc->color[3]); |
} |
} |
static void dump_sampler_state(struct brw_context *brw, |
uint32_t offset, uint32_t size) |
{ |
int i; |
struct brw_sampler_state *samp = brw->batch.bo->virtual + offset; |
assert(brw->gen < 7); |
for (i = 0; i < size / sizeof(*samp); i++) { |
char name[20]; |
sprintf(name, "WM SAMP%d", i); |
batch_out(brw, name, offset, 0, "filtering\n"); |
batch_out(brw, name, offset, 1, "wrapping, lod\n"); |
batch_out(brw, name, offset, 2, "default color pointer\n"); |
batch_out(brw, name, offset, 3, "chroma key, aniso\n"); |
samp++; |
offset += sizeof(*samp); |
} |
} |
static void dump_gen7_sampler_state(struct brw_context *brw, |
uint32_t offset, uint32_t size) |
{ |
struct gen7_sampler_state *samp = brw->batch.bo->virtual + offset; |
int i; |
assert(brw->gen >= 7); |
for (i = 0; i < size / sizeof(*samp); i++) { |
char name[20]; |
sprintf(name, "WM SAMP%d", i); |
batch_out(brw, name, offset, 0, "filtering\n"); |
batch_out(brw, name, offset, 1, "wrapping, lod\n"); |
batch_out(brw, name, offset, 2, "default color pointer\n"); |
batch_out(brw, name, offset, 3, "chroma key, aniso\n"); |
samp++; |
offset += sizeof(*samp); |
} |
} |
static void dump_sf_viewport_state(struct brw_context *brw, |
uint32_t offset) |
{ |
const char *name = "SF VP"; |
struct brw_sf_viewport *vp = brw->batch.bo->virtual + offset; |
assert(brw->gen < 7); |
batch_out(brw, name, offset, 0, "m00 = %f\n", vp->viewport.m00); |
batch_out(brw, name, offset, 1, "m11 = %f\n", vp->viewport.m11); |
batch_out(brw, name, offset, 2, "m22 = %f\n", vp->viewport.m22); |
batch_out(brw, name, offset, 3, "m30 = %f\n", vp->viewport.m30); |
batch_out(brw, name, offset, 4, "m31 = %f\n", vp->viewport.m31); |
batch_out(brw, name, offset, 5, "m32 = %f\n", vp->viewport.m32); |
batch_out(brw, name, offset, 6, "top left = %d,%d\n", |
vp->scissor.xmin, vp->scissor.ymin); |
batch_out(brw, name, offset, 7, "bottom right = %d,%d\n", |
vp->scissor.xmax, vp->scissor.ymax); |
} |
static void dump_clip_viewport_state(struct brw_context *brw, |
uint32_t offset) |
{ |
const char *name = "CLIP VP"; |
struct brw_clipper_viewport *vp = brw->batch.bo->virtual + offset; |
assert(brw->gen < 7); |
batch_out(brw, name, offset, 0, "xmin = %f\n", vp->xmin); |
batch_out(brw, name, offset, 1, "xmax = %f\n", vp->xmax); |
batch_out(brw, name, offset, 2, "ymin = %f\n", vp->ymin); |
batch_out(brw, name, offset, 3, "ymax = %f\n", vp->ymax); |
} |
static void dump_sf_clip_viewport_state(struct brw_context *brw, |
uint32_t offset) |
{ |
const char *name = "SF_CLIP VP"; |
struct gen7_sf_clip_viewport *vp = brw->batch.bo->virtual + offset; |
assert(brw->gen >= 7); |
batch_out(brw, name, offset, 0, "m00 = %f\n", vp->viewport.m00); |
batch_out(brw, name, offset, 1, "m11 = %f\n", vp->viewport.m11); |
batch_out(brw, name, offset, 2, "m22 = %f\n", vp->viewport.m22); |
batch_out(brw, name, offset, 3, "m30 = %f\n", vp->viewport.m30); |
batch_out(brw, name, offset, 4, "m31 = %f\n", vp->viewport.m31); |
batch_out(brw, name, offset, 5, "m32 = %f\n", vp->viewport.m32); |
batch_out(brw, name, offset, 6, "guardband xmin = %f\n", vp->guardband.xmin); |
batch_out(brw, name, offset, 7, "guardband xmax = %f\n", vp->guardband.xmax); |
batch_out(brw, name, offset, 8, "guardband ymin = %f\n", vp->guardband.ymin); |
batch_out(brw, name, offset, 9, "guardband ymax = %f\n", vp->guardband.ymax); |
} |
static void dump_cc_viewport_state(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "CC VP"; |
struct brw_cc_viewport *vp = brw->batch.bo->virtual + offset; |
batch_out(brw, name, offset, 0, "min_depth = %f\n", vp->min_depth); |
batch_out(brw, name, offset, 1, "max_depth = %f\n", vp->max_depth); |
} |
static void dump_depth_stencil_state(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "D_S"; |
struct gen6_depth_stencil_state *ds = brw->batch.bo->virtual + offset; |
batch_out(brw, name, offset, 0, |
"stencil %sable, func %d, write %sable\n", |
ds->ds0.stencil_enable ? "en" : "dis", |
ds->ds0.stencil_func, |
ds->ds0.stencil_write_enable ? "en" : "dis"); |
batch_out(brw, name, offset, 1, |
"stencil test mask 0x%x, write mask 0x%x\n", |
ds->ds1.stencil_test_mask, ds->ds1.stencil_write_mask); |
batch_out(brw, name, offset, 2, |
"depth test %sable, func %d, write %sable\n", |
ds->ds2.depth_test_enable ? "en" : "dis", |
ds->ds2.depth_test_func, |
ds->ds2.depth_write_enable ? "en" : "dis"); |
} |
static void dump_cc_state_gen4(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "CC"; |
batch_out(brw, name, offset, 0, "cc0\n"); |
batch_out(brw, name, offset, 1, "cc1\n"); |
batch_out(brw, name, offset, 2, "cc2\n"); |
batch_out(brw, name, offset, 3, "cc3\n"); |
batch_out(brw, name, offset, 4, "cc4: viewport offset\n"); |
batch_out(brw, name, offset, 5, "cc5\n"); |
batch_out(brw, name, offset, 6, "cc6\n"); |
batch_out(brw, name, offset, 7, "cc7\n"); |
} |
static void dump_cc_state_gen6(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "CC"; |
struct gen6_color_calc_state *cc = brw->batch.bo->virtual + offset; |
batch_out(brw, name, offset, 0, |
"alpha test format %s, round disable %d, stencil ref %d, " |
"bf stencil ref %d\n", |
cc->cc0.alpha_test_format ? "FLOAT32" : "UNORM8", |
cc->cc0.round_disable, |
cc->cc0.stencil_ref, |
cc->cc0.bf_stencil_ref); |
batch_out(brw, name, offset, 1, "\n"); |
batch_out(brw, name, offset, 2, "constant red %f\n", cc->constant_r); |
batch_out(brw, name, offset, 3, "constant green %f\n", cc->constant_g); |
batch_out(brw, name, offset, 4, "constant blue %f\n", cc->constant_b); |
batch_out(brw, name, offset, 5, "constant alpha %f\n", cc->constant_a); |
} |
static void dump_blend_state(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "BLEND"; |
batch_out(brw, name, offset, 0, "\n"); |
batch_out(brw, name, offset, 1, "\n"); |
} |
static void |
dump_scissor(struct brw_context *brw, uint32_t offset) |
{ |
const char *name = "SCISSOR"; |
struct gen6_scissor_rect *scissor = brw->batch.bo->virtual + offset; |
batch_out(brw, name, offset, 0, "xmin %d, ymin %d\n", |
scissor->xmin, scissor->ymin); |
batch_out(brw, name, offset, 1, "xmax %d, ymax %d\n", |
scissor->xmax, scissor->ymax); |
} |
static void |
dump_vs_constants(struct brw_context *brw, uint32_t offset, uint32_t size) |
{ |
const char *name = "VS_CONST"; |
uint32_t *as_uint = brw->batch.bo->virtual + offset; |
float *as_float = brw->batch.bo->virtual + offset; |
int i; |
for (i = 0; i < size / 4; i += 4) { |
batch_out(brw, name, offset, i, "%3d: (% f % f % f % f) (0x%08x 0x%08x 0x%08x 0x%08x)\n", |
i / 4, |
as_float[i], as_float[i + 1], as_float[i + 2], as_float[i + 3], |
as_uint[i], as_uint[i + 1], as_uint[i + 2], as_uint[i + 3]); |
} |
} |
static void |
dump_wm_constants(struct brw_context *brw, uint32_t offset, uint32_t size) |
{ |
const char *name = "WM_CONST"; |
uint32_t *as_uint = brw->batch.bo->virtual + offset; |
float *as_float = brw->batch.bo->virtual + offset; |
int i; |
for (i = 0; i < size / 4; i += 4) { |
batch_out(brw, name, offset, i, "%3d: (% f % f % f % f) (0x%08x 0x%08x 0x%08x 0x%08x)\n", |
i / 4, |
as_float[i], as_float[i + 1], as_float[i + 2], as_float[i + 3], |
as_uint[i], as_uint[i + 1], as_uint[i + 2], as_uint[i + 3]); |
} |
} |
static void dump_binding_table(struct brw_context *brw, uint32_t offset, |
uint32_t size) |
{ |
char name[20]; |
int i; |
uint32_t *data = brw->batch.bo->virtual + offset; |
for (i = 0; i < size / 4; i++) { |
if (data[i] == 0) |
continue; |
sprintf(name, "BIND%d", i); |
batch_out(brw, name, offset, i, "surface state address\n"); |
} |
} |
static void |
dump_prog_cache(struct brw_context *brw) |
{ |
struct brw_cache *cache = &brw->cache; |
unsigned int b, i; |
uint32_t *data; |
drm_intel_bo_map(brw->cache.bo, false); |
for (b = 0; b < cache->size; b++) { |
struct brw_cache_item *item; |
for (item = cache->items[b]; item; item = item->next) { |
const char *name; |
uint32_t offset = item->offset; |
data = brw->cache.bo->virtual + item->offset; |
switch (item->cache_id) { |
case BRW_VS_PROG: |
name = "VS kernel"; |
break; |
case BRW_GS_PROG: |
name = "GS kernel"; |
break; |
case BRW_CLIP_PROG: |
name = "CLIP kernel"; |
break; |
case BRW_SF_PROG: |
name = "SF kernel"; |
break; |
case BRW_WM_PROG: |
name = "WM kernel"; |
break; |
default: |
name = "unknown"; |
break; |
} |
for (i = 0; i < item->size / 4 / 4; i++) { |
fprintf(stderr, "0x%08x: %8s: 0x%08x 0x%08x 0x%08x 0x%08x ", |
offset + i * 4 * 4, |
name, |
data[i * 4], data[i * 4 + 1], data[i * 4 + 2], data[i * 4 + 3]); |
brw_disasm(stderr, (void *)(data + i * 4), brw->gen); |
} |
} |
} |
drm_intel_bo_unmap(brw->cache.bo); |
} |
static void |
dump_state_batch(struct brw_context *brw) |
{ |
int i; |
for (i = 0; i < brw->state_batch_count; i++) { |
uint32_t offset = brw->state_batch_list[i].offset; |
uint32_t size = brw->state_batch_list[i].size; |
switch (brw->state_batch_list[i].type) { |
case AUB_TRACE_VS_STATE: |
dump_vs_state(brw, offset); |
break; |
case AUB_TRACE_GS_STATE: |
dump_gs_state(brw, offset); |
break; |
case AUB_TRACE_CLIP_STATE: |
dump_clip_state(brw, offset); |
break; |
case AUB_TRACE_SF_STATE: |
dump_sf_state(brw, offset); |
break; |
case AUB_TRACE_WM_STATE: |
dump_wm_state(brw, offset); |
break; |
case AUB_TRACE_CLIP_VP_STATE: |
dump_clip_viewport_state(brw, offset); |
break; |
case AUB_TRACE_SF_VP_STATE: |
if (brw->gen >= 7) { |
dump_sf_clip_viewport_state(brw, offset); |
} else { |
dump_sf_viewport_state(brw, offset); |
} |
break; |
case AUB_TRACE_CC_VP_STATE: |
dump_cc_viewport_state(brw, offset); |
break; |
case AUB_TRACE_DEPTH_STENCIL_STATE: |
dump_depth_stencil_state(brw, offset); |
break; |
case AUB_TRACE_CC_STATE: |
if (brw->gen >= 6) |
dump_cc_state_gen6(brw, offset); |
else |
dump_cc_state_gen4(brw, offset); |
break; |
case AUB_TRACE_BLEND_STATE: |
dump_blend_state(brw, offset); |
break; |
case AUB_TRACE_BINDING_TABLE: |
dump_binding_table(brw, offset, size); |
break; |
case AUB_TRACE_SURFACE_STATE: |
if (brw->gen < 7) { |
dump_surface_state(brw, offset); |
} else { |
dump_gen7_surface_state(brw, offset); |
} |
break; |
case AUB_TRACE_SAMPLER_STATE: |
if (brw->gen < 7) { |
dump_sampler_state(brw, offset, size); |
} else { |
dump_gen7_sampler_state(brw, offset, size); |
} |
break; |
case AUB_TRACE_SAMPLER_DEFAULT_COLOR: |
dump_sdc(brw, offset); |
break; |
case AUB_TRACE_SCISSOR_STATE: |
dump_scissor(brw, offset); |
break; |
case AUB_TRACE_VS_CONSTANTS: |
dump_vs_constants(brw, offset, size); |
break; |
case AUB_TRACE_WM_CONSTANTS: |
dump_wm_constants(brw, offset, size); |
break; |
default: |
break; |
} |
} |
} |
/** |
* Print additional debug information associated with the batchbuffer |
* when DEBUG_BATCH is set. |
* |
* For 965, this means mapping the state buffers that would have been referenced |
* by the batchbuffer and dumping them. |
* |
* The buffer offsets printed rely on the buffer containing the last offset |
* it was validated at. |
*/ |
void brw_debug_batch(struct brw_context *brw) |
{ |
drm_intel_bo_map(brw->batch.bo, false); |
dump_state_batch(brw); |
drm_intel_bo_unmap(brw->batch.bo); |
if (0) |
dump_prog_cache(brw); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_state_upload.c |
---|
0,0 → 1,531 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "brw_context.h" |
#include "brw_state.h" |
#include "drivers/common/meta.h" |
#include "intel_batchbuffer.h" |
#include "intel_buffers.h" |
static const struct brw_tracked_state *gen4_atoms[] = |
{ |
&brw_vs_prog, /* must do before GS prog, state base address. */ |
&brw_gs_prog, /* must do before state base address */ |
&brw_clip_prog, /* must do before state base address */ |
&brw_sf_prog, /* must do before state base address */ |
&brw_wm_prog, /* must do before state base address */ |
/* Once all the programs are done, we know how large urb entry |
* sizes need to be and can decide if we need to change the urb |
* layout. |
*/ |
&brw_curbe_offsets, |
&brw_recalculate_urb_fence, |
&brw_cc_vp, |
&brw_cc_unit, |
/* Surface state setup. Must come before the VS/WM unit. The binding |
* table upload must be last. |
*/ |
&brw_vs_pull_constants, |
&brw_wm_pull_constants, |
&brw_renderbuffer_surfaces, |
&brw_texture_surfaces, |
&brw_vs_binding_table, |
&brw_wm_binding_table, |
&brw_samplers, |
/* These set up state for brw_psp_urb_cbs */ |
&brw_wm_unit, |
&brw_sf_vp, |
&brw_sf_unit, |
&brw_vs_unit, /* always required, enabled or not */ |
&brw_clip_unit, |
&brw_gs_unit, |
/* Command packets: |
*/ |
&brw_invariant_state, |
&brw_state_base_address, |
&brw_binding_table_pointers, |
&brw_blend_constant_color, |
&brw_depthbuffer, |
&brw_polygon_stipple, |
&brw_polygon_stipple_offset, |
&brw_line_stipple, |
&brw_aa_line_parameters, |
&brw_psp_urb_cbs, |
&brw_drawing_rect, |
&brw_indices, |
&brw_index_buffer, |
&brw_vertices, |
&brw_constant_buffer |
}; |
static const struct brw_tracked_state *gen6_atoms[] = |
{ |
&brw_vs_prog, /* must do before state base address */ |
&brw_gs_prog, /* must do before state base address */ |
&brw_wm_prog, /* must do before state base address */ |
&gen6_clip_vp, |
&gen6_sf_vp, |
/* Command packets: */ |
/* must do before binding table pointers, cc state ptrs */ |
&brw_state_base_address, |
&brw_cc_vp, |
&gen6_viewport_state, /* must do after *_vp stages */ |
&gen6_urb, |
&gen6_blend_state, /* must do before cc unit */ |
&gen6_color_calc_state, /* must do before cc unit */ |
&gen6_depth_stencil_state, /* must do before cc unit */ |
&gen6_vs_push_constants, /* Before vs_state */ |
&gen6_wm_push_constants, /* Before wm_state */ |
/* Surface state setup. Must come before the VS/WM unit. The binding |
* table upload must be last. |
*/ |
&brw_vs_pull_constants, |
&brw_vs_ubo_surfaces, |
&brw_wm_pull_constants, |
&brw_wm_ubo_surfaces, |
&gen6_renderbuffer_surfaces, |
&brw_texture_surfaces, |
&gen6_sol_surface, |
&brw_vs_binding_table, |
&gen6_gs_binding_table, |
&brw_wm_binding_table, |
&brw_samplers, |
&gen6_sampler_state, |
&gen6_multisample_state, |
&gen6_vs_state, |
&gen6_gs_state, |
&gen6_clip_state, |
&gen6_sf_state, |
&gen6_wm_state, |
&gen6_scissor_state, |
&gen6_binding_table_pointers, |
&brw_depthbuffer, |
&brw_polygon_stipple, |
&brw_polygon_stipple_offset, |
&brw_line_stipple, |
&brw_aa_line_parameters, |
&brw_drawing_rect, |
&brw_indices, |
&brw_index_buffer, |
&brw_vertices, |
}; |
static const struct brw_tracked_state *gen7_atoms[] = |
{ |
&brw_vs_prog, |
&brw_wm_prog, |
/* Command packets: */ |
/* must do before binding table pointers, cc state ptrs */ |
&brw_state_base_address, |
&brw_cc_vp, |
&gen7_cc_viewport_state_pointer, /* must do after brw_cc_vp */ |
&gen7_sf_clip_viewport, |
&gen7_urb, |
&gen6_blend_state, /* must do before cc unit */ |
&gen6_color_calc_state, /* must do before cc unit */ |
&gen6_depth_stencil_state, /* must do before cc unit */ |
&gen6_vs_push_constants, /* Before vs_state */ |
&gen6_wm_push_constants, /* Before wm_surfaces and constant_buffer */ |
/* Surface state setup. Must come before the VS/WM unit. The binding |
* table upload must be last. |
*/ |
&brw_vs_pull_constants, |
&brw_vs_ubo_surfaces, |
&brw_wm_pull_constants, |
&brw_wm_ubo_surfaces, |
&gen6_renderbuffer_surfaces, |
&brw_texture_surfaces, |
&brw_vs_binding_table, |
&brw_wm_binding_table, |
&gen7_samplers, |
&gen6_multisample_state, |
&gen7_disable_stages, |
&gen7_vs_state, |
&gen7_sol_state, |
&gen7_clip_state, |
&gen7_sbe_state, |
&gen7_sf_state, |
&gen7_wm_state, |
&gen7_ps_state, |
&gen6_scissor_state, |
&gen7_depthbuffer, |
&brw_polygon_stipple, |
&brw_polygon_stipple_offset, |
&brw_line_stipple, |
&brw_aa_line_parameters, |
&brw_drawing_rect, |
&brw_indices, |
&brw_index_buffer, |
&brw_vertices, |
&haswell_cut_index, |
}; |
static void |
brw_upload_initial_gpu_state(struct brw_context *brw) |
{ |
/* On platforms with hardware contexts, we can set our initial GPU state |
* right away rather than doing it via state atoms. This saves a small |
* amount of overhead on every draw call. |
*/ |
if (!brw->hw_ctx) |
return; |
brw_upload_invariant_state(brw); |
if (brw->gen >= 7) { |
gen7_allocate_push_constants(brw); |
} |
} |
void brw_init_state( struct brw_context *brw ) |
{ |
const struct brw_tracked_state **atoms; |
int num_atoms; |
brw_init_caches(brw); |
if (brw->gen >= 7) { |
atoms = gen7_atoms; |
num_atoms = ARRAY_SIZE(gen7_atoms); |
} else if (brw->gen == 6) { |
atoms = gen6_atoms; |
num_atoms = ARRAY_SIZE(gen6_atoms); |
} else { |
atoms = gen4_atoms; |
num_atoms = ARRAY_SIZE(gen4_atoms); |
} |
brw->atoms = atoms; |
brw->num_atoms = num_atoms; |
while (num_atoms--) { |
assert((*atoms)->dirty.mesa | |
(*atoms)->dirty.brw | |
(*atoms)->dirty.cache); |
assert((*atoms)->emit); |
atoms++; |
} |
brw_upload_initial_gpu_state(brw); |
} |
void brw_destroy_state( struct brw_context *brw ) |
{ |
brw_destroy_caches(brw); |
} |
/*********************************************************************** |
*/ |
static bool |
check_state(const struct brw_state_flags *a, const struct brw_state_flags *b) |
{ |
return ((a->mesa & b->mesa) | |
(a->brw & b->brw) | |
(a->cache & b->cache)) != 0; |
} |
static void accumulate_state( struct brw_state_flags *a, |
const struct brw_state_flags *b ) |
{ |
a->mesa |= b->mesa; |
a->brw |= b->brw; |
a->cache |= b->cache; |
} |
static void xor_states( struct brw_state_flags *result, |
const struct brw_state_flags *a, |
const struct brw_state_flags *b ) |
{ |
result->mesa = a->mesa ^ b->mesa; |
result->brw = a->brw ^ b->brw; |
result->cache = a->cache ^ b->cache; |
} |
struct dirty_bit_map { |
uint32_t bit; |
char *name; |
uint32_t count; |
}; |
#define DEFINE_BIT(name) {name, #name, 0} |
static struct dirty_bit_map mesa_bits[] = { |
DEFINE_BIT(_NEW_MODELVIEW), |
DEFINE_BIT(_NEW_PROJECTION), |
DEFINE_BIT(_NEW_TEXTURE_MATRIX), |
DEFINE_BIT(_NEW_COLOR), |
DEFINE_BIT(_NEW_DEPTH), |
DEFINE_BIT(_NEW_EVAL), |
DEFINE_BIT(_NEW_FOG), |
DEFINE_BIT(_NEW_HINT), |
DEFINE_BIT(_NEW_LIGHT), |
DEFINE_BIT(_NEW_LINE), |
DEFINE_BIT(_NEW_PIXEL), |
DEFINE_BIT(_NEW_POINT), |
DEFINE_BIT(_NEW_POLYGON), |
DEFINE_BIT(_NEW_POLYGONSTIPPLE), |
DEFINE_BIT(_NEW_SCISSOR), |
DEFINE_BIT(_NEW_STENCIL), |
DEFINE_BIT(_NEW_TEXTURE), |
DEFINE_BIT(_NEW_TRANSFORM), |
DEFINE_BIT(_NEW_VIEWPORT), |
DEFINE_BIT(_NEW_ARRAY), |
DEFINE_BIT(_NEW_RENDERMODE), |
DEFINE_BIT(_NEW_BUFFERS), |
DEFINE_BIT(_NEW_MULTISAMPLE), |
DEFINE_BIT(_NEW_TRACK_MATRIX), |
DEFINE_BIT(_NEW_PROGRAM), |
DEFINE_BIT(_NEW_PROGRAM_CONSTANTS), |
DEFINE_BIT(_NEW_BUFFER_OBJECT), |
DEFINE_BIT(_NEW_FRAG_CLAMP), |
DEFINE_BIT(_NEW_VARYING_VP_INPUTS), |
{0, 0, 0} |
}; |
static struct dirty_bit_map brw_bits[] = { |
DEFINE_BIT(BRW_NEW_URB_FENCE), |
DEFINE_BIT(BRW_NEW_FRAGMENT_PROGRAM), |
DEFINE_BIT(BRW_NEW_VERTEX_PROGRAM), |
DEFINE_BIT(BRW_NEW_CURBE_OFFSETS), |
DEFINE_BIT(BRW_NEW_REDUCED_PRIMITIVE), |
DEFINE_BIT(BRW_NEW_PRIMITIVE), |
DEFINE_BIT(BRW_NEW_CONTEXT), |
DEFINE_BIT(BRW_NEW_PSP), |
DEFINE_BIT(BRW_NEW_SURFACES), |
DEFINE_BIT(BRW_NEW_VS_BINDING_TABLE), |
DEFINE_BIT(BRW_NEW_GS_BINDING_TABLE), |
DEFINE_BIT(BRW_NEW_PS_BINDING_TABLE), |
DEFINE_BIT(BRW_NEW_INDICES), |
DEFINE_BIT(BRW_NEW_VERTICES), |
DEFINE_BIT(BRW_NEW_BATCH), |
DEFINE_BIT(BRW_NEW_INDEX_BUFFER), |
DEFINE_BIT(BRW_NEW_VS_CONSTBUF), |
DEFINE_BIT(BRW_NEW_PROGRAM_CACHE), |
DEFINE_BIT(BRW_NEW_STATE_BASE_ADDRESS), |
DEFINE_BIT(BRW_NEW_VUE_MAP_GEOM_OUT), |
DEFINE_BIT(BRW_NEW_TRANSFORM_FEEDBACK), |
DEFINE_BIT(BRW_NEW_RASTERIZER_DISCARD), |
DEFINE_BIT(BRW_NEW_UNIFORM_BUFFER), |
DEFINE_BIT(BRW_NEW_META_IN_PROGRESS), |
{0, 0, 0} |
}; |
static struct dirty_bit_map cache_bits[] = { |
DEFINE_BIT(CACHE_NEW_CC_VP), |
DEFINE_BIT(CACHE_NEW_CC_UNIT), |
DEFINE_BIT(CACHE_NEW_WM_PROG), |
DEFINE_BIT(CACHE_NEW_SAMPLER), |
DEFINE_BIT(CACHE_NEW_WM_UNIT), |
DEFINE_BIT(CACHE_NEW_SF_PROG), |
DEFINE_BIT(CACHE_NEW_SF_VP), |
DEFINE_BIT(CACHE_NEW_SF_UNIT), |
DEFINE_BIT(CACHE_NEW_VS_UNIT), |
DEFINE_BIT(CACHE_NEW_VS_PROG), |
DEFINE_BIT(CACHE_NEW_GS_UNIT), |
DEFINE_BIT(CACHE_NEW_GS_PROG), |
DEFINE_BIT(CACHE_NEW_CLIP_VP), |
DEFINE_BIT(CACHE_NEW_CLIP_UNIT), |
DEFINE_BIT(CACHE_NEW_CLIP_PROG), |
{0, 0, 0} |
}; |
static void |
brw_update_dirty_count(struct dirty_bit_map *bit_map, int32_t bits) |
{ |
int i; |
for (i = 0; i < 32; i++) { |
if (bit_map[i].bit == 0) |
return; |
if (bit_map[i].bit & bits) |
bit_map[i].count++; |
} |
} |
static void |
brw_print_dirty_count(struct dirty_bit_map *bit_map) |
{ |
int i; |
for (i = 0; i < 32; i++) { |
if (bit_map[i].bit == 0) |
return; |
fprintf(stderr, "0x%08x: %12d (%s)\n", |
bit_map[i].bit, bit_map[i].count, bit_map[i].name); |
} |
} |
/*********************************************************************** |
* Emit all state: |
*/ |
void brw_upload_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_state_flags *state = &brw->state.dirty; |
int i; |
static int dirty_count = 0; |
state->mesa |= brw->NewGLState; |
brw->NewGLState = 0; |
state->brw |= ctx->NewDriverState; |
ctx->NewDriverState = 0; |
if (brw->emit_state_always) { |
state->mesa |= ~0; |
state->brw |= ~0; |
state->cache |= ~0; |
} |
if (brw->fragment_program != ctx->FragmentProgram._Current) { |
brw->fragment_program = ctx->FragmentProgram._Current; |
brw->state.dirty.brw |= BRW_NEW_FRAGMENT_PROGRAM; |
} |
if (brw->vertex_program != ctx->VertexProgram._Current) { |
brw->vertex_program = ctx->VertexProgram._Current; |
brw->state.dirty.brw |= BRW_NEW_VERTEX_PROGRAM; |
} |
if (brw->meta_in_progress != _mesa_meta_in_progress(ctx)) { |
brw->meta_in_progress = _mesa_meta_in_progress(ctx); |
brw->state.dirty.brw |= BRW_NEW_META_IN_PROGRESS; |
} |
if ((state->mesa | state->cache | state->brw) == 0) |
return; |
intel_check_front_buffer_rendering(brw); |
if (unlikely(INTEL_DEBUG)) { |
/* Debug version which enforces various sanity checks on the |
* state flags which are generated and checked to help ensure |
* state atoms are ordered correctly in the list. |
*/ |
struct brw_state_flags examined, prev; |
memset(&examined, 0, sizeof(examined)); |
prev = *state; |
for (i = 0; i < brw->num_atoms; i++) { |
const struct brw_tracked_state *atom = brw->atoms[i]; |
struct brw_state_flags generated; |
if (check_state(state, &atom->dirty)) { |
atom->emit(brw); |
} |
accumulate_state(&examined, &atom->dirty); |
/* generated = (prev ^ state) |
* if (examined & generated) |
* fail; |
*/ |
xor_states(&generated, &prev, state); |
assert(!check_state(&examined, &generated)); |
prev = *state; |
} |
} |
else { |
for (i = 0; i < brw->num_atoms; i++) { |
const struct brw_tracked_state *atom = brw->atoms[i]; |
if (check_state(state, &atom->dirty)) { |
atom->emit(brw); |
} |
} |
} |
if (unlikely(INTEL_DEBUG & DEBUG_STATE)) { |
brw_update_dirty_count(mesa_bits, state->mesa); |
brw_update_dirty_count(brw_bits, state->brw); |
brw_update_dirty_count(cache_bits, state->cache); |
if (dirty_count++ % 1000 == 0) { |
brw_print_dirty_count(mesa_bits); |
brw_print_dirty_count(brw_bits); |
brw_print_dirty_count(cache_bits); |
fprintf(stderr, "\n"); |
} |
} |
memset(state, 0, sizeof(*state)); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_structs.h |
---|
0,0 → 1,1422 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 BRW_STRUCTS_H |
#define BRW_STRUCTS_H |
struct brw_urb_fence |
{ |
struct |
{ |
GLuint length:8; |
GLuint vs_realloc:1; |
GLuint gs_realloc:1; |
GLuint clp_realloc:1; |
GLuint sf_realloc:1; |
GLuint vfe_realloc:1; |
GLuint cs_realloc:1; |
GLuint pad:2; |
GLuint opcode:16; |
} header; |
struct |
{ |
GLuint vs_fence:10; |
GLuint gs_fence:10; |
GLuint clp_fence:10; |
GLuint pad:2; |
} bits0; |
struct |
{ |
GLuint sf_fence:10; |
GLuint vf_fence:10; |
GLuint cs_fence:11; |
GLuint pad:1; |
} bits1; |
}; |
/* State structs for the various fixed function units: |
*/ |
struct thread0 |
{ |
GLuint pad0:1; |
GLuint grf_reg_count:3; |
GLuint pad1:2; |
GLuint kernel_start_pointer:26; /* Offset from GENERAL_STATE_BASE */ |
}; |
struct thread1 |
{ |
GLuint ext_halt_exception_enable:1; |
GLuint sw_exception_enable:1; |
GLuint mask_stack_exception_enable:1; |
GLuint timeout_exception_enable:1; |
GLuint illegal_op_exception_enable:1; |
GLuint pad0:3; |
GLuint depth_coef_urb_read_offset:6; /* WM only */ |
GLuint pad1:2; |
GLuint floating_point_mode:1; |
GLuint thread_priority:1; |
GLuint binding_table_entry_count:8; |
GLuint pad3:5; |
GLuint single_program_flow:1; |
}; |
struct thread2 |
{ |
GLuint per_thread_scratch_space:4; |
GLuint pad0:6; |
GLuint scratch_space_base_pointer:22; |
}; |
struct thread3 |
{ |
GLuint dispatch_grf_start_reg:4; |
GLuint urb_entry_read_offset:6; |
GLuint pad0:1; |
GLuint urb_entry_read_length:6; |
GLuint pad1:1; |
GLuint const_urb_entry_read_offset:6; |
GLuint pad2:1; |
GLuint const_urb_entry_read_length:6; |
GLuint pad3:1; |
}; |
struct brw_clip_unit_state |
{ |
struct thread0 thread0; |
struct |
{ |
GLuint pad0:7; |
GLuint sw_exception_enable:1; |
GLuint pad1:3; |
GLuint mask_stack_exception_enable:1; |
GLuint pad2:1; |
GLuint illegal_op_exception_enable:1; |
GLuint pad3:2; |
GLuint floating_point_mode:1; |
GLuint thread_priority:1; |
GLuint binding_table_entry_count:8; |
GLuint pad4:5; |
GLuint single_program_flow:1; |
} thread1; |
struct thread2 thread2; |
struct thread3 thread3; |
struct |
{ |
GLuint pad0:9; |
GLuint gs_output_stats:1; /* not always */ |
GLuint stats_enable:1; |
GLuint nr_urb_entries:7; |
GLuint pad1:1; |
GLuint urb_entry_allocation_size:5; |
GLuint pad2:1; |
GLuint max_threads:5; /* may be less */ |
GLuint pad3:2; |
} thread4; |
struct |
{ |
GLuint pad0:13; |
GLuint clip_mode:3; |
GLuint userclip_enable_flags:8; |
GLuint userclip_must_clip:1; |
GLuint negative_w_clip_test:1; |
GLuint guard_band_enable:1; |
GLuint viewport_z_clip_enable:1; |
GLuint viewport_xy_clip_enable:1; |
GLuint vertex_position_space:1; |
GLuint api_mode:1; |
GLuint pad2:1; |
} clip5; |
struct |
{ |
GLuint pad0:5; |
GLuint clipper_viewport_state_ptr:27; |
} clip6; |
GLfloat viewport_xmin; |
GLfloat viewport_xmax; |
GLfloat viewport_ymin; |
GLfloat viewport_ymax; |
}; |
struct gen6_blend_state |
{ |
struct { |
GLuint dest_blend_factor:5; |
GLuint source_blend_factor:5; |
GLuint pad3:1; |
GLuint blend_func:3; |
GLuint pad2:1; |
GLuint ia_dest_blend_factor:5; |
GLuint ia_source_blend_factor:5; |
GLuint pad1:1; |
GLuint ia_blend_func:3; |
GLuint pad0:1; |
GLuint ia_blend_enable:1; |
GLuint blend_enable:1; |
} blend0; |
struct { |
GLuint post_blend_clamp_enable:1; |
GLuint pre_blend_clamp_enable:1; |
GLuint clamp_range:2; |
GLuint pad0:4; |
GLuint x_dither_offset:2; |
GLuint y_dither_offset:2; |
GLuint dither_enable:1; |
GLuint alpha_test_func:3; |
GLuint alpha_test_enable:1; |
GLuint pad1:1; |
GLuint logic_op_func:4; |
GLuint logic_op_enable:1; |
GLuint pad2:1; |
GLuint write_disable_b:1; |
GLuint write_disable_g:1; |
GLuint write_disable_r:1; |
GLuint write_disable_a:1; |
GLuint pad3:1; |
GLuint alpha_to_coverage_dither:1; |
GLuint alpha_to_one:1; |
GLuint alpha_to_coverage:1; |
} blend1; |
}; |
struct gen6_color_calc_state |
{ |
struct { |
GLuint alpha_test_format:1; |
GLuint pad0:14; |
GLuint round_disable:1; |
GLuint bf_stencil_ref:8; |
GLuint stencil_ref:8; |
} cc0; |
union { |
GLfloat alpha_ref_f; |
struct { |
GLuint ui:8; |
GLuint pad0:24; |
} alpha_ref_fi; |
} cc1; |
GLfloat constant_r; |
GLfloat constant_g; |
GLfloat constant_b; |
GLfloat constant_a; |
}; |
struct gen6_depth_stencil_state |
{ |
struct { |
GLuint pad0:3; |
GLuint bf_stencil_pass_depth_pass_op:3; |
GLuint bf_stencil_pass_depth_fail_op:3; |
GLuint bf_stencil_fail_op:3; |
GLuint bf_stencil_func:3; |
GLuint bf_stencil_enable:1; |
GLuint pad1:2; |
GLuint stencil_write_enable:1; |
GLuint stencil_pass_depth_pass_op:3; |
GLuint stencil_pass_depth_fail_op:3; |
GLuint stencil_fail_op:3; |
GLuint stencil_func:3; |
GLuint stencil_enable:1; |
} ds0; |
struct { |
GLuint bf_stencil_write_mask:8; |
GLuint bf_stencil_test_mask:8; |
GLuint stencil_write_mask:8; |
GLuint stencil_test_mask:8; |
} ds1; |
struct { |
GLuint pad0:26; |
GLuint depth_write_enable:1; |
GLuint depth_test_func:3; |
GLuint pad1:1; |
GLuint depth_test_enable:1; |
} ds2; |
}; |
struct brw_cc_unit_state |
{ |
struct |
{ |
GLuint pad0:3; |
GLuint bf_stencil_pass_depth_pass_op:3; |
GLuint bf_stencil_pass_depth_fail_op:3; |
GLuint bf_stencil_fail_op:3; |
GLuint bf_stencil_func:3; |
GLuint bf_stencil_enable:1; |
GLuint pad1:2; |
GLuint stencil_write_enable:1; |
GLuint stencil_pass_depth_pass_op:3; |
GLuint stencil_pass_depth_fail_op:3; |
GLuint stencil_fail_op:3; |
GLuint stencil_func:3; |
GLuint stencil_enable:1; |
} cc0; |
struct |
{ |
GLuint bf_stencil_ref:8; |
GLuint stencil_write_mask:8; |
GLuint stencil_test_mask:8; |
GLuint stencil_ref:8; |
} cc1; |
struct |
{ |
GLuint logicop_enable:1; |
GLuint pad0:10; |
GLuint depth_write_enable:1; |
GLuint depth_test_function:3; |
GLuint depth_test:1; |
GLuint bf_stencil_write_mask:8; |
GLuint bf_stencil_test_mask:8; |
} cc2; |
struct |
{ |
GLuint pad0:8; |
GLuint alpha_test_func:3; |
GLuint alpha_test:1; |
GLuint blend_enable:1; |
GLuint ia_blend_enable:1; |
GLuint pad1:1; |
GLuint alpha_test_format:1; |
GLuint pad2:16; |
} cc3; |
struct |
{ |
GLuint pad0:5; |
GLuint cc_viewport_state_offset:27; /* Offset from GENERAL_STATE_BASE */ |
} cc4; |
struct |
{ |
GLuint pad0:2; |
GLuint ia_dest_blend_factor:5; |
GLuint ia_src_blend_factor:5; |
GLuint ia_blend_function:3; |
GLuint statistics_enable:1; |
GLuint logicop_func:4; |
GLuint pad1:11; |
GLuint dither_enable:1; |
} cc5; |
struct |
{ |
GLuint clamp_post_alpha_blend:1; |
GLuint clamp_pre_alpha_blend:1; |
GLuint clamp_range:2; |
GLuint pad0:11; |
GLuint y_dither_offset:2; |
GLuint x_dither_offset:2; |
GLuint dest_blend_factor:5; |
GLuint src_blend_factor:5; |
GLuint blend_function:3; |
} cc6; |
struct { |
union { |
GLfloat f; |
GLubyte ub[4]; |
} alpha_ref; |
} cc7; |
}; |
struct brw_sf_unit_state |
{ |
struct thread0 thread0; |
struct thread1 thread1; |
struct thread2 thread2; |
struct thread3 thread3; |
struct |
{ |
GLuint pad0:10; |
GLuint stats_enable:1; |
GLuint nr_urb_entries:7; |
GLuint pad1:1; |
GLuint urb_entry_allocation_size:5; |
GLuint pad2:1; |
GLuint max_threads:6; |
GLuint pad3:1; |
} thread4; |
struct |
{ |
GLuint front_winding:1; |
GLuint viewport_transform:1; |
GLuint pad0:3; |
GLuint sf_viewport_state_offset:27; /* Offset from GENERAL_STATE_BASE */ |
} sf5; |
struct |
{ |
GLuint pad0:9; |
GLuint dest_org_vbias:4; |
GLuint dest_org_hbias:4; |
GLuint scissor:1; |
GLuint disable_2x2_trifilter:1; |
GLuint disable_zero_pix_trifilter:1; |
GLuint point_rast_rule:2; |
GLuint line_endcap_aa_region_width:2; |
GLuint line_width:4; |
GLuint fast_scissor_disable:1; |
GLuint cull_mode:2; |
GLuint aa_enable:1; |
} sf6; |
struct |
{ |
GLuint point_size:11; |
GLuint use_point_size_state:1; |
GLuint subpixel_precision:1; |
GLuint sprite_point:1; |
GLuint pad0:10; |
GLuint aa_line_distance_mode:1; |
GLuint trifan_pv:2; |
GLuint linestrip_pv:2; |
GLuint tristrip_pv:2; |
GLuint line_last_pixel_enable:1; |
} sf7; |
}; |
struct gen6_scissor_rect |
{ |
GLuint xmin:16; |
GLuint ymin:16; |
GLuint xmax:16; |
GLuint ymax:16; |
}; |
struct brw_gs_unit_state |
{ |
struct thread0 thread0; |
struct thread1 thread1; |
struct thread2 thread2; |
struct thread3 thread3; |
struct |
{ |
GLuint pad0:8; |
GLuint rendering_enable:1; /* for Ironlake */ |
GLuint pad4:1; |
GLuint stats_enable:1; |
GLuint nr_urb_entries:7; |
GLuint pad1:1; |
GLuint urb_entry_allocation_size:5; |
GLuint pad2:1; |
GLuint max_threads:5; |
GLuint pad3:2; |
} thread4; |
struct |
{ |
GLuint sampler_count:3; |
GLuint pad0:2; |
GLuint sampler_state_pointer:27; |
} gs5; |
struct |
{ |
GLuint max_vp_index:4; |
GLuint pad0:12; |
GLuint svbi_post_inc_value:10; |
GLuint pad1:1; |
GLuint svbi_post_inc_enable:1; |
GLuint svbi_payload:1; |
GLuint discard_adjaceny:1; |
GLuint reorder_enable:1; |
GLuint pad2:1; |
} gs6; |
}; |
struct brw_vs_unit_state |
{ |
struct thread0 thread0; |
struct thread1 thread1; |
struct thread2 thread2; |
struct thread3 thread3; |
struct |
{ |
GLuint pad0:10; |
GLuint stats_enable:1; |
GLuint nr_urb_entries:7; |
GLuint pad1:1; |
GLuint urb_entry_allocation_size:5; |
GLuint pad2:1; |
GLuint max_threads:6; |
GLuint pad3:1; |
} thread4; |
struct |
{ |
GLuint sampler_count:3; |
GLuint pad0:2; |
GLuint sampler_state_pointer:27; |
} vs5; |
struct |
{ |
GLuint vs_enable:1; |
GLuint vert_cache_disable:1; |
GLuint pad0:30; |
} vs6; |
}; |
struct brw_wm_unit_state |
{ |
struct thread0 thread0; |
struct thread1 thread1; |
struct thread2 thread2; |
struct thread3 thread3; |
struct { |
GLuint stats_enable:1; |
GLuint depth_buffer_clear:1; |
GLuint sampler_count:3; |
GLuint sampler_state_pointer:27; |
} wm4; |
struct |
{ |
GLuint enable_8_pix:1; |
GLuint enable_16_pix:1; |
GLuint enable_32_pix:1; |
GLuint enable_con_32_pix:1; |
GLuint enable_con_64_pix:1; |
GLuint pad0:1; |
/* These next four bits are for Ironlake+ */ |
GLuint fast_span_coverage_enable:1; |
GLuint depth_buffer_clear:1; |
GLuint depth_buffer_resolve_enable:1; |
GLuint hierarchical_depth_buffer_resolve_enable:1; |
GLuint legacy_global_depth_bias:1; |
GLuint line_stipple:1; |
GLuint depth_offset:1; |
GLuint polygon_stipple:1; |
GLuint line_aa_region_width:2; |
GLuint line_endcap_aa_region_width:2; |
GLuint early_depth_test:1; |
GLuint thread_dispatch_enable:1; |
GLuint program_uses_depth:1; |
GLuint program_computes_depth:1; |
GLuint program_uses_killpixel:1; |
GLuint legacy_line_rast: 1; |
GLuint transposed_urb_read_enable:1; |
GLuint max_threads:7; |
} wm5; |
GLfloat global_depth_offset_constant; |
GLfloat global_depth_offset_scale; |
/* for Ironlake only */ |
struct { |
GLuint pad0:1; |
GLuint grf_reg_count_1:3; |
GLuint pad1:2; |
GLuint kernel_start_pointer_1:26; |
} wm8; |
struct { |
GLuint pad0:1; |
GLuint grf_reg_count_2:3; |
GLuint pad1:2; |
GLuint kernel_start_pointer_2:26; |
} wm9; |
struct { |
GLuint pad0:1; |
GLuint grf_reg_count_3:3; |
GLuint pad1:2; |
GLuint kernel_start_pointer_3:26; |
} wm10; |
}; |
struct brw_sampler_default_color { |
GLfloat color[4]; |
}; |
struct gen5_sampler_default_color { |
uint8_t ub[4]; |
float f[4]; |
uint16_t hf[4]; |
uint16_t us[4]; |
int16_t s[4]; |
uint8_t b[4]; |
}; |
struct brw_sampler_state |
{ |
struct |
{ |
GLuint shadow_function:3; |
GLuint lod_bias:11; |
GLuint min_filter:3; |
GLuint mag_filter:3; |
GLuint mip_filter:2; |
GLuint base_level:5; |
GLuint min_mag_neq:1; |
GLuint lod_preclamp:1; |
GLuint default_color_mode:1; |
GLuint pad0:1; |
GLuint disable:1; |
} ss0; |
struct |
{ |
GLuint r_wrap_mode:3; |
GLuint t_wrap_mode:3; |
GLuint s_wrap_mode:3; |
GLuint cube_control_mode:1; |
GLuint pad:2; |
GLuint max_lod:10; |
GLuint min_lod:10; |
} ss1; |
struct |
{ |
GLuint pad:5; |
GLuint default_color_pointer:27; |
} ss2; |
struct |
{ |
GLuint non_normalized_coord:1; |
GLuint pad:12; |
GLuint address_round:6; |
GLuint max_aniso:3; |
GLuint chroma_key_mode:1; |
GLuint chroma_key_index:2; |
GLuint chroma_key_enable:1; |
GLuint monochrome_filter_width:3; |
GLuint monochrome_filter_height:3; |
} ss3; |
}; |
struct gen7_sampler_state |
{ |
struct |
{ |
GLuint aniso_algorithm:1; |
GLuint lod_bias:13; |
GLuint min_filter:3; |
GLuint mag_filter:3; |
GLuint mip_filter:2; |
GLuint base_level:5; |
GLuint pad1:1; |
GLuint lod_preclamp:1; |
GLuint default_color_mode:1; |
GLuint pad0:1; |
GLuint disable:1; |
} ss0; |
struct |
{ |
GLuint cube_control_mode:1; |
GLuint shadow_function:3; |
GLuint pad:4; |
GLuint max_lod:12; |
GLuint min_lod:12; |
} ss1; |
struct |
{ |
GLuint pad:5; |
GLuint default_color_pointer:27; |
} ss2; |
struct |
{ |
GLuint r_wrap_mode:3; |
GLuint t_wrap_mode:3; |
GLuint s_wrap_mode:3; |
GLuint pad:1; |
GLuint non_normalized_coord:1; |
GLuint trilinear_quality:2; |
GLuint address_round:6; |
GLuint max_aniso:3; |
GLuint chroma_key_mode:1; |
GLuint chroma_key_index:2; |
GLuint chroma_key_enable:1; |
GLuint pad0:6; |
} ss3; |
}; |
struct brw_clipper_viewport |
{ |
GLfloat xmin; |
GLfloat xmax; |
GLfloat ymin; |
GLfloat ymax; |
}; |
struct brw_cc_viewport |
{ |
GLfloat min_depth; |
GLfloat max_depth; |
}; |
struct brw_sf_viewport |
{ |
struct { |
GLfloat m00; |
GLfloat m11; |
GLfloat m22; |
GLfloat m30; |
GLfloat m31; |
GLfloat m32; |
} viewport; |
/* scissor coordinates are inclusive */ |
struct { |
GLshort xmin; |
GLshort ymin; |
GLshort xmax; |
GLshort ymax; |
} scissor; |
}; |
struct gen6_sf_viewport { |
GLfloat m00; |
GLfloat m11; |
GLfloat m22; |
GLfloat m30; |
GLfloat m31; |
GLfloat m32; |
}; |
struct gen7_sf_clip_viewport { |
struct { |
GLfloat m00; |
GLfloat m11; |
GLfloat m22; |
GLfloat m30; |
GLfloat m31; |
GLfloat m32; |
} viewport; |
GLuint pad0[2]; |
struct { |
GLfloat xmin; |
GLfloat xmax; |
GLfloat ymin; |
GLfloat ymax; |
} guardband; |
GLfloat pad1[4]; |
}; |
struct brw_urb_immediate { |
GLuint opcode:4; |
GLuint offset:6; |
GLuint swizzle_control:2; |
GLuint pad:1; |
GLuint allocate:1; |
GLuint used:1; |
GLuint complete:1; |
GLuint response_length:4; |
GLuint msg_length:4; |
GLuint msg_target:4; |
GLuint pad1:3; |
GLuint end_of_thread:1; |
}; |
/* Instruction format for the execution units: |
*/ |
struct brw_instruction |
{ |
struct |
{ |
GLuint opcode:7; |
GLuint pad:1; |
GLuint access_mode:1; |
GLuint mask_control:1; |
GLuint dependency_control:2; |
GLuint compression_control:2; /* gen6: quarter control */ |
GLuint thread_control:2; |
GLuint predicate_control:4; |
GLuint predicate_inverse:1; |
GLuint execution_size:3; |
/** |
* Conditional Modifier for most instructions. On Gen6+, this is also |
* used for the SEND instruction's Message Target/SFID. |
*/ |
GLuint destreg__conditionalmod:4; |
GLuint acc_wr_control:1; |
GLuint cmpt_control:1; |
GLuint debug_control:1; |
GLuint saturate:1; |
} header; |
union { |
struct |
{ |
GLuint dest_reg_file:2; |
GLuint dest_reg_type:3; |
GLuint src0_reg_file:2; |
GLuint src0_reg_type:3; |
GLuint src1_reg_file:2; |
GLuint src1_reg_type:3; |
GLuint nibctrl:1; /* gen7+ */ |
GLuint dest_subreg_nr:5; |
GLuint dest_reg_nr:8; |
GLuint dest_horiz_stride:2; |
GLuint dest_address_mode:1; |
} da1; |
struct |
{ |
GLuint dest_reg_file:2; |
GLuint dest_reg_type:3; |
GLuint src0_reg_file:2; |
GLuint src0_reg_type:3; |
GLuint src1_reg_file:2; /* 0x00000c00 */ |
GLuint src1_reg_type:3; /* 0x00007000 */ |
GLuint nibctrl:1; /* gen7+ */ |
GLint dest_indirect_offset:10; /* offset against the deref'd address reg */ |
GLuint dest_subreg_nr:3; /* subnr for the address reg a0.x */ |
GLuint dest_horiz_stride:2; |
GLuint dest_address_mode:1; |
} ia1; |
struct |
{ |
GLuint dest_reg_file:2; |
GLuint dest_reg_type:3; |
GLuint src0_reg_file:2; |
GLuint src0_reg_type:3; |
GLuint src1_reg_file:2; |
GLuint src1_reg_type:3; |
GLuint nibctrl:1; /* gen7+ */ |
GLuint dest_writemask:4; |
GLuint dest_subreg_nr:1; |
GLuint dest_reg_nr:8; |
GLuint dest_horiz_stride:2; |
GLuint dest_address_mode:1; |
} da16; |
struct |
{ |
GLuint dest_reg_file:2; |
GLuint dest_reg_type:3; |
GLuint src0_reg_file:2; |
GLuint src0_reg_type:3; |
GLuint src1_reg_file:2; |
GLuint src1_reg_type:3; |
GLuint nibctrl:1; /* gen7+ */ |
GLuint dest_writemask:4; |
GLint dest_indirect_offset:6; |
GLuint dest_subreg_nr:3; |
GLuint dest_horiz_stride:2; |
GLuint dest_address_mode:1; |
} ia16; |
struct { |
GLuint dest_reg_file:2; |
GLuint dest_reg_type:3; |
GLuint src0_reg_file:2; |
GLuint src0_reg_type:3; |
GLuint src1_reg_file:2; |
GLuint src1_reg_type:3; |
GLuint pad:1; |
GLint jump_count:16; |
} branch_gen6; |
struct { |
GLuint dest_reg_file:1; /* gen6, not gen7+ */ |
GLuint flag_subreg_num:1; |
GLuint flag_reg_nr:1; /* gen7+ */ |
GLuint pad0:1; |
GLuint src0_abs:1; |
GLuint src0_negate:1; |
GLuint src1_abs:1; |
GLuint src1_negate:1; |
GLuint src2_abs:1; |
GLuint src2_negate:1; |
GLuint src_type:2; /* gen7+ */ |
GLuint dst_type:2; /* gen7+ */ |
GLuint pad1:1; |
GLuint nibctrl:1; /* gen7+ */ |
GLuint pad2:1; |
GLuint dest_writemask:4; |
GLuint dest_subreg_nr:3; |
GLuint dest_reg_nr:8; |
} da3src; |
uint32_t ud; |
} bits1; |
union { |
struct |
{ |
GLuint src0_subreg_nr:5; |
GLuint src0_reg_nr:8; |
GLuint src0_abs:1; |
GLuint src0_negate:1; |
GLuint src0_address_mode:1; |
GLuint src0_horiz_stride:2; |
GLuint src0_width:3; |
GLuint src0_vert_stride:4; |
GLuint flag_subreg_nr:1; |
GLuint flag_reg_nr:1; /* gen7+ */ |
GLuint pad:5; |
} da1; |
struct |
{ |
GLint src0_indirect_offset:10; |
GLuint src0_subreg_nr:3; |
GLuint src0_abs:1; |
GLuint src0_negate:1; |
GLuint src0_address_mode:1; |
GLuint src0_horiz_stride:2; |
GLuint src0_width:3; |
GLuint src0_vert_stride:4; |
GLuint flag_subreg_nr:1; |
GLuint flag_reg_nr:1; /* gen7+ */ |
GLuint pad:5; |
} ia1; |
struct |
{ |
GLuint src0_swz_x:2; |
GLuint src0_swz_y:2; |
GLuint src0_subreg_nr:1; |
GLuint src0_reg_nr:8; |
GLuint src0_abs:1; |
GLuint src0_negate:1; |
GLuint src0_address_mode:1; |
GLuint src0_swz_z:2; |
GLuint src0_swz_w:2; |
GLuint pad0:1; |
GLuint src0_vert_stride:4; |
GLuint flag_subreg_nr:1; |
GLuint flag_reg_nr:1; /* gen7+ */ |
GLuint pad1:5; |
} da16; |
struct |
{ |
GLuint src0_swz_x:2; |
GLuint src0_swz_y:2; |
GLint src0_indirect_offset:6; |
GLuint src0_subreg_nr:3; |
GLuint src0_abs:1; |
GLuint src0_negate:1; |
GLuint src0_address_mode:1; |
GLuint src0_swz_z:2; |
GLuint src0_swz_w:2; |
GLuint pad0:1; |
GLuint src0_vert_stride:4; |
GLuint flag_subreg_nr:1; |
GLuint flag_reg_nr:1; /* gen7+ */ |
GLuint pad1:5; |
} ia16; |
/* Extended Message Descriptor for Ironlake (Gen5) SEND instruction. |
* |
* Does not apply to Gen6+. The SFID/message target moved to bits |
* 27:24 of the header (destreg__conditionalmod); EOT is in bits3. |
*/ |
struct |
{ |
GLuint pad:26; |
GLuint end_of_thread:1; |
GLuint pad1:1; |
GLuint sfid:4; |
} send_gen5; /* for Ironlake only */ |
struct { |
GLuint src0_rep_ctrl:1; |
GLuint src0_swizzle:8; |
GLuint src0_subreg_nr:3; |
GLuint src0_reg_nr:8; |
GLuint pad0:1; |
GLuint src1_rep_ctrl:1; |
GLuint src1_swizzle:8; |
GLuint src1_subreg_nr_low:2; |
} da3src; |
uint32_t ud; |
} bits2; |
union |
{ |
struct |
{ |
GLuint src1_subreg_nr:5; |
GLuint src1_reg_nr:8; |
GLuint src1_abs:1; |
GLuint src1_negate:1; |
GLuint src1_address_mode:1; |
GLuint src1_horiz_stride:2; |
GLuint src1_width:3; |
GLuint src1_vert_stride:4; |
GLuint pad0:7; |
} da1; |
struct |
{ |
GLuint src1_swz_x:2; |
GLuint src1_swz_y:2; |
GLuint src1_subreg_nr:1; |
GLuint src1_reg_nr:8; |
GLuint src1_abs:1; |
GLuint src1_negate:1; |
GLuint src1_address_mode:1; |
GLuint src1_swz_z:2; |
GLuint src1_swz_w:2; |
GLuint pad1:1; |
GLuint src1_vert_stride:4; |
GLuint pad2:7; |
} da16; |
struct |
{ |
GLint src1_indirect_offset:10; |
GLuint src1_subreg_nr:3; |
GLuint src1_abs:1; |
GLuint src1_negate:1; |
GLuint src1_address_mode:1; |
GLuint src1_horiz_stride:2; |
GLuint src1_width:3; |
GLuint src1_vert_stride:4; |
GLuint pad1:7; |
} ia1; |
struct |
{ |
GLuint src1_swz_x:2; |
GLuint src1_swz_y:2; |
GLint src1_indirect_offset:6; |
GLuint src1_subreg_nr:3; |
GLuint src1_abs:1; |
GLuint src1_negate:1; |
GLuint pad0:1; |
GLuint src1_swz_z:2; |
GLuint src1_swz_w:2; |
GLuint pad1:1; |
GLuint src1_vert_stride:4; |
GLuint pad2:7; |
} ia16; |
struct |
{ |
GLint jump_count:16; /* note: signed */ |
GLuint pop_count:4; |
GLuint pad0:12; |
} if_else; |
/* This is also used for gen7 IF/ELSE instructions */ |
struct |
{ |
/* Signed jump distance to the ip to jump to if all channels |
* are disabled after the break or continue. It should point |
* to the end of the innermost control flow block, as that's |
* where some channel could get re-enabled. |
*/ |
int jip:16; |
/* Signed jump distance to the location to resume execution |
* of this channel if it's enabled for the break or continue. |
*/ |
int uip:16; |
} break_cont; |
/** |
* \defgroup SEND instructions / Message Descriptors |
* |
* @{ |
*/ |
/** |
* Generic Message Descriptor for Gen4 SEND instructions. The structs |
* below expand function_control to something specific for their |
* message. Due to struct packing issues, they duplicate these bits. |
* |
* See the G45 PRM, Volume 4, Table 14-15. |
*/ |
struct { |
GLuint function_control:16; |
GLuint response_length:4; |
GLuint msg_length:4; |
GLuint msg_target:4; |
GLuint pad1:3; |
GLuint end_of_thread:1; |
} generic; |
/** |
* Generic Message Descriptor for Gen5-7 SEND instructions. |
* |
* See the Sandybridge PRM, Volume 2 Part 2, Table 8-15. (Sadly, most |
* of the information on the SEND instruction is missing from the public |
* Ironlake PRM.) |
* |
* The table claims that bit 31 is reserved/MBZ on Gen6+, but it lies. |
* According to the SEND instruction description: |
* "The MSb of the message description, the EOT field, always comes from |
* bit 127 of the instruction word"...which is bit 31 of this field. |
*/ |
struct { |
GLuint function_control:19; |
GLuint header_present:1; |
GLuint response_length:5; |
GLuint msg_length:4; |
GLuint pad1:2; |
GLuint end_of_thread:1; |
} generic_gen5; |
/** G45 PRM, Volume 4, Section 6.1.1.1 */ |
struct { |
GLuint function:4; |
GLuint int_type:1; |
GLuint precision:1; |
GLuint saturate:1; |
GLuint data_type:1; |
GLuint pad0:8; |
GLuint response_length:4; |
GLuint msg_length:4; |
GLuint msg_target:4; |
GLuint pad1:3; |
GLuint end_of_thread:1; |
} math; |
/** Ironlake PRM, Volume 4 Part 1, Section 6.1.1.1 */ |
struct { |
GLuint function:4; |
GLuint int_type:1; |
GLuint precision:1; |
GLuint saturate:1; |
GLuint data_type:1; |
GLuint snapshot:1; |
GLuint pad0:10; |
GLuint header_present:1; |
GLuint response_length:5; |
GLuint msg_length:4; |
GLuint pad1:2; |
GLuint end_of_thread:1; |
} math_gen5; |
/** G45 PRM, Volume 4, Section 4.8.1.1.1 [DevBW] and [DevCL] */ |
struct { |
GLuint binding_table_index:8; |
GLuint sampler:4; |
GLuint return_format:2; |
GLuint msg_type:2; |
GLuint response_length:4; |
GLuint msg_length:4; |
GLuint msg_target:4; |
GLuint pad1:3; |
GLuint end_of_thread:1; |
} sampler; |
/** G45 PRM, Volume 4, Section 4.8.1.1.2 [DevCTG] */ |
struct { |
GLuint binding_table_index:8; |
GLuint sampler:4; |
GLuint msg_type:4; |
GLuint response_length:4; |
GLuint msg_length:4; |
GLuint msg_target:4; |
GLuint pad1:3; |
GLuint end_of_thread:1; |
} sampler_g4x; |
/** Ironlake PRM, Volume 4 Part 1, Section 4.11.1.1.3 */ |
struct { |
GLuint binding_table_index:8; |
GLuint sampler:4; |
GLuint msg_type:4; |
GLuint simd_mode:2; |
GLuint pad0:1; |
GLuint header_present:1; |
GLuint response_length:5; |
GLuint msg_length:4; |
GLuint pad1:2; |
GLuint end_of_thread:1; |
} sampler_gen5; |
struct { |
GLuint binding_table_index:8; |
GLuint sampler:4; |
GLuint msg_type:5; |
GLuint simd_mode:2; |
GLuint header_present:1; |
GLuint response_length:5; |
GLuint msg_length:4; |
GLuint pad1:2; |
GLuint end_of_thread:1; |
} sampler_gen7; |
struct brw_urb_immediate urb; |
struct { |
GLuint opcode:4; |
GLuint offset:6; |
GLuint swizzle_control:2; |
GLuint pad:1; |
GLuint allocate:1; |
GLuint used:1; |
GLuint complete:1; |
GLuint pad0:3; |
GLuint header_present:1; |
GLuint response_length:5; |
GLuint msg_length:4; |
GLuint pad1:2; |
GLuint end_of_thread:1; |
} urb_gen5; |
struct { |
GLuint opcode:3; |
GLuint offset:11; |
GLuint swizzle_control:1; |
GLuint complete:1; |
GLuint per_slot_offset:1; |
GLuint pad0:2; |
GLuint header_present:1; |
GLuint response_length:5; |
GLuint msg_length:4; |
GLuint pad1:2; |
GLuint end_of_thread:1; |
} urb_gen7; |
/** 965 PRM, Volume 4, Section 5.10.1.1: Message Descriptor */ |
struct { |
GLuint binding_table_index:8; |
GLuint msg_control:4; |
GLuint msg_type:2; |
GLuint target_cache:2; |
GLuint response_length:4; |
GLuint msg_length:4; |
GLuint msg_target:4; |
GLuint pad1:3; |
GLuint end_of_thread:1; |
} dp_read; |
/** G45 PRM, Volume 4, Section 5.10.1.1.2 */ |
struct { |
GLuint binding_table_index:8; |
GLuint msg_control:3; |
GLuint msg_type:3; |
GLuint target_cache:2; |
GLuint response_length:4; |
GLuint msg_length:4; |
GLuint msg_target:4; |
GLuint pad1:3; |
GLuint end_of_thread:1; |
} dp_read_g4x; |
/** Ironlake PRM, Volume 4 Part 1, Section 5.10.2.1.2. */ |
struct { |
GLuint binding_table_index:8; |
GLuint msg_control:3; |
GLuint msg_type:3; |
GLuint target_cache:2; |
GLuint pad0:3; |
GLuint header_present:1; |
GLuint response_length:5; |
GLuint msg_length:4; |
GLuint pad1:2; |
GLuint end_of_thread:1; |
} dp_read_gen5; |
/** G45 PRM, Volume 4, Section 5.10.1.1.2. For both Gen4 and G45. */ |
struct { |
GLuint binding_table_index:8; |
GLuint msg_control:3; |
GLuint last_render_target:1; |
GLuint msg_type:3; |
GLuint send_commit_msg:1; |
GLuint response_length:4; |
GLuint msg_length:4; |
GLuint msg_target:4; |
GLuint pad1:3; |
GLuint end_of_thread:1; |
} dp_write; |
/** Ironlake PRM, Volume 4 Part 1, Section 5.10.2.1.2. */ |
struct { |
GLuint binding_table_index:8; |
GLuint msg_control:3; |
GLuint last_render_target:1; |
GLuint msg_type:3; |
GLuint send_commit_msg:1; |
GLuint pad0:3; |
GLuint header_present:1; |
GLuint response_length:5; |
GLuint msg_length:4; |
GLuint pad1:2; |
GLuint end_of_thread:1; |
} dp_write_gen5; |
/** |
* Message for the Sandybridge Sampler Cache or Constant Cache Data Port. |
* |
* See the Sandybridge PRM, Volume 4 Part 1, Section 3.9.2.1.1. |
**/ |
struct { |
GLuint binding_table_index:8; |
GLuint msg_control:5; |
GLuint msg_type:3; |
GLuint pad0:3; |
GLuint header_present:1; |
GLuint response_length:5; |
GLuint msg_length:4; |
GLuint pad1:2; |
GLuint end_of_thread:1; |
} gen6_dp_sampler_const_cache; |
/** |
* Message for the Sandybridge Render Cache Data Port. |
* |
* Most fields are defined in the Sandybridge PRM, Volume 4 Part 1, |
* Section 3.9.2.1.1: Message Descriptor. |
* |
* "Slot Group Select" and "Last Render Target" are part of the |
* 5-bit message control for Render Target Write messages. See |
* Section 3.9.9.2.1 of the same volume. |
*/ |
struct { |
GLuint binding_table_index:8; |
GLuint msg_control:3; |
GLuint slot_group_select:1; |
GLuint last_render_target:1; |
GLuint msg_type:4; |
GLuint send_commit_msg:1; |
GLuint pad0:1; |
GLuint header_present:1; |
GLuint response_length:5; |
GLuint msg_length:4; |
GLuint pad1:2; |
GLuint end_of_thread:1; |
} gen6_dp; |
/** |
* Message for any of the Gen7 Data Port caches. |
* |
* Most fields are defined in the Ivybridge PRM, Volume 4 Part 1, |
* section 3.9.2.1.1 "Message Descriptor". Once again, "Slot Group |
* Select" and "Last Render Target" are part of the 6-bit message |
* control for Render Target Writes (section 3.9.11.2). |
*/ |
struct { |
GLuint binding_table_index:8; |
GLuint msg_control:3; |
GLuint slot_group_select:1; |
GLuint last_render_target:1; |
GLuint msg_control_pad:1; |
GLuint msg_type:4; |
GLuint pad1:1; |
GLuint header_present:1; |
GLuint response_length:5; |
GLuint msg_length:4; |
GLuint pad2:2; |
GLuint end_of_thread:1; |
} gen7_dp; |
/** @} */ |
struct { |
GLuint src1_subreg_nr_high:1; |
GLuint src1_reg_nr:8; |
GLuint pad0:1; |
GLuint src2_rep_ctrl:1; |
GLuint src2_swizzle:8; |
GLuint src2_subreg_nr:3; |
GLuint src2_reg_nr:8; |
GLuint pad1:2; |
} da3src; |
GLint d; |
GLuint ud; |
float f; |
} bits3; |
}; |
struct brw_compact_instruction { |
struct { |
unsigned opcode:7; /* 0- 6 */ |
unsigned debug_control:1; /* 7- 7 */ |
unsigned control_index:5; /* 8-12 */ |
unsigned data_type_index:5; /* 13-17 */ |
unsigned sub_reg_index:5; /* 18-22 */ |
unsigned acc_wr_control:1; /* 23-23 */ |
unsigned conditionalmod:4; /* 24-27 */ |
unsigned flag_subreg_nr:1; /* 28-28 */ |
unsigned cmpt_ctrl:1; /* 29-29 */ |
unsigned src0_index:2; /* 30-31 */ |
} dw0; |
struct { |
unsigned src0_index:3; /* 32-24 */ |
unsigned src1_index:5; /* 35-39 */ |
unsigned dst_reg_nr:8; /* 40-47 */ |
unsigned src0_reg_nr:8; /* 48-55 */ |
unsigned src1_reg_nr:8; /* 56-63 */ |
} dw1; |
}; |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_surface_formats.c |
---|
0,0 → 1,748 |
/* |
* Copyright © 2011 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 "main/context.h" |
#include "main/mtypes.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_wm.h" |
struct surface_format_info { |
bool exists; |
int sampling; |
int filtering; |
int shadow_compare; |
int chroma_key; |
int render_target; |
int alpha_blend; |
int input_vb; |
int streamed_output_vb; |
int color_processing; |
}; |
/* This macro allows us to write the table almost as it appears in the PRM, |
* while restructuring it to turn it into the C code we want. |
*/ |
#define SF(sampl, filt, shad, ck, rt, ab, vb, so, color, sf) \ |
[sf] = { true, sampl, filt, shad, ck, rt, ab, vb, so, color }, |
#define Y 0 |
#define x 999 |
/** |
* This is the table of support for surface (texture, renderbuffer, and vertex |
* buffer, but not depthbuffer) formats across the various hardware generations. |
* |
* The table is formatted to match the documentation, except that the docs have |
* this ridiculous mapping of Y[*+~^#&] for "supported on DevWhatever". To put |
* it in our table, here's the mapping: |
* |
* Y*: 45 |
* Y+: 45 (g45/gm45) |
* Y~: 50 (gen5) |
* Y^: 60 (gen6) |
* Y#: 70 (gen7) |
* |
* The abbreviations in the header below are: |
* smpl - Sampling Engine |
* filt - Sampling Engine Filtering |
* shad - Sampling Engine Shadow Map |
* CK - Sampling Engine Chroma Key |
* RT - Render Target |
* AB - Alpha Blend Render Target |
* VB - Input Vertex Buffer |
* SO - Steamed Output Vertex Buffers (transform feedback) |
* color - Color Processing |
* |
* See page 88 of the Sandybridge PRM VOL4_Part1 PDF. |
* |
* As of Ivybridge, the columns are no longer in that table and the |
* information can be found spread across: |
* |
* - VOL2_Part1 section 2.5.11 Format Conversion (vertex fetch). |
* - VOL4_Part1 section 2.12.2.1.2 Sampler Output Channel Mapping. |
* - VOL4_Part1 section 3.9.11 Render Target Write. |
*/ |
const struct surface_format_info surface_formats[] = { |
/* smpl filt shad CK RT AB VB SO color */ |
SF( Y, 50, x, x, Y, Y, Y, Y, x, BRW_SURFACEFORMAT_R32G32B32A32_FLOAT) |
SF( Y, x, x, x, Y, x, Y, Y, x, BRW_SURFACEFORMAT_R32G32B32A32_SINT) |
SF( Y, x, x, x, Y, x, Y, Y, x, BRW_SURFACEFORMAT_R32G32B32A32_UINT) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32B32A32_UNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32B32A32_SNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R64G64_FLOAT) |
SF( Y, 50, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R32G32B32X32_FLOAT) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32B32A32_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32B32A32_USCALED) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R32G32B32A32_SFIXED) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R64G64_PASSTHRU) |
SF( Y, 50, x, x, x, x, Y, Y, x, BRW_SURFACEFORMAT_R32G32B32_FLOAT) |
SF( Y, x, x, x, x, x, Y, Y, x, BRW_SURFACEFORMAT_R32G32B32_SINT) |
SF( Y, x, x, x, x, x, Y, Y, x, BRW_SURFACEFORMAT_R32G32B32_UINT) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32B32_UNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32B32_SNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32B32_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32B32_USCALED) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R32G32B32_SFIXED) |
SF( Y, Y, x, x, Y, 45, Y, x, 60, BRW_SURFACEFORMAT_R16G16B16A16_UNORM) |
SF( Y, Y, x, x, Y, 60, Y, x, x, BRW_SURFACEFORMAT_R16G16B16A16_SNORM) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R16G16B16A16_SINT) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R16G16B16A16_UINT) |
SF( Y, Y, x, x, Y, Y, Y, x, x, BRW_SURFACEFORMAT_R16G16B16A16_FLOAT) |
SF( Y, 50, x, x, Y, Y, Y, Y, x, BRW_SURFACEFORMAT_R32G32_FLOAT) |
SF( Y, x, x, x, Y, x, Y, Y, x, BRW_SURFACEFORMAT_R32G32_SINT) |
SF( Y, x, x, x, Y, x, Y, Y, x, BRW_SURFACEFORMAT_R32G32_UINT) |
SF( Y, 50, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_R32_FLOAT_X8X24_TYPELESS) |
SF( Y, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_X32_TYPELESS_G8X24_UINT) |
SF( Y, 50, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_L32A32_FLOAT) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32_UNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32_SNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R64_FLOAT) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R16G16B16X16_UNORM) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R16G16B16X16_FLOAT) |
SF( Y, 50, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_A32X32_FLOAT) |
SF( Y, 50, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_L32X32_FLOAT) |
SF( Y, 50, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_I32X32_FLOAT) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R16G16B16A16_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R16G16B16A16_USCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32G32_USCALED) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R32G32_SFIXED) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R64_PASSTHRU) |
SF( Y, Y, x, Y, Y, Y, Y, x, 60, BRW_SURFACEFORMAT_B8G8R8A8_UNORM) |
SF( Y, Y, x, x, Y, Y, x, x, x, BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB) |
/* smpl filt shad CK RT AB VB SO color */ |
SF( Y, Y, x, x, Y, Y, Y, x, 60, BRW_SURFACEFORMAT_R10G10B10A2_UNORM) |
SF( Y, Y, x, x, x, x, x, x, 60, BRW_SURFACEFORMAT_R10G10B10A2_UNORM_SRGB) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R10G10B10A2_UINT) |
SF( Y, Y, x, x, x, Y, Y, x, x, BRW_SURFACEFORMAT_R10G10B10_SNORM_A2_UNORM) |
SF( Y, Y, x, x, Y, Y, Y, x, 60, BRW_SURFACEFORMAT_R8G8B8A8_UNORM) |
SF( Y, Y, x, x, Y, Y, x, x, 60, BRW_SURFACEFORMAT_R8G8B8A8_UNORM_SRGB) |
SF( Y, Y, x, x, Y, 60, Y, x, x, BRW_SURFACEFORMAT_R8G8B8A8_SNORM) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R8G8B8A8_SINT) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R8G8B8A8_UINT) |
SF( Y, Y, x, x, Y, 45, Y, x, x, BRW_SURFACEFORMAT_R16G16_UNORM) |
SF( Y, Y, x, x, Y, 60, Y, x, x, BRW_SURFACEFORMAT_R16G16_SNORM) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R16G16_SINT) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R16G16_UINT) |
SF( Y, Y, x, x, Y, Y, Y, x, x, BRW_SURFACEFORMAT_R16G16_FLOAT) |
SF( Y, Y, x, x, Y, Y, x, x, 60, BRW_SURFACEFORMAT_B10G10R10A2_UNORM) |
SF( Y, Y, x, x, Y, Y, x, x, 60, BRW_SURFACEFORMAT_B10G10R10A2_UNORM_SRGB) |
SF( Y, Y, x, x, Y, Y, Y, x, x, BRW_SURFACEFORMAT_R11G11B10_FLOAT) |
SF( Y, x, x, x, Y, x, Y, Y, x, BRW_SURFACEFORMAT_R32_SINT) |
SF( Y, x, x, x, Y, x, Y, Y, x, BRW_SURFACEFORMAT_R32_UINT) |
SF( Y, 50, Y, x, Y, Y, Y, Y, x, BRW_SURFACEFORMAT_R32_FLOAT) |
SF( Y, 50, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_R24_UNORM_X8_TYPELESS) |
SF( Y, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_X24_TYPELESS_G8_UINT) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_L16A16_UNORM) |
SF( Y, 50, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_I24X8_UNORM) |
SF( Y, 50, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_L24X8_UNORM) |
SF( Y, 50, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_A24X8_UNORM) |
SF( Y, 50, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_I32_FLOAT) |
SF( Y, 50, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_L32_FLOAT) |
SF( Y, 50, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_A32_FLOAT) |
SF( Y, Y, x, Y, x, x, x, x, 60, BRW_SURFACEFORMAT_B8G8R8X8_UNORM) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_B8G8R8X8_UNORM_SRGB) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R8G8B8X8_UNORM) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R8G8B8X8_UNORM_SRGB) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R9G9B9E5_SHAREDEXP) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_B10G10R10X2_UNORM) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_L16A16_FLOAT) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32_UNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32_SNORM) |
/* smpl filt shad CK RT AB VB SO color */ |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R10G10B10X2_USCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R8G8B8A8_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R8G8B8A8_USCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R16G16_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R16G16_USCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R32_USCALED) |
SF( Y, Y, x, Y, Y, Y, x, x, x, BRW_SURFACEFORMAT_B5G6R5_UNORM) |
SF( Y, Y, x, x, Y, Y, x, x, x, BRW_SURFACEFORMAT_B5G6R5_UNORM_SRGB) |
SF( Y, Y, x, Y, Y, Y, x, x, x, BRW_SURFACEFORMAT_B5G5R5A1_UNORM) |
SF( Y, Y, x, x, Y, Y, x, x, x, BRW_SURFACEFORMAT_B5G5R5A1_UNORM_SRGB) |
SF( Y, Y, x, Y, Y, Y, x, x, x, BRW_SURFACEFORMAT_B4G4R4A4_UNORM) |
SF( Y, Y, x, x, Y, Y, x, x, x, BRW_SURFACEFORMAT_B4G4R4A4_UNORM_SRGB) |
SF( Y, Y, x, x, Y, Y, Y, x, x, BRW_SURFACEFORMAT_R8G8_UNORM) |
SF( Y, Y, x, Y, Y, 60, Y, x, x, BRW_SURFACEFORMAT_R8G8_SNORM) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R8G8_SINT) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R8G8_UINT) |
SF( Y, Y, Y, x, Y, 45, Y, x, 70, BRW_SURFACEFORMAT_R16_UNORM) |
SF( Y, Y, x, x, Y, 60, Y, x, x, BRW_SURFACEFORMAT_R16_SNORM) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R16_SINT) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R16_UINT) |
SF( Y, Y, x, x, Y, Y, Y, x, x, BRW_SURFACEFORMAT_R16_FLOAT) |
SF(50, 50, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_A8P8_UNORM_PALETTE0) |
SF(50, 50, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_A8P8_UNORM_PALETTE1) |
SF( Y, Y, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_I16_UNORM) |
SF( Y, Y, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_L16_UNORM) |
SF( Y, Y, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_A16_UNORM) |
SF( Y, Y, x, Y, x, x, x, x, x, BRW_SURFACEFORMAT_L8A8_UNORM) |
SF( Y, Y, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_I16_FLOAT) |
SF( Y, Y, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_L16_FLOAT) |
SF( Y, Y, Y, x, x, x, x, x, x, BRW_SURFACEFORMAT_A16_FLOAT) |
SF(45, 45, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_L8A8_UNORM_SRGB) |
SF( Y, Y, x, Y, x, x, x, x, x, BRW_SURFACEFORMAT_R5G5_SNORM_B6_UNORM) |
SF( x, x, x, x, Y, Y, x, x, x, BRW_SURFACEFORMAT_B5G5R5X1_UNORM) |
SF( x, x, x, x, Y, Y, x, x, x, BRW_SURFACEFORMAT_B5G5R5X1_UNORM_SRGB) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R8G8_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R8G8_USCALED) |
/* smpl filt shad CK RT AB VB SO color */ |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R16_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R16_USCALED) |
SF(50, 50, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_P8A8_UNORM_PALETTE0) |
SF(50, 50, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_P8A8_UNORM_PALETTE1) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_A1B5G5R5_UNORM) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_A4B4G4R4_UNORM) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_L8A8_UINT) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_L8A8_SINT) |
SF( Y, Y, x, 45, Y, Y, Y, x, x, BRW_SURFACEFORMAT_R8_UNORM) |
SF( Y, Y, x, x, Y, 60, Y, x, x, BRW_SURFACEFORMAT_R8_SNORM) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R8_SINT) |
SF( Y, x, x, x, Y, x, Y, x, x, BRW_SURFACEFORMAT_R8_UINT) |
SF( Y, Y, x, Y, Y, Y, x, x, x, BRW_SURFACEFORMAT_A8_UNORM) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_I8_UNORM) |
SF( Y, Y, x, Y, x, x, x, x, x, BRW_SURFACEFORMAT_L8_UNORM) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_P4A4_UNORM) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_A4P4_UNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R8_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R8_USCALED) |
SF(45, 45, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_P8_UNORM_PALETTE0) |
SF(45, 45, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_L8_UNORM_SRGB) |
SF(45, 45, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_P8_UNORM_PALETTE1) |
SF(45, 45, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_P4A4_UNORM_PALETTE1) |
SF(45, 45, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_A4P4_UNORM_PALETTE1) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_Y8_SNORM) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_L8_UINT) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_L8_SINT) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_I8_UINT) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_I8_SINT) |
SF(45, 45, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_DXT1_RGB_SRGB) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R1_UINT) |
SF( Y, Y, x, Y, Y, x, x, x, 60, BRW_SURFACEFORMAT_YCRCB_NORMAL) |
SF( Y, Y, x, Y, Y, x, x, x, 60, BRW_SURFACEFORMAT_YCRCB_SWAPUVY) |
SF(45, 45, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_P2_UNORM_PALETTE0) |
SF(45, 45, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_P2_UNORM_PALETTE1) |
SF( Y, Y, x, Y, x, x, x, x, x, BRW_SURFACEFORMAT_BC1_UNORM) |
SF( Y, Y, x, Y, x, x, x, x, x, BRW_SURFACEFORMAT_BC2_UNORM) |
SF( Y, Y, x, Y, x, x, x, x, x, BRW_SURFACEFORMAT_BC3_UNORM) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_BC4_UNORM) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_BC5_UNORM) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_BC1_UNORM_SRGB) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_BC2_UNORM_SRGB) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_BC3_UNORM_SRGB) |
SF( Y, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_MONO8) |
SF( Y, Y, x, x, Y, x, x, x, 60, BRW_SURFACEFORMAT_YCRCB_SWAPUV) |
SF( Y, Y, x, x, Y, x, x, x, 60, BRW_SURFACEFORMAT_YCRCB_SWAPY) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_DXT1_RGB) |
/* smpl filt shad CK RT AB VB SO color */ |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_FXT1) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R8G8B8_UNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R8G8B8_SNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R8G8B8_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R8G8B8_USCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R64G64B64A64_FLOAT) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R64G64B64_FLOAT) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_BC4_SNORM) |
SF( Y, Y, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_BC5_SNORM) |
SF(50, 50, x, x, x, x, 60, x, x, BRW_SURFACEFORMAT_R16G16B16_FLOAT) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R16G16B16_UNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R16G16B16_SNORM) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R16G16B16_SSCALED) |
SF( x, x, x, x, x, x, Y, x, x, BRW_SURFACEFORMAT_R16G16B16_USCALED) |
SF(70, 70, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_BC6H_SF16) |
SF(70, 70, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_BC7_UNORM) |
SF(70, 70, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_BC7_UNORM_SRGB) |
SF(70, 70, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_BC6H_UF16) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_PLANAR_420_8) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R8G8B8_UNORM_SRGB) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_ETC1_RGB8) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_ETC2_RGB8) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_EAC_R11) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_EAC_RG11) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_EAC_SIGNED_R11) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_EAC_SIGNED_RG11) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_ETC2_SRGB8) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R16G16B16_UINT) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R16G16B16_SINT) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R32_SFIXED) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R10G10B10A2_SNORM) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R10G10B10A2_USCALED) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R10G10B10A2_SSCALED) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R10G10B10A2_SINT) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_B10G10R10A2_SNORM) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_B10G10R10A2_USCALED) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_B10G10R10A2_SSCALED) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_B10G10R10A2_UINT) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_B10G10R10A2_SINT) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R64G64B64A64_PASSTHRU) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R64G64B64_PASSTHRU) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_ETC2_RGB8_PTA) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_ETC2_SRGB8_PTA) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_ETC2_EAC_RGBA8) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_ETC2_EAC_SRGB8_A8) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R8G8B8_UINT) |
SF( x, x, x, x, x, x, x, x, x, BRW_SURFACEFORMAT_R8G8B8_SINT) |
}; |
#undef x |
#undef Y |
uint32_t |
brw_format_for_mesa_format(gl_format mesa_format) |
{ |
/* This table is ordered according to the enum ordering in formats.h. We do |
* expect that enum to be extended without our explicit initialization |
* staying in sync, so we initialize to 0 even though |
* BRW_SURFACEFORMAT_R32G32B32A32_FLOAT happens to also be 0. |
*/ |
static const uint32_t table[MESA_FORMAT_COUNT] = |
{ |
[MESA_FORMAT_RGBA8888] = 0, |
[MESA_FORMAT_RGBA8888_REV] = BRW_SURFACEFORMAT_R8G8B8A8_UNORM, |
[MESA_FORMAT_ARGB8888] = BRW_SURFACEFORMAT_B8G8R8A8_UNORM, |
[MESA_FORMAT_ARGB8888_REV] = 0, |
[MESA_FORMAT_RGBX8888] = 0, |
[MESA_FORMAT_RGBX8888_REV] = BRW_SURFACEFORMAT_R8G8B8X8_UNORM, |
[MESA_FORMAT_XRGB8888] = BRW_SURFACEFORMAT_B8G8R8X8_UNORM, |
[MESA_FORMAT_XRGB8888_REV] = 0, |
[MESA_FORMAT_RGB888] = 0, |
[MESA_FORMAT_BGR888] = BRW_SURFACEFORMAT_R8G8B8_UNORM, |
[MESA_FORMAT_RGB565] = BRW_SURFACEFORMAT_B5G6R5_UNORM, |
[MESA_FORMAT_RGB565_REV] = 0, |
[MESA_FORMAT_ARGB4444] = BRW_SURFACEFORMAT_B4G4R4A4_UNORM, |
[MESA_FORMAT_ARGB4444_REV] = 0, |
[MESA_FORMAT_RGBA5551] = 0, |
[MESA_FORMAT_ARGB1555] = BRW_SURFACEFORMAT_B5G5R5A1_UNORM, |
[MESA_FORMAT_ARGB1555_REV] = 0, |
[MESA_FORMAT_AL44] = 0, |
[MESA_FORMAT_AL88] = BRW_SURFACEFORMAT_L8A8_UNORM, |
[MESA_FORMAT_AL88_REV] = 0, |
[MESA_FORMAT_AL1616] = BRW_SURFACEFORMAT_L16A16_UNORM, |
[MESA_FORMAT_AL1616_REV] = 0, |
[MESA_FORMAT_RGB332] = 0, |
[MESA_FORMAT_A8] = BRW_SURFACEFORMAT_A8_UNORM, |
[MESA_FORMAT_A16] = BRW_SURFACEFORMAT_A16_UNORM, |
[MESA_FORMAT_L8] = BRW_SURFACEFORMAT_L8_UNORM, |
[MESA_FORMAT_L16] = BRW_SURFACEFORMAT_L16_UNORM, |
[MESA_FORMAT_I8] = BRW_SURFACEFORMAT_I8_UNORM, |
[MESA_FORMAT_I16] = BRW_SURFACEFORMAT_I16_UNORM, |
[MESA_FORMAT_YCBCR_REV] = BRW_SURFACEFORMAT_YCRCB_NORMAL, |
[MESA_FORMAT_YCBCR] = BRW_SURFACEFORMAT_YCRCB_SWAPUVY, |
[MESA_FORMAT_R8] = BRW_SURFACEFORMAT_R8_UNORM, |
[MESA_FORMAT_GR88] = BRW_SURFACEFORMAT_R8G8_UNORM, |
[MESA_FORMAT_RG88] = 0, |
[MESA_FORMAT_R16] = BRW_SURFACEFORMAT_R16_UNORM, |
[MESA_FORMAT_GR1616] = BRW_SURFACEFORMAT_R16G16_UNORM, |
[MESA_FORMAT_RG1616] = 0, |
[MESA_FORMAT_ARGB2101010] = BRW_SURFACEFORMAT_B10G10R10A2_UNORM, |
[MESA_FORMAT_Z24_S8] = 0, |
[MESA_FORMAT_S8_Z24] = 0, |
[MESA_FORMAT_Z16] = 0, |
[MESA_FORMAT_X8_Z24] = 0, |
[MESA_FORMAT_Z24_X8] = 0, |
[MESA_FORMAT_Z32] = 0, |
[MESA_FORMAT_S8] = 0, |
[MESA_FORMAT_SRGB8] = 0, |
[MESA_FORMAT_SRGBA8] = 0, |
[MESA_FORMAT_SARGB8] = BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB, |
[MESA_FORMAT_SL8] = BRW_SURFACEFORMAT_L8_UNORM_SRGB, |
[MESA_FORMAT_SLA8] = BRW_SURFACEFORMAT_L8A8_UNORM_SRGB, |
[MESA_FORMAT_SRGB_DXT1] = BRW_SURFACEFORMAT_DXT1_RGB_SRGB, |
[MESA_FORMAT_SRGBA_DXT1] = BRW_SURFACEFORMAT_BC1_UNORM_SRGB, |
[MESA_FORMAT_SRGBA_DXT3] = BRW_SURFACEFORMAT_BC2_UNORM_SRGB, |
[MESA_FORMAT_SRGBA_DXT5] = BRW_SURFACEFORMAT_BC3_UNORM_SRGB, |
[MESA_FORMAT_RGB_FXT1] = BRW_SURFACEFORMAT_FXT1, |
[MESA_FORMAT_RGBA_FXT1] = BRW_SURFACEFORMAT_FXT1, |
[MESA_FORMAT_RGB_DXT1] = BRW_SURFACEFORMAT_DXT1_RGB, |
[MESA_FORMAT_RGBA_DXT1] = BRW_SURFACEFORMAT_BC1_UNORM, |
[MESA_FORMAT_RGBA_DXT3] = BRW_SURFACEFORMAT_BC2_UNORM, |
[MESA_FORMAT_RGBA_DXT5] = BRW_SURFACEFORMAT_BC3_UNORM, |
[MESA_FORMAT_RGBA_FLOAT32] = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT, |
[MESA_FORMAT_RGBA_FLOAT16] = BRW_SURFACEFORMAT_R16G16B16A16_FLOAT, |
[MESA_FORMAT_RGB_FLOAT32] = BRW_SURFACEFORMAT_R32G32B32_FLOAT, |
[MESA_FORMAT_RGB_FLOAT16] = BRW_SURFACEFORMAT_R16G16B16_FLOAT, |
[MESA_FORMAT_ALPHA_FLOAT32] = BRW_SURFACEFORMAT_A32_FLOAT, |
[MESA_FORMAT_ALPHA_FLOAT16] = BRW_SURFACEFORMAT_A16_FLOAT, |
[MESA_FORMAT_LUMINANCE_FLOAT32] = BRW_SURFACEFORMAT_L32_FLOAT, |
[MESA_FORMAT_LUMINANCE_FLOAT16] = BRW_SURFACEFORMAT_L16_FLOAT, |
[MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32] = BRW_SURFACEFORMAT_L32A32_FLOAT, |
[MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16] = BRW_SURFACEFORMAT_L16A16_FLOAT, |
[MESA_FORMAT_INTENSITY_FLOAT32] = BRW_SURFACEFORMAT_I32_FLOAT, |
[MESA_FORMAT_INTENSITY_FLOAT16] = BRW_SURFACEFORMAT_I16_FLOAT, |
[MESA_FORMAT_R_FLOAT32] = BRW_SURFACEFORMAT_R32_FLOAT, |
[MESA_FORMAT_R_FLOAT16] = BRW_SURFACEFORMAT_R16_FLOAT, |
[MESA_FORMAT_RG_FLOAT32] = BRW_SURFACEFORMAT_R32G32_FLOAT, |
[MESA_FORMAT_RG_FLOAT16] = BRW_SURFACEFORMAT_R16G16_FLOAT, |
[MESA_FORMAT_ALPHA_UINT8] = 0, |
[MESA_FORMAT_ALPHA_UINT16] = 0, |
[MESA_FORMAT_ALPHA_UINT32] = 0, |
[MESA_FORMAT_ALPHA_INT8] = 0, |
[MESA_FORMAT_ALPHA_INT16] = 0, |
[MESA_FORMAT_ALPHA_INT32] = 0, |
[MESA_FORMAT_INTENSITY_UINT8] = 0, |
[MESA_FORMAT_INTENSITY_UINT16] = 0, |
[MESA_FORMAT_INTENSITY_UINT32] = 0, |
[MESA_FORMAT_INTENSITY_INT8] = 0, |
[MESA_FORMAT_INTENSITY_INT16] = 0, |
[MESA_FORMAT_INTENSITY_INT32] = 0, |
[MESA_FORMAT_LUMINANCE_UINT8] = 0, |
[MESA_FORMAT_LUMINANCE_UINT16] = 0, |
[MESA_FORMAT_LUMINANCE_UINT32] = 0, |
[MESA_FORMAT_LUMINANCE_INT8] = 0, |
[MESA_FORMAT_LUMINANCE_INT16] = 0, |
[MESA_FORMAT_LUMINANCE_INT32] = 0, |
[MESA_FORMAT_LUMINANCE_ALPHA_UINT8] = 0, |
[MESA_FORMAT_LUMINANCE_ALPHA_UINT16] = 0, |
[MESA_FORMAT_LUMINANCE_ALPHA_UINT32] = 0, |
[MESA_FORMAT_LUMINANCE_ALPHA_INT8] = 0, |
[MESA_FORMAT_LUMINANCE_ALPHA_INT16] = 0, |
[MESA_FORMAT_LUMINANCE_ALPHA_INT32] = 0, |
[MESA_FORMAT_R_INT8] = BRW_SURFACEFORMAT_R8_SINT, |
[MESA_FORMAT_RG_INT8] = BRW_SURFACEFORMAT_R8G8_SINT, |
[MESA_FORMAT_RGB_INT8] = BRW_SURFACEFORMAT_R8G8B8_SINT, |
[MESA_FORMAT_RGBA_INT8] = BRW_SURFACEFORMAT_R8G8B8A8_SINT, |
[MESA_FORMAT_R_INT16] = BRW_SURFACEFORMAT_R16_SINT, |
[MESA_FORMAT_RG_INT16] = BRW_SURFACEFORMAT_R16G16_SINT, |
[MESA_FORMAT_RGB_INT16] = BRW_SURFACEFORMAT_R16G16B16_SINT, |
[MESA_FORMAT_RGBA_INT16] = BRW_SURFACEFORMAT_R16G16B16A16_SINT, |
[MESA_FORMAT_R_INT32] = BRW_SURFACEFORMAT_R32_SINT, |
[MESA_FORMAT_RG_INT32] = BRW_SURFACEFORMAT_R32G32_SINT, |
[MESA_FORMAT_RGB_INT32] = BRW_SURFACEFORMAT_R32G32B32_SINT, |
[MESA_FORMAT_RGBA_INT32] = BRW_SURFACEFORMAT_R32G32B32A32_SINT, |
[MESA_FORMAT_R_UINT8] = BRW_SURFACEFORMAT_R8_UINT, |
[MESA_FORMAT_RG_UINT8] = BRW_SURFACEFORMAT_R8G8_UINT, |
[MESA_FORMAT_RGB_UINT8] = BRW_SURFACEFORMAT_R8G8B8_UINT, |
[MESA_FORMAT_RGBA_UINT8] = BRW_SURFACEFORMAT_R8G8B8A8_UINT, |
[MESA_FORMAT_R_UINT16] = BRW_SURFACEFORMAT_R16_UINT, |
[MESA_FORMAT_RG_UINT16] = BRW_SURFACEFORMAT_R16G16_UINT, |
[MESA_FORMAT_RGB_UINT16] = BRW_SURFACEFORMAT_R16G16B16_UINT, |
[MESA_FORMAT_RGBA_UINT16] = BRW_SURFACEFORMAT_R16G16B16A16_UINT, |
[MESA_FORMAT_R_UINT32] = BRW_SURFACEFORMAT_R32_UINT, |
[MESA_FORMAT_RG_UINT32] = BRW_SURFACEFORMAT_R32G32_UINT, |
[MESA_FORMAT_RGB_UINT32] = BRW_SURFACEFORMAT_R32G32B32_UINT, |
[MESA_FORMAT_RGBA_UINT32] = BRW_SURFACEFORMAT_R32G32B32A32_UINT, |
[MESA_FORMAT_DUDV8] = BRW_SURFACEFORMAT_R8G8_SNORM, |
[MESA_FORMAT_SIGNED_R8] = BRW_SURFACEFORMAT_R8_SNORM, |
[MESA_FORMAT_SIGNED_RG88_REV] = BRW_SURFACEFORMAT_R8G8_SNORM, |
[MESA_FORMAT_SIGNED_RGBX8888] = 0, |
[MESA_FORMAT_SIGNED_RGBA8888] = 0, |
[MESA_FORMAT_SIGNED_RGBA8888_REV] = BRW_SURFACEFORMAT_R8G8B8A8_SNORM, |
[MESA_FORMAT_SIGNED_R16] = BRW_SURFACEFORMAT_R16_SNORM, |
[MESA_FORMAT_SIGNED_GR1616] = BRW_SURFACEFORMAT_R16G16_SNORM, |
[MESA_FORMAT_SIGNED_RGB_16] = BRW_SURFACEFORMAT_R16G16B16_SNORM, |
[MESA_FORMAT_SIGNED_RGBA_16] = BRW_SURFACEFORMAT_R16G16B16A16_SNORM, |
[MESA_FORMAT_RGBA_16] = BRW_SURFACEFORMAT_R16G16B16A16_UNORM, |
[MESA_FORMAT_RED_RGTC1] = BRW_SURFACEFORMAT_BC4_UNORM, |
[MESA_FORMAT_SIGNED_RED_RGTC1] = BRW_SURFACEFORMAT_BC4_SNORM, |
[MESA_FORMAT_RG_RGTC2] = BRW_SURFACEFORMAT_BC5_UNORM, |
[MESA_FORMAT_SIGNED_RG_RGTC2] = BRW_SURFACEFORMAT_BC5_SNORM, |
[MESA_FORMAT_L_LATC1] = 0, |
[MESA_FORMAT_SIGNED_L_LATC1] = 0, |
[MESA_FORMAT_LA_LATC2] = 0, |
[MESA_FORMAT_SIGNED_LA_LATC2] = 0, |
[MESA_FORMAT_ETC1_RGB8] = BRW_SURFACEFORMAT_ETC1_RGB8, |
[MESA_FORMAT_ETC2_RGB8] = BRW_SURFACEFORMAT_ETC2_RGB8, |
[MESA_FORMAT_ETC2_SRGB8] = BRW_SURFACEFORMAT_ETC2_SRGB8, |
[MESA_FORMAT_ETC2_RGBA8_EAC] = BRW_SURFACEFORMAT_ETC2_EAC_RGBA8, |
[MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC] = BRW_SURFACEFORMAT_ETC2_EAC_SRGB8_A8, |
[MESA_FORMAT_ETC2_R11_EAC] = BRW_SURFACEFORMAT_EAC_R11, |
[MESA_FORMAT_ETC2_RG11_EAC] = BRW_SURFACEFORMAT_EAC_RG11, |
[MESA_FORMAT_ETC2_SIGNED_R11_EAC] = BRW_SURFACEFORMAT_EAC_SIGNED_R11, |
[MESA_FORMAT_ETC2_SIGNED_RG11_EAC] = BRW_SURFACEFORMAT_EAC_SIGNED_RG11, |
[MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1] = BRW_SURFACEFORMAT_ETC2_RGB8_PTA, |
[MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1] = BRW_SURFACEFORMAT_ETC2_SRGB8_PTA, |
[MESA_FORMAT_SIGNED_A8] = 0, |
[MESA_FORMAT_SIGNED_L8] = 0, |
[MESA_FORMAT_SIGNED_AL88] = 0, |
[MESA_FORMAT_SIGNED_I8] = 0, |
[MESA_FORMAT_SIGNED_A16] = 0, |
[MESA_FORMAT_SIGNED_L16] = 0, |
[MESA_FORMAT_SIGNED_AL1616] = 0, |
[MESA_FORMAT_SIGNED_I16] = 0, |
[MESA_FORMAT_RGB9_E5_FLOAT] = BRW_SURFACEFORMAT_R9G9B9E5_SHAREDEXP, |
[MESA_FORMAT_R11_G11_B10_FLOAT] = BRW_SURFACEFORMAT_R11G11B10_FLOAT, |
[MESA_FORMAT_Z32_FLOAT] = 0, |
[MESA_FORMAT_Z32_FLOAT_X24S8] = 0, |
[MESA_FORMAT_ARGB2101010_UINT] = BRW_SURFACEFORMAT_B10G10R10A2_UINT, |
[MESA_FORMAT_ABGR2101010_UINT] = BRW_SURFACEFORMAT_R10G10B10A2_UINT, |
[MESA_FORMAT_XRGB4444_UNORM] = 0, |
[MESA_FORMAT_XRGB1555_UNORM] = BRW_SURFACEFORMAT_B5G5R5X1_UNORM, |
[MESA_FORMAT_XBGR8888_SNORM] = 0, |
[MESA_FORMAT_XBGR8888_SRGB] = 0, |
[MESA_FORMAT_XBGR8888_UINT] = 0, |
[MESA_FORMAT_XBGR8888_SINT] = 0, |
[MESA_FORMAT_XRGB2101010_UNORM] = BRW_SURFACEFORMAT_B10G10R10X2_UNORM, |
[MESA_FORMAT_XBGR16161616_UNORM] = BRW_SURFACEFORMAT_R16G16B16X16_UNORM, |
[MESA_FORMAT_XBGR16161616_SNORM] = 0, |
[MESA_FORMAT_XBGR16161616_FLOAT] = BRW_SURFACEFORMAT_R16G16B16X16_FLOAT, |
[MESA_FORMAT_XBGR16161616_UINT] = 0, |
[MESA_FORMAT_XBGR16161616_SINT] = 0, |
[MESA_FORMAT_XBGR32323232_FLOAT] = BRW_SURFACEFORMAT_R32G32B32X32_FLOAT, |
[MESA_FORMAT_XBGR32323232_UINT] = 0, |
[MESA_FORMAT_XBGR32323232_SINT] = 0, |
}; |
assert(mesa_format < MESA_FORMAT_COUNT); |
return table[mesa_format]; |
} |
void |
brw_init_surface_formats(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
int gen; |
gl_format format; |
gen = brw->gen * 10; |
if (brw->is_g4x) |
gen += 5; |
for (format = MESA_FORMAT_NONE + 1; format < MESA_FORMAT_COUNT; format++) { |
uint32_t texture, render; |
const struct surface_format_info *rinfo, *tinfo; |
bool is_integer = _mesa_is_format_integer_color(format); |
render = texture = brw_format_for_mesa_format(format); |
tinfo = &surface_formats[texture]; |
/* The value of BRW_SURFACEFORMAT_R32G32B32A32_FLOAT is 0, so don't skip |
* it. |
*/ |
if (texture == 0 && format != MESA_FORMAT_RGBA_FLOAT32) |
continue; |
if (gen >= tinfo->sampling && (gen >= tinfo->filtering || is_integer)) |
ctx->TextureFormatSupported[format] = true; |
/* Re-map some render target formats to make them supported when they |
* wouldn't be using their format for texturing. |
*/ |
switch (render) { |
/* For these formats, we just need to read/write the first |
* channel into R, which is to say that we just treat them as |
* GL_RED. |
*/ |
case BRW_SURFACEFORMAT_I32_FLOAT: |
case BRW_SURFACEFORMAT_L32_FLOAT: |
render = BRW_SURFACEFORMAT_R32_FLOAT; |
break; |
case BRW_SURFACEFORMAT_I16_FLOAT: |
case BRW_SURFACEFORMAT_L16_FLOAT: |
render = BRW_SURFACEFORMAT_R16_FLOAT; |
break; |
case BRW_SURFACEFORMAT_B8G8R8X8_UNORM: |
/* XRGB is handled as ARGB because the chips in this family |
* cannot render to XRGB targets. This means that we have to |
* mask writes to alpha (ala glColorMask) and reconfigure the |
* alpha blending hardware to use GL_ONE (or GL_ZERO) for |
* cases where GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is |
* used. |
*/ |
render = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; |
break; |
} |
rinfo = &surface_formats[render]; |
/* Note that GL_EXT_texture_integer says that blending doesn't occur for |
* integer, so we don't need hardware support for blending on it. Other |
* than that, GL in general requires alpha blending for render targets, |
* even though we don't support it for some formats. |
*/ |
if (gen >= rinfo->render_target && |
(gen >= rinfo->alpha_blend || is_integer)) { |
brw->render_target_format[format] = render; |
brw->format_supported_as_render_target[format] = true; |
} |
} |
/* We will check this table for FBO completeness, but the surface format |
* table above only covered color rendering. |
*/ |
brw->format_supported_as_render_target[MESA_FORMAT_S8_Z24] = true; |
brw->format_supported_as_render_target[MESA_FORMAT_X8_Z24] = true; |
brw->format_supported_as_render_target[MESA_FORMAT_S8] = true; |
brw->format_supported_as_render_target[MESA_FORMAT_Z16] = true; |
brw->format_supported_as_render_target[MESA_FORMAT_Z32_FLOAT] = true; |
brw->format_supported_as_render_target[MESA_FORMAT_Z32_FLOAT_X24S8] = true; |
/* We remap depth formats to a supported texturing format in |
* translate_tex_format(). |
*/ |
ctx->TextureFormatSupported[MESA_FORMAT_S8_Z24] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_X8_Z24] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_Z32_FLOAT_X24S8] = true; |
/* It appears that Z16 is slower than Z24 (on Intel Ivybridge and newer |
* hardware at least), so there's no real reason to prefer it unless you're |
* under memory (not memory bandwidth) pressure. Our speculation is that |
* this is due to either increased fragment shader execution from |
* GL_LEQUAL/GL_EQUAL depth tests at the reduced precision, or due to |
* increased depth stalls from a cacheline-based heuristic for detecting |
* depth stalls. |
* |
* However, desktop GL 3.0+ require that you get exactly 16 bits when |
* asking for DEPTH_COMPONENT16, so we have to respect that. |
*/ |
if (_mesa_is_desktop_gl(ctx)) |
ctx->TextureFormatSupported[MESA_FORMAT_Z16] = true; |
/* On hardware that lacks support for ETC1, we map ETC1 to RGBX |
* during glCompressedTexImage2D(). See intel_mipmap_tree::wraps_etc1. |
*/ |
ctx->TextureFormatSupported[MESA_FORMAT_ETC1_RGB8] = true; |
/* On hardware that lacks support for ETC2, we map ETC2 to a suitable |
* MESA_FORMAT during glCompressedTexImage2D(). |
* See intel_mipmap_tree::wraps_etc2. |
*/ |
ctx->TextureFormatSupported[MESA_FORMAT_ETC2_RGB8] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_ETC2_SRGB8] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_ETC2_RGBA8_EAC] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_ETC2_R11_EAC] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_ETC2_RG11_EAC] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_ETC2_SIGNED_R11_EAC] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_ETC2_SIGNED_RG11_EAC] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1] = true; |
ctx->TextureFormatSupported[MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1] = true; |
} |
bool |
brw_render_target_supported(struct brw_context *brw, |
struct gl_renderbuffer *rb) |
{ |
gl_format format = rb->Format; |
/* Many integer formats are promoted to RGBA (like XRGB8888 is), which means |
* we would consider them renderable even though we don't have surface |
* support for their alpha behavior and don't have the blending unit |
* available to fake it like we do for XRGB8888. Force them to being |
* unsupported. |
*/ |
if ((rb->_BaseFormat != GL_RGBA && |
rb->_BaseFormat != GL_RG && |
rb->_BaseFormat != GL_RED) && _mesa_is_format_integer_color(format)) |
return false; |
/* Under some conditions, MSAA is not supported for formats whose width is |
* more than 64 bits. |
*/ |
if (rb->NumSamples > 0 && _mesa_get_format_bytes(format) > 8) { |
/* Gen6: MSAA on >64 bit formats is unsupported. */ |
if (brw->gen <= 6) |
return false; |
/* Gen7: 8x MSAA on >64 bit formats is unsupported. */ |
if (rb->NumSamples >= 8) |
return false; |
} |
return brw->format_supported_as_render_target[format]; |
} |
GLuint |
translate_tex_format(struct brw_context *brw, |
gl_format mesa_format, |
GLenum depth_mode, |
GLenum srgb_decode) |
{ |
struct gl_context *ctx = &brw->ctx; |
if (srgb_decode == GL_SKIP_DECODE_EXT) |
mesa_format = _mesa_get_srgb_format_linear(mesa_format); |
switch( mesa_format ) { |
case MESA_FORMAT_Z16: |
return BRW_SURFACEFORMAT_I16_UNORM; |
case MESA_FORMAT_S8_Z24: |
case MESA_FORMAT_X8_Z24: |
return BRW_SURFACEFORMAT_I24X8_UNORM; |
case MESA_FORMAT_Z32_FLOAT: |
return BRW_SURFACEFORMAT_I32_FLOAT; |
case MESA_FORMAT_Z32_FLOAT_X24S8: |
return BRW_SURFACEFORMAT_R32G32_FLOAT; |
case MESA_FORMAT_RGBA_FLOAT32: |
/* The value of this BRW_SURFACEFORMAT is 0, which tricks the |
* assertion below. |
*/ |
return BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; |
case MESA_FORMAT_SRGB_DXT1: |
if (brw->gen == 4 && !brw->is_g4x) { |
/* Work around missing SRGB DXT1 support on original gen4 by just |
* skipping SRGB decode. It's not worth not supporting sRGB in |
* general to prevent this. |
*/ |
WARN_ONCE(true, "Demoting sRGB DXT1 texture to non-sRGB\n"); |
mesa_format = MESA_FORMAT_RGB_DXT1; |
} |
return brw_format_for_mesa_format(mesa_format); |
default: |
assert(brw_format_for_mesa_format(mesa_format) != 0); |
return brw_format_for_mesa_format(mesa_format); |
} |
} |
/** Can HiZ be enabled on a depthbuffer of the given format? */ |
bool |
brw_is_hiz_depth_format(struct brw_context *brw, gl_format format) |
{ |
if (!brw->has_hiz) |
return false; |
switch (format) { |
case MESA_FORMAT_Z32_FLOAT: |
case MESA_FORMAT_Z32_FLOAT_X24S8: |
case MESA_FORMAT_X8_Z24: |
case MESA_FORMAT_S8_Z24: |
case MESA_FORMAT_Z16: |
return true; |
default: |
return false; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_tex.c |
---|
0,0 → 1,57 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/mtypes.h" |
#include "main/teximage.h" |
#include "intel_regions.h" |
#include "intel_tex.h" |
#include "brw_context.h" |
/** |
* Finalizes all textures, completing any rendering that needs to be done |
* to prepare them. |
*/ |
void brw_validate_textures( struct brw_context *brw ) |
{ |
struct gl_context *ctx = &brw->ctx; |
int i; |
for (i = 0; i < BRW_MAX_TEX_UNIT; i++) { |
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; |
if (texUnit->_ReallyEnabled) { |
intel_finalize_mipmap_tree(brw, i); |
} |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_tex_layout.c |
---|
0,0 → 1,329 |
/* |
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. |
* Copyright © 2006 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 COPYRIGHT OWNER(S) 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. |
*/ |
/** |
* \file brw_tex_layout.cpp |
* |
* Code to lay out images in a mipmap tree. |
* |
* \author Keith Whitwell <keith@tungstengraphics.com> |
* \author Michel Dänzer <michel@tungstengraphics.com> |
*/ |
#include "intel_mipmap_tree.h" |
#include "brw_context.h" |
#include "main/macros.h" |
#define FILE_DEBUG_FLAG DEBUG_MIPTREE |
static unsigned int |
intel_horizontal_texture_alignment_unit(struct brw_context *brw, |
gl_format format) |
{ |
/** |
* From the "Alignment Unit Size" section of various specs, namely: |
* - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4 |
* - i965 and G45 PRMs: Volume 1, Section 6.17.3.4. |
* - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4 |
* - BSpec (for Ivybridge and slight variations in separate stencil) |
* |
* +----------------------------------------------------------------------+ |
* | | alignment unit width ("i") | |
* | Surface Property |-----------------------------| |
* | | 915 | 965 | ILK | SNB | IVB | |
* +----------------------------------------------------------------------+ |
* | YUV 4:2:2 format | 8 | 4 | 4 | 4 | 4 | |
* | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 | |
* | FXT1 compressed format | 8 | 8 | 8 | 8 | 8 | |
* | Depth Buffer (16-bit) | 4 | 4 | 4 | 4 | 8 | |
* | Depth Buffer (other) | 4 | 4 | 4 | 4 | 4 | |
* | Separate Stencil Buffer | N/A | N/A | 8 | 8 | 8 | |
* | All Others | 4 | 4 | 4 | 4 | 4 | |
* +----------------------------------------------------------------------+ |
* |
* On IVB+, non-special cases can be overridden by setting the SURFACE_STATE |
* "Surface Horizontal Alignment" field to HALIGN_4 or HALIGN_8. |
*/ |
if (_mesa_is_format_compressed(format)) { |
/* The hardware alignment requirements for compressed textures |
* happen to match the block boundaries. |
*/ |
unsigned int i, j; |
_mesa_get_format_block_size(format, &i, &j); |
return i; |
} |
if (format == MESA_FORMAT_S8) |
return 8; |
/* The depth alignment requirements in the table above are for rendering to |
* depth miplevels using the LOD control fields. We don't use LOD control |
* fields, and instead use page offsets plus intra-tile x/y offsets, which |
* require that the low 3 bits are zero. To reduce the number of x/y |
* offset workaround blits we do, align the X to 8, which depth texturing |
* can handle (sadly, it can't handle 8 in the Y direction). |
*/ |
if (brw->gen >= 7 && |
_mesa_get_format_base_format(format) == GL_DEPTH_COMPONENT) |
return 8; |
return 4; |
} |
static unsigned int |
intel_vertical_texture_alignment_unit(struct brw_context *brw, |
gl_format format) |
{ |
/** |
* From the "Alignment Unit Size" section of various specs, namely: |
* - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4 |
* - i965 and G45 PRMs: Volume 1, Section 6.17.3.4. |
* - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4 |
* - BSpec (for Ivybridge and slight variations in separate stencil) |
* |
* +----------------------------------------------------------------------+ |
* | | alignment unit height ("j") | |
* | Surface Property |-----------------------------| |
* | | 915 | 965 | ILK | SNB | IVB | |
* +----------------------------------------------------------------------+ |
* | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 | |
* | FXT1 compressed format | 4 | 4 | 4 | 4 | 4 | |
* | Depth Buffer | 2 | 2 | 2 | 4 | 4 | |
* | Separate Stencil Buffer | N/A | N/A | N/A | 4 | 8 | |
* | Multisampled (4x or 8x) render target | N/A | N/A | N/A | 4 | 4 | |
* | All Others | 2 | 2 | 2 | 2 | 2 | |
* +----------------------------------------------------------------------+ |
* |
* On SNB+, non-special cases can be overridden by setting the SURFACE_STATE |
* "Surface Vertical Alignment" field to VALIGN_2 or VALIGN_4. |
* |
* We currently don't support multisampling. |
*/ |
if (_mesa_is_format_compressed(format)) |
return 4; |
if (format == MESA_FORMAT_S8) |
return brw->gen >= 7 ? 8 : 4; |
GLenum base_format = _mesa_get_format_base_format(format); |
if (brw->gen >= 6 && |
(base_format == GL_DEPTH_COMPONENT || |
base_format == GL_DEPTH_STENCIL)) { |
return 4; |
} |
return 2; |
} |
static void |
brw_miptree_layout_2d(struct intel_mipmap_tree *mt) |
{ |
unsigned x = 0; |
unsigned y = 0; |
unsigned width = mt->physical_width0; |
unsigned height = mt->physical_height0; |
unsigned depth = mt->physical_depth0; /* number of array layers. */ |
mt->total_width = mt->physical_width0; |
if (mt->compressed) { |
mt->total_width = ALIGN(mt->physical_width0, mt->align_w); |
} |
/* May need to adjust width to accomodate the placement of |
* the 2nd mipmap. This occurs when the alignment |
* constraints of mipmap placement push the right edge of the |
* 2nd mipmap out past the width of its parent. |
*/ |
if (mt->first_level != mt->last_level) { |
unsigned mip1_width; |
if (mt->compressed) { |
mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) + |
ALIGN(minify(mt->physical_width0, 2), mt->align_w); |
} else { |
mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) + |
minify(mt->physical_width0, 2); |
} |
if (mip1_width > mt->total_width) { |
mt->total_width = mip1_width; |
} |
} |
mt->total_height = 0; |
for (unsigned level = mt->first_level; level <= mt->last_level; level++) { |
unsigned img_height; |
intel_miptree_set_level_info(mt, level, x, y, width, |
height, depth); |
img_height = ALIGN(height, mt->align_h); |
if (mt->compressed) |
img_height /= mt->align_h; |
/* Because the images are packed better, the final offset |
* might not be the maximal one: |
*/ |
mt->total_height = MAX2(mt->total_height, y + img_height); |
/* Layout_below: step right after second mipmap. |
*/ |
if (level == mt->first_level + 1) { |
x += ALIGN(width, mt->align_w); |
} else { |
y += img_height; |
} |
width = minify(width, 1); |
height = minify(height, 1); |
} |
} |
static void |
align_cube(struct intel_mipmap_tree *mt) |
{ |
/* The 965's sampler lays cachelines out according to how accesses |
* in the texture surfaces run, so they may be "vertical" through |
* memory. As a result, the docs say in Surface Padding Requirements: |
* Sampling Engine Surfaces that two extra rows of padding are required. |
*/ |
if (mt->target == GL_TEXTURE_CUBE_MAP) |
mt->total_height += 2; |
} |
static void |
brw_miptree_layout_texture_array(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
unsigned qpitch = 0; |
int h0, h1; |
h0 = ALIGN(mt->physical_height0, mt->align_h); |
h1 = ALIGN(minify(mt->physical_height0, 1), mt->align_h); |
if (mt->array_spacing_lod0) |
qpitch = h0; |
else |
qpitch = (h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h); |
if (mt->compressed) |
qpitch /= 4; |
brw_miptree_layout_2d(mt); |
for (unsigned level = mt->first_level; level <= mt->last_level; level++) { |
for (int q = 0; q < mt->physical_depth0; q++) { |
intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch); |
} |
} |
mt->total_height = qpitch * mt->physical_depth0; |
align_cube(mt); |
} |
static void |
brw_miptree_layout_texture_3d(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
unsigned yscale = mt->compressed ? 4 : 1; |
mt->total_width = 0; |
mt->total_height = 0; |
unsigned ysum = 0; |
for (unsigned level = mt->first_level; level <= mt->last_level; level++) { |
unsigned WL = MAX2(mt->physical_width0 >> level, 1); |
unsigned HL = MAX2(mt->physical_height0 >> level, 1); |
unsigned DL = MAX2(mt->physical_depth0 >> level, 1); |
unsigned wL = ALIGN(WL, mt->align_w); |
unsigned hL = ALIGN(HL, mt->align_h); |
if (mt->target == GL_TEXTURE_CUBE_MAP) |
DL = 6; |
intel_miptree_set_level_info(mt, level, 0, 0, WL, HL, DL); |
for (unsigned q = 0; q < DL; q++) { |
unsigned x = (q % (1 << level)) * wL; |
unsigned y = ysum + (q >> level) * hL; |
intel_miptree_set_image_offset(mt, level, q, x, y / yscale); |
mt->total_width = MAX2(mt->total_width, x + wL); |
mt->total_height = MAX2(mt->total_height, (y + hL) / yscale); |
} |
ysum += ALIGN(DL, 1 << level) / (1 << level) * hL; |
} |
align_cube(mt); |
} |
void |
brw_miptree_layout(struct brw_context *brw, struct intel_mipmap_tree *mt) |
{ |
mt->align_w = intel_horizontal_texture_alignment_unit(brw, mt->format); |
mt->align_h = intel_vertical_texture_alignment_unit(brw, mt->format); |
switch (mt->target) { |
case GL_TEXTURE_CUBE_MAP: |
if (brw->gen == 4) { |
/* Gen4 stores cube maps as 3D textures. */ |
assert(mt->physical_depth0 == 6); |
brw_miptree_layout_texture_3d(brw, mt); |
} else { |
/* All other hardware stores cube maps as 2D arrays. */ |
brw_miptree_layout_texture_array(brw, mt); |
} |
break; |
case GL_TEXTURE_3D: |
brw_miptree_layout_texture_3d(brw, mt); |
break; |
case GL_TEXTURE_1D_ARRAY: |
case GL_TEXTURE_2D_ARRAY: |
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: |
case GL_TEXTURE_CUBE_MAP_ARRAY: |
brw_miptree_layout_texture_array(brw, mt); |
break; |
default: |
switch (mt->msaa_layout) { |
case INTEL_MSAA_LAYOUT_UMS: |
case INTEL_MSAA_LAYOUT_CMS: |
brw_miptree_layout_texture_array(brw, mt); |
break; |
case INTEL_MSAA_LAYOUT_NONE: |
case INTEL_MSAA_LAYOUT_IMS: |
brw_miptree_layout_2d(mt); |
break; |
} |
break; |
} |
DBG("%s: %dx%dx%d\n", __FUNCTION__, |
mt->total_width, mt->total_height, mt->cpp); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_urb.c |
---|
0,0 → 1,259 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "intel_batchbuffer.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#define VS 0 |
#define GS 1 |
#define CLP 2 |
#define SF 3 |
#define CS 4 |
/** @file brw_urb.c |
* |
* Manages the division of the URB space between the various fixed-function |
* units. |
* |
* See the Thread Initiation Management section of the GEN4 B-Spec, and |
* the individual *_STATE structures for restrictions on numbers of |
* entries and threads. |
*/ |
/* |
* Generally, a unit requires a min_nr_entries based on how many entries |
* it produces before the downstream unit gets unblocked and can use and |
* dereference some of its handles. |
* |
* The SF unit preallocates a PUE at the start of thread dispatch, and only |
* uses that one. So it requires one entry per thread. |
* |
* For CLIP, the SF unit will hold the previous primitive while the |
* next is getting assembled, meaning that linestrips require 3 CLIP VUEs |
* (vertices) to ensure continued processing, trifans require 4, and tristrips |
* require 5. There can be 1 or 2 threads, and each has the same requirement. |
* |
* GS has the same requirement as CLIP, but it never handles tristrips, |
* so we can lower the minimum to 4 for the POLYGONs (trifans) it produces. |
* We only run it single-threaded. |
* |
* For VS, the number of entries may be 8, 12, 16, or 32 (or 64 on G4X). |
* Each thread processes 2 preallocated VUEs (vertices) at a time, and they |
* get streamed down as soon as threads processing earlier vertices get |
* theirs accepted. |
* |
* Each unit will take the number of URB entries we give it (based on the |
* entry size calculated in brw_vs_emit.c for VUEs, brw_sf_emit.c for PUEs, |
* and brw_curbe.c for the CURBEs) and decide its maximum number of |
* threads it can support based on that. in brw_*_state.c. |
* |
* XXX: Are the min_entry_size numbers useful? |
* XXX: Verify min_nr_entries, esp for VS. |
* XXX: Verify SF min_entry_size. |
*/ |
static const struct { |
GLuint min_nr_entries; |
GLuint preferred_nr_entries; |
GLuint min_entry_size; |
GLuint max_entry_size; |
} limits[CS+1] = { |
{ 16, 32, 1, 5 }, /* vs */ |
{ 4, 8, 1, 5 }, /* gs */ |
{ 5, 10, 1, 5 }, /* clp */ |
{ 1, 8, 1, 12 }, /* sf */ |
{ 1, 4, 1, 32 } /* cs */ |
}; |
static bool check_urb_layout(struct brw_context *brw) |
{ |
brw->urb.vs_start = 0; |
brw->urb.gs_start = brw->urb.nr_vs_entries * brw->urb.vsize; |
brw->urb.clip_start = brw->urb.gs_start + brw->urb.nr_gs_entries * brw->urb.vsize; |
brw->urb.sf_start = brw->urb.clip_start + brw->urb.nr_clip_entries * brw->urb.vsize; |
brw->urb.cs_start = brw->urb.sf_start + brw->urb.nr_sf_entries * brw->urb.sfsize; |
return brw->urb.cs_start + brw->urb.nr_cs_entries * |
brw->urb.csize <= brw->urb.size; |
} |
/* Most minimal update, forces re-emit of URB fence packet after GS |
* unit turned on/off. |
*/ |
static void recalculate_urb_fence( struct brw_context *brw ) |
{ |
GLuint csize = brw->curbe.total_size; |
GLuint vsize = brw->vs.prog_data->base.urb_entry_size; |
GLuint sfsize = brw->sf.prog_data->urb_entry_size; |
if (csize < limits[CS].min_entry_size) |
csize = limits[CS].min_entry_size; |
if (vsize < limits[VS].min_entry_size) |
vsize = limits[VS].min_entry_size; |
if (sfsize < limits[SF].min_entry_size) |
sfsize = limits[SF].min_entry_size; |
if (brw->urb.vsize < vsize || |
brw->urb.sfsize < sfsize || |
brw->urb.csize < csize || |
(brw->urb.constrained && (brw->urb.vsize > vsize || |
brw->urb.sfsize > sfsize || |
brw->urb.csize > csize))) { |
brw->urb.csize = csize; |
brw->urb.sfsize = sfsize; |
brw->urb.vsize = vsize; |
brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries; |
brw->urb.nr_gs_entries = limits[GS].preferred_nr_entries; |
brw->urb.nr_clip_entries = limits[CLP].preferred_nr_entries; |
brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries; |
brw->urb.nr_cs_entries = limits[CS].preferred_nr_entries; |
brw->urb.constrained = 0; |
if (brw->gen == 5) { |
brw->urb.nr_vs_entries = 128; |
brw->urb.nr_sf_entries = 48; |
if (check_urb_layout(brw)) { |
goto done; |
} else { |
brw->urb.constrained = 1; |
brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries; |
brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries; |
} |
} else if (brw->is_g4x) { |
brw->urb.nr_vs_entries = 64; |
if (check_urb_layout(brw)) { |
goto done; |
} else { |
brw->urb.constrained = 1; |
brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries; |
} |
} |
if (!check_urb_layout(brw)) { |
brw->urb.nr_vs_entries = limits[VS].min_nr_entries; |
brw->urb.nr_gs_entries = limits[GS].min_nr_entries; |
brw->urb.nr_clip_entries = limits[CLP].min_nr_entries; |
brw->urb.nr_sf_entries = limits[SF].min_nr_entries; |
brw->urb.nr_cs_entries = limits[CS].min_nr_entries; |
/* Mark us as operating with constrained nr_entries, so that next |
* time we recalculate we'll resize the fences in the hope of |
* escaping constrained mode and getting back to normal performance. |
*/ |
brw->urb.constrained = 1; |
if (!check_urb_layout(brw)) { |
/* This is impossible, given the maximal sizes of urb |
* entries and the values for minimum nr of entries |
* provided above. |
*/ |
printf("couldn't calculate URB layout!\n"); |
exit(1); |
} |
if (unlikely(INTEL_DEBUG & (DEBUG_URB|DEBUG_PERF))) |
printf("URB CONSTRAINED\n"); |
} |
done: |
if (unlikely(INTEL_DEBUG & DEBUG_URB)) |
printf("URB fence: %d ..VS.. %d ..GS.. %d ..CLP.. %d ..SF.. %d ..CS.. %d\n", |
brw->urb.vs_start, |
brw->urb.gs_start, |
brw->urb.clip_start, |
brw->urb.sf_start, |
brw->urb.cs_start, |
brw->urb.size); |
brw->state.dirty.brw |= BRW_NEW_URB_FENCE; |
} |
} |
const struct brw_tracked_state brw_recalculate_urb_fence = { |
.dirty = { |
.mesa = 0, |
.brw = BRW_NEW_CURBE_OFFSETS, |
.cache = (CACHE_NEW_VS_PROG | |
CACHE_NEW_SF_PROG) |
}, |
.emit = recalculate_urb_fence |
}; |
void brw_upload_urb_fence(struct brw_context *brw) |
{ |
struct brw_urb_fence uf; |
memset(&uf, 0, sizeof(uf)); |
uf.header.opcode = CMD_URB_FENCE; |
uf.header.length = sizeof(uf)/4-2; |
uf.header.vs_realloc = 1; |
uf.header.gs_realloc = 1; |
uf.header.clp_realloc = 1; |
uf.header.sf_realloc = 1; |
uf.header.vfe_realloc = 1; |
uf.header.cs_realloc = 1; |
/* The ordering below is correct, not the layout in the |
* instruction. |
* |
* There are 256/384 urb reg pairs in total. |
*/ |
uf.bits0.vs_fence = brw->urb.gs_start; |
uf.bits0.gs_fence = brw->urb.clip_start; |
uf.bits0.clp_fence = brw->urb.sf_start; |
uf.bits1.sf_fence = brw->urb.cs_start; |
uf.bits1.cs_fence = brw->urb.size; |
/* erratum: URB_FENCE must not cross a 64byte cacheline */ |
if ((brw->batch.used & 15) > 12) { |
int pad = 16 - (brw->batch.used & 15); |
do |
brw->batch.map[brw->batch.used++] = MI_NOOP; |
while (--pad); |
} |
BRW_BATCH_STRUCT(brw, &uf); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_util.c |
---|
0,0 → 1,106 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 <assert.h> |
#include "main/mtypes.h" |
#include "program/prog_parameter.h" |
#include "brw_util.h" |
#include "brw_defines.h" |
GLuint brw_translate_blend_equation( GLenum mode ) |
{ |
switch (mode) { |
case GL_FUNC_ADD: |
return BRW_BLENDFUNCTION_ADD; |
case GL_MIN: |
return BRW_BLENDFUNCTION_MIN; |
case GL_MAX: |
return BRW_BLENDFUNCTION_MAX; |
case GL_FUNC_SUBTRACT: |
return BRW_BLENDFUNCTION_SUBTRACT; |
case GL_FUNC_REVERSE_SUBTRACT: |
return BRW_BLENDFUNCTION_REVERSE_SUBTRACT; |
default: |
assert(0); |
return BRW_BLENDFUNCTION_ADD; |
} |
} |
GLuint brw_translate_blend_factor( GLenum factor ) |
{ |
switch(factor) { |
case GL_ZERO: |
return BRW_BLENDFACTOR_ZERO; |
case GL_SRC_ALPHA: |
return BRW_BLENDFACTOR_SRC_ALPHA; |
case GL_ONE: |
return BRW_BLENDFACTOR_ONE; |
case GL_SRC_COLOR: |
return BRW_BLENDFACTOR_SRC_COLOR; |
case GL_ONE_MINUS_SRC_COLOR: |
return BRW_BLENDFACTOR_INV_SRC_COLOR; |
case GL_DST_COLOR: |
return BRW_BLENDFACTOR_DST_COLOR; |
case GL_ONE_MINUS_DST_COLOR: |
return BRW_BLENDFACTOR_INV_DST_COLOR; |
case GL_ONE_MINUS_SRC_ALPHA: |
return BRW_BLENDFACTOR_INV_SRC_ALPHA; |
case GL_DST_ALPHA: |
return BRW_BLENDFACTOR_DST_ALPHA; |
case GL_ONE_MINUS_DST_ALPHA: |
return BRW_BLENDFACTOR_INV_DST_ALPHA; |
case GL_SRC_ALPHA_SATURATE: |
return BRW_BLENDFACTOR_SRC_ALPHA_SATURATE; |
case GL_CONSTANT_COLOR: |
return BRW_BLENDFACTOR_CONST_COLOR; |
case GL_ONE_MINUS_CONSTANT_COLOR: |
return BRW_BLENDFACTOR_INV_CONST_COLOR; |
case GL_CONSTANT_ALPHA: |
return BRW_BLENDFACTOR_CONST_ALPHA; |
case GL_ONE_MINUS_CONSTANT_ALPHA: |
return BRW_BLENDFACTOR_INV_CONST_ALPHA; |
case GL_SRC1_COLOR: |
return BRW_BLENDFACTOR_SRC1_COLOR; |
case GL_SRC1_ALPHA: |
return BRW_BLENDFACTOR_SRC1_ALPHA; |
case GL_ONE_MINUS_SRC1_COLOR: |
return BRW_BLENDFACTOR_INV_SRC1_COLOR; |
case GL_ONE_MINUS_SRC1_ALPHA: |
return BRW_BLENDFACTOR_INV_SRC1_ALPHA; |
default: |
assert(0); |
return BRW_BLENDFACTOR_ZERO; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_util.h |
---|
0,0 → 1,43 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 BRW_UTIL_H |
#define BRW_UTIL_H |
#include "main/mtypes.h" |
#include "main/imports.h" |
extern GLuint brw_translate_blend_factor( GLenum factor ); |
extern GLuint brw_translate_blend_equation( GLenum mode ); |
extern GLenum brw_fix_xRGB_alpha(GLenum function); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vec4.cpp |
---|
0,0 → 1,1568 |
/* |
* Copyright © 2011 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 "brw_vec4.h" |
#include "brw_cfg.h" |
extern "C" { |
#include "main/macros.h" |
#include "main/shaderobj.h" |
#include "program/prog_print.h" |
#include "program/prog_parameter.h" |
} |
#define MAX_INSTRUCTION (1 << 30) |
using namespace brw; |
namespace brw { |
/** |
* Common helper for constructing swizzles. When only a subset of |
* channels of a vec4 are used, we don't want to reference the other |
* channels, as that will tell optimization passes that those other |
* channels are used. |
*/ |
unsigned |
swizzle_for_size(int size) |
{ |
static const unsigned size_swizzles[4] = { |
BRW_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X), |
BRW_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y), |
BRW_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_Z), |
BRW_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W), |
}; |
assert((size >= 1) && (size <= 4)); |
return size_swizzles[size - 1]; |
} |
void |
src_reg::init() |
{ |
memset(this, 0, sizeof(*this)); |
this->file = BAD_FILE; |
} |
src_reg::src_reg(register_file file, int reg, const glsl_type *type) |
{ |
init(); |
this->file = file; |
this->reg = reg; |
if (type && (type->is_scalar() || type->is_vector() || type->is_matrix())) |
this->swizzle = swizzle_for_size(type->vector_elements); |
else |
this->swizzle = SWIZZLE_XYZW; |
} |
/** Generic unset register constructor. */ |
src_reg::src_reg() |
{ |
init(); |
} |
src_reg::src_reg(float f) |
{ |
init(); |
this->file = IMM; |
this->type = BRW_REGISTER_TYPE_F; |
this->imm.f = f; |
} |
src_reg::src_reg(uint32_t u) |
{ |
init(); |
this->file = IMM; |
this->type = BRW_REGISTER_TYPE_UD; |
this->imm.u = u; |
} |
src_reg::src_reg(int32_t i) |
{ |
init(); |
this->file = IMM; |
this->type = BRW_REGISTER_TYPE_D; |
this->imm.i = i; |
} |
src_reg::src_reg(dst_reg reg) |
{ |
init(); |
this->file = reg.file; |
this->reg = reg.reg; |
this->reg_offset = reg.reg_offset; |
this->type = reg.type; |
this->reladdr = reg.reladdr; |
this->fixed_hw_reg = reg.fixed_hw_reg; |
int swizzles[4]; |
int next_chan = 0; |
int last = 0; |
for (int i = 0; i < 4; i++) { |
if (!(reg.writemask & (1 << i))) |
continue; |
swizzles[next_chan++] = last = i; |
} |
for (; next_chan < 4; next_chan++) { |
swizzles[next_chan] = last; |
} |
this->swizzle = BRW_SWIZZLE4(swizzles[0], swizzles[1], |
swizzles[2], swizzles[3]); |
} |
void |
dst_reg::init() |
{ |
memset(this, 0, sizeof(*this)); |
this->file = BAD_FILE; |
this->writemask = WRITEMASK_XYZW; |
} |
dst_reg::dst_reg() |
{ |
init(); |
} |
dst_reg::dst_reg(register_file file, int reg) |
{ |
init(); |
this->file = file; |
this->reg = reg; |
} |
dst_reg::dst_reg(register_file file, int reg, const glsl_type *type, |
int writemask) |
{ |
init(); |
this->file = file; |
this->reg = reg; |
this->type = brw_type_for_base_type(type); |
this->writemask = writemask; |
} |
dst_reg::dst_reg(struct brw_reg reg) |
{ |
init(); |
this->file = HW_REG; |
this->fixed_hw_reg = reg; |
} |
dst_reg::dst_reg(src_reg reg) |
{ |
init(); |
this->file = reg.file; |
this->reg = reg.reg; |
this->reg_offset = reg.reg_offset; |
this->type = reg.type; |
/* How should we do writemasking when converting from a src_reg? It seems |
* pretty obvious that for src.xxxx the caller wants to write to src.x, but |
* what about for src.wx? Just special-case src.xxxx for now. |
*/ |
if (reg.swizzle == BRW_SWIZZLE_XXXX) |
this->writemask = WRITEMASK_X; |
else |
this->writemask = WRITEMASK_XYZW; |
this->reladdr = reg.reladdr; |
this->fixed_hw_reg = reg.fixed_hw_reg; |
} |
bool |
vec4_instruction::is_send_from_grf() |
{ |
switch (opcode) { |
case SHADER_OPCODE_SHADER_TIME_ADD: |
case VS_OPCODE_PULL_CONSTANT_LOAD_GEN7: |
return true; |
default: |
return false; |
} |
} |
bool |
vec4_visitor::can_do_source_mods(vec4_instruction *inst) |
{ |
if (brw->gen == 6 && inst->is_math()) |
return false; |
if (inst->is_send_from_grf()) |
return false; |
return true; |
} |
/** |
* Returns how many MRFs an opcode will write over. |
* |
* Note that this is not the 0 or 1 implied writes in an actual gen |
* instruction -- the generate_* functions generate additional MOVs |
* for setup. |
*/ |
int |
vec4_visitor::implied_mrf_writes(vec4_instruction *inst) |
{ |
if (inst->mlen == 0) |
return 0; |
switch (inst->opcode) { |
case SHADER_OPCODE_RCP: |
case SHADER_OPCODE_RSQ: |
case SHADER_OPCODE_SQRT: |
case SHADER_OPCODE_EXP2: |
case SHADER_OPCODE_LOG2: |
case SHADER_OPCODE_SIN: |
case SHADER_OPCODE_COS: |
return 1; |
case SHADER_OPCODE_INT_QUOTIENT: |
case SHADER_OPCODE_INT_REMAINDER: |
case SHADER_OPCODE_POW: |
return 2; |
case VS_OPCODE_URB_WRITE: |
return 1; |
case VS_OPCODE_PULL_CONSTANT_LOAD: |
return 2; |
case VS_OPCODE_SCRATCH_READ: |
return 2; |
case VS_OPCODE_SCRATCH_WRITE: |
return 3; |
case SHADER_OPCODE_SHADER_TIME_ADD: |
return 0; |
case SHADER_OPCODE_TEX: |
case SHADER_OPCODE_TXL: |
case SHADER_OPCODE_TXD: |
case SHADER_OPCODE_TXF: |
case SHADER_OPCODE_TXF_MS: |
case SHADER_OPCODE_TXS: |
return inst->header_present ? 1 : 0; |
default: |
assert(!"not reached"); |
return inst->mlen; |
} |
} |
bool |
src_reg::equals(src_reg *r) |
{ |
return (file == r->file && |
reg == r->reg && |
reg_offset == r->reg_offset && |
type == r->type && |
negate == r->negate && |
abs == r->abs && |
swizzle == r->swizzle && |
!reladdr && !r->reladdr && |
memcmp(&fixed_hw_reg, &r->fixed_hw_reg, |
sizeof(fixed_hw_reg)) == 0 && |
imm.u == r->imm.u); |
} |
/** |
* Must be called after calculate_live_intervales() to remove unused |
* writes to registers -- register allocation will fail otherwise |
* because something deffed but not used won't be considered to |
* interfere with other regs. |
*/ |
bool |
vec4_visitor::dead_code_eliminate() |
{ |
bool progress = false; |
int pc = 0; |
calculate_live_intervals(); |
foreach_list_safe(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
if (inst->dst.file == GRF) { |
assert(this->virtual_grf_end[inst->dst.reg] >= pc); |
if (this->virtual_grf_end[inst->dst.reg] == pc) { |
inst->remove(); |
progress = true; |
} |
} |
pc++; |
} |
if (progress) |
live_intervals_valid = false; |
return progress; |
} |
void |
vec4_visitor::split_uniform_registers() |
{ |
/* Prior to this, uniforms have been in an array sized according to |
* the number of vector uniforms present, sparsely filled (so an |
* aggregate results in reg indices being skipped over). Now we're |
* going to cut those aggregates up so each .reg index is one |
* vector. The goal is to make elimination of unused uniform |
* components easier later. |
*/ |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
for (int i = 0 ; i < 3; i++) { |
if (inst->src[i].file != UNIFORM) |
continue; |
assert(!inst->src[i].reladdr); |
inst->src[i].reg += inst->src[i].reg_offset; |
inst->src[i].reg_offset = 0; |
} |
} |
/* Update that everything is now vector-sized. */ |
for (int i = 0; i < this->uniforms; i++) { |
this->uniform_size[i] = 1; |
} |
} |
void |
vec4_visitor::pack_uniform_registers() |
{ |
bool uniform_used[this->uniforms]; |
int new_loc[this->uniforms]; |
int new_chan[this->uniforms]; |
memset(uniform_used, 0, sizeof(uniform_used)); |
memset(new_loc, 0, sizeof(new_loc)); |
memset(new_chan, 0, sizeof(new_chan)); |
/* Find which uniform vectors are actually used by the program. We |
* expect unused vector elements when we've moved array access out |
* to pull constants, and from some GLSL code generators like wine. |
*/ |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
for (int i = 0 ; i < 3; i++) { |
if (inst->src[i].file != UNIFORM) |
continue; |
uniform_used[inst->src[i].reg] = true; |
} |
} |
int new_uniform_count = 0; |
/* Now, figure out a packing of the live uniform vectors into our |
* push constants. |
*/ |
for (int src = 0; src < uniforms; src++) { |
int size = this->uniform_vector_size[src]; |
if (!uniform_used[src]) { |
this->uniform_vector_size[src] = 0; |
continue; |
} |
int dst; |
/* Find the lowest place we can slot this uniform in. */ |
for (dst = 0; dst < src; dst++) { |
if (this->uniform_vector_size[dst] + size <= 4) |
break; |
} |
if (src == dst) { |
new_loc[src] = dst; |
new_chan[src] = 0; |
} else { |
new_loc[src] = dst; |
new_chan[src] = this->uniform_vector_size[dst]; |
/* Move the references to the data */ |
for (int j = 0; j < size; j++) { |
prog_data->param[dst * 4 + new_chan[src] + j] = |
prog_data->param[src * 4 + j]; |
} |
this->uniform_vector_size[dst] += size; |
this->uniform_vector_size[src] = 0; |
} |
new_uniform_count = MAX2(new_uniform_count, dst + 1); |
} |
this->uniforms = new_uniform_count; |
/* Now, update the instructions for our repacked uniforms. */ |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
for (int i = 0 ; i < 3; i++) { |
int src = inst->src[i].reg; |
if (inst->src[i].file != UNIFORM) |
continue; |
inst->src[i].reg = new_loc[src]; |
int sx = BRW_GET_SWZ(inst->src[i].swizzle, 0) + new_chan[src]; |
int sy = BRW_GET_SWZ(inst->src[i].swizzle, 1) + new_chan[src]; |
int sz = BRW_GET_SWZ(inst->src[i].swizzle, 2) + new_chan[src]; |
int sw = BRW_GET_SWZ(inst->src[i].swizzle, 3) + new_chan[src]; |
inst->src[i].swizzle = BRW_SWIZZLE4(sx, sy, sz, sw); |
} |
} |
} |
bool |
src_reg::is_zero() const |
{ |
if (file != IMM) |
return false; |
if (type == BRW_REGISTER_TYPE_F) { |
return imm.f == 0.0; |
} else { |
return imm.i == 0; |
} |
} |
bool |
src_reg::is_one() const |
{ |
if (file != IMM) |
return false; |
if (type == BRW_REGISTER_TYPE_F) { |
return imm.f == 1.0; |
} else { |
return imm.i == 1; |
} |
} |
/** |
* Does algebraic optimizations (0 * a = 0, 1 * a = a, a + 0 = a). |
* |
* While GLSL IR also performs this optimization, we end up with it in |
* our instruction stream for a couple of reasons. One is that we |
* sometimes generate silly instructions, for example in array access |
* where we'll generate "ADD offset, index, base" even if base is 0. |
* The other is that GLSL IR's constant propagation doesn't track the |
* components of aggregates, so some VS patterns (initialize matrix to |
* 0, accumulate in vertex blending factors) end up breaking down to |
* instructions involving 0. |
*/ |
bool |
vec4_visitor::opt_algebraic() |
{ |
bool progress = false; |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
switch (inst->opcode) { |
case BRW_OPCODE_ADD: |
if (inst->src[1].is_zero()) { |
inst->opcode = BRW_OPCODE_MOV; |
inst->src[1] = src_reg(); |
progress = true; |
} |
break; |
case BRW_OPCODE_MUL: |
if (inst->src[1].is_zero()) { |
inst->opcode = BRW_OPCODE_MOV; |
switch (inst->src[0].type) { |
case BRW_REGISTER_TYPE_F: |
inst->src[0] = src_reg(0.0f); |
break; |
case BRW_REGISTER_TYPE_D: |
inst->src[0] = src_reg(0); |
break; |
case BRW_REGISTER_TYPE_UD: |
inst->src[0] = src_reg(0u); |
break; |
default: |
assert(!"not reached"); |
inst->src[0] = src_reg(0.0f); |
break; |
} |
inst->src[1] = src_reg(); |
progress = true; |
} else if (inst->src[1].is_one()) { |
inst->opcode = BRW_OPCODE_MOV; |
inst->src[1] = src_reg(); |
progress = true; |
} |
break; |
default: |
break; |
} |
} |
if (progress) |
this->live_intervals_valid = false; |
return progress; |
} |
/** |
* Only a limited number of hardware registers may be used for push |
* constants, so this turns access to the overflowed constants into |
* pull constants. |
*/ |
void |
vec4_visitor::move_push_constants_to_pull_constants() |
{ |
int pull_constant_loc[this->uniforms]; |
/* Only allow 32 registers (256 uniform components) as push constants, |
* which is the limit on gen6. |
*/ |
int max_uniform_components = 32 * 8; |
if (this->uniforms * 4 <= max_uniform_components) |
return; |
/* Make some sort of choice as to which uniforms get sent to pull |
* constants. We could potentially do something clever here like |
* look for the most infrequently used uniform vec4s, but leave |
* that for later. |
*/ |
for (int i = 0; i < this->uniforms * 4; i += 4) { |
pull_constant_loc[i / 4] = -1; |
if (i >= max_uniform_components) { |
const float **values = &prog_data->param[i]; |
/* Try to find an existing copy of this uniform in the pull |
* constants if it was part of an array access already. |
*/ |
for (unsigned int j = 0; j < prog_data->nr_pull_params; j += 4) { |
int matches; |
for (matches = 0; matches < 4; matches++) { |
if (prog_data->pull_param[j + matches] != values[matches]) |
break; |
} |
if (matches == 4) { |
pull_constant_loc[i / 4] = j / 4; |
break; |
} |
} |
if (pull_constant_loc[i / 4] == -1) { |
assert(prog_data->nr_pull_params % 4 == 0); |
pull_constant_loc[i / 4] = prog_data->nr_pull_params / 4; |
for (int j = 0; j < 4; j++) { |
prog_data->pull_param[prog_data->nr_pull_params++] = values[j]; |
} |
} |
} |
} |
/* Now actually rewrite usage of the things we've moved to pull |
* constants. |
*/ |
foreach_list_safe(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
for (int i = 0 ; i < 3; i++) { |
if (inst->src[i].file != UNIFORM || |
pull_constant_loc[inst->src[i].reg] == -1) |
continue; |
int uniform = inst->src[i].reg; |
dst_reg temp = dst_reg(this, glsl_type::vec4_type); |
emit_pull_constant_load(inst, temp, inst->src[i], |
pull_constant_loc[uniform]); |
inst->src[i].file = temp.file; |
inst->src[i].reg = temp.reg; |
inst->src[i].reg_offset = temp.reg_offset; |
inst->src[i].reladdr = NULL; |
} |
} |
/* Repack push constants to remove the now-unused ones. */ |
pack_uniform_registers(); |
} |
/** |
* Sets the dependency control fields on instructions after register |
* allocation and before the generator is run. |
* |
* When you have a sequence of instructions like: |
* |
* DP4 temp.x vertex uniform[0] |
* DP4 temp.y vertex uniform[0] |
* DP4 temp.z vertex uniform[0] |
* DP4 temp.w vertex uniform[0] |
* |
* The hardware doesn't know that it can actually run the later instructions |
* while the previous ones are in flight, producing stalls. However, we have |
* manual fields we can set in the instructions that let it do so. |
*/ |
void |
vec4_visitor::opt_set_dependency_control() |
{ |
vec4_instruction *last_grf_write[BRW_MAX_GRF]; |
uint8_t grf_channels_written[BRW_MAX_GRF]; |
vec4_instruction *last_mrf_write[BRW_MAX_GRF]; |
uint8_t mrf_channels_written[BRW_MAX_GRF]; |
cfg_t cfg(this); |
assert(prog_data->total_grf || |
!"Must be called after register allocation"); |
for (int i = 0; i < cfg.num_blocks; i++) { |
bblock_t *bblock = cfg.blocks[i]; |
vec4_instruction *inst; |
memset(last_grf_write, 0, sizeof(last_grf_write)); |
memset(last_mrf_write, 0, sizeof(last_mrf_write)); |
for (inst = (vec4_instruction *)bblock->start; |
inst != (vec4_instruction *)bblock->end->next; |
inst = (vec4_instruction *)inst->next) { |
/* If we read from a register that we were doing dependency control |
* on, don't do dependency control across the read. |
*/ |
for (int i = 0; i < 3; i++) { |
int reg = inst->src[i].reg + inst->src[i].reg_offset; |
if (inst->src[i].file == GRF) { |
last_grf_write[reg] = NULL; |
} else if (inst->src[i].file == HW_REG) { |
memset(last_grf_write, 0, sizeof(last_grf_write)); |
break; |
} |
assert(inst->src[i].file != MRF); |
} |
/* In the presence of send messages, totally interrupt dependency |
* control. They're long enough that the chance of dependency |
* control around them just doesn't matter. |
*/ |
if (inst->mlen) { |
memset(last_grf_write, 0, sizeof(last_grf_write)); |
memset(last_mrf_write, 0, sizeof(last_mrf_write)); |
continue; |
} |
/* It looks like setting dependency control on a predicated |
* instruction hangs the GPU. |
*/ |
if (inst->predicate) { |
memset(last_grf_write, 0, sizeof(last_grf_write)); |
memset(last_mrf_write, 0, sizeof(last_mrf_write)); |
continue; |
} |
/* Now, see if we can do dependency control for this instruction |
* against a previous one writing to its destination. |
*/ |
int reg = inst->dst.reg + inst->dst.reg_offset; |
if (inst->dst.file == GRF) { |
if (last_grf_write[reg] && |
!(inst->dst.writemask & grf_channels_written[reg])) { |
last_grf_write[reg]->no_dd_clear = true; |
inst->no_dd_check = true; |
} else { |
grf_channels_written[reg] = 0; |
} |
last_grf_write[reg] = inst; |
grf_channels_written[reg] |= inst->dst.writemask; |
} else if (inst->dst.file == MRF) { |
if (last_mrf_write[reg] && |
!(inst->dst.writemask & mrf_channels_written[reg])) { |
last_mrf_write[reg]->no_dd_clear = true; |
inst->no_dd_check = true; |
} else { |
mrf_channels_written[reg] = 0; |
} |
last_mrf_write[reg] = inst; |
mrf_channels_written[reg] |= inst->dst.writemask; |
} else if (inst->dst.reg == HW_REG) { |
if (inst->dst.fixed_hw_reg.file == BRW_GENERAL_REGISTER_FILE) |
memset(last_grf_write, 0, sizeof(last_grf_write)); |
if (inst->dst.fixed_hw_reg.file == BRW_MESSAGE_REGISTER_FILE) |
memset(last_mrf_write, 0, sizeof(last_mrf_write)); |
} |
} |
} |
} |
bool |
vec4_instruction::can_reswizzle_dst(int dst_writemask, |
int swizzle, |
int swizzle_mask) |
{ |
/* If this instruction sets anything not referenced by swizzle, then we'd |
* totally break it when we reswizzle. |
*/ |
if (dst.writemask & ~swizzle_mask) |
return false; |
switch (opcode) { |
case BRW_OPCODE_DP4: |
case BRW_OPCODE_DP3: |
case BRW_OPCODE_DP2: |
return true; |
default: |
/* Check if there happens to be no reswizzling required. */ |
for (int c = 0; c < 4; c++) { |
int bit = 1 << BRW_GET_SWZ(swizzle, c); |
/* Skip components of the swizzle not used by the dst. */ |
if (!(dst_writemask & (1 << c))) |
continue; |
/* We don't do the reswizzling yet, so just sanity check that we |
* don't have to. |
*/ |
if (bit != (1 << c)) |
return false; |
} |
return true; |
} |
} |
/** |
* For any channels in the swizzle's source that were populated by this |
* instruction, rewrite the instruction to put the appropriate result directly |
* in those channels. |
* |
* e.g. for swizzle=yywx, MUL a.xy b c -> MUL a.yy_x b.yy z.yy_x |
*/ |
void |
vec4_instruction::reswizzle_dst(int dst_writemask, int swizzle) |
{ |
int new_writemask = 0; |
switch (opcode) { |
case BRW_OPCODE_DP4: |
case BRW_OPCODE_DP3: |
case BRW_OPCODE_DP2: |
for (int c = 0; c < 4; c++) { |
int bit = 1 << BRW_GET_SWZ(swizzle, c); |
/* Skip components of the swizzle not used by the dst. */ |
if (!(dst_writemask & (1 << c))) |
continue; |
/* If we were populating this component, then populate the |
* corresponding channel of the new dst. |
*/ |
if (dst.writemask & bit) |
new_writemask |= (1 << c); |
} |
dst.writemask = new_writemask; |
break; |
default: |
for (int c = 0; c < 4; c++) { |
/* Skip components of the swizzle not used by the dst. */ |
if (!(dst_writemask & (1 << c))) |
continue; |
/* We don't do the reswizzling yet, so just sanity check that we |
* don't have to. |
*/ |
assert((1 << BRW_GET_SWZ(swizzle, c)) == (1 << c)); |
} |
break; |
} |
} |
/* |
* Tries to reduce extra MOV instructions by taking temporary GRFs that get |
* just written and then MOVed into another reg and making the original write |
* of the GRF write directly to the final destination instead. |
*/ |
bool |
vec4_visitor::opt_register_coalesce() |
{ |
bool progress = false; |
int next_ip = 0; |
calculate_live_intervals(); |
foreach_list_safe(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
int ip = next_ip; |
next_ip++; |
if (inst->opcode != BRW_OPCODE_MOV || |
(inst->dst.file != GRF && inst->dst.file != MRF) || |
inst->predicate || |
inst->src[0].file != GRF || |
inst->dst.type != inst->src[0].type || |
inst->src[0].abs || inst->src[0].negate || inst->src[0].reladdr) |
continue; |
bool to_mrf = (inst->dst.file == MRF); |
/* Can't coalesce this GRF if someone else was going to |
* read it later. |
*/ |
if (this->virtual_grf_end[inst->src[0].reg] > ip) |
continue; |
/* We need to check interference with the final destination between this |
* instruction and the earliest instruction involved in writing the GRF |
* we're eliminating. To do that, keep track of which of our source |
* channels we've seen initialized. |
*/ |
bool chans_needed[4] = {false, false, false, false}; |
int chans_remaining = 0; |
int swizzle_mask = 0; |
for (int i = 0; i < 4; i++) { |
int chan = BRW_GET_SWZ(inst->src[0].swizzle, i); |
if (!(inst->dst.writemask & (1 << i))) |
continue; |
swizzle_mask |= (1 << chan); |
if (!chans_needed[chan]) { |
chans_needed[chan] = true; |
chans_remaining++; |
} |
} |
/* Now walk up the instruction stream trying to see if we can rewrite |
* everything writing to the temporary to write into the destination |
* instead. |
*/ |
vec4_instruction *scan_inst; |
for (scan_inst = (vec4_instruction *)inst->prev; |
scan_inst->prev != NULL; |
scan_inst = (vec4_instruction *)scan_inst->prev) { |
if (scan_inst->dst.file == GRF && |
scan_inst->dst.reg == inst->src[0].reg && |
scan_inst->dst.reg_offset == inst->src[0].reg_offset) { |
/* Found something writing to the reg we want to coalesce away. */ |
if (to_mrf) { |
/* SEND instructions can't have MRF as a destination. */ |
if (scan_inst->mlen) |
break; |
if (brw->gen == 6) { |
/* gen6 math instructions must have the destination be |
* GRF, so no compute-to-MRF for them. |
*/ |
if (scan_inst->is_math()) { |
break; |
} |
} |
} |
/* If we can't handle the swizzle, bail. */ |
if (!scan_inst->can_reswizzle_dst(inst->dst.writemask, |
inst->src[0].swizzle, |
swizzle_mask)) { |
break; |
} |
/* Mark which channels we found unconditional writes for. */ |
if (!scan_inst->predicate) { |
for (int i = 0; i < 4; i++) { |
if (scan_inst->dst.writemask & (1 << i) && |
chans_needed[i]) { |
chans_needed[i] = false; |
chans_remaining--; |
} |
} |
} |
if (chans_remaining == 0) |
break; |
} |
/* We don't handle flow control here. Most computation of values |
* that could be coalesced happens just before their use. |
*/ |
if (scan_inst->opcode == BRW_OPCODE_DO || |
scan_inst->opcode == BRW_OPCODE_WHILE || |
scan_inst->opcode == BRW_OPCODE_ELSE || |
scan_inst->opcode == BRW_OPCODE_ENDIF) { |
break; |
} |
/* You can't read from an MRF, so if someone else reads our MRF's |
* source GRF that we wanted to rewrite, that stops us. If it's a |
* GRF we're trying to coalesce to, we don't actually handle |
* rewriting sources so bail in that case as well. |
*/ |
bool interfered = false; |
for (int i = 0; i < 3; i++) { |
if (scan_inst->src[i].file == GRF && |
scan_inst->src[i].reg == inst->src[0].reg && |
scan_inst->src[i].reg_offset == inst->src[0].reg_offset) { |
interfered = true; |
} |
} |
if (interfered) |
break; |
/* If somebody else writes our destination here, we can't coalesce |
* before that. |
*/ |
if (scan_inst->dst.file == inst->dst.file && |
scan_inst->dst.reg == inst->dst.reg) { |
break; |
} |
/* Check for reads of the register we're trying to coalesce into. We |
* can't go rewriting instructions above that to put some other value |
* in the register instead. |
*/ |
if (to_mrf && scan_inst->mlen > 0) { |
if (inst->dst.reg >= scan_inst->base_mrf && |
inst->dst.reg < scan_inst->base_mrf + scan_inst->mlen) { |
break; |
} |
} else { |
for (int i = 0; i < 3; i++) { |
if (scan_inst->src[i].file == inst->dst.file && |
scan_inst->src[i].reg == inst->dst.reg && |
scan_inst->src[i].reg_offset == inst->src[0].reg_offset) { |
interfered = true; |
} |
} |
if (interfered) |
break; |
} |
} |
if (chans_remaining == 0) { |
/* If we've made it here, we have an MOV we want to coalesce out, and |
* a scan_inst pointing to the earliest instruction involved in |
* computing the value. Now go rewrite the instruction stream |
* between the two. |
*/ |
while (scan_inst != inst) { |
if (scan_inst->dst.file == GRF && |
scan_inst->dst.reg == inst->src[0].reg && |
scan_inst->dst.reg_offset == inst->src[0].reg_offset) { |
scan_inst->reswizzle_dst(inst->dst.writemask, |
inst->src[0].swizzle); |
scan_inst->dst.file = inst->dst.file; |
scan_inst->dst.reg = inst->dst.reg; |
scan_inst->dst.reg_offset = inst->dst.reg_offset; |
scan_inst->saturate |= inst->saturate; |
} |
scan_inst = (vec4_instruction *)scan_inst->next; |
} |
inst->remove(); |
progress = true; |
} |
} |
if (progress) |
live_intervals_valid = false; |
return progress; |
} |
/** |
* Splits virtual GRFs requesting more than one contiguous physical register. |
* |
* We initially create large virtual GRFs for temporary structures, arrays, |
* and matrices, so that the dereference visitor functions can add reg_offsets |
* to work their way down to the actual member being accessed. But when it |
* comes to optimization, we'd like to treat each register as individual |
* storage if possible. |
* |
* So far, the only thing that might prevent splitting is a send message from |
* a GRF on IVB. |
*/ |
void |
vec4_visitor::split_virtual_grfs() |
{ |
int num_vars = this->virtual_grf_count; |
int new_virtual_grf[num_vars]; |
bool split_grf[num_vars]; |
memset(new_virtual_grf, 0, sizeof(new_virtual_grf)); |
/* Try to split anything > 0 sized. */ |
for (int i = 0; i < num_vars; i++) { |
split_grf[i] = this->virtual_grf_sizes[i] != 1; |
} |
/* Check that the instructions are compatible with the registers we're trying |
* to split. |
*/ |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
/* If there's a SEND message loading from a GRF on gen7+, it needs to be |
* contiguous. |
*/ |
if (inst->is_send_from_grf()) { |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
split_grf[inst->src[i].reg] = false; |
} |
} |
} |
} |
/* Allocate new space for split regs. Note that the virtual |
* numbers will be contiguous. |
*/ |
for (int i = 0; i < num_vars; i++) { |
if (!split_grf[i]) |
continue; |
new_virtual_grf[i] = virtual_grf_alloc(1); |
for (int j = 2; j < this->virtual_grf_sizes[i]; j++) { |
int reg = virtual_grf_alloc(1); |
assert(reg == new_virtual_grf[i] + j - 1); |
(void) reg; |
} |
this->virtual_grf_sizes[i] = 1; |
} |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
if (inst->dst.file == GRF && split_grf[inst->dst.reg] && |
inst->dst.reg_offset != 0) { |
inst->dst.reg = (new_virtual_grf[inst->dst.reg] + |
inst->dst.reg_offset - 1); |
inst->dst.reg_offset = 0; |
} |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF && split_grf[inst->src[i].reg] && |
inst->src[i].reg_offset != 0) { |
inst->src[i].reg = (new_virtual_grf[inst->src[i].reg] + |
inst->src[i].reg_offset - 1); |
inst->src[i].reg_offset = 0; |
} |
} |
} |
this->live_intervals_valid = false; |
} |
void |
vec4_visitor::dump_instruction(backend_instruction *be_inst) |
{ |
vec4_instruction *inst = (vec4_instruction *)be_inst; |
printf("%s ", brw_instruction_name(inst->opcode)); |
switch (inst->dst.file) { |
case GRF: |
printf("vgrf%d.%d", inst->dst.reg, inst->dst.reg_offset); |
break; |
case MRF: |
printf("m%d", inst->dst.reg); |
break; |
case BAD_FILE: |
printf("(null)"); |
break; |
default: |
printf("???"); |
break; |
} |
if (inst->dst.writemask != WRITEMASK_XYZW) { |
printf("."); |
if (inst->dst.writemask & 1) |
printf("x"); |
if (inst->dst.writemask & 2) |
printf("y"); |
if (inst->dst.writemask & 4) |
printf("z"); |
if (inst->dst.writemask & 8) |
printf("w"); |
} |
printf(", "); |
for (int i = 0; i < 3; i++) { |
switch (inst->src[i].file) { |
case GRF: |
printf("vgrf%d", inst->src[i].reg); |
break; |
case ATTR: |
printf("attr%d", inst->src[i].reg); |
break; |
case UNIFORM: |
printf("u%d", inst->src[i].reg); |
break; |
case IMM: |
switch (inst->src[i].type) { |
case BRW_REGISTER_TYPE_F: |
printf("%fF", inst->src[i].imm.f); |
break; |
case BRW_REGISTER_TYPE_D: |
printf("%dD", inst->src[i].imm.i); |
break; |
case BRW_REGISTER_TYPE_UD: |
printf("%uU", inst->src[i].imm.u); |
break; |
default: |
printf("???"); |
break; |
} |
break; |
case BAD_FILE: |
printf("(null)"); |
break; |
default: |
printf("???"); |
break; |
} |
if (inst->src[i].reg_offset) |
printf(".%d", inst->src[i].reg_offset); |
static const char *chans[4] = {"x", "y", "z", "w"}; |
printf("."); |
for (int c = 0; c < 4; c++) { |
printf("%s", chans[BRW_GET_SWZ(inst->src[i].swizzle, c)]); |
} |
if (i < 3) |
printf(", "); |
} |
printf("\n"); |
} |
/** |
* Replace each register of type ATTR in this->instructions with a reference |
* to a fixed HW register. |
*/ |
void |
vec4_visitor::lower_attributes_to_hw_regs(const int *attribute_map) |
{ |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
/* We have to support ATTR as a destination for GL_FIXED fixup. */ |
if (inst->dst.file == ATTR) { |
int grf = attribute_map[inst->dst.reg + inst->dst.reg_offset]; |
/* All attributes used in the shader need to have been assigned a |
* hardware register by the caller |
*/ |
assert(grf != 0); |
struct brw_reg reg = brw_vec8_grf(grf, 0); |
reg.type = inst->dst.type; |
reg.dw1.bits.writemask = inst->dst.writemask; |
inst->dst.file = HW_REG; |
inst->dst.fixed_hw_reg = reg; |
} |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file != ATTR) |
continue; |
int grf = attribute_map[inst->src[i].reg + inst->src[i].reg_offset]; |
/* All attributes used in the shader need to have been assigned a |
* hardware register by the caller |
*/ |
assert(grf != 0); |
struct brw_reg reg = brw_vec8_grf(grf, 0); |
reg.dw1.bits.swizzle = inst->src[i].swizzle; |
reg.type = inst->src[i].type; |
if (inst->src[i].abs) |
reg = brw_abs(reg); |
if (inst->src[i].negate) |
reg = negate(reg); |
inst->src[i].file = HW_REG; |
inst->src[i].fixed_hw_reg = reg; |
} |
} |
} |
int |
vec4_vs_visitor::setup_attributes(int payload_reg) |
{ |
int nr_attributes; |
int attribute_map[VERT_ATTRIB_MAX + 1]; |
memset(attribute_map, 0, sizeof(attribute_map)); |
nr_attributes = 0; |
for (int i = 0; i < VERT_ATTRIB_MAX; i++) { |
if (vs_prog_data->inputs_read & BITFIELD64_BIT(i)) { |
attribute_map[i] = payload_reg + nr_attributes; |
nr_attributes++; |
} |
} |
/* VertexID is stored by the VF as the last vertex element, but we |
* don't represent it with a flag in inputs_read, so we call it |
* VERT_ATTRIB_MAX. |
*/ |
if (vs_prog_data->uses_vertexid) { |
attribute_map[VERT_ATTRIB_MAX] = payload_reg + nr_attributes; |
nr_attributes++; |
} |
lower_attributes_to_hw_regs(attribute_map); |
/* The BSpec says we always have to read at least one thing from |
* the VF, and it appears that the hardware wedges otherwise. |
*/ |
if (nr_attributes == 0) |
nr_attributes = 1; |
prog_data->urb_read_length = (nr_attributes + 1) / 2; |
unsigned vue_entries = |
MAX2(nr_attributes, prog_data->vue_map.num_slots); |
if (brw->gen == 6) |
prog_data->urb_entry_size = ALIGN(vue_entries, 8) / 8; |
else |
prog_data->urb_entry_size = ALIGN(vue_entries, 4) / 4; |
return payload_reg + nr_attributes; |
} |
int |
vec4_visitor::setup_uniforms(int reg) |
{ |
/* The pre-gen6 VS requires that some push constants get loaded no |
* matter what, or the GPU would hang. |
*/ |
if (brw->gen < 6 && this->uniforms == 0) { |
this->uniform_vector_size[this->uniforms] = 1; |
for (unsigned int i = 0; i < 4; i++) { |
unsigned int slot = this->uniforms * 4 + i; |
static float zero = 0.0; |
prog_data->param[slot] = &zero; |
} |
this->uniforms++; |
reg++; |
} else { |
reg += ALIGN(uniforms, 2) / 2; |
} |
prog_data->nr_params = this->uniforms * 4; |
prog_data->curb_read_length = reg - 1; |
return reg; |
} |
void |
vec4_visitor::setup_payload(void) |
{ |
int reg = 0; |
/* The payload always contains important data in g0, which contains |
* the URB handles that are passed on to the URB write at the end |
* of the thread. So, we always start push constants at g1. |
*/ |
reg++; |
reg = setup_uniforms(reg); |
reg = setup_attributes(reg); |
this->first_non_payload_grf = reg; |
} |
src_reg |
vec4_visitor::get_timestamp() |
{ |
assert(brw->gen >= 7); |
src_reg ts = src_reg(brw_reg(BRW_ARCHITECTURE_REGISTER_FILE, |
BRW_ARF_TIMESTAMP, |
0, |
BRW_REGISTER_TYPE_UD, |
BRW_VERTICAL_STRIDE_0, |
BRW_WIDTH_4, |
BRW_HORIZONTAL_STRIDE_4, |
BRW_SWIZZLE_XYZW, |
WRITEMASK_XYZW)); |
dst_reg dst = dst_reg(this, glsl_type::uvec4_type); |
vec4_instruction *mov = emit(MOV(dst, ts)); |
/* We want to read the 3 fields we care about (mostly field 0, but also 2) |
* even if it's not enabled in the dispatch. |
*/ |
mov->force_writemask_all = true; |
return src_reg(dst); |
} |
void |
vec4_visitor::emit_shader_time_begin() |
{ |
current_annotation = "shader time start"; |
shader_start_time = get_timestamp(); |
} |
void |
vec4_visitor::emit_shader_time_end() |
{ |
current_annotation = "shader time end"; |
src_reg shader_end_time = get_timestamp(); |
/* Check that there weren't any timestamp reset events (assuming these |
* were the only two timestamp reads that happened). |
*/ |
src_reg reset_end = shader_end_time; |
reset_end.swizzle = BRW_SWIZZLE_ZZZZ; |
vec4_instruction *test = emit(AND(dst_null_d(), reset_end, src_reg(1u))); |
test->conditional_mod = BRW_CONDITIONAL_Z; |
emit(IF(BRW_PREDICATE_NORMAL)); |
/* Take the current timestamp and get the delta. */ |
shader_start_time.negate = true; |
dst_reg diff = dst_reg(this, glsl_type::uint_type); |
emit(ADD(diff, shader_start_time, shader_end_time)); |
/* If there were no instructions between the two timestamp gets, the diff |
* is 2 cycles. Remove that overhead, so I can forget about that when |
* trying to determine the time taken for single instructions. |
*/ |
emit(ADD(diff, src_reg(diff), src_reg(-2u))); |
emit_shader_time_write(ST_VS, src_reg(diff)); |
emit_shader_time_write(ST_VS_WRITTEN, src_reg(1u)); |
emit(BRW_OPCODE_ELSE); |
emit_shader_time_write(ST_VS_RESET, src_reg(1u)); |
emit(BRW_OPCODE_ENDIF); |
} |
void |
vec4_visitor::emit_shader_time_write(enum shader_time_shader_type type, |
src_reg value) |
{ |
int shader_time_index = |
brw_get_shader_time_index(brw, shader_prog, prog, type); |
dst_reg dst = |
dst_reg(this, glsl_type::get_array_instance(glsl_type::vec4_type, 2)); |
dst_reg offset = dst; |
dst_reg time = dst; |
time.reg_offset++; |
offset.type = BRW_REGISTER_TYPE_UD; |
emit(MOV(offset, src_reg(shader_time_index * SHADER_TIME_STRIDE))); |
time.type = BRW_REGISTER_TYPE_UD; |
emit(MOV(time, src_reg(value))); |
emit(SHADER_OPCODE_SHADER_TIME_ADD, dst_reg(), src_reg(dst)); |
} |
bool |
vec4_visitor::run() |
{ |
sanity_param_count = prog->Parameters->NumParameters; |
if (INTEL_DEBUG & DEBUG_SHADER_TIME) |
emit_shader_time_begin(); |
emit_prolog(); |
/* Generate VS IR for main(). (the visitor only descends into |
* functions called "main"). |
*/ |
if (shader) { |
visit_instructions(shader->ir); |
} else { |
emit_program_code(); |
} |
base_ir = NULL; |
if (key->userclip_active && !key->uses_clip_distance) |
setup_uniform_clipplane_values(); |
emit_thread_end(); |
/* Before any optimization, push array accesses out to scratch |
* space where we need them to be. This pass may allocate new |
* virtual GRFs, so we want to do it early. It also makes sure |
* that we have reladdr computations available for CSE, since we'll |
* often do repeated subexpressions for those. |
*/ |
if (shader) { |
move_grf_array_access_to_scratch(); |
move_uniform_array_access_to_pull_constants(); |
} else { |
/* The ARB_vertex_program frontend emits pull constant loads directly |
* rather than using reladdr, so we don't need to walk through all the |
* instructions looking for things to move. There isn't anything. |
* |
* We do still need to split things to vec4 size. |
*/ |
split_uniform_registers(); |
} |
pack_uniform_registers(); |
move_push_constants_to_pull_constants(); |
split_virtual_grfs(); |
bool progress; |
do { |
progress = false; |
progress = dead_code_eliminate() || progress; |
progress = opt_copy_propagation() || progress; |
progress = opt_algebraic() || progress; |
progress = opt_register_coalesce() || progress; |
} while (progress); |
if (failed) |
return false; |
setup_payload(); |
if (false) { |
/* Debug of register spilling: Go spill everything. */ |
const int grf_count = virtual_grf_count; |
float spill_costs[virtual_grf_count]; |
bool no_spill[virtual_grf_count]; |
evaluate_spill_costs(spill_costs, no_spill); |
for (int i = 0; i < grf_count; i++) { |
if (no_spill[i]) |
continue; |
spill_reg(i); |
} |
} |
while (!reg_allocate()) { |
if (failed) |
break; |
} |
opt_schedule_instructions(); |
opt_set_dependency_control(); |
/* If any state parameters were appended, then ParameterValues could have |
* been realloced, in which case the driver uniform storage set up by |
* _mesa_associate_uniform_storage() would point to freed memory. Make |
* sure that didn't happen. |
*/ |
assert(sanity_param_count == prog->Parameters->NumParameters); |
return !failed; |
} |
} /* namespace brw */ |
extern "C" { |
/** |
* Compile a vertex shader. |
* |
* Returns the final assembly and the program's size. |
*/ |
const unsigned * |
brw_vs_emit(struct brw_context *brw, |
struct gl_shader_program *prog, |
struct brw_vs_compile *c, |
struct brw_vs_prog_data *prog_data, |
void *mem_ctx, |
unsigned *final_assembly_size) |
{ |
bool start_busy = false; |
float start_time = 0; |
if (unlikely(brw->perf_debug)) { |
start_busy = (brw->batch.last_bo && |
drm_intel_bo_busy(brw->batch.last_bo)); |
start_time = get_time(); |
} |
struct brw_shader *shader = NULL; |
if (prog) |
shader = (brw_shader *) prog->_LinkedShaders[MESA_SHADER_VERTEX]; |
if (unlikely(INTEL_DEBUG & DEBUG_VS)) { |
if (prog) { |
printf("GLSL IR for native vertex shader %d:\n", prog->Name); |
_mesa_print_ir(shader->ir, NULL); |
printf("\n\n"); |
} else { |
printf("ARB_vertex_program %d for native vertex shader\n", |
c->vp->program.Base.Id); |
_mesa_print_program(&c->vp->program.Base); |
} |
} |
vec4_vs_visitor v(brw, c, prog_data, prog, shader, mem_ctx); |
if (!v.run()) { |
if (prog) { |
prog->LinkStatus = false; |
ralloc_strcat(&prog->InfoLog, v.fail_msg); |
} |
_mesa_problem(NULL, "Failed to compile vertex shader: %s\n", |
v.fail_msg); |
return NULL; |
} |
vec4_generator g(brw, prog, &c->vp->program.Base, mem_ctx, |
INTEL_DEBUG & DEBUG_VS); |
const unsigned *generated =g.generate_assembly(&v.instructions, |
final_assembly_size); |
if (unlikely(brw->perf_debug) && shader) { |
if (shader->compiled_once) { |
brw_vs_debug_recompile(brw, prog, &c->key); |
} |
if (start_busy && !drm_intel_bo_busy(brw->batch.last_bo)) { |
perf_debug("VS compile took %.03f ms and stalled the GPU\n", |
(get_time() - start_time) * 1000); |
} |
shader->compiled_once = true; |
} |
return generated; |
} |
} /* extern "C" */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vec4.h |
---|
0,0 → 1,604 |
/* |
* Copyright © 2011 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. |
*/ |
#ifndef BRW_VEC4_H |
#define BRW_VEC4_H |
#include <stdint.h> |
#include "brw_shader.h" |
#include "main/compiler.h" |
#include "program/hash_table.h" |
extern "C" { |
#include "brw_vs.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
}; |
#include "glsl/ir.h" |
namespace brw { |
class dst_reg; |
unsigned |
swizzle_for_size(int size); |
class reg |
{ |
public: |
/** Register file: ARF, GRF, MRF, IMM. */ |
enum register_file file; |
/** virtual register number. 0 = fixed hw reg */ |
int reg; |
/** Offset within the virtual register. */ |
int reg_offset; |
/** Register type. BRW_REGISTER_TYPE_* */ |
int type; |
struct brw_reg fixed_hw_reg; |
/** Value for file == BRW_IMMMEDIATE_FILE */ |
union { |
int32_t i; |
uint32_t u; |
float f; |
} imm; |
}; |
class src_reg : public reg |
{ |
public: |
/* Callers of this ralloc-based new need not call delete. It's |
* easier to just ralloc_free 'ctx' (or any of its ancestors). */ |
static void* operator new(size_t size, void *ctx) |
{ |
void *node; |
node = ralloc_size(ctx, size); |
assert(node != NULL); |
return node; |
} |
void init(); |
src_reg(register_file file, int reg, const glsl_type *type); |
src_reg(); |
src_reg(float f); |
src_reg(uint32_t u); |
src_reg(int32_t i); |
bool equals(src_reg *r); |
bool is_zero() const; |
bool is_one() const; |
src_reg(class vec4_visitor *v, const struct glsl_type *type); |
explicit src_reg(dst_reg reg); |
GLuint swizzle; /**< SWIZZLE_XYZW swizzles from Mesa. */ |
bool negate; |
bool abs; |
src_reg *reladdr; |
}; |
class dst_reg : public reg |
{ |
public: |
/* Callers of this ralloc-based new need not call delete. It's |
* easier to just ralloc_free 'ctx' (or any of its ancestors). */ |
static void* operator new(size_t size, void *ctx) |
{ |
void *node; |
node = ralloc_size(ctx, size); |
assert(node != NULL); |
return node; |
} |
void init(); |
dst_reg(); |
dst_reg(register_file file, int reg); |
dst_reg(register_file file, int reg, const glsl_type *type, int writemask); |
dst_reg(struct brw_reg reg); |
dst_reg(class vec4_visitor *v, const struct glsl_type *type); |
explicit dst_reg(src_reg reg); |
int writemask; /**< Bitfield of WRITEMASK_[XYZW] */ |
src_reg *reladdr; |
}; |
class vec4_instruction : public backend_instruction { |
public: |
/* Callers of this ralloc-based new need not call delete. It's |
* easier to just ralloc_free 'ctx' (or any of its ancestors). */ |
static void* operator new(size_t size, void *ctx) |
{ |
void *node; |
node = rzalloc_size(ctx, size); |
assert(node != NULL); |
return node; |
} |
vec4_instruction(vec4_visitor *v, enum opcode opcode, |
dst_reg dst = dst_reg(), |
src_reg src0 = src_reg(), |
src_reg src1 = src_reg(), |
src_reg src2 = src_reg()); |
struct brw_reg get_dst(void); |
struct brw_reg get_src(int i); |
dst_reg dst; |
src_reg src[3]; |
bool saturate; |
bool force_writemask_all; |
bool no_dd_clear, no_dd_check; |
int conditional_mod; /**< BRW_CONDITIONAL_* */ |
int sampler; |
uint32_t texture_offset; /**< Texture Offset bitfield */ |
int target; /**< MRT target. */ |
bool shadow_compare; |
bool eot; |
bool header_present; |
int mlen; /**< SEND message length */ |
int base_mrf; /**< First MRF in the SEND message, if mlen is nonzero. */ |
uint32_t offset; /* spill/unspill offset */ |
/** @{ |
* Annotation for the generated IR. One of the two can be set. |
*/ |
const void *ir; |
const char *annotation; |
bool is_send_from_grf(); |
bool can_reswizzle_dst(int dst_writemask, int swizzle, int swizzle_mask); |
void reswizzle_dst(int dst_writemask, int swizzle); |
}; |
/** |
* The vertex shader front-end. |
* |
* Translates either GLSL IR or Mesa IR (for ARB_vertex_program and |
* fixed-function) into VS IR. |
*/ |
class vec4_visitor : public backend_visitor |
{ |
public: |
vec4_visitor(struct brw_context *brw, |
struct brw_vec4_compile *c, |
struct gl_program *prog, |
const struct brw_vec4_prog_key *key, |
struct brw_vec4_prog_data *prog_data, |
struct gl_shader_program *shader_prog, |
struct brw_shader *shader, |
void *mem_ctx, |
bool debug_flag); |
~vec4_visitor(); |
dst_reg dst_null_f() |
{ |
return dst_reg(brw_null_reg()); |
} |
dst_reg dst_null_d() |
{ |
return dst_reg(retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); |
} |
struct gl_program *prog; |
struct brw_vec4_compile *c; |
const struct brw_vec4_prog_key *key; |
struct brw_vec4_prog_data *prog_data; |
unsigned int sanity_param_count; |
char *fail_msg; |
bool failed; |
/** |
* GLSL IR currently being processed, which is associated with our |
* driver IR instructions for debugging purposes. |
*/ |
const void *base_ir; |
const char *current_annotation; |
int *virtual_grf_sizes; |
int virtual_grf_count; |
int virtual_grf_array_size; |
int first_non_payload_grf; |
unsigned int max_grf; |
int *virtual_grf_start; |
int *virtual_grf_end; |
dst_reg userplane[MAX_CLIP_PLANES]; |
/** |
* This is the size to be used for an array with an element per |
* reg_offset |
*/ |
int virtual_grf_reg_count; |
/** Per-virtual-grf indices into an array of size virtual_grf_reg_count */ |
int *virtual_grf_reg_map; |
bool live_intervals_valid; |
dst_reg *variable_storage(ir_variable *var); |
void reladdr_to_temp(ir_instruction *ir, src_reg *reg, int *num_reladdr); |
bool need_all_constants_in_pull_buffer; |
/** |
* \name Visit methods |
* |
* As typical for the visitor pattern, there must be one \c visit method for |
* each concrete subclass of \c ir_instruction. Virtual base classes within |
* the hierarchy should not have \c visit methods. |
*/ |
/*@{*/ |
virtual void visit(ir_variable *); |
virtual void visit(ir_loop *); |
virtual void visit(ir_loop_jump *); |
virtual void visit(ir_function_signature *); |
virtual void visit(ir_function *); |
virtual void visit(ir_expression *); |
virtual void visit(ir_swizzle *); |
virtual void visit(ir_dereference_variable *); |
virtual void visit(ir_dereference_array *); |
virtual void visit(ir_dereference_record *); |
virtual void visit(ir_assignment *); |
virtual void visit(ir_constant *); |
virtual void visit(ir_call *); |
virtual void visit(ir_return *); |
virtual void visit(ir_discard *); |
virtual void visit(ir_texture *); |
virtual void visit(ir_if *); |
/*@}*/ |
src_reg result; |
/* Regs for vertex results. Generated at ir_variable visiting time |
* for the ir->location's used. |
*/ |
dst_reg output_reg[BRW_VARYING_SLOT_COUNT]; |
const char *output_reg_annotation[BRW_VARYING_SLOT_COUNT]; |
int uniform_size[MAX_UNIFORMS]; |
int uniform_vector_size[MAX_UNIFORMS]; |
int uniforms; |
src_reg shader_start_time; |
struct hash_table *variable_ht; |
bool run(void); |
void fail(const char *msg, ...); |
int virtual_grf_alloc(int size); |
void setup_uniform_clipplane_values(); |
void setup_uniform_values(ir_variable *ir); |
void setup_builtin_uniform_values(ir_variable *ir); |
int setup_uniforms(int payload_reg); |
void setup_payload(); |
bool reg_allocate_trivial(); |
bool reg_allocate(); |
void evaluate_spill_costs(float *spill_costs, bool *no_spill); |
int choose_spill_reg(struct ra_graph *g); |
void spill_reg(int spill_reg); |
void move_grf_array_access_to_scratch(); |
void move_uniform_array_access_to_pull_constants(); |
void move_push_constants_to_pull_constants(); |
void split_uniform_registers(); |
void pack_uniform_registers(); |
void calculate_live_intervals(); |
void split_virtual_grfs(); |
bool dead_code_eliminate(); |
bool virtual_grf_interferes(int a, int b); |
bool opt_copy_propagation(); |
bool opt_algebraic(); |
bool opt_register_coalesce(); |
void opt_set_dependency_control(); |
void opt_schedule_instructions(); |
bool can_do_source_mods(vec4_instruction *inst); |
vec4_instruction *emit(vec4_instruction *inst); |
vec4_instruction *emit(enum opcode opcode); |
vec4_instruction *emit(enum opcode opcode, dst_reg dst, src_reg src0); |
vec4_instruction *emit(enum opcode opcode, dst_reg dst, |
src_reg src0, src_reg src1); |
vec4_instruction *emit(enum opcode opcode, dst_reg dst, |
src_reg src0, src_reg src1, src_reg src2); |
vec4_instruction *emit_before(vec4_instruction *inst, |
vec4_instruction *new_inst); |
vec4_instruction *MOV(dst_reg dst, src_reg src0); |
vec4_instruction *NOT(dst_reg dst, src_reg src0); |
vec4_instruction *RNDD(dst_reg dst, src_reg src0); |
vec4_instruction *RNDE(dst_reg dst, src_reg src0); |
vec4_instruction *RNDZ(dst_reg dst, src_reg src0); |
vec4_instruction *FRC(dst_reg dst, src_reg src0); |
vec4_instruction *F32TO16(dst_reg dst, src_reg src0); |
vec4_instruction *F16TO32(dst_reg dst, src_reg src0); |
vec4_instruction *ADD(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *MUL(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *MACH(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *MAC(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *AND(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *OR(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *XOR(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *DP3(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *DP4(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *DPH(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *SHL(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *SHR(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *ASR(dst_reg dst, src_reg src0, src_reg src1); |
vec4_instruction *CMP(dst_reg dst, src_reg src0, src_reg src1, |
uint32_t condition); |
vec4_instruction *IF(src_reg src0, src_reg src1, uint32_t condition); |
vec4_instruction *IF(uint32_t predicate); |
vec4_instruction *PULL_CONSTANT_LOAD(dst_reg dst, src_reg index); |
vec4_instruction *SCRATCH_READ(dst_reg dst, src_reg index); |
vec4_instruction *SCRATCH_WRITE(dst_reg dst, src_reg src, src_reg index); |
vec4_instruction *LRP(dst_reg dst, src_reg a, src_reg y, src_reg x); |
vec4_instruction *BFREV(dst_reg dst, src_reg value); |
vec4_instruction *BFE(dst_reg dst, src_reg bits, src_reg offset, src_reg value); |
vec4_instruction *BFI1(dst_reg dst, src_reg bits, src_reg offset); |
vec4_instruction *BFI2(dst_reg dst, src_reg bfi1_dst, src_reg insert, src_reg base); |
vec4_instruction *FBH(dst_reg dst, src_reg value); |
vec4_instruction *FBL(dst_reg dst, src_reg value); |
vec4_instruction *CBIT(dst_reg dst, src_reg value); |
int implied_mrf_writes(vec4_instruction *inst); |
bool try_rewrite_rhs_to_dst(ir_assignment *ir, |
dst_reg dst, |
src_reg src, |
vec4_instruction *pre_rhs_inst, |
vec4_instruction *last_rhs_inst); |
bool try_copy_propagation(vec4_instruction *inst, int arg, |
src_reg *values[4]); |
/** Walks an exec_list of ir_instruction and sends it through this visitor. */ |
void visit_instructions(const exec_list *list); |
void emit_vp_sop(uint32_t condmod, dst_reg dst, |
src_reg src0, src_reg src1, src_reg one); |
void emit_bool_to_cond_code(ir_rvalue *ir, uint32_t *predicate); |
void emit_bool_comparison(unsigned int op, dst_reg dst, src_reg src0, src_reg src1); |
void emit_if_gen6(ir_if *ir); |
void emit_minmax(uint32_t condmod, dst_reg dst, src_reg src0, src_reg src1); |
void emit_block_move(dst_reg *dst, src_reg *src, |
const struct glsl_type *type, uint32_t predicate); |
void emit_constant_values(dst_reg *dst, ir_constant *value); |
/** |
* Emit the correct dot-product instruction for the type of arguments |
*/ |
void emit_dp(dst_reg dst, src_reg src0, src_reg src1, unsigned elements); |
void emit_scalar(ir_instruction *ir, enum prog_opcode op, |
dst_reg dst, src_reg src0); |
void emit_scalar(ir_instruction *ir, enum prog_opcode op, |
dst_reg dst, src_reg src0, src_reg src1); |
void emit_scs(ir_instruction *ir, enum prog_opcode op, |
dst_reg dst, const src_reg &src); |
src_reg fix_3src_operand(src_reg src); |
void emit_math1_gen6(enum opcode opcode, dst_reg dst, src_reg src); |
void emit_math1_gen4(enum opcode opcode, dst_reg dst, src_reg src); |
void emit_math(enum opcode opcode, dst_reg dst, src_reg src); |
void emit_math2_gen6(enum opcode opcode, dst_reg dst, src_reg src0, src_reg src1); |
void emit_math2_gen4(enum opcode opcode, dst_reg dst, src_reg src0, src_reg src1); |
void emit_math(enum opcode opcode, dst_reg dst, src_reg src0, src_reg src1); |
src_reg fix_math_operand(src_reg src); |
void emit_pack_half_2x16(dst_reg dst, src_reg src0); |
void emit_unpack_half_2x16(dst_reg dst, src_reg src0); |
void swizzle_result(ir_texture *ir, src_reg orig_val, int sampler); |
void emit_ndc_computation(); |
void emit_psiz_and_flags(struct brw_reg reg); |
void emit_clip_distances(struct brw_reg reg, int offset); |
void emit_generic_urb_slot(dst_reg reg, int varying); |
void emit_urb_slot(int mrf, int varying); |
void emit_shader_time_begin(); |
void emit_shader_time_end(); |
void emit_shader_time_write(enum shader_time_shader_type type, |
src_reg value); |
src_reg get_scratch_offset(vec4_instruction *inst, |
src_reg *reladdr, int reg_offset); |
src_reg get_pull_constant_offset(vec4_instruction *inst, |
src_reg *reladdr, int reg_offset); |
void emit_scratch_read(vec4_instruction *inst, |
dst_reg dst, |
src_reg orig_src, |
int base_offset); |
void emit_scratch_write(vec4_instruction *inst, |
int base_offset); |
void emit_pull_constant_load(vec4_instruction *inst, |
dst_reg dst, |
src_reg orig_src, |
int base_offset); |
bool try_emit_sat(ir_expression *ir); |
bool try_emit_mad(ir_expression *ir, int mul_arg); |
void resolve_ud_negate(src_reg *reg); |
src_reg get_timestamp(); |
bool process_move_condition(ir_rvalue *ir); |
void dump_instruction(backend_instruction *inst); |
protected: |
void emit_vertex(); |
void lower_attributes_to_hw_regs(const int *attribute_map); |
virtual dst_reg *make_reg_for_system_value(ir_variable *ir) = 0; |
virtual int setup_attributes(int payload_reg) = 0; |
virtual void emit_prolog() = 0; |
virtual void emit_program_code() = 0; |
virtual void emit_thread_end() = 0; |
virtual void emit_urb_write_header(int mrf) = 0; |
virtual vec4_instruction *emit_urb_write_opcode(bool complete) = 0; |
virtual int compute_array_stride(ir_dereference_array *ir); |
const bool debug_flag; |
}; |
class vec4_vs_visitor : public vec4_visitor |
{ |
public: |
vec4_vs_visitor(struct brw_context *brw, |
struct brw_vs_compile *vs_compile, |
struct brw_vs_prog_data *vs_prog_data, |
struct gl_shader_program *prog, |
struct brw_shader *shader, |
void *mem_ctx); |
protected: |
virtual dst_reg *make_reg_for_system_value(ir_variable *ir); |
virtual int setup_attributes(int payload_reg); |
virtual void emit_prolog(); |
virtual void emit_program_code(); |
virtual void emit_thread_end(); |
virtual void emit_urb_write_header(int mrf); |
virtual vec4_instruction *emit_urb_write_opcode(bool complete); |
private: |
void setup_vp_regs(); |
dst_reg get_vp_dst_reg(const prog_dst_register &dst); |
src_reg get_vp_src_reg(const prog_src_register &src); |
struct brw_vs_compile * const vs_compile; |
struct brw_vs_prog_data * const vs_prog_data; |
src_reg *vp_temp_regs; |
src_reg vp_addr_reg; |
}; |
/** |
* The vertex shader code generator. |
* |
* Translates VS IR to actual i965 assembly code. |
*/ |
class vec4_generator |
{ |
public: |
vec4_generator(struct brw_context *brw, |
struct gl_shader_program *shader_prog, |
struct gl_program *prog, |
void *mem_ctx, |
bool debug_flag); |
~vec4_generator(); |
const unsigned *generate_assembly(exec_list *insts, unsigned *asm_size); |
private: |
void generate_code(exec_list *instructions); |
void generate_vec4_instruction(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg *src); |
void generate_math1_gen4(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src); |
void generate_math1_gen6(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src); |
void generate_math2_gen4(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src0, |
struct brw_reg src1); |
void generate_math2_gen6(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src0, |
struct brw_reg src1); |
void generate_math2_gen7(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src0, |
struct brw_reg src1); |
void generate_tex(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src); |
void generate_urb_write(vec4_instruction *inst); |
void generate_oword_dual_block_offsets(struct brw_reg m1, |
struct brw_reg index); |
void generate_scratch_write(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src, |
struct brw_reg index); |
void generate_scratch_read(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg index); |
void generate_pull_constant_load(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg index, |
struct brw_reg offset); |
void generate_pull_constant_load_gen7(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg surf_index, |
struct brw_reg offset); |
struct brw_context *brw; |
struct gl_context *ctx; |
struct brw_compile *p; |
struct gl_shader_program *shader_prog; |
struct gl_shader *shader; |
const struct gl_program *prog; |
void *mem_ctx; |
const bool debug_flag; |
}; |
} /* namespace brw */ |
#endif /* BRW_VEC4_H */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp |
---|
0,0 → 1,357 |
/* |
* Copyright © 2011 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. |
*/ |
/** |
* @file brw_vec4_copy_propagation.cpp |
* |
* Implements tracking of values copied between registers, and |
* optimizations based on that: copy propagation and constant |
* propagation. |
*/ |
#include "brw_vec4.h" |
extern "C" { |
#include "main/macros.h" |
} |
namespace brw { |
static bool |
is_direct_copy(vec4_instruction *inst) |
{ |
return (inst->opcode == BRW_OPCODE_MOV && |
!inst->predicate && |
inst->dst.file == GRF && |
!inst->saturate && |
!inst->dst.reladdr && |
!inst->src[0].reladdr && |
inst->dst.type == inst->src[0].type); |
} |
static bool |
is_dominated_by_previous_instruction(vec4_instruction *inst) |
{ |
return (inst->opcode != BRW_OPCODE_DO && |
inst->opcode != BRW_OPCODE_WHILE && |
inst->opcode != BRW_OPCODE_ELSE && |
inst->opcode != BRW_OPCODE_ENDIF); |
} |
static bool |
try_constant_propagation(vec4_instruction *inst, int arg, src_reg *values[4]) |
{ |
/* For constant propagation, we only handle the same constant |
* across all 4 channels. Some day, we should handle the 8-bit |
* float vector format, which would let us constant propagate |
* vectors better. |
*/ |
src_reg value = *values[0]; |
for (int i = 1; i < 4; i++) { |
if (!value.equals(values[i])) |
return false; |
} |
if (value.file != IMM) |
return false; |
if (inst->src[arg].abs) { |
if (value.type == BRW_REGISTER_TYPE_F) { |
value.imm.f = fabs(value.imm.f); |
} else if (value.type == BRW_REGISTER_TYPE_D) { |
if (value.imm.i < 0) |
value.imm.i = -value.imm.i; |
} |
} |
if (inst->src[arg].negate) { |
if (value.type == BRW_REGISTER_TYPE_F) |
value.imm.f = -value.imm.f; |
else |
value.imm.u = -value.imm.u; |
} |
switch (inst->opcode) { |
case BRW_OPCODE_MOV: |
inst->src[arg] = value; |
return true; |
case BRW_OPCODE_MACH: |
case BRW_OPCODE_MUL: |
case BRW_OPCODE_ADD: |
if (arg == 1) { |
inst->src[arg] = value; |
return true; |
} else if (arg == 0 && inst->src[1].file != IMM) { |
/* Fit this constant in by commuting the operands. Exception: we |
* can't do this for 32-bit integer MUL/MACH because it's asymmetric. |
*/ |
if ((inst->opcode == BRW_OPCODE_MUL || |
inst->opcode == BRW_OPCODE_MACH) && |
(inst->src[1].type == BRW_REGISTER_TYPE_D || |
inst->src[1].type == BRW_REGISTER_TYPE_UD)) |
break; |
inst->src[0] = inst->src[1]; |
inst->src[1] = value; |
return true; |
} |
break; |
case BRW_OPCODE_CMP: |
if (arg == 1) { |
inst->src[arg] = value; |
return true; |
} else if (arg == 0 && inst->src[1].file != IMM) { |
uint32_t new_cmod; |
new_cmod = brw_swap_cmod(inst->conditional_mod); |
if (new_cmod != ~0u) { |
/* Fit this constant in by swapping the operands and |
* flipping the test. |
*/ |
inst->src[0] = inst->src[1]; |
inst->src[1] = value; |
inst->conditional_mod = new_cmod; |
return true; |
} |
} |
break; |
case BRW_OPCODE_SEL: |
if (arg == 1) { |
inst->src[arg] = value; |
return true; |
} else if (arg == 0 && inst->src[1].file != IMM) { |
inst->src[0] = inst->src[1]; |
inst->src[1] = value; |
/* If this was predicated, flipping operands means |
* we also need to flip the predicate. |
*/ |
if (inst->conditional_mod == BRW_CONDITIONAL_NONE) { |
inst->predicate_inverse = !inst->predicate_inverse; |
} |
return true; |
} |
break; |
default: |
break; |
} |
return false; |
} |
bool |
vec4_visitor::try_copy_propagation(vec4_instruction *inst, int arg, |
src_reg *values[4]) |
{ |
/* For constant propagation, we only handle the same constant |
* across all 4 channels. Some day, we should handle the 8-bit |
* float vector format, which would let us constant propagate |
* vectors better. |
*/ |
src_reg value = *values[0]; |
for (int i = 1; i < 4; i++) { |
/* This is equals() except we don't care about the swizzle. */ |
if (value.file != values[i]->file || |
value.reg != values[i]->reg || |
value.reg_offset != values[i]->reg_offset || |
value.type != values[i]->type || |
value.negate != values[i]->negate || |
value.abs != values[i]->abs) { |
return false; |
} |
} |
/* Compute the swizzle of the original register by swizzling the |
* component loaded from each value according to the swizzle of |
* operand we're going to change. |
*/ |
int s[4]; |
for (int i = 0; i < 4; i++) { |
s[i] = BRW_GET_SWZ(values[i]->swizzle, |
BRW_GET_SWZ(inst->src[arg].swizzle, i)); |
} |
value.swizzle = BRW_SWIZZLE4(s[0], s[1], s[2], s[3]); |
if (value.file != UNIFORM && |
value.file != GRF && |
value.file != ATTR) |
return false; |
if (inst->src[arg].abs) { |
value.negate = false; |
value.abs = true; |
} |
if (inst->src[arg].negate) |
value.negate = !value.negate; |
bool has_source_modifiers = value.negate || value.abs; |
/* gen6 math and gen7+ SENDs from GRFs ignore source modifiers on |
* instructions. |
*/ |
if ((has_source_modifiers || value.file == UNIFORM || |
value.swizzle != BRW_SWIZZLE_XYZW) && !can_do_source_mods(inst)) |
return false; |
if (has_source_modifiers && value.type != inst->src[arg].type) |
return false; |
bool is_3src_inst = (inst->opcode == BRW_OPCODE_LRP || |
inst->opcode == BRW_OPCODE_MAD || |
inst->opcode == BRW_OPCODE_BFE || |
inst->opcode == BRW_OPCODE_BFI2); |
if (is_3src_inst && value.file == UNIFORM) |
return false; |
/* We can't copy-propagate a UD negation into a condmod |
* instruction, because the condmod ends up looking at the 33-bit |
* signed accumulator value instead of the 32-bit value we wanted |
*/ |
if (inst->conditional_mod && |
value.negate && |
value.type == BRW_REGISTER_TYPE_UD) |
return false; |
/* Don't report progress if this is a noop. */ |
if (value.equals(&inst->src[arg])) |
return false; |
value.type = inst->src[arg].type; |
inst->src[arg] = value; |
return true; |
} |
bool |
vec4_visitor::opt_copy_propagation() |
{ |
bool progress = false; |
src_reg *cur_value[virtual_grf_reg_count][4]; |
memset(&cur_value, 0, sizeof(cur_value)); |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
/* This pass only works on basic blocks. If there's flow |
* control, throw out all our information and start from |
* scratch. |
* |
* This should really be fixed by using a structure like in |
* src/glsl/opt_copy_propagation.cpp to track available copies. |
*/ |
if (!is_dominated_by_previous_instruction(inst)) { |
memset(cur_value, 0, sizeof(cur_value)); |
continue; |
} |
/* For each source arg, see if each component comes from a copy |
* from the same type file (IMM, GRF, UNIFORM), and try |
* optimizing out access to the copy result |
*/ |
for (int i = 2; i >= 0; i--) { |
/* Copied values end up in GRFs, and we don't track reladdr |
* accesses. |
*/ |
if (inst->src[i].file != GRF || |
inst->src[i].reladdr) |
continue; |
int reg = (virtual_grf_reg_map[inst->src[i].reg] + |
inst->src[i].reg_offset); |
/* Find the regs that each swizzle component came from. |
*/ |
src_reg *values[4]; |
int c; |
for (c = 0; c < 4; c++) { |
values[c] = cur_value[reg][BRW_GET_SWZ(inst->src[i].swizzle, c)]; |
/* If there's no available copy for this channel, bail. |
* We could be more aggressive here -- some channels might |
* not get used based on the destination writemask. |
*/ |
if (!values[c]) |
break; |
/* We'll only be able to copy propagate if the sources are |
* all from the same file -- there's no ability to swizzle |
* 0 or 1 constants in with source registers like in i915. |
*/ |
if (c > 0 && values[c - 1]->file != values[c]->file) |
break; |
} |
if (c != 4) |
continue; |
if (try_constant_propagation(inst, i, values) || |
try_copy_propagation(inst, i, values)) |
progress = true; |
} |
/* Track available source registers. */ |
if (inst->dst.file == GRF) { |
const int reg = |
virtual_grf_reg_map[inst->dst.reg] + inst->dst.reg_offset; |
/* Update our destination's current channel values. For a direct copy, |
* the value is the newly propagated source. Otherwise, we don't know |
* the new value, so clear it. |
*/ |
bool direct_copy = is_direct_copy(inst); |
for (int i = 0; i < 4; i++) { |
if (inst->dst.writemask & (1 << i)) { |
cur_value[reg][i] = direct_copy ? &inst->src[0] : NULL; |
} |
} |
/* Clear the records for any registers whose current value came from |
* our destination's updated channels, as the two are no longer equal. |
*/ |
if (inst->dst.reladdr) |
memset(cur_value, 0, sizeof(cur_value)); |
else { |
for (int i = 0; i < virtual_grf_reg_count; i++) { |
for (int j = 0; j < 4; j++) { |
if (inst->dst.writemask & (1 << j) && |
cur_value[i][j] && |
cur_value[i][j]->file == GRF && |
cur_value[i][j]->reg == inst->dst.reg && |
cur_value[i][j]->reg_offset == inst->dst.reg_offset) { |
cur_value[i][j] = NULL; |
} |
} |
} |
} |
} |
} |
if (progress) |
live_intervals_valid = false; |
return progress; |
} |
} /* namespace brw */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vec4_emit.cpp |
---|
0,0 → 1,969 |
/* Copyright © 2011 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 "brw_vec4.h" |
extern "C" { |
#include "brw_eu.h" |
#include "main/macros.h" |
#include "program/prog_print.h" |
#include "program/prog_parameter.h" |
}; |
namespace brw { |
struct brw_reg |
vec4_instruction::get_dst(void) |
{ |
struct brw_reg brw_reg; |
switch (dst.file) { |
case GRF: |
brw_reg = brw_vec8_grf(dst.reg + dst.reg_offset, 0); |
brw_reg = retype(brw_reg, dst.type); |
brw_reg.dw1.bits.writemask = dst.writemask; |
break; |
case MRF: |
brw_reg = brw_message_reg(dst.reg + dst.reg_offset); |
brw_reg = retype(brw_reg, dst.type); |
brw_reg.dw1.bits.writemask = dst.writemask; |
break; |
case HW_REG: |
brw_reg = dst.fixed_hw_reg; |
break; |
case BAD_FILE: |
brw_reg = brw_null_reg(); |
break; |
default: |
assert(!"not reached"); |
brw_reg = brw_null_reg(); |
break; |
} |
return brw_reg; |
} |
struct brw_reg |
vec4_instruction::get_src(int i) |
{ |
struct brw_reg brw_reg; |
switch (src[i].file) { |
case GRF: |
brw_reg = brw_vec8_grf(src[i].reg + src[i].reg_offset, 0); |
brw_reg = retype(brw_reg, src[i].type); |
brw_reg.dw1.bits.swizzle = src[i].swizzle; |
if (src[i].abs) |
brw_reg = brw_abs(brw_reg); |
if (src[i].negate) |
brw_reg = negate(brw_reg); |
break; |
case IMM: |
switch (src[i].type) { |
case BRW_REGISTER_TYPE_F: |
brw_reg = brw_imm_f(src[i].imm.f); |
break; |
case BRW_REGISTER_TYPE_D: |
brw_reg = brw_imm_d(src[i].imm.i); |
break; |
case BRW_REGISTER_TYPE_UD: |
brw_reg = brw_imm_ud(src[i].imm.u); |
break; |
default: |
assert(!"not reached"); |
brw_reg = brw_null_reg(); |
break; |
} |
break; |
case UNIFORM: |
brw_reg = stride(brw_vec4_grf(1 + (src[i].reg + src[i].reg_offset) / 2, |
((src[i].reg + src[i].reg_offset) % 2) * 4), |
0, 4, 1); |
brw_reg = retype(brw_reg, src[i].type); |
brw_reg.dw1.bits.swizzle = src[i].swizzle; |
if (src[i].abs) |
brw_reg = brw_abs(brw_reg); |
if (src[i].negate) |
brw_reg = negate(brw_reg); |
/* This should have been moved to pull constants. */ |
assert(!src[i].reladdr); |
break; |
case HW_REG: |
brw_reg = src[i].fixed_hw_reg; |
break; |
case BAD_FILE: |
/* Probably unused. */ |
brw_reg = brw_null_reg(); |
break; |
case ATTR: |
default: |
assert(!"not reached"); |
brw_reg = brw_null_reg(); |
break; |
} |
return brw_reg; |
} |
vec4_generator::vec4_generator(struct brw_context *brw, |
struct gl_shader_program *shader_prog, |
struct gl_program *prog, |
void *mem_ctx, |
bool debug_flag) |
: brw(brw), shader_prog(shader_prog), prog(prog), mem_ctx(mem_ctx), |
debug_flag(debug_flag) |
{ |
shader = shader_prog ? shader_prog->_LinkedShaders[MESA_SHADER_VERTEX] : NULL; |
p = rzalloc(mem_ctx, struct brw_compile); |
brw_init_compile(brw, p, mem_ctx); |
} |
vec4_generator::~vec4_generator() |
{ |
} |
void |
vec4_generator::generate_math1_gen4(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src) |
{ |
brw_math(p, |
dst, |
brw_math_function(inst->opcode), |
inst->base_mrf, |
src, |
BRW_MATH_DATA_VECTOR, |
BRW_MATH_PRECISION_FULL); |
} |
static void |
check_gen6_math_src_arg(struct brw_reg src) |
{ |
/* Source swizzles are ignored. */ |
assert(!src.abs); |
assert(!src.negate); |
assert(src.dw1.bits.swizzle == BRW_SWIZZLE_XYZW); |
} |
void |
vec4_generator::generate_math1_gen6(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src) |
{ |
/* Can't do writemask because math can't be align16. */ |
assert(dst.dw1.bits.writemask == WRITEMASK_XYZW); |
check_gen6_math_src_arg(src); |
brw_set_access_mode(p, BRW_ALIGN_1); |
brw_math(p, |
dst, |
brw_math_function(inst->opcode), |
inst->base_mrf, |
src, |
BRW_MATH_DATA_SCALAR, |
BRW_MATH_PRECISION_FULL); |
brw_set_access_mode(p, BRW_ALIGN_16); |
} |
void |
vec4_generator::generate_math2_gen7(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src0, |
struct brw_reg src1) |
{ |
brw_math2(p, |
dst, |
brw_math_function(inst->opcode), |
src0, src1); |
} |
void |
vec4_generator::generate_math2_gen6(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src0, |
struct brw_reg src1) |
{ |
/* Can't do writemask because math can't be align16. */ |
assert(dst.dw1.bits.writemask == WRITEMASK_XYZW); |
/* Source swizzles are ignored. */ |
check_gen6_math_src_arg(src0); |
check_gen6_math_src_arg(src1); |
brw_set_access_mode(p, BRW_ALIGN_1); |
brw_math2(p, |
dst, |
brw_math_function(inst->opcode), |
src0, src1); |
brw_set_access_mode(p, BRW_ALIGN_16); |
} |
void |
vec4_generator::generate_math2_gen4(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src0, |
struct brw_reg src1) |
{ |
/* From the Ironlake PRM, Volume 4, Part 1, Section 6.1.13 |
* "Message Payload": |
* |
* "Operand0[7]. For the INT DIV functions, this operand is the |
* denominator." |
* ... |
* "Operand1[7]. For the INT DIV functions, this operand is the |
* numerator." |
*/ |
bool is_int_div = inst->opcode != SHADER_OPCODE_POW; |
struct brw_reg &op0 = is_int_div ? src1 : src0; |
struct brw_reg &op1 = is_int_div ? src0 : src1; |
brw_push_insn_state(p); |
brw_set_saturate(p, false); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
brw_MOV(p, retype(brw_message_reg(inst->base_mrf + 1), op1.type), op1); |
brw_pop_insn_state(p); |
brw_math(p, |
dst, |
brw_math_function(inst->opcode), |
inst->base_mrf, |
op0, |
BRW_MATH_DATA_VECTOR, |
BRW_MATH_PRECISION_FULL); |
} |
void |
vec4_generator::generate_tex(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src) |
{ |
int msg_type = -1; |
if (brw->gen >= 5) { |
switch (inst->opcode) { |
case SHADER_OPCODE_TEX: |
case SHADER_OPCODE_TXL: |
if (inst->shadow_compare) { |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LOD_COMPARE; |
} else { |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LOD; |
} |
break; |
case SHADER_OPCODE_TXD: |
if (inst->shadow_compare) { |
/* Gen7.5+. Otherwise, lowered by brw_lower_texture_gradients(). */ |
assert(brw->is_haswell); |
msg_type = HSW_SAMPLER_MESSAGE_SAMPLE_DERIV_COMPARE; |
} else { |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_DERIVS; |
} |
break; |
case SHADER_OPCODE_TXF: |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LD; |
break; |
case SHADER_OPCODE_TXF_MS: |
if (brw->gen >= 7) |
msg_type = GEN7_SAMPLER_MESSAGE_SAMPLE_LD2DMS; |
else |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_LD; |
break; |
case SHADER_OPCODE_TXS: |
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_RESINFO; |
break; |
default: |
assert(!"should not get here: invalid VS texture opcode"); |
break; |
} |
} else { |
switch (inst->opcode) { |
case SHADER_OPCODE_TEX: |
case SHADER_OPCODE_TXL: |
if (inst->shadow_compare) { |
msg_type = BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD_COMPARE; |
assert(inst->mlen == 3); |
} else { |
msg_type = BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_LOD; |
assert(inst->mlen == 2); |
} |
break; |
case SHADER_OPCODE_TXD: |
/* There is no sample_d_c message; comparisons are done manually. */ |
msg_type = BRW_SAMPLER_MESSAGE_SIMD4X2_SAMPLE_GRADIENTS; |
assert(inst->mlen == 4); |
break; |
case SHADER_OPCODE_TXF: |
msg_type = BRW_SAMPLER_MESSAGE_SIMD4X2_LD; |
assert(inst->mlen == 2); |
break; |
case SHADER_OPCODE_TXS: |
msg_type = BRW_SAMPLER_MESSAGE_SIMD4X2_RESINFO; |
assert(inst->mlen == 2); |
break; |
default: |
assert(!"should not get here: invalid VS texture opcode"); |
break; |
} |
} |
assert(msg_type != -1); |
/* Load the message header if present. If there's a texture offset, we need |
* to set it up explicitly and load the offset bitfield. Otherwise, we can |
* use an implied move from g0 to the first message register. |
*/ |
if (inst->texture_offset) { |
/* Explicitly set up the message header by copying g0 to the MRF. */ |
brw_push_insn_state(p); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
brw_MOV(p, retype(brw_message_reg(inst->base_mrf), BRW_REGISTER_TYPE_UD), |
retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)); |
/* Then set the offset bits in DWord 2. */ |
brw_set_access_mode(p, BRW_ALIGN_1); |
brw_MOV(p, |
retype(brw_vec1_reg(BRW_MESSAGE_REGISTER_FILE, inst->base_mrf, 2), |
BRW_REGISTER_TYPE_UD), |
brw_imm_uw(inst->texture_offset)); |
brw_pop_insn_state(p); |
} else if (inst->header_present) { |
/* Set up an implied move from g0 to the MRF. */ |
src = brw_vec8_grf(0, 0); |
} |
uint32_t return_format; |
switch (dst.type) { |
case BRW_REGISTER_TYPE_D: |
return_format = BRW_SAMPLER_RETURN_FORMAT_SINT32; |
break; |
case BRW_REGISTER_TYPE_UD: |
return_format = BRW_SAMPLER_RETURN_FORMAT_UINT32; |
break; |
default: |
return_format = BRW_SAMPLER_RETURN_FORMAT_FLOAT32; |
break; |
} |
brw_SAMPLE(p, |
dst, |
inst->base_mrf, |
src, |
SURF_INDEX_VS_TEXTURE(inst->sampler), |
inst->sampler, |
msg_type, |
1, /* response length */ |
inst->mlen, |
inst->header_present, |
BRW_SAMPLER_SIMD_MODE_SIMD4X2, |
return_format); |
} |
void |
vec4_generator::generate_urb_write(vec4_instruction *inst) |
{ |
brw_urb_WRITE(p, |
brw_null_reg(), /* dest */ |
inst->base_mrf, /* starting mrf reg nr */ |
brw_vec8_grf(0, 0), /* src */ |
false, /* allocate */ |
true, /* used */ |
inst->mlen, |
0, /* response len */ |
inst->eot, /* eot */ |
inst->eot, /* writes complete */ |
inst->offset, /* urb destination offset */ |
BRW_URB_SWIZZLE_INTERLEAVE); |
} |
void |
vec4_generator::generate_oword_dual_block_offsets(struct brw_reg m1, |
struct brw_reg index) |
{ |
int second_vertex_offset; |
if (brw->gen >= 6) |
second_vertex_offset = 1; |
else |
second_vertex_offset = 16; |
m1 = retype(m1, BRW_REGISTER_TYPE_D); |
/* Set up M1 (message payload). Only the block offsets in M1.0 and |
* M1.4 are used, and the rest are ignored. |
*/ |
struct brw_reg m1_0 = suboffset(vec1(m1), 0); |
struct brw_reg m1_4 = suboffset(vec1(m1), 4); |
struct brw_reg index_0 = suboffset(vec1(index), 0); |
struct brw_reg index_4 = suboffset(vec1(index), 4); |
brw_push_insn_state(p); |
brw_set_mask_control(p, BRW_MASK_DISABLE); |
brw_set_access_mode(p, BRW_ALIGN_1); |
brw_MOV(p, m1_0, index_0); |
if (index.file == BRW_IMMEDIATE_VALUE) { |
index_4.dw1.ud += second_vertex_offset; |
brw_MOV(p, m1_4, index_4); |
} else { |
brw_ADD(p, m1_4, index_4, brw_imm_d(second_vertex_offset)); |
} |
brw_pop_insn_state(p); |
} |
void |
vec4_generator::generate_scratch_read(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg index) |
{ |
struct brw_reg header = brw_vec8_grf(0, 0); |
gen6_resolve_implied_move(p, &header, inst->base_mrf); |
generate_oword_dual_block_offsets(brw_message_reg(inst->base_mrf + 1), |
index); |
uint32_t msg_type; |
if (brw->gen >= 6) |
msg_type = GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ; |
else if (brw->gen == 5 || brw->is_g4x) |
msg_type = G45_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ; |
else |
msg_type = BRW_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ; |
/* Each of the 8 channel enables is considered for whether each |
* dword is written. |
*/ |
struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND); |
brw_set_dest(p, send, dst); |
brw_set_src0(p, send, header); |
if (brw->gen < 6) |
send->header.destreg__conditionalmod = inst->base_mrf; |
brw_set_dp_read_message(p, send, |
255, /* binding table index: stateless access */ |
BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD, |
msg_type, |
BRW_DATAPORT_READ_TARGET_RENDER_CACHE, |
2, /* mlen */ |
true, /* header_present */ |
1 /* rlen */); |
} |
void |
vec4_generator::generate_scratch_write(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg src, |
struct brw_reg index) |
{ |
struct brw_reg header = brw_vec8_grf(0, 0); |
bool write_commit; |
/* If the instruction is predicated, we'll predicate the send, not |
* the header setup. |
*/ |
brw_set_predicate_control(p, false); |
gen6_resolve_implied_move(p, &header, inst->base_mrf); |
generate_oword_dual_block_offsets(brw_message_reg(inst->base_mrf + 1), |
index); |
brw_MOV(p, |
retype(brw_message_reg(inst->base_mrf + 2), BRW_REGISTER_TYPE_D), |
retype(src, BRW_REGISTER_TYPE_D)); |
uint32_t msg_type; |
if (brw->gen >= 7) |
msg_type = GEN7_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE; |
else if (brw->gen == 6) |
msg_type = GEN6_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE; |
else |
msg_type = BRW_DATAPORT_WRITE_MESSAGE_OWORD_DUAL_BLOCK_WRITE; |
brw_set_predicate_control(p, inst->predicate); |
/* Pre-gen6, we have to specify write commits to ensure ordering |
* between reads and writes within a thread. Afterwards, that's |
* guaranteed and write commits only matter for inter-thread |
* synchronization. |
*/ |
if (brw->gen >= 6) { |
write_commit = false; |
} else { |
/* The visitor set up our destination register to be g0. This |
* means that when the next read comes along, we will end up |
* reading from g0 and causing a block on the write commit. For |
* write-after-read, we are relying on the value of the previous |
* read being used (and thus blocking on completion) before our |
* write is executed. This means we have to be careful in |
* instruction scheduling to not violate this assumption. |
*/ |
write_commit = true; |
} |
/* Each of the 8 channel enables is considered for whether each |
* dword is written. |
*/ |
struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND); |
brw_set_dest(p, send, dst); |
brw_set_src0(p, send, header); |
if (brw->gen < 6) |
send->header.destreg__conditionalmod = inst->base_mrf; |
brw_set_dp_write_message(p, send, |
255, /* binding table index: stateless access */ |
BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD, |
msg_type, |
3, /* mlen */ |
true, /* header present */ |
false, /* not a render target write */ |
write_commit, /* rlen */ |
false, /* eot */ |
write_commit); |
} |
void |
vec4_generator::generate_pull_constant_load(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg index, |
struct brw_reg offset) |
{ |
assert(brw->gen <= 7); |
assert(index.file == BRW_IMMEDIATE_VALUE && |
index.type == BRW_REGISTER_TYPE_UD); |
uint32_t surf_index = index.dw1.ud; |
struct brw_reg header = brw_vec8_grf(0, 0); |
gen6_resolve_implied_move(p, &header, inst->base_mrf); |
brw_MOV(p, retype(brw_message_reg(inst->base_mrf + 1), BRW_REGISTER_TYPE_D), |
offset); |
uint32_t msg_type; |
if (brw->gen >= 6) |
msg_type = GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ; |
else if (brw->gen == 5 || brw->is_g4x) |
msg_type = G45_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ; |
else |
msg_type = BRW_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ; |
/* Each of the 8 channel enables is considered for whether each |
* dword is written. |
*/ |
struct brw_instruction *send = brw_next_insn(p, BRW_OPCODE_SEND); |
brw_set_dest(p, send, dst); |
brw_set_src0(p, send, header); |
if (brw->gen < 6) |
send->header.destreg__conditionalmod = inst->base_mrf; |
brw_set_dp_read_message(p, send, |
surf_index, |
BRW_DATAPORT_OWORD_DUAL_BLOCK_1OWORD, |
msg_type, |
BRW_DATAPORT_READ_TARGET_DATA_CACHE, |
2, /* mlen */ |
true, /* header_present */ |
1 /* rlen */); |
} |
void |
vec4_generator::generate_pull_constant_load_gen7(vec4_instruction *inst, |
struct brw_reg dst, |
struct brw_reg surf_index, |
struct brw_reg offset) |
{ |
assert(surf_index.file == BRW_IMMEDIATE_VALUE && |
surf_index.type == BRW_REGISTER_TYPE_UD); |
brw_instruction *insn = brw_next_insn(p, BRW_OPCODE_SEND); |
brw_set_dest(p, insn, dst); |
brw_set_src0(p, insn, offset); |
brw_set_sampler_message(p, insn, |
surf_index.dw1.ud, |
0, /* LD message ignores sampler unit */ |
GEN5_SAMPLER_MESSAGE_SAMPLE_LD, |
1, /* rlen */ |
1, /* mlen */ |
false, /* no header */ |
BRW_SAMPLER_SIMD_MODE_SIMD4X2, |
0); |
} |
/** |
* Generate assembly for a Vec4 IR instruction. |
* |
* \param instruction The Vec4 IR instruction to generate code for. |
* \param dst The destination register. |
* \param src An array of up to three source registers. |
*/ |
void |
vec4_generator::generate_vec4_instruction(vec4_instruction *instruction, |
struct brw_reg dst, |
struct brw_reg *src) |
{ |
vec4_instruction *inst = (vec4_instruction *) instruction; |
switch (inst->opcode) { |
case BRW_OPCODE_MOV: |
brw_MOV(p, dst, src[0]); |
break; |
case BRW_OPCODE_ADD: |
brw_ADD(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_MUL: |
brw_MUL(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_MACH: |
brw_set_acc_write_control(p, 1); |
brw_MACH(p, dst, src[0], src[1]); |
brw_set_acc_write_control(p, 0); |
break; |
case BRW_OPCODE_MAD: |
brw_MAD(p, dst, src[0], src[1], src[2]); |
break; |
case BRW_OPCODE_FRC: |
brw_FRC(p, dst, src[0]); |
break; |
case BRW_OPCODE_RNDD: |
brw_RNDD(p, dst, src[0]); |
break; |
case BRW_OPCODE_RNDE: |
brw_RNDE(p, dst, src[0]); |
break; |
case BRW_OPCODE_RNDZ: |
brw_RNDZ(p, dst, src[0]); |
break; |
case BRW_OPCODE_AND: |
brw_AND(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_OR: |
brw_OR(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_XOR: |
brw_XOR(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_NOT: |
brw_NOT(p, dst, src[0]); |
break; |
case BRW_OPCODE_ASR: |
brw_ASR(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_SHR: |
brw_SHR(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_SHL: |
brw_SHL(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_CMP: |
brw_CMP(p, dst, inst->conditional_mod, src[0], src[1]); |
break; |
case BRW_OPCODE_SEL: |
brw_SEL(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_DPH: |
brw_DPH(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_DP4: |
brw_DP4(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_DP3: |
brw_DP3(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_DP2: |
brw_DP2(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_F32TO16: |
brw_F32TO16(p, dst, src[0]); |
break; |
case BRW_OPCODE_F16TO32: |
brw_F16TO32(p, dst, src[0]); |
break; |
case BRW_OPCODE_LRP: |
brw_LRP(p, dst, src[0], src[1], src[2]); |
break; |
case BRW_OPCODE_BFREV: |
/* BFREV only supports UD type for src and dst. */ |
brw_BFREV(p, retype(dst, BRW_REGISTER_TYPE_UD), |
retype(src[0], BRW_REGISTER_TYPE_UD)); |
break; |
case BRW_OPCODE_FBH: |
/* FBH only supports UD type for dst. */ |
brw_FBH(p, retype(dst, BRW_REGISTER_TYPE_UD), src[0]); |
break; |
case BRW_OPCODE_FBL: |
/* FBL only supports UD type for dst. */ |
brw_FBL(p, retype(dst, BRW_REGISTER_TYPE_UD), src[0]); |
break; |
case BRW_OPCODE_CBIT: |
/* CBIT only supports UD type for dst. */ |
brw_CBIT(p, retype(dst, BRW_REGISTER_TYPE_UD), src[0]); |
break; |
case BRW_OPCODE_BFE: |
brw_BFE(p, dst, src[0], src[1], src[2]); |
break; |
case BRW_OPCODE_BFI1: |
brw_BFI1(p, dst, src[0], src[1]); |
break; |
case BRW_OPCODE_BFI2: |
brw_BFI2(p, dst, src[0], src[1], src[2]); |
break; |
case BRW_OPCODE_IF: |
if (inst->src[0].file != BAD_FILE) { |
/* The instruction has an embedded compare (only allowed on gen6) */ |
assert(brw->gen == 6); |
gen6_IF(p, inst->conditional_mod, src[0], src[1]); |
} else { |
struct brw_instruction *brw_inst = brw_IF(p, BRW_EXECUTE_8); |
brw_inst->header.predicate_control = inst->predicate; |
} |
break; |
case BRW_OPCODE_ELSE: |
brw_ELSE(p); |
break; |
case BRW_OPCODE_ENDIF: |
brw_ENDIF(p); |
break; |
case BRW_OPCODE_DO: |
brw_DO(p, BRW_EXECUTE_8); |
break; |
case BRW_OPCODE_BREAK: |
brw_BREAK(p); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
break; |
case BRW_OPCODE_CONTINUE: |
/* FINISHME: We need to write the loop instruction support still. */ |
if (brw->gen >= 6) |
gen6_CONT(p); |
else |
brw_CONT(p); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
break; |
case BRW_OPCODE_WHILE: |
brw_WHILE(p); |
break; |
case SHADER_OPCODE_RCP: |
case SHADER_OPCODE_RSQ: |
case SHADER_OPCODE_SQRT: |
case SHADER_OPCODE_EXP2: |
case SHADER_OPCODE_LOG2: |
case SHADER_OPCODE_SIN: |
case SHADER_OPCODE_COS: |
if (brw->gen == 6) { |
generate_math1_gen6(inst, dst, src[0]); |
} else { |
/* Also works for Gen7. */ |
generate_math1_gen4(inst, dst, src[0]); |
} |
break; |
case SHADER_OPCODE_POW: |
case SHADER_OPCODE_INT_QUOTIENT: |
case SHADER_OPCODE_INT_REMAINDER: |
if (brw->gen >= 7) { |
generate_math2_gen7(inst, dst, src[0], src[1]); |
} else if (brw->gen == 6) { |
generate_math2_gen6(inst, dst, src[0], src[1]); |
} else { |
generate_math2_gen4(inst, dst, src[0], src[1]); |
} |
break; |
case SHADER_OPCODE_TEX: |
case SHADER_OPCODE_TXD: |
case SHADER_OPCODE_TXF: |
case SHADER_OPCODE_TXF_MS: |
case SHADER_OPCODE_TXL: |
case SHADER_OPCODE_TXS: |
generate_tex(inst, dst, src[0]); |
break; |
case VS_OPCODE_URB_WRITE: |
generate_urb_write(inst); |
break; |
case VS_OPCODE_SCRATCH_READ: |
generate_scratch_read(inst, dst, src[0]); |
break; |
case VS_OPCODE_SCRATCH_WRITE: |
generate_scratch_write(inst, dst, src[0], src[1]); |
break; |
case VS_OPCODE_PULL_CONSTANT_LOAD: |
generate_pull_constant_load(inst, dst, src[0], src[1]); |
break; |
case VS_OPCODE_PULL_CONSTANT_LOAD_GEN7: |
generate_pull_constant_load_gen7(inst, dst, src[0], src[1]); |
break; |
case SHADER_OPCODE_SHADER_TIME_ADD: |
brw_shader_time_add(p, src[0], SURF_INDEX_VS_SHADER_TIME); |
break; |
default: |
if (inst->opcode < (int) ARRAY_SIZE(opcode_descs)) { |
_mesa_problem(ctx, "Unsupported opcode in `%s' in VS\n", |
opcode_descs[inst->opcode].name); |
} else { |
_mesa_problem(ctx, "Unsupported opcode %d in VS", inst->opcode); |
} |
abort(); |
} |
} |
void |
vec4_generator::generate_code(exec_list *instructions) |
{ |
int last_native_insn_offset = 0; |
const char *last_annotation_string = NULL; |
const void *last_annotation_ir = NULL; |
if (unlikely(debug_flag)) { |
if (shader) { |
printf("Native code for vertex shader %d:\n", shader_prog->Name); |
} else { |
printf("Native code for vertex program %d:\n", prog->Id); |
} |
} |
foreach_list(node, instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
struct brw_reg src[3], dst; |
if (unlikely(debug_flag)) { |
if (last_annotation_ir != inst->ir) { |
last_annotation_ir = inst->ir; |
if (last_annotation_ir) { |
printf(" "); |
if (shader) { |
((ir_instruction *) last_annotation_ir)->print(); |
} else { |
const prog_instruction *vpi; |
vpi = (const prog_instruction *) inst->ir; |
printf("%d: ", (int)(vpi - prog->Instructions)); |
_mesa_fprint_instruction_opt(stdout, vpi, 0, |
PROG_PRINT_DEBUG, NULL); |
} |
printf("\n"); |
} |
} |
if (last_annotation_string != inst->annotation) { |
last_annotation_string = inst->annotation; |
if (last_annotation_string) |
printf(" %s\n", last_annotation_string); |
} |
} |
for (unsigned int i = 0; i < 3; i++) { |
src[i] = inst->get_src(i); |
} |
dst = inst->get_dst(); |
brw_set_conditionalmod(p, inst->conditional_mod); |
brw_set_predicate_control(p, inst->predicate); |
brw_set_predicate_inverse(p, inst->predicate_inverse); |
brw_set_saturate(p, inst->saturate); |
brw_set_mask_control(p, inst->force_writemask_all); |
unsigned pre_emit_nr_insn = p->nr_insn; |
generate_vec4_instruction(inst, dst, src); |
if (inst->no_dd_clear || inst->no_dd_check) { |
assert(p->nr_insn == pre_emit_nr_insn + 1 || |
!"no_dd_check or no_dd_clear set for IR emitting more " |
"than 1 instruction"); |
struct brw_instruction *last = &p->store[pre_emit_nr_insn]; |
if (inst->no_dd_clear) |
last->header.dependency_control |= BRW_DEPENDENCY_NOTCLEARED; |
if (inst->no_dd_check) |
last->header.dependency_control |= BRW_DEPENDENCY_NOTCHECKED; |
} |
if (unlikely(debug_flag)) { |
brw_dump_compile(p, stdout, |
last_native_insn_offset, p->next_insn_offset); |
} |
last_native_insn_offset = p->next_insn_offset; |
} |
if (unlikely(debug_flag)) { |
printf("\n"); |
} |
brw_set_uip_jip(p); |
/* OK, while the INTEL_DEBUG=vs above is very nice for debugging VS |
* emit issues, it doesn't get the jump distances into the output, |
* which is often something we want to debug. So this is here in |
* case you're doing that. |
*/ |
if (0 && unlikely(debug_flag)) { |
brw_dump_compile(p, stdout, 0, p->next_insn_offset); |
} |
} |
const unsigned * |
vec4_generator::generate_assembly(exec_list *instructions, |
unsigned *assembly_size) |
{ |
brw_set_access_mode(p, BRW_ALIGN_16); |
generate_code(instructions); |
return brw_get_program(p, assembly_size); |
} |
} /* namespace brw */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vec4_live_variables.cpp |
---|
0,0 → 1,271 |
/* |
* 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_cfg.h" |
#include "brw_vec4_live_variables.h" |
using namespace brw; |
/** @file brw_vec4_live_variables.cpp |
* |
* Support for computing at the basic block level which variables |
* (virtual GRFs in our case) are live at entry and exit. |
* |
* See Muchnik's Advanced Compiler Design and Implementation, section |
* 14.1 (p444). |
*/ |
/** |
* Sets up the use[] and def[] arrays. |
* |
* The basic-block-level live variable analysis needs to know which |
* variables get used before they're completely defined, and which |
* variables are completely defined before they're used. |
* |
* We independently track each channel of a vec4. This is because we need to |
* be able to recognize a sequence like: |
* |
* ... |
* DP4 tmp.x a b; |
* DP4 tmp.y c d; |
* MUL result.xy tmp.xy e.xy |
* ... |
* |
* as having tmp live only across that sequence (assuming it's used nowhere |
* else), because it's a common pattern. A more conservative approach that |
* doesn't get tmp marked a deffed in this block will tend to result in |
* spilling. |
*/ |
void |
vec4_live_variables::setup_def_use() |
{ |
int ip = 0; |
for (int b = 0; b < cfg->num_blocks; b++) { |
bblock_t *block = cfg->blocks[b]; |
assert(ip == block->start_ip); |
if (b > 0) |
assert(cfg->blocks[b - 1]->end_ip == ip - 1); |
for (vec4_instruction *inst = (vec4_instruction *)block->start; |
inst != block->end->next; |
inst = (vec4_instruction *)inst->next) { |
/* Set use[] for this instruction */ |
for (unsigned int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
int reg = inst->src[i].reg; |
for (int j = 0; j < 4; j++) { |
int c = BRW_GET_SWZ(inst->src[i].swizzle, j); |
if (!bd[b].def[reg * 4 + c]) |
bd[b].use[reg * 4 + c] = true; |
} |
} |
} |
/* Check for unconditional writes to whole registers. These |
* are the things that screen off preceding definitions of a |
* variable, and thus qualify for being in def[]. |
*/ |
if (inst->dst.file == GRF && |
v->virtual_grf_sizes[inst->dst.reg] == 1 && |
!inst->predicate) { |
for (int c = 0; c < 4; c++) { |
if (inst->dst.writemask & (1 << c)) { |
int reg = inst->dst.reg; |
if (!bd[b].use[reg * 4 + c]) |
bd[b].def[reg * 4 + c] = true; |
} |
} |
} |
ip++; |
} |
} |
} |
/** |
* The algorithm incrementally sets bits in liveout and livein, |
* propagating it through control flow. It will eventually terminate |
* because it only ever adds bits, and stops when no bits are added in |
* a pass. |
*/ |
void |
vec4_live_variables::compute_live_variables() |
{ |
bool cont = true; |
while (cont) { |
cont = false; |
for (int b = 0; b < cfg->num_blocks; b++) { |
/* Update livein */ |
for (int i = 0; i < num_vars; i++) { |
if (bd[b].use[i] || (bd[b].liveout[i] && !bd[b].def[i])) { |
if (!bd[b].livein[i]) { |
bd[b].livein[i] = true; |
cont = true; |
} |
} |
} |
/* Update liveout */ |
foreach_list(block_node, &cfg->blocks[b]->children) { |
bblock_link *link = (bblock_link *)block_node; |
bblock_t *block = link->block; |
for (int i = 0; i < num_vars; i++) { |
if (bd[block->block_num].livein[i] && !bd[b].liveout[i]) { |
bd[b].liveout[i] = true; |
cont = true; |
} |
} |
} |
} |
} |
} |
vec4_live_variables::vec4_live_variables(vec4_visitor *v, cfg_t *cfg) |
: v(v), cfg(cfg) |
{ |
mem_ctx = ralloc_context(cfg->mem_ctx); |
num_vars = v->virtual_grf_count * 4; |
bd = rzalloc_array(mem_ctx, struct block_data, cfg->num_blocks); |
for (int i = 0; i < cfg->num_blocks; i++) { |
bd[i].def = rzalloc_array(mem_ctx, bool, num_vars); |
bd[i].use = rzalloc_array(mem_ctx, bool, num_vars); |
bd[i].livein = rzalloc_array(mem_ctx, bool, num_vars); |
bd[i].liveout = rzalloc_array(mem_ctx, bool, num_vars); |
} |
setup_def_use(); |
compute_live_variables(); |
} |
vec4_live_variables::~vec4_live_variables() |
{ |
ralloc_free(mem_ctx); |
} |
#define MAX_INSTRUCTION (1 << 30) |
/** |
* Computes a conservative start/end of the live intervals for each virtual GRF. |
* |
* We could expose per-channel live intervals to the consumer based on the |
* information we computed in vec4_live_variables, except that our only |
* current user is virtual_grf_interferes(). So we instead union the |
* per-channel ranges into a per-vgrf range for virtual_grf_start[] and |
* virtual_grf_end[]. |
* |
* We could potentially have virtual_grf_interferes() do the test per-channel, |
* which would let some interesting register allocation occur (particularly on |
* code-generated GLSL sequences from the Cg compiler which does register |
* allocation at the GLSL level and thus reuses components of the variable |
* with distinct lifetimes). But right now the complexity of doing so doesn't |
* seem worth it, since having virtual_grf_interferes() be cheap is important |
* for register allocation performance. |
*/ |
void |
vec4_visitor::calculate_live_intervals() |
{ |
if (this->live_intervals_valid) |
return; |
int *start = ralloc_array(mem_ctx, int, this->virtual_grf_count); |
int *end = ralloc_array(mem_ctx, int, this->virtual_grf_count); |
ralloc_free(this->virtual_grf_start); |
ralloc_free(this->virtual_grf_end); |
this->virtual_grf_start = start; |
this->virtual_grf_end = end; |
for (int i = 0; i < this->virtual_grf_count; i++) { |
start[i] = MAX_INSTRUCTION; |
end[i] = -1; |
} |
/* Start by setting up the intervals with no knowledge of control |
* flow. |
*/ |
int ip = 0; |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
for (unsigned int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
int reg = inst->src[i].reg; |
start[reg] = MIN2(start[reg], ip); |
end[reg] = ip; |
} |
} |
if (inst->dst.file == GRF) { |
int reg = inst->dst.reg; |
start[reg] = MIN2(start[reg], ip); |
end[reg] = ip; |
} |
ip++; |
} |
/* Now, extend those intervals using our analysis of control flow. |
* |
* The control flow-aware analysis was done at a channel level, while at |
* this point we're distilling it down to vgrfs. |
*/ |
cfg_t cfg(this); |
vec4_live_variables livevars(this, &cfg); |
for (int b = 0; b < cfg.num_blocks; b++) { |
for (int i = 0; i < livevars.num_vars; i++) { |
if (livevars.bd[b].livein[i]) { |
start[i / 4] = MIN2(start[i / 4], cfg.blocks[b]->start_ip); |
end[i / 4] = MAX2(end[i / 4], cfg.blocks[b]->start_ip); |
} |
if (livevars.bd[b].liveout[i]) { |
start[i / 4] = MIN2(start[i / 4], cfg.blocks[b]->end_ip); |
end[i / 4] = MAX2(end[i / 4], cfg.blocks[b]->end_ip); |
} |
} |
} |
this->live_intervals_valid = true; |
} |
bool |
vec4_visitor::virtual_grf_interferes(int a, int b) |
{ |
return !(virtual_grf_end[a] <= virtual_grf_start[b] || |
virtual_grf_end[b] <= virtual_grf_start[a]); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vec4_live_variables.h |
---|
0,0 → 1,81 |
/* |
* 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_vec4.h" |
namespace brw { |
struct block_data { |
/** |
* Which variables are defined before being used in the block. |
* |
* Note that for our purposes, "defined" means unconditionally, completely |
* defined. |
*/ |
bool *def; |
/** |
* Which variables are used before being defined in the block. |
*/ |
bool *use; |
/** Which defs reach the entry point of the block. */ |
bool *livein; |
/** Which defs reach the exit point of the block. */ |
bool *liveout; |
}; |
class vec4_live_variables { |
public: |
static void* operator new(size_t size, void *ctx) |
{ |
void *node; |
node = rzalloc_size(ctx, size); |
assert(node != NULL); |
return node; |
} |
vec4_live_variables(vec4_visitor *v, cfg_t *cfg); |
~vec4_live_variables(); |
void setup_def_use(); |
void compute_live_variables(); |
vec4_visitor *v; |
cfg_t *cfg; |
void *mem_ctx; |
int num_vars; |
/** Per-basic-block information on live variables */ |
struct block_data *bd; |
}; |
} /* namespace brw */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vec4_reg_allocate.cpp |
---|
0,0 → 1,357 |
/* |
* Copyright © 2011 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. |
*/ |
extern "C" { |
#include "main/macros.h" |
#include "program/register_allocate.h" |
} /* extern "C" */ |
#include "brw_vec4.h" |
using namespace brw; |
namespace brw { |
static void |
assign(unsigned int *reg_hw_locations, reg *reg) |
{ |
if (reg->file == GRF) { |
reg->reg = reg_hw_locations[reg->reg]; |
} |
} |
bool |
vec4_visitor::reg_allocate_trivial() |
{ |
unsigned int hw_reg_mapping[this->virtual_grf_count]; |
bool virtual_grf_used[this->virtual_grf_count]; |
int i; |
int next; |
/* Calculate which virtual GRFs are actually in use after whatever |
* optimization passes have occurred. |
*/ |
for (int i = 0; i < this->virtual_grf_count; i++) { |
virtual_grf_used[i] = false; |
} |
foreach_iter(exec_list_iterator, iter, this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)iter.get(); |
if (inst->dst.file == GRF) |
virtual_grf_used[inst->dst.reg] = true; |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) |
virtual_grf_used[inst->src[i].reg] = true; |
} |
} |
hw_reg_mapping[0] = this->first_non_payload_grf; |
next = hw_reg_mapping[0] + this->virtual_grf_sizes[0]; |
for (i = 1; i < this->virtual_grf_count; i++) { |
if (virtual_grf_used[i]) { |
hw_reg_mapping[i] = next; |
next += this->virtual_grf_sizes[i]; |
} |
} |
prog_data->total_grf = next; |
foreach_iter(exec_list_iterator, iter, this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)iter.get(); |
assign(hw_reg_mapping, &inst->dst); |
assign(hw_reg_mapping, &inst->src[0]); |
assign(hw_reg_mapping, &inst->src[1]); |
assign(hw_reg_mapping, &inst->src[2]); |
} |
if (prog_data->total_grf > max_grf) { |
fail("Ran out of regs on trivial allocator (%d/%d)\n", |
prog_data->total_grf, max_grf); |
return false; |
} |
return true; |
} |
static void |
brw_alloc_reg_set_for_classes(struct brw_context *brw, |
int *class_sizes, |
int class_count, |
int base_reg_count) |
{ |
/* Compute the total number of registers across all classes. */ |
int ra_reg_count = 0; |
for (int i = 0; i < class_count; i++) { |
ra_reg_count += base_reg_count - (class_sizes[i] - 1); |
} |
ralloc_free(brw->vs.ra_reg_to_grf); |
brw->vs.ra_reg_to_grf = ralloc_array(brw, uint8_t, ra_reg_count); |
ralloc_free(brw->vs.regs); |
brw->vs.regs = ra_alloc_reg_set(brw, ra_reg_count); |
if (brw->gen >= 6) |
ra_set_allocate_round_robin(brw->vs.regs); |
ralloc_free(brw->vs.classes); |
brw->vs.classes = ralloc_array(brw, int, class_count + 1); |
/* Now, add the registers to their classes, and add the conflicts |
* between them and the base GRF registers (and also each other). |
*/ |
int reg = 0; |
for (int i = 0; i < class_count; i++) { |
int class_reg_count = base_reg_count - (class_sizes[i] - 1); |
brw->vs.classes[i] = ra_alloc_reg_class(brw->vs.regs); |
for (int j = 0; j < class_reg_count; j++) { |
ra_class_add_reg(brw->vs.regs, brw->vs.classes[i], reg); |
brw->vs.ra_reg_to_grf[reg] = j; |
for (int base_reg = j; |
base_reg < j + class_sizes[i]; |
base_reg++) { |
ra_add_transitive_reg_conflict(brw->vs.regs, base_reg, reg); |
} |
reg++; |
} |
} |
assert(reg == ra_reg_count); |
ra_set_finalize(brw->vs.regs, NULL); |
} |
bool |
vec4_visitor::reg_allocate() |
{ |
unsigned int hw_reg_mapping[virtual_grf_count]; |
int first_assigned_grf = this->first_non_payload_grf; |
int base_reg_count = max_grf - first_assigned_grf; |
int class_sizes[base_reg_count]; |
int class_count = 0; |
/* Using the trivial allocator can be useful in debugging undefined |
* register access as a result of broken optimization passes. |
*/ |
if (0) |
return reg_allocate_trivial(); |
calculate_live_intervals(); |
/* Set up the register classes. |
* |
* The base registers store a vec4. However, we'll need larger |
* storage for arrays, structures, and matrices, which will be sets |
* of contiguous registers. |
*/ |
class_sizes[class_count++] = 1; |
for (int r = 0; r < virtual_grf_count; r++) { |
int i; |
for (i = 0; i < class_count; i++) { |
if (class_sizes[i] == this->virtual_grf_sizes[r]) |
break; |
} |
if (i == class_count) { |
if (this->virtual_grf_sizes[r] >= base_reg_count) { |
fail("Object too large to register allocate.\n"); |
} |
class_sizes[class_count++] = this->virtual_grf_sizes[r]; |
} |
} |
brw_alloc_reg_set_for_classes(brw, class_sizes, class_count, base_reg_count); |
struct ra_graph *g = ra_alloc_interference_graph(brw->vs.regs, |
virtual_grf_count); |
for (int i = 0; i < virtual_grf_count; i++) { |
for (int c = 0; c < class_count; c++) { |
if (class_sizes[c] == this->virtual_grf_sizes[i]) { |
ra_set_node_class(g, i, brw->vs.classes[c]); |
break; |
} |
} |
for (int j = 0; j < i; j++) { |
if (virtual_grf_interferes(i, j)) { |
ra_add_node_interference(g, i, j); |
} |
} |
} |
if (!ra_allocate_no_spills(g)) { |
/* Failed to allocate registers. Spill a reg, and the caller will |
* loop back into here to try again. |
*/ |
int reg = choose_spill_reg(g); |
if (reg == -1) { |
fail("no register to spill\n"); |
} else { |
spill_reg(reg); |
} |
ralloc_free(g); |
return false; |
} |
/* Get the chosen virtual registers for each node, and map virtual |
* regs in the register classes back down to real hardware reg |
* numbers. |
*/ |
prog_data->total_grf = first_assigned_grf; |
for (int i = 0; i < virtual_grf_count; i++) { |
int reg = ra_get_node_reg(g, i); |
hw_reg_mapping[i] = first_assigned_grf + brw->vs.ra_reg_to_grf[reg]; |
prog_data->total_grf = MAX2(prog_data->total_grf, |
hw_reg_mapping[i] + virtual_grf_sizes[i]); |
} |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
assign(hw_reg_mapping, &inst->dst); |
assign(hw_reg_mapping, &inst->src[0]); |
assign(hw_reg_mapping, &inst->src[1]); |
assign(hw_reg_mapping, &inst->src[2]); |
} |
ralloc_free(g); |
return true; |
} |
void |
vec4_visitor::evaluate_spill_costs(float *spill_costs, bool *no_spill) |
{ |
float loop_scale = 1.0; |
for (int i = 0; i < this->virtual_grf_count; i++) { |
spill_costs[i] = 0.0; |
no_spill[i] = virtual_grf_sizes[i] != 1; |
} |
/* Calculate costs for spilling nodes. Call it a cost of 1 per |
* spill/unspill we'll have to do, and guess that the insides of |
* loops run 10 times. |
*/ |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *) node; |
for (unsigned int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) { |
spill_costs[inst->src[i].reg] += loop_scale; |
if (inst->src[i].reladdr) |
no_spill[inst->src[i].reg] = true; |
} |
} |
if (inst->dst.file == GRF) { |
spill_costs[inst->dst.reg] += loop_scale; |
if (inst->dst.reladdr) |
no_spill[inst->dst.reg] = true; |
} |
switch (inst->opcode) { |
case BRW_OPCODE_DO: |
loop_scale *= 10; |
break; |
case BRW_OPCODE_WHILE: |
loop_scale /= 10; |
break; |
case VS_OPCODE_SCRATCH_READ: |
case VS_OPCODE_SCRATCH_WRITE: |
for (int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF) |
no_spill[inst->src[i].reg] = true; |
} |
if (inst->dst.file == GRF) |
no_spill[inst->dst.reg] = true; |
break; |
default: |
break; |
} |
} |
} |
int |
vec4_visitor::choose_spill_reg(struct ra_graph *g) |
{ |
float spill_costs[this->virtual_grf_count]; |
bool no_spill[this->virtual_grf_count]; |
evaluate_spill_costs(spill_costs, no_spill); |
for (int i = 0; i < this->virtual_grf_count; i++) { |
if (!no_spill[i]) |
ra_set_node_spill_cost(g, i, spill_costs[i]); |
} |
return ra_get_best_spill_node(g); |
} |
void |
vec4_visitor::spill_reg(int spill_reg_nr) |
{ |
assert(virtual_grf_sizes[spill_reg_nr] == 1); |
unsigned int spill_offset = c->last_scratch++; |
/* Generate spill/unspill instructions for the objects being spilled. */ |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *) node; |
for (unsigned int i = 0; i < 3; i++) { |
if (inst->src[i].file == GRF && inst->src[i].reg == spill_reg_nr) { |
src_reg spill_reg = inst->src[i]; |
inst->src[i].reg = virtual_grf_alloc(1); |
dst_reg temp = dst_reg(inst->src[i]); |
/* Only read the necessary channels, to avoid overwriting the rest |
* with data that may not have been written to scratch. |
*/ |
temp.writemask = 0; |
for (int c = 0; c < 4; c++) |
temp.writemask |= (1 << BRW_GET_SWZ(inst->src[i].swizzle, c)); |
assert(temp.writemask != 0); |
emit_scratch_read(inst, temp, spill_reg, spill_offset); |
} |
} |
if (inst->dst.file == GRF && inst->dst.reg == spill_reg_nr) { |
emit_scratch_write(inst, spill_offset); |
} |
} |
this->live_intervals_valid = false; |
} |
} /* namespace brw */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp |
---|
0,0 → 1,3307 |
/* |
* Copyright © 2011 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 "brw_vec4.h" |
#include "glsl/ir_uniform.h" |
extern "C" { |
#include "main/context.h" |
#include "main/macros.h" |
#include "program/prog_parameter.h" |
#include "program/sampler.h" |
} |
namespace brw { |
vec4_instruction::vec4_instruction(vec4_visitor *v, |
enum opcode opcode, dst_reg dst, |
src_reg src0, src_reg src1, src_reg src2) |
{ |
this->opcode = opcode; |
this->dst = dst; |
this->src[0] = src0; |
this->src[1] = src1; |
this->src[2] = src2; |
this->ir = v->base_ir; |
this->annotation = v->current_annotation; |
} |
vec4_instruction * |
vec4_visitor::emit(vec4_instruction *inst) |
{ |
this->instructions.push_tail(inst); |
return inst; |
} |
vec4_instruction * |
vec4_visitor::emit_before(vec4_instruction *inst, vec4_instruction *new_inst) |
{ |
new_inst->ir = inst->ir; |
new_inst->annotation = inst->annotation; |
inst->insert_before(new_inst); |
return inst; |
} |
vec4_instruction * |
vec4_visitor::emit(enum opcode opcode, dst_reg dst, |
src_reg src0, src_reg src1, src_reg src2) |
{ |
return emit(new(mem_ctx) vec4_instruction(this, opcode, dst, |
src0, src1, src2)); |
} |
vec4_instruction * |
vec4_visitor::emit(enum opcode opcode, dst_reg dst, src_reg src0, src_reg src1) |
{ |
return emit(new(mem_ctx) vec4_instruction(this, opcode, dst, src0, src1)); |
} |
vec4_instruction * |
vec4_visitor::emit(enum opcode opcode, dst_reg dst, src_reg src0) |
{ |
return emit(new(mem_ctx) vec4_instruction(this, opcode, dst, src0)); |
} |
vec4_instruction * |
vec4_visitor::emit(enum opcode opcode) |
{ |
return emit(new(mem_ctx) vec4_instruction(this, opcode, dst_reg())); |
} |
#define ALU1(op) \ |
vec4_instruction * \ |
vec4_visitor::op(dst_reg dst, src_reg src0) \ |
{ \ |
return new(mem_ctx) vec4_instruction(this, BRW_OPCODE_##op, dst, \ |
src0); \ |
} |
#define ALU2(op) \ |
vec4_instruction * \ |
vec4_visitor::op(dst_reg dst, src_reg src0, src_reg src1) \ |
{ \ |
return new(mem_ctx) vec4_instruction(this, BRW_OPCODE_##op, dst, \ |
src0, src1); \ |
} |
#define ALU3(op) \ |
vec4_instruction * \ |
vec4_visitor::op(dst_reg dst, src_reg src0, src_reg src1, src_reg src2)\ |
{ \ |
return new(mem_ctx) vec4_instruction(this, BRW_OPCODE_##op, dst, \ |
src0, src1, src2); \ |
} |
ALU1(NOT) |
ALU1(MOV) |
ALU1(FRC) |
ALU1(RNDD) |
ALU1(RNDE) |
ALU1(RNDZ) |
ALU1(F32TO16) |
ALU1(F16TO32) |
ALU2(ADD) |
ALU2(MUL) |
ALU2(MACH) |
ALU2(AND) |
ALU2(OR) |
ALU2(XOR) |
ALU2(DP3) |
ALU2(DP4) |
ALU2(DPH) |
ALU2(SHL) |
ALU2(SHR) |
ALU2(ASR) |
ALU3(LRP) |
ALU1(BFREV) |
ALU3(BFE) |
ALU2(BFI1) |
ALU3(BFI2) |
ALU1(FBH) |
ALU1(FBL) |
ALU1(CBIT) |
/** Gen4 predicated IF. */ |
vec4_instruction * |
vec4_visitor::IF(uint32_t predicate) |
{ |
vec4_instruction *inst; |
inst = new(mem_ctx) vec4_instruction(this, BRW_OPCODE_IF); |
inst->predicate = predicate; |
return inst; |
} |
/** Gen6+ IF with embedded comparison. */ |
vec4_instruction * |
vec4_visitor::IF(src_reg src0, src_reg src1, uint32_t condition) |
{ |
assert(brw->gen >= 6); |
vec4_instruction *inst; |
resolve_ud_negate(&src0); |
resolve_ud_negate(&src1); |
inst = new(mem_ctx) vec4_instruction(this, BRW_OPCODE_IF, dst_null_d(), |
src0, src1); |
inst->conditional_mod = condition; |
return inst; |
} |
/** |
* CMP: Sets the low bit of the destination channels with the result |
* of the comparison, while the upper bits are undefined, and updates |
* the flag register with the packed 16 bits of the result. |
*/ |
vec4_instruction * |
vec4_visitor::CMP(dst_reg dst, src_reg src0, src_reg src1, uint32_t condition) |
{ |
vec4_instruction *inst; |
/* original gen4 does type conversion to the destination type |
* before before comparison, producing garbage results for floating |
* point comparisons. |
*/ |
if (brw->gen == 4) { |
dst.type = src0.type; |
if (dst.file == HW_REG) |
dst.fixed_hw_reg.type = dst.type; |
} |
resolve_ud_negate(&src0); |
resolve_ud_negate(&src1); |
inst = new(mem_ctx) vec4_instruction(this, BRW_OPCODE_CMP, dst, src0, src1); |
inst->conditional_mod = condition; |
return inst; |
} |
vec4_instruction * |
vec4_visitor::SCRATCH_READ(dst_reg dst, src_reg index) |
{ |
vec4_instruction *inst; |
inst = new(mem_ctx) vec4_instruction(this, VS_OPCODE_SCRATCH_READ, |
dst, index); |
inst->base_mrf = 14; |
inst->mlen = 2; |
return inst; |
} |
vec4_instruction * |
vec4_visitor::SCRATCH_WRITE(dst_reg dst, src_reg src, src_reg index) |
{ |
vec4_instruction *inst; |
inst = new(mem_ctx) vec4_instruction(this, VS_OPCODE_SCRATCH_WRITE, |
dst, src, index); |
inst->base_mrf = 13; |
inst->mlen = 3; |
return inst; |
} |
void |
vec4_visitor::emit_dp(dst_reg dst, src_reg src0, src_reg src1, unsigned elements) |
{ |
static enum opcode dot_opcodes[] = { |
BRW_OPCODE_DP2, BRW_OPCODE_DP3, BRW_OPCODE_DP4 |
}; |
emit(dot_opcodes[elements - 2], dst, src0, src1); |
} |
src_reg |
vec4_visitor::fix_3src_operand(src_reg src) |
{ |
/* Using vec4 uniforms in SIMD4x2 programs is difficult. You'd like to be |
* able to use vertical stride of zero to replicate the vec4 uniform, like |
* |
* g3<0;4,1>:f - [0, 4][1, 5][2, 6][3, 7] |
* |
* But you can't, since vertical stride is always four in three-source |
* instructions. Instead, insert a MOV instruction to do the replication so |
* that the three-source instruction can consume it. |
*/ |
/* The MOV is only needed if the source is a uniform or immediate. */ |
if (src.file != UNIFORM && src.file != IMM) |
return src; |
dst_reg expanded = dst_reg(this, glsl_type::vec4_type); |
expanded.type = src.type; |
emit(MOV(expanded, src)); |
return src_reg(expanded); |
} |
src_reg |
vec4_visitor::fix_math_operand(src_reg src) |
{ |
/* The gen6 math instruction ignores the source modifiers -- |
* swizzle, abs, negate, and at least some parts of the register |
* region description. |
* |
* Rather than trying to enumerate all these cases, *always* expand the |
* operand to a temp GRF for gen6. |
* |
* For gen7, keep the operand as-is, except if immediate, which gen7 still |
* can't use. |
*/ |
if (brw->gen == 7 && src.file != IMM) |
return src; |
dst_reg expanded = dst_reg(this, glsl_type::vec4_type); |
expanded.type = src.type; |
emit(MOV(expanded, src)); |
return src_reg(expanded); |
} |
void |
vec4_visitor::emit_math1_gen6(enum opcode opcode, dst_reg dst, src_reg src) |
{ |
src = fix_math_operand(src); |
if (dst.writemask != WRITEMASK_XYZW) { |
/* The gen6 math instruction must be align1, so we can't do |
* writemasks. |
*/ |
dst_reg temp_dst = dst_reg(this, glsl_type::vec4_type); |
emit(opcode, temp_dst, src); |
emit(MOV(dst, src_reg(temp_dst))); |
} else { |
emit(opcode, dst, src); |
} |
} |
void |
vec4_visitor::emit_math1_gen4(enum opcode opcode, dst_reg dst, src_reg src) |
{ |
vec4_instruction *inst = emit(opcode, dst, src); |
inst->base_mrf = 1; |
inst->mlen = 1; |
} |
void |
vec4_visitor::emit_math(opcode opcode, dst_reg dst, src_reg src) |
{ |
switch (opcode) { |
case SHADER_OPCODE_RCP: |
case SHADER_OPCODE_RSQ: |
case SHADER_OPCODE_SQRT: |
case SHADER_OPCODE_EXP2: |
case SHADER_OPCODE_LOG2: |
case SHADER_OPCODE_SIN: |
case SHADER_OPCODE_COS: |
break; |
default: |
assert(!"not reached: bad math opcode"); |
return; |
} |
if (brw->gen >= 6) { |
return emit_math1_gen6(opcode, dst, src); |
} else { |
return emit_math1_gen4(opcode, dst, src); |
} |
} |
void |
vec4_visitor::emit_math2_gen6(enum opcode opcode, |
dst_reg dst, src_reg src0, src_reg src1) |
{ |
src0 = fix_math_operand(src0); |
src1 = fix_math_operand(src1); |
if (dst.writemask != WRITEMASK_XYZW) { |
/* The gen6 math instruction must be align1, so we can't do |
* writemasks. |
*/ |
dst_reg temp_dst = dst_reg(this, glsl_type::vec4_type); |
temp_dst.type = dst.type; |
emit(opcode, temp_dst, src0, src1); |
emit(MOV(dst, src_reg(temp_dst))); |
} else { |
emit(opcode, dst, src0, src1); |
} |
} |
void |
vec4_visitor::emit_math2_gen4(enum opcode opcode, |
dst_reg dst, src_reg src0, src_reg src1) |
{ |
vec4_instruction *inst = emit(opcode, dst, src0, src1); |
inst->base_mrf = 1; |
inst->mlen = 2; |
} |
void |
vec4_visitor::emit_math(enum opcode opcode, |
dst_reg dst, src_reg src0, src_reg src1) |
{ |
switch (opcode) { |
case SHADER_OPCODE_POW: |
case SHADER_OPCODE_INT_QUOTIENT: |
case SHADER_OPCODE_INT_REMAINDER: |
break; |
default: |
assert(!"not reached: unsupported binary math opcode"); |
return; |
} |
if (brw->gen >= 6) { |
return emit_math2_gen6(opcode, dst, src0, src1); |
} else { |
return emit_math2_gen4(opcode, dst, src0, src1); |
} |
} |
void |
vec4_visitor::emit_pack_half_2x16(dst_reg dst, src_reg src0) |
{ |
if (brw->gen < 7) |
assert(!"ir_unop_pack_half_2x16 should be lowered"); |
assert(dst.type == BRW_REGISTER_TYPE_UD); |
assert(src0.type == BRW_REGISTER_TYPE_F); |
/* From the Ivybridge PRM, Vol4, Part3, Section 6.27 f32to16: |
* |
* Because this instruction does not have a 16-bit floating-point type, |
* the destination data type must be Word (W). |
* |
* The destination must be DWord-aligned and specify a horizontal stride |
* (HorzStride) of 2. The 16-bit result is stored in the lower word of |
* each destination channel and the upper word is not modified. |
* |
* The above restriction implies that the f32to16 instruction must use |
* align1 mode, because only in align1 mode is it possible to specify |
* horizontal stride. We choose here to defy the hardware docs and emit |
* align16 instructions. |
* |
* (I [chadv] did attempt to emit align1 instructions for VS f32to16 |
* instructions. I was partially successful in that the code passed all |
* tests. However, the code was dubiously correct and fragile, and the |
* tests were not harsh enough to probe that frailty. Not trusting the |
* code, I chose instead to remain in align16 mode in defiance of the hw |
* docs). |
* |
* I've [chadv] experimentally confirmed that, on gen7 hardware and the |
* simulator, emitting a f32to16 in align16 mode with UD as destination |
* data type is safe. The behavior differs from that specified in the PRM |
* in that the upper word of each destination channel is cleared to 0. |
*/ |
dst_reg tmp_dst(this, glsl_type::uvec2_type); |
src_reg tmp_src(tmp_dst); |
#if 0 |
/* Verify the undocumented behavior on which the following instructions |
* rely. If f32to16 fails to clear the upper word of the X and Y channels, |
* then the result of the bit-or instruction below will be incorrect. |
* |
* You should inspect the disasm output in order to verify that the MOV is |
* not optimized away. |
*/ |
emit(MOV(tmp_dst, src_reg(0x12345678u))); |
#endif |
/* Give tmp the form below, where "." means untouched. |
* |
* w z y x w z y x |
* |.|.|0x0000hhhh|0x0000llll|.|.|0x0000hhhh|0x0000llll| |
* |
* That the upper word of each write-channel be 0 is required for the |
* following bit-shift and bit-or instructions to work. Note that this |
* relies on the undocumented hardware behavior mentioned above. |
*/ |
tmp_dst.writemask = WRITEMASK_XY; |
emit(F32TO16(tmp_dst, src0)); |
/* Give the write-channels of dst the form: |
* 0xhhhh0000 |
*/ |
tmp_src.swizzle = SWIZZLE_Y; |
emit(SHL(dst, tmp_src, src_reg(16u))); |
/* Finally, give the write-channels of dst the form of packHalf2x16's |
* output: |
* 0xhhhhllll |
*/ |
tmp_src.swizzle = SWIZZLE_X; |
emit(OR(dst, src_reg(dst), tmp_src)); |
} |
void |
vec4_visitor::emit_unpack_half_2x16(dst_reg dst, src_reg src0) |
{ |
if (brw->gen < 7) |
assert(!"ir_unop_unpack_half_2x16 should be lowered"); |
assert(dst.type == BRW_REGISTER_TYPE_F); |
assert(src0.type == BRW_REGISTER_TYPE_UD); |
/* From the Ivybridge PRM, Vol4, Part3, Section 6.26 f16to32: |
* |
* Because this instruction does not have a 16-bit floating-point type, |
* the source data type must be Word (W). The destination type must be |
* F (Float). |
* |
* To use W as the source data type, we must adjust horizontal strides, |
* which is only possible in align1 mode. All my [chadv] attempts at |
* emitting align1 instructions for unpackHalf2x16 failed to pass the |
* Piglit tests, so I gave up. |
* |
* I've verified that, on gen7 hardware and the simulator, it is safe to |
* emit f16to32 in align16 mode with UD as source data type. |
*/ |
dst_reg tmp_dst(this, glsl_type::uvec2_type); |
src_reg tmp_src(tmp_dst); |
tmp_dst.writemask = WRITEMASK_X; |
emit(AND(tmp_dst, src0, src_reg(0xffffu))); |
tmp_dst.writemask = WRITEMASK_Y; |
emit(SHR(tmp_dst, src0, src_reg(16u))); |
dst.writemask = WRITEMASK_XY; |
emit(F16TO32(dst, tmp_src)); |
} |
void |
vec4_visitor::visit_instructions(const exec_list *list) |
{ |
foreach_list(node, list) { |
ir_instruction *ir = (ir_instruction *)node; |
base_ir = ir; |
ir->accept(this); |
} |
} |
static int |
type_size(const struct glsl_type *type) |
{ |
unsigned int i; |
int size; |
switch (type->base_type) { |
case GLSL_TYPE_UINT: |
case GLSL_TYPE_INT: |
case GLSL_TYPE_FLOAT: |
case GLSL_TYPE_BOOL: |
if (type->is_matrix()) { |
return type->matrix_columns; |
} else { |
/* Regardless of size of vector, it gets a vec4. This is bad |
* packing for things like floats, but otherwise arrays become a |
* mess. Hopefully a later pass over the code can pack scalars |
* down if appropriate. |
*/ |
return 1; |
} |
case GLSL_TYPE_ARRAY: |
assert(type->length > 0); |
return type_size(type->fields.array) * type->length; |
case GLSL_TYPE_STRUCT: |
size = 0; |
for (i = 0; i < type->length; i++) { |
size += type_size(type->fields.structure[i].type); |
} |
return size; |
case GLSL_TYPE_SAMPLER: |
/* Samplers take up one slot in UNIFORMS[], but they're baked in |
* at link time. |
*/ |
return 1; |
case GLSL_TYPE_VOID: |
case GLSL_TYPE_ERROR: |
case GLSL_TYPE_INTERFACE: |
assert(0); |
break; |
} |
return 0; |
} |
int |
vec4_visitor::virtual_grf_alloc(int size) |
{ |
if (virtual_grf_array_size <= virtual_grf_count) { |
if (virtual_grf_array_size == 0) |
virtual_grf_array_size = 16; |
else |
virtual_grf_array_size *= 2; |
virtual_grf_sizes = reralloc(mem_ctx, virtual_grf_sizes, int, |
virtual_grf_array_size); |
virtual_grf_reg_map = reralloc(mem_ctx, virtual_grf_reg_map, int, |
virtual_grf_array_size); |
} |
virtual_grf_reg_map[virtual_grf_count] = virtual_grf_reg_count; |
virtual_grf_reg_count += size; |
virtual_grf_sizes[virtual_grf_count] = size; |
return virtual_grf_count++; |
} |
src_reg::src_reg(class vec4_visitor *v, const struct glsl_type *type) |
{ |
init(); |
this->file = GRF; |
this->reg = v->virtual_grf_alloc(type_size(type)); |
if (type->is_array() || type->is_record()) { |
this->swizzle = BRW_SWIZZLE_NOOP; |
} else { |
this->swizzle = swizzle_for_size(type->vector_elements); |
} |
this->type = brw_type_for_base_type(type); |
} |
dst_reg::dst_reg(class vec4_visitor *v, const struct glsl_type *type) |
{ |
init(); |
this->file = GRF; |
this->reg = v->virtual_grf_alloc(type_size(type)); |
if (type->is_array() || type->is_record()) { |
this->writemask = WRITEMASK_XYZW; |
} else { |
this->writemask = (1 << type->vector_elements) - 1; |
} |
this->type = brw_type_for_base_type(type); |
} |
/* Our support for uniforms is piggy-backed on the struct |
* gl_fragment_program, because that's where the values actually |
* get stored, rather than in some global gl_shader_program uniform |
* store. |
*/ |
void |
vec4_visitor::setup_uniform_values(ir_variable *ir) |
{ |
int namelen = strlen(ir->name); |
/* The data for our (non-builtin) uniforms is stored in a series of |
* gl_uniform_driver_storage structs for each subcomponent that |
* glGetUniformLocation() could name. We know it's been set up in the same |
* order we'd walk the type, so walk the list of storage and find anything |
* with our name, or the prefix of a component that starts with our name. |
*/ |
for (unsigned u = 0; u < shader_prog->NumUserUniformStorage; u++) { |
struct gl_uniform_storage *storage = &shader_prog->UniformStorage[u]; |
if (strncmp(ir->name, storage->name, namelen) != 0 || |
(storage->name[namelen] != 0 && |
storage->name[namelen] != '.' && |
storage->name[namelen] != '[')) { |
continue; |
} |
gl_constant_value *components = storage->storage; |
unsigned vector_count = (MAX2(storage->array_elements, 1) * |
storage->type->matrix_columns); |
for (unsigned s = 0; s < vector_count; s++) { |
uniform_vector_size[uniforms] = storage->type->vector_elements; |
int i; |
for (i = 0; i < uniform_vector_size[uniforms]; i++) { |
prog_data->param[uniforms * 4 + i] = &components->f; |
components++; |
} |
for (; i < 4; i++) { |
static float zero = 0; |
prog_data->param[uniforms * 4 + i] = &zero; |
} |
uniforms++; |
} |
} |
} |
void |
vec4_visitor::setup_uniform_clipplane_values() |
{ |
gl_clip_plane *clip_planes = brw_select_clip_planes(ctx); |
if (brw->gen < 6) { |
/* Pre-Gen6, we compact clip planes. For example, if the user |
* enables just clip planes 0, 1, and 3, we will enable clip planes |
* 0, 1, and 2 in the hardware, and we'll move clip plane 3 to clip |
* plane 2. This simplifies the implementation of the Gen6 clip |
* thread. |
*/ |
int compacted_clipplane_index = 0; |
for (int i = 0; i < MAX_CLIP_PLANES; ++i) { |
if (!(key->userclip_planes_enabled_gen_4_5 & (1 << i))) |
continue; |
this->uniform_vector_size[this->uniforms] = 4; |
this->userplane[compacted_clipplane_index] = dst_reg(UNIFORM, this->uniforms); |
this->userplane[compacted_clipplane_index].type = BRW_REGISTER_TYPE_F; |
for (int j = 0; j < 4; ++j) { |
prog_data->param[this->uniforms * 4 + j] = &clip_planes[i][j]; |
} |
++compacted_clipplane_index; |
++this->uniforms; |
} |
} else { |
/* In Gen6 and later, we don't compact clip planes, because this |
* simplifies the implementation of gl_ClipDistance. |
*/ |
for (int i = 0; i < key->nr_userclip_plane_consts; ++i) { |
this->uniform_vector_size[this->uniforms] = 4; |
this->userplane[i] = dst_reg(UNIFORM, this->uniforms); |
this->userplane[i].type = BRW_REGISTER_TYPE_F; |
for (int j = 0; j < 4; ++j) { |
prog_data->param[this->uniforms * 4 + j] = &clip_planes[i][j]; |
} |
++this->uniforms; |
} |
} |
} |
/* Our support for builtin uniforms is even scarier than non-builtin. |
* It sits on top of the PROG_STATE_VAR parameters that are |
* automatically updated from GL context state. |
*/ |
void |
vec4_visitor::setup_builtin_uniform_values(ir_variable *ir) |
{ |
const ir_state_slot *const slots = ir->state_slots; |
assert(ir->state_slots != NULL); |
for (unsigned int i = 0; i < ir->num_state_slots; i++) { |
/* This state reference has already been setup by ir_to_mesa, |
* but we'll get the same index back here. We can reference |
* ParameterValues directly, since unlike brw_fs.cpp, we never |
* add new state references during compile. |
*/ |
int index = _mesa_add_state_reference(this->prog->Parameters, |
(gl_state_index *)slots[i].tokens); |
float *values = &this->prog->Parameters->ParameterValues[index][0].f; |
this->uniform_vector_size[this->uniforms] = 0; |
/* Add each of the unique swizzled channels of the element. |
* This will end up matching the size of the glsl_type of this field. |
*/ |
int last_swiz = -1; |
for (unsigned int j = 0; j < 4; j++) { |
int swiz = GET_SWZ(slots[i].swizzle, j); |
last_swiz = swiz; |
prog_data->param[this->uniforms * 4 + j] = &values[swiz]; |
if (swiz <= last_swiz) |
this->uniform_vector_size[this->uniforms]++; |
} |
this->uniforms++; |
} |
} |
dst_reg * |
vec4_visitor::variable_storage(ir_variable *var) |
{ |
return (dst_reg *)hash_table_find(this->variable_ht, var); |
} |
void |
vec4_visitor::emit_bool_to_cond_code(ir_rvalue *ir, uint32_t *predicate) |
{ |
ir_expression *expr = ir->as_expression(); |
*predicate = BRW_PREDICATE_NORMAL; |
if (expr) { |
src_reg op[2]; |
vec4_instruction *inst; |
assert(expr->get_num_operands() <= 2); |
for (unsigned int i = 0; i < expr->get_num_operands(); i++) { |
expr->operands[i]->accept(this); |
op[i] = this->result; |
resolve_ud_negate(&op[i]); |
} |
switch (expr->operation) { |
case ir_unop_logic_not: |
inst = emit(AND(dst_null_d(), op[0], src_reg(1))); |
inst->conditional_mod = BRW_CONDITIONAL_Z; |
break; |
case ir_binop_logic_xor: |
inst = emit(XOR(dst_null_d(), op[0], op[1])); |
inst->conditional_mod = BRW_CONDITIONAL_NZ; |
break; |
case ir_binop_logic_or: |
inst = emit(OR(dst_null_d(), op[0], op[1])); |
inst->conditional_mod = BRW_CONDITIONAL_NZ; |
break; |
case ir_binop_logic_and: |
inst = emit(AND(dst_null_d(), op[0], op[1])); |
inst->conditional_mod = BRW_CONDITIONAL_NZ; |
break; |
case ir_unop_f2b: |
if (brw->gen >= 6) { |
emit(CMP(dst_null_d(), op[0], src_reg(0.0f), BRW_CONDITIONAL_NZ)); |
} else { |
inst = emit(MOV(dst_null_f(), op[0])); |
inst->conditional_mod = BRW_CONDITIONAL_NZ; |
} |
break; |
case ir_unop_i2b: |
if (brw->gen >= 6) { |
emit(CMP(dst_null_d(), op[0], src_reg(0), BRW_CONDITIONAL_NZ)); |
} else { |
inst = emit(MOV(dst_null_d(), op[0])); |
inst->conditional_mod = BRW_CONDITIONAL_NZ; |
} |
break; |
case ir_binop_all_equal: |
inst = emit(CMP(dst_null_d(), op[0], op[1], BRW_CONDITIONAL_Z)); |
*predicate = BRW_PREDICATE_ALIGN16_ALL4H; |
break; |
case ir_binop_any_nequal: |
inst = emit(CMP(dst_null_d(), op[0], op[1], BRW_CONDITIONAL_NZ)); |
*predicate = BRW_PREDICATE_ALIGN16_ANY4H; |
break; |
case ir_unop_any: |
inst = emit(CMP(dst_null_d(), op[0], src_reg(0), BRW_CONDITIONAL_NZ)); |
*predicate = BRW_PREDICATE_ALIGN16_ANY4H; |
break; |
case ir_binop_greater: |
case ir_binop_gequal: |
case ir_binop_less: |
case ir_binop_lequal: |
case ir_binop_equal: |
case ir_binop_nequal: |
emit(CMP(dst_null_d(), op[0], op[1], |
brw_conditional_for_comparison(expr->operation))); |
break; |
default: |
assert(!"not reached"); |
break; |
} |
return; |
} |
ir->accept(this); |
resolve_ud_negate(&this->result); |
if (brw->gen >= 6) { |
vec4_instruction *inst = emit(AND(dst_null_d(), |
this->result, src_reg(1))); |
inst->conditional_mod = BRW_CONDITIONAL_NZ; |
} else { |
vec4_instruction *inst = emit(MOV(dst_null_d(), this->result)); |
inst->conditional_mod = BRW_CONDITIONAL_NZ; |
} |
} |
/** |
* Emit a gen6 IF statement with the comparison folded into the IF |
* instruction. |
*/ |
void |
vec4_visitor::emit_if_gen6(ir_if *ir) |
{ |
ir_expression *expr = ir->condition->as_expression(); |
if (expr) { |
src_reg op[2]; |
dst_reg temp; |
assert(expr->get_num_operands() <= 2); |
for (unsigned int i = 0; i < expr->get_num_operands(); i++) { |
expr->operands[i]->accept(this); |
op[i] = this->result; |
} |
switch (expr->operation) { |
case ir_unop_logic_not: |
emit(IF(op[0], src_reg(0), BRW_CONDITIONAL_Z)); |
return; |
case ir_binop_logic_xor: |
emit(IF(op[0], op[1], BRW_CONDITIONAL_NZ)); |
return; |
case ir_binop_logic_or: |
temp = dst_reg(this, glsl_type::bool_type); |
emit(OR(temp, op[0], op[1])); |
emit(IF(src_reg(temp), src_reg(0), BRW_CONDITIONAL_NZ)); |
return; |
case ir_binop_logic_and: |
temp = dst_reg(this, glsl_type::bool_type); |
emit(AND(temp, op[0], op[1])); |
emit(IF(src_reg(temp), src_reg(0), BRW_CONDITIONAL_NZ)); |
return; |
case ir_unop_f2b: |
emit(IF(op[0], src_reg(0), BRW_CONDITIONAL_NZ)); |
return; |
case ir_unop_i2b: |
emit(IF(op[0], src_reg(0), BRW_CONDITIONAL_NZ)); |
return; |
case ir_binop_greater: |
case ir_binop_gequal: |
case ir_binop_less: |
case ir_binop_lequal: |
case ir_binop_equal: |
case ir_binop_nequal: |
emit(IF(op[0], op[1], |
brw_conditional_for_comparison(expr->operation))); |
return; |
case ir_binop_all_equal: |
emit(CMP(dst_null_d(), op[0], op[1], BRW_CONDITIONAL_Z)); |
emit(IF(BRW_PREDICATE_ALIGN16_ALL4H)); |
return; |
case ir_binop_any_nequal: |
emit(CMP(dst_null_d(), op[0], op[1], BRW_CONDITIONAL_NZ)); |
emit(IF(BRW_PREDICATE_ALIGN16_ANY4H)); |
return; |
case ir_unop_any: |
emit(CMP(dst_null_d(), op[0], src_reg(0), BRW_CONDITIONAL_NZ)); |
emit(IF(BRW_PREDICATE_ALIGN16_ANY4H)); |
return; |
default: |
assert(!"not reached"); |
emit(IF(op[0], src_reg(0), BRW_CONDITIONAL_NZ)); |
return; |
} |
return; |
} |
ir->condition->accept(this); |
emit(IF(this->result, src_reg(0), BRW_CONDITIONAL_NZ)); |
} |
static dst_reg |
with_writemask(dst_reg const & r, int mask) |
{ |
dst_reg result = r; |
result.writemask = mask; |
return result; |
} |
void |
vec4_vs_visitor::emit_prolog() |
{ |
dst_reg sign_recovery_shift; |
dst_reg normalize_factor; |
dst_reg es3_normalize_factor; |
for (int i = 0; i < VERT_ATTRIB_MAX; i++) { |
if (vs_prog_data->inputs_read & BITFIELD64_BIT(i)) { |
uint8_t wa_flags = vs_compile->key.gl_attrib_wa_flags[i]; |
dst_reg reg(ATTR, i); |
dst_reg reg_d = reg; |
reg_d.type = BRW_REGISTER_TYPE_D; |
dst_reg reg_ud = reg; |
reg_ud.type = BRW_REGISTER_TYPE_UD; |
/* Do GL_FIXED rescaling for GLES2.0. Our GL_FIXED attributes |
* come in as floating point conversions of the integer values. |
*/ |
if (wa_flags & BRW_ATTRIB_WA_COMPONENT_MASK) { |
dst_reg dst = reg; |
dst.type = brw_type_for_base_type(glsl_type::vec4_type); |
dst.writemask = (1 << (wa_flags & BRW_ATTRIB_WA_COMPONENT_MASK)) - 1; |
emit(MUL(dst, src_reg(dst), src_reg(1.0f / 65536.0f))); |
} |
/* Do sign recovery for 2101010 formats if required. */ |
if (wa_flags & BRW_ATTRIB_WA_SIGN) { |
if (sign_recovery_shift.file == BAD_FILE) { |
/* shift constant: <22,22,22,30> */ |
sign_recovery_shift = dst_reg(this, glsl_type::uvec4_type); |
emit(MOV(with_writemask(sign_recovery_shift, WRITEMASK_XYZ), src_reg(22u))); |
emit(MOV(with_writemask(sign_recovery_shift, WRITEMASK_W), src_reg(30u))); |
} |
emit(SHL(reg_ud, src_reg(reg_ud), src_reg(sign_recovery_shift))); |
emit(ASR(reg_d, src_reg(reg_d), src_reg(sign_recovery_shift))); |
} |
/* Apply BGRA swizzle if required. */ |
if (wa_flags & BRW_ATTRIB_WA_BGRA) { |
src_reg temp = src_reg(reg); |
temp.swizzle = BRW_SWIZZLE4(2,1,0,3); |
emit(MOV(reg, temp)); |
} |
if (wa_flags & BRW_ATTRIB_WA_NORMALIZE) { |
/* ES 3.0 has different rules for converting signed normalized |
* fixed-point numbers than desktop GL. |
*/ |
if (_mesa_is_gles3(ctx) && (wa_flags & BRW_ATTRIB_WA_SIGN)) { |
/* According to equation 2.2 of the ES 3.0 specification, |
* signed normalization conversion is done by: |
* |
* f = c / (2^(b-1)-1) |
*/ |
if (es3_normalize_factor.file == BAD_FILE) { |
/* mul constant: 1 / (2^(b-1) - 1) */ |
es3_normalize_factor = dst_reg(this, glsl_type::vec4_type); |
emit(MOV(with_writemask(es3_normalize_factor, WRITEMASK_XYZ), |
src_reg(1.0f / ((1<<9) - 1)))); |
emit(MOV(with_writemask(es3_normalize_factor, WRITEMASK_W), |
src_reg(1.0f / ((1<<1) - 1)))); |
} |
dst_reg dst = reg; |
dst.type = brw_type_for_base_type(glsl_type::vec4_type); |
emit(MOV(dst, src_reg(reg_d))); |
emit(MUL(dst, src_reg(dst), src_reg(es3_normalize_factor))); |
emit_minmax(BRW_CONDITIONAL_G, dst, src_reg(dst), src_reg(-1.0f)); |
} else { |
/* The following equations are from the OpenGL 3.2 specification: |
* |
* 2.1 unsigned normalization |
* f = c/(2^n-1) |
* |
* 2.2 signed normalization |
* f = (2c+1)/(2^n-1) |
* |
* Both of these share a common divisor, which is represented by |
* "normalize_factor" in the code below. |
*/ |
if (normalize_factor.file == BAD_FILE) { |
/* 1 / (2^b - 1) for b=<10,10,10,2> */ |
normalize_factor = dst_reg(this, glsl_type::vec4_type); |
emit(MOV(with_writemask(normalize_factor, WRITEMASK_XYZ), |
src_reg(1.0f / ((1<<10) - 1)))); |
emit(MOV(with_writemask(normalize_factor, WRITEMASK_W), |
src_reg(1.0f / ((1<<2) - 1)))); |
} |
dst_reg dst = reg; |
dst.type = brw_type_for_base_type(glsl_type::vec4_type); |
emit(MOV(dst, src_reg((wa_flags & BRW_ATTRIB_WA_SIGN) ? reg_d : reg_ud))); |
/* For signed normalization, we want the numerator to be 2c+1. */ |
if (wa_flags & BRW_ATTRIB_WA_SIGN) { |
emit(MUL(dst, src_reg(dst), src_reg(2.0f))); |
emit(ADD(dst, src_reg(dst), src_reg(1.0f))); |
} |
emit(MUL(dst, src_reg(dst), src_reg(normalize_factor))); |
} |
} |
if (wa_flags & BRW_ATTRIB_WA_SCALE) { |
dst_reg dst = reg; |
dst.type = brw_type_for_base_type(glsl_type::vec4_type); |
emit(MOV(dst, src_reg((wa_flags & BRW_ATTRIB_WA_SIGN) ? reg_d : reg_ud))); |
} |
} |
} |
} |
dst_reg * |
vec4_vs_visitor::make_reg_for_system_value(ir_variable *ir) |
{ |
/* VertexID is stored by the VF as the last vertex element, but |
* we don't represent it with a flag in inputs_read, so we call |
* it VERT_ATTRIB_MAX, which setup_attributes() picks up on. |
*/ |
dst_reg *reg = new(mem_ctx) dst_reg(ATTR, VERT_ATTRIB_MAX); |
vs_prog_data->uses_vertexid = true; |
switch (ir->location) { |
case SYSTEM_VALUE_VERTEX_ID: |
reg->writemask = WRITEMASK_X; |
break; |
case SYSTEM_VALUE_INSTANCE_ID: |
reg->writemask = WRITEMASK_Y; |
break; |
default: |
assert(!"not reached"); |
break; |
} |
return reg; |
} |
void |
vec4_visitor::visit(ir_variable *ir) |
{ |
dst_reg *reg = NULL; |
if (variable_storage(ir)) |
return; |
switch (ir->mode) { |
case ir_var_shader_in: |
reg = new(mem_ctx) dst_reg(ATTR, ir->location); |
break; |
case ir_var_shader_out: |
reg = new(mem_ctx) dst_reg(this, ir->type); |
for (int i = 0; i < type_size(ir->type); i++) { |
output_reg[ir->location + i] = *reg; |
output_reg[ir->location + i].reg_offset = i; |
output_reg[ir->location + i].type = |
brw_type_for_base_type(ir->type->get_scalar_type()); |
output_reg_annotation[ir->location + i] = ir->name; |
} |
break; |
case ir_var_auto: |
case ir_var_temporary: |
reg = new(mem_ctx) dst_reg(this, ir->type); |
break; |
case ir_var_uniform: |
reg = new(this->mem_ctx) dst_reg(UNIFORM, this->uniforms); |
/* Thanks to the lower_ubo_reference pass, we will see only |
* ir_binop_ubo_load expressions and not ir_dereference_variable for UBO |
* variables, so no need for them to be in variable_ht. |
*/ |
if (ir->is_in_uniform_block()) |
return; |
/* Track how big the whole uniform variable is, in case we need to put a |
* copy of its data into pull constants for array access. |
*/ |
this->uniform_size[this->uniforms] = type_size(ir->type); |
if (!strncmp(ir->name, "gl_", 3)) { |
setup_builtin_uniform_values(ir); |
} else { |
setup_uniform_values(ir); |
} |
break; |
case ir_var_system_value: |
reg = make_reg_for_system_value(ir); |
break; |
default: |
assert(!"not reached"); |
} |
reg->type = brw_type_for_base_type(ir->type); |
hash_table_insert(this->variable_ht, reg, ir); |
} |
void |
vec4_visitor::visit(ir_loop *ir) |
{ |
dst_reg counter; |
/* We don't want debugging output to print the whole body of the |
* loop as the annotation. |
*/ |
this->base_ir = NULL; |
if (ir->counter != NULL) { |
this->base_ir = ir->counter; |
ir->counter->accept(this); |
counter = *(variable_storage(ir->counter)); |
if (ir->from != NULL) { |
this->base_ir = ir->from; |
ir->from->accept(this); |
emit(MOV(counter, this->result)); |
} |
} |
emit(BRW_OPCODE_DO); |
if (ir->to) { |
this->base_ir = ir->to; |
ir->to->accept(this); |
emit(CMP(dst_null_d(), src_reg(counter), this->result, |
brw_conditional_for_comparison(ir->cmp))); |
vec4_instruction *inst = emit(BRW_OPCODE_BREAK); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
visit_instructions(&ir->body_instructions); |
if (ir->increment) { |
this->base_ir = ir->increment; |
ir->increment->accept(this); |
emit(ADD(counter, src_reg(counter), this->result)); |
} |
emit(BRW_OPCODE_WHILE); |
} |
void |
vec4_visitor::visit(ir_loop_jump *ir) |
{ |
switch (ir->mode) { |
case ir_loop_jump::jump_break: |
emit(BRW_OPCODE_BREAK); |
break; |
case ir_loop_jump::jump_continue: |
emit(BRW_OPCODE_CONTINUE); |
break; |
} |
} |
void |
vec4_visitor::visit(ir_function_signature *ir) |
{ |
assert(0); |
(void)ir; |
} |
void |
vec4_visitor::visit(ir_function *ir) |
{ |
/* Ignore function bodies other than main() -- we shouldn't see calls to |
* them since they should all be inlined. |
*/ |
if (strcmp(ir->name, "main") == 0) { |
const ir_function_signature *sig; |
exec_list empty; |
sig = ir->matching_signature(&empty); |
assert(sig); |
visit_instructions(&sig->body); |
} |
} |
bool |
vec4_visitor::try_emit_sat(ir_expression *ir) |
{ |
ir_rvalue *sat_src = ir->as_rvalue_to_saturate(); |
if (!sat_src) |
return false; |
sat_src->accept(this); |
src_reg src = this->result; |
this->result = src_reg(this, ir->type); |
vec4_instruction *inst; |
inst = emit(MOV(dst_reg(this->result), src)); |
inst->saturate = true; |
return true; |
} |
bool |
vec4_visitor::try_emit_mad(ir_expression *ir, int mul_arg) |
{ |
/* 3-src instructions were introduced in gen6. */ |
if (brw->gen < 6) |
return false; |
/* MAD can only handle floating-point data. */ |
if (ir->type->base_type != GLSL_TYPE_FLOAT) |
return false; |
ir_rvalue *nonmul = ir->operands[1 - mul_arg]; |
ir_expression *mul = ir->operands[mul_arg]->as_expression(); |
if (!mul || mul->operation != ir_binop_mul) |
return false; |
nonmul->accept(this); |
src_reg src0 = fix_3src_operand(this->result); |
mul->operands[0]->accept(this); |
src_reg src1 = fix_3src_operand(this->result); |
mul->operands[1]->accept(this); |
src_reg src2 = fix_3src_operand(this->result); |
this->result = src_reg(this, ir->type); |
emit(BRW_OPCODE_MAD, dst_reg(this->result), src0, src1, src2); |
return true; |
} |
void |
vec4_visitor::emit_bool_comparison(unsigned int op, |
dst_reg dst, src_reg src0, src_reg src1) |
{ |
/* original gen4 does destination conversion before comparison. */ |
if (brw->gen < 5) |
dst.type = src0.type; |
emit(CMP(dst, src0, src1, brw_conditional_for_comparison(op))); |
dst.type = BRW_REGISTER_TYPE_D; |
emit(AND(dst, src_reg(dst), src_reg(0x1))); |
} |
void |
vec4_visitor::emit_minmax(uint32_t conditionalmod, dst_reg dst, |
src_reg src0, src_reg src1) |
{ |
vec4_instruction *inst; |
if (brw->gen >= 6) { |
inst = emit(BRW_OPCODE_SEL, dst, src0, src1); |
inst->conditional_mod = conditionalmod; |
} else { |
emit(CMP(dst, src0, src1, conditionalmod)); |
inst = emit(BRW_OPCODE_SEL, dst, src0, src1); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
} |
static bool |
is_16bit_constant(ir_rvalue *rvalue) |
{ |
ir_constant *constant = rvalue->as_constant(); |
if (!constant) |
return false; |
if (constant->type != glsl_type::int_type && |
constant->type != glsl_type::uint_type) |
return false; |
return constant->value.u[0] < (1 << 16); |
} |
void |
vec4_visitor::visit(ir_expression *ir) |
{ |
unsigned int operand; |
src_reg op[Elements(ir->operands)]; |
src_reg result_src; |
dst_reg result_dst; |
vec4_instruction *inst; |
if (try_emit_sat(ir)) |
return; |
if (ir->operation == ir_binop_add) { |
if (try_emit_mad(ir, 0) || try_emit_mad(ir, 1)) |
return; |
} |
for (operand = 0; operand < ir->get_num_operands(); operand++) { |
this->result.file = BAD_FILE; |
ir->operands[operand]->accept(this); |
if (this->result.file == BAD_FILE) { |
printf("Failed to get tree for expression operand:\n"); |
ir->operands[operand]->print(); |
exit(1); |
} |
op[operand] = this->result; |
/* Matrix expression operands should have been broken down to vector |
* operations already. |
*/ |
assert(!ir->operands[operand]->type->is_matrix()); |
} |
int vector_elements = ir->operands[0]->type->vector_elements; |
if (ir->operands[1]) { |
vector_elements = MAX2(vector_elements, |
ir->operands[1]->type->vector_elements); |
} |
this->result.file = BAD_FILE; |
/* Storage for our result. Ideally for an assignment we'd be using |
* the actual storage for the result here, instead. |
*/ |
result_src = src_reg(this, ir->type); |
/* convenience for the emit functions below. */ |
result_dst = dst_reg(result_src); |
/* If nothing special happens, this is the result. */ |
this->result = result_src; |
/* Limit writes to the channels that will be used by result_src later. |
* This does limit this temp's use as a temporary for multi-instruction |
* sequences. |
*/ |
result_dst.writemask = (1 << ir->type->vector_elements) - 1; |
switch (ir->operation) { |
case ir_unop_logic_not: |
/* Note that BRW_OPCODE_NOT is not appropriate here, since it is |
* ones complement of the whole register, not just bit 0. |
*/ |
emit(XOR(result_dst, op[0], src_reg(1))); |
break; |
case ir_unop_neg: |
op[0].negate = !op[0].negate; |
emit(MOV(result_dst, op[0])); |
break; |
case ir_unop_abs: |
op[0].abs = true; |
op[0].negate = false; |
emit(MOV(result_dst, op[0])); |
break; |
case ir_unop_sign: |
emit(MOV(result_dst, src_reg(0.0f))); |
emit(CMP(dst_null_d(), op[0], src_reg(0.0f), BRW_CONDITIONAL_G)); |
inst = emit(MOV(result_dst, src_reg(1.0f))); |
inst->predicate = BRW_PREDICATE_NORMAL; |
emit(CMP(dst_null_d(), op[0], src_reg(0.0f), BRW_CONDITIONAL_L)); |
inst = emit(MOV(result_dst, src_reg(-1.0f))); |
inst->predicate = BRW_PREDICATE_NORMAL; |
break; |
case ir_unop_rcp: |
emit_math(SHADER_OPCODE_RCP, result_dst, op[0]); |
break; |
case ir_unop_exp2: |
emit_math(SHADER_OPCODE_EXP2, result_dst, op[0]); |
break; |
case ir_unop_log2: |
emit_math(SHADER_OPCODE_LOG2, result_dst, op[0]); |
break; |
case ir_unop_exp: |
case ir_unop_log: |
assert(!"not reached: should be handled by ir_explog_to_explog2"); |
break; |
case ir_unop_sin: |
case ir_unop_sin_reduced: |
emit_math(SHADER_OPCODE_SIN, result_dst, op[0]); |
break; |
case ir_unop_cos: |
case ir_unop_cos_reduced: |
emit_math(SHADER_OPCODE_COS, result_dst, op[0]); |
break; |
case ir_unop_dFdx: |
case ir_unop_dFdy: |
assert(!"derivatives not valid in vertex shader"); |
break; |
case ir_unop_bitfield_reverse: |
emit(BFREV(result_dst, op[0])); |
break; |
case ir_unop_bit_count: |
emit(CBIT(result_dst, op[0])); |
break; |
case ir_unop_find_msb: { |
src_reg temp = src_reg(this, glsl_type::uint_type); |
inst = emit(FBH(dst_reg(temp), op[0])); |
inst->dst.writemask = WRITEMASK_XYZW; |
/* FBH counts from the MSB side, while GLSL's findMSB() wants the count |
* from the LSB side. If FBH didn't return an error (0xFFFFFFFF), then |
* subtract the result from 31 to convert the MSB count into an LSB count. |
*/ |
/* FBH only supports UD type for dst, so use a MOV to convert UD to D. */ |
temp.swizzle = BRW_SWIZZLE_NOOP; |
emit(MOV(result_dst, temp)); |
src_reg src_tmp = src_reg(result_dst); |
emit(CMP(dst_null_d(), src_tmp, src_reg(-1), BRW_CONDITIONAL_NZ)); |
src_tmp.negate = true; |
inst = emit(ADD(result_dst, src_tmp, src_reg(31))); |
inst->predicate = BRW_PREDICATE_NORMAL; |
break; |
} |
case ir_unop_find_lsb: |
emit(FBL(result_dst, op[0])); |
break; |
case ir_unop_noise: |
assert(!"not reached: should be handled by lower_noise"); |
break; |
case ir_binop_add: |
emit(ADD(result_dst, op[0], op[1])); |
break; |
case ir_binop_sub: |
assert(!"not reached: should be handled by ir_sub_to_add_neg"); |
break; |
case ir_binop_mul: |
if (ir->type->is_integer()) { |
/* For integer multiplication, the MUL uses the low 16 bits of one of |
* the operands (src0 through SNB, src1 on IVB and later). The MACH |
* accumulates in the contribution of the upper 16 bits of that |
* operand. If we can determine that one of the args is in the low |
* 16 bits, though, we can just emit a single MUL. |
*/ |
if (is_16bit_constant(ir->operands[0])) { |
if (brw->gen < 7) |
emit(MUL(result_dst, op[0], op[1])); |
else |
emit(MUL(result_dst, op[1], op[0])); |
} else if (is_16bit_constant(ir->operands[1])) { |
if (brw->gen < 7) |
emit(MUL(result_dst, op[1], op[0])); |
else |
emit(MUL(result_dst, op[0], op[1])); |
} else { |
struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_D); |
emit(MUL(acc, op[0], op[1])); |
emit(MACH(dst_null_d(), op[0], op[1])); |
emit(MOV(result_dst, src_reg(acc))); |
} |
} else { |
emit(MUL(result_dst, op[0], op[1])); |
} |
break; |
case ir_binop_div: |
/* Floating point should be lowered by DIV_TO_MUL_RCP in the compiler. */ |
assert(ir->type->is_integer()); |
emit_math(SHADER_OPCODE_INT_QUOTIENT, result_dst, op[0], op[1]); |
break; |
case ir_binop_mod: |
/* Floating point should be lowered by MOD_TO_FRACT in the compiler. */ |
assert(ir->type->is_integer()); |
emit_math(SHADER_OPCODE_INT_REMAINDER, result_dst, op[0], op[1]); |
break; |
case ir_binop_less: |
case ir_binop_greater: |
case ir_binop_lequal: |
case ir_binop_gequal: |
case ir_binop_equal: |
case ir_binop_nequal: { |
emit(CMP(result_dst, op[0], op[1], |
brw_conditional_for_comparison(ir->operation))); |
emit(AND(result_dst, result_src, src_reg(0x1))); |
break; |
} |
case ir_binop_all_equal: |
/* "==" operator producing a scalar boolean. */ |
if (ir->operands[0]->type->is_vector() || |
ir->operands[1]->type->is_vector()) { |
emit(CMP(dst_null_d(), op[0], op[1], BRW_CONDITIONAL_Z)); |
emit(MOV(result_dst, src_reg(0))); |
inst = emit(MOV(result_dst, src_reg(1))); |
inst->predicate = BRW_PREDICATE_ALIGN16_ALL4H; |
} else { |
emit(CMP(result_dst, op[0], op[1], BRW_CONDITIONAL_Z)); |
emit(AND(result_dst, result_src, src_reg(0x1))); |
} |
break; |
case ir_binop_any_nequal: |
/* "!=" operator producing a scalar boolean. */ |
if (ir->operands[0]->type->is_vector() || |
ir->operands[1]->type->is_vector()) { |
emit(CMP(dst_null_d(), op[0], op[1], BRW_CONDITIONAL_NZ)); |
emit(MOV(result_dst, src_reg(0))); |
inst = emit(MOV(result_dst, src_reg(1))); |
inst->predicate = BRW_PREDICATE_ALIGN16_ANY4H; |
} else { |
emit(CMP(result_dst, op[0], op[1], BRW_CONDITIONAL_NZ)); |
emit(AND(result_dst, result_src, src_reg(0x1))); |
} |
break; |
case ir_unop_any: |
emit(CMP(dst_null_d(), op[0], src_reg(0), BRW_CONDITIONAL_NZ)); |
emit(MOV(result_dst, src_reg(0))); |
inst = emit(MOV(result_dst, src_reg(1))); |
inst->predicate = BRW_PREDICATE_ALIGN16_ANY4H; |
break; |
case ir_binop_logic_xor: |
emit(XOR(result_dst, op[0], op[1])); |
break; |
case ir_binop_logic_or: |
emit(OR(result_dst, op[0], op[1])); |
break; |
case ir_binop_logic_and: |
emit(AND(result_dst, op[0], op[1])); |
break; |
case ir_binop_dot: |
assert(ir->operands[0]->type->is_vector()); |
assert(ir->operands[0]->type == ir->operands[1]->type); |
emit_dp(result_dst, op[0], op[1], ir->operands[0]->type->vector_elements); |
break; |
case ir_unop_sqrt: |
emit_math(SHADER_OPCODE_SQRT, result_dst, op[0]); |
break; |
case ir_unop_rsq: |
emit_math(SHADER_OPCODE_RSQ, result_dst, op[0]); |
break; |
case ir_unop_bitcast_i2f: |
case ir_unop_bitcast_u2f: |
this->result = op[0]; |
this->result.type = BRW_REGISTER_TYPE_F; |
break; |
case ir_unop_bitcast_f2i: |
this->result = op[0]; |
this->result.type = BRW_REGISTER_TYPE_D; |
break; |
case ir_unop_bitcast_f2u: |
this->result = op[0]; |
this->result.type = BRW_REGISTER_TYPE_UD; |
break; |
case ir_unop_i2f: |
case ir_unop_i2u: |
case ir_unop_u2i: |
case ir_unop_u2f: |
case ir_unop_b2f: |
case ir_unop_b2i: |
case ir_unop_f2i: |
case ir_unop_f2u: |
emit(MOV(result_dst, op[0])); |
break; |
case ir_unop_f2b: |
case ir_unop_i2b: { |
emit(CMP(result_dst, op[0], src_reg(0.0f), BRW_CONDITIONAL_NZ)); |
emit(AND(result_dst, result_src, src_reg(1))); |
break; |
} |
case ir_unop_trunc: |
emit(RNDZ(result_dst, op[0])); |
break; |
case ir_unop_ceil: |
op[0].negate = !op[0].negate; |
inst = emit(RNDD(result_dst, op[0])); |
this->result.negate = true; |
break; |
case ir_unop_floor: |
inst = emit(RNDD(result_dst, op[0])); |
break; |
case ir_unop_fract: |
inst = emit(FRC(result_dst, op[0])); |
break; |
case ir_unop_round_even: |
emit(RNDE(result_dst, op[0])); |
break; |
case ir_binop_min: |
emit_minmax(BRW_CONDITIONAL_L, result_dst, op[0], op[1]); |
break; |
case ir_binop_max: |
emit_minmax(BRW_CONDITIONAL_G, result_dst, op[0], op[1]); |
break; |
case ir_binop_pow: |
emit_math(SHADER_OPCODE_POW, result_dst, op[0], op[1]); |
break; |
case ir_unop_bit_not: |
inst = emit(NOT(result_dst, op[0])); |
break; |
case ir_binop_bit_and: |
inst = emit(AND(result_dst, op[0], op[1])); |
break; |
case ir_binop_bit_xor: |
inst = emit(XOR(result_dst, op[0], op[1])); |
break; |
case ir_binop_bit_or: |
inst = emit(OR(result_dst, op[0], op[1])); |
break; |
case ir_binop_lshift: |
inst = emit(SHL(result_dst, op[0], op[1])); |
break; |
case ir_binop_rshift: |
if (ir->type->base_type == GLSL_TYPE_INT) |
inst = emit(ASR(result_dst, op[0], op[1])); |
else |
inst = emit(SHR(result_dst, op[0], op[1])); |
break; |
case ir_binop_bfm: |
emit(BFI1(result_dst, op[0], op[1])); |
break; |
case ir_binop_ubo_load: { |
ir_constant *uniform_block = ir->operands[0]->as_constant(); |
ir_constant *const_offset_ir = ir->operands[1]->as_constant(); |
unsigned const_offset = const_offset_ir ? const_offset_ir->value.u[0] : 0; |
src_reg offset = op[1]; |
/* Now, load the vector from that offset. */ |
assert(ir->type->is_vector() || ir->type->is_scalar()); |
src_reg packed_consts = src_reg(this, glsl_type::vec4_type); |
packed_consts.type = result.type; |
src_reg surf_index = |
src_reg(SURF_INDEX_VS_UBO(uniform_block->value.u[0])); |
if (const_offset_ir) { |
offset = src_reg(const_offset / 16); |
} else { |
emit(SHR(dst_reg(offset), offset, src_reg(4))); |
} |
vec4_instruction *pull = |
emit(new(mem_ctx) vec4_instruction(this, |
VS_OPCODE_PULL_CONSTANT_LOAD, |
dst_reg(packed_consts), |
surf_index, |
offset)); |
pull->base_mrf = 14; |
pull->mlen = 1; |
packed_consts.swizzle = swizzle_for_size(ir->type->vector_elements); |
packed_consts.swizzle += BRW_SWIZZLE4(const_offset % 16 / 4, |
const_offset % 16 / 4, |
const_offset % 16 / 4, |
const_offset % 16 / 4); |
/* UBO bools are any nonzero int. We store bools as either 0 or 1. */ |
if (ir->type->base_type == GLSL_TYPE_BOOL) { |
emit(CMP(result_dst, packed_consts, src_reg(0u), |
BRW_CONDITIONAL_NZ)); |
emit(AND(result_dst, result, src_reg(0x1))); |
} else { |
emit(MOV(result_dst, packed_consts)); |
} |
break; |
} |
case ir_binop_vector_extract: |
assert(!"should have been lowered by vec_index_to_cond_assign"); |
break; |
case ir_triop_lrp: |
op[0] = fix_3src_operand(op[0]); |
op[1] = fix_3src_operand(op[1]); |
op[2] = fix_3src_operand(op[2]); |
/* Note that the instruction's argument order is reversed from GLSL |
* and the IR. |
*/ |
emit(LRP(result_dst, op[2], op[1], op[0])); |
break; |
case ir_triop_bfi: |
op[0] = fix_3src_operand(op[0]); |
op[1] = fix_3src_operand(op[1]); |
op[2] = fix_3src_operand(op[2]); |
emit(BFI2(result_dst, op[0], op[1], op[2])); |
break; |
case ir_triop_bitfield_extract: |
op[0] = fix_3src_operand(op[0]); |
op[1] = fix_3src_operand(op[1]); |
op[2] = fix_3src_operand(op[2]); |
/* Note that the instruction's argument order is reversed from GLSL |
* and the IR. |
*/ |
emit(BFE(result_dst, op[2], op[1], op[0])); |
break; |
case ir_triop_vector_insert: |
assert(!"should have been lowered by lower_vector_insert"); |
break; |
case ir_quadop_bitfield_insert: |
assert(!"not reached: should be handled by " |
"bitfield_insert_to_bfm_bfi\n"); |
break; |
case ir_quadop_vector: |
assert(!"not reached: should be handled by lower_quadop_vector"); |
break; |
case ir_unop_pack_half_2x16: |
emit_pack_half_2x16(result_dst, op[0]); |
break; |
case ir_unop_unpack_half_2x16: |
emit_unpack_half_2x16(result_dst, op[0]); |
break; |
case ir_unop_pack_snorm_2x16: |
case ir_unop_pack_snorm_4x8: |
case ir_unop_pack_unorm_2x16: |
case ir_unop_pack_unorm_4x8: |
case ir_unop_unpack_snorm_2x16: |
case ir_unop_unpack_snorm_4x8: |
case ir_unop_unpack_unorm_2x16: |
case ir_unop_unpack_unorm_4x8: |
assert(!"not reached: should be handled by lower_packing_builtins"); |
break; |
case ir_unop_unpack_half_2x16_split_x: |
case ir_unop_unpack_half_2x16_split_y: |
case ir_binop_pack_half_2x16_split: |
assert(!"not reached: should not occur in vertex shader"); |
break; |
} |
} |
void |
vec4_visitor::visit(ir_swizzle *ir) |
{ |
src_reg src; |
int i = 0; |
int swizzle[4]; |
/* Note that this is only swizzles in expressions, not those on the left |
* hand side of an assignment, which do write masking. See ir_assignment |
* for that. |
*/ |
ir->val->accept(this); |
src = this->result; |
assert(src.file != BAD_FILE); |
for (i = 0; i < ir->type->vector_elements; i++) { |
switch (i) { |
case 0: |
swizzle[i] = BRW_GET_SWZ(src.swizzle, ir->mask.x); |
break; |
case 1: |
swizzle[i] = BRW_GET_SWZ(src.swizzle, ir->mask.y); |
break; |
case 2: |
swizzle[i] = BRW_GET_SWZ(src.swizzle, ir->mask.z); |
break; |
case 3: |
swizzle[i] = BRW_GET_SWZ(src.swizzle, ir->mask.w); |
break; |
} |
} |
for (; i < 4; i++) { |
/* Replicate the last channel out. */ |
swizzle[i] = swizzle[ir->type->vector_elements - 1]; |
} |
src.swizzle = BRW_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]); |
this->result = src; |
} |
void |
vec4_visitor::visit(ir_dereference_variable *ir) |
{ |
const struct glsl_type *type = ir->type; |
dst_reg *reg = variable_storage(ir->var); |
if (!reg) { |
fail("Failed to find variable storage for %s\n", ir->var->name); |
this->result = src_reg(brw_null_reg()); |
return; |
} |
this->result = src_reg(*reg); |
/* System values get their swizzle from the dst_reg writemask */ |
if (ir->var->mode == ir_var_system_value) |
return; |
if (type->is_scalar() || type->is_vector() || type->is_matrix()) |
this->result.swizzle = swizzle_for_size(type->vector_elements); |
} |
int |
vec4_visitor::compute_array_stride(ir_dereference_array *ir) |
{ |
/* Under normal circumstances array elements are stored consecutively, so |
* the stride is equal to the size of the array element. |
*/ |
return type_size(ir->type); |
} |
void |
vec4_visitor::visit(ir_dereference_array *ir) |
{ |
ir_constant *constant_index; |
src_reg src; |
int array_stride = compute_array_stride(ir); |
constant_index = ir->array_index->constant_expression_value(); |
ir->array->accept(this); |
src = this->result; |
if (constant_index) { |
src.reg_offset += constant_index->value.i[0] * array_stride; |
} else { |
/* Variable index array dereference. It eats the "vec4" of the |
* base of the array and an index that offsets the Mesa register |
* index. |
*/ |
ir->array_index->accept(this); |
src_reg index_reg; |
if (array_stride == 1) { |
index_reg = this->result; |
} else { |
index_reg = src_reg(this, glsl_type::int_type); |
emit(MUL(dst_reg(index_reg), this->result, src_reg(array_stride))); |
} |
if (src.reladdr) { |
src_reg temp = src_reg(this, glsl_type::int_type); |
emit(ADD(dst_reg(temp), *src.reladdr, index_reg)); |
index_reg = temp; |
} |
src.reladdr = ralloc(mem_ctx, src_reg); |
memcpy(src.reladdr, &index_reg, sizeof(index_reg)); |
} |
/* If the type is smaller than a vec4, replicate the last channel out. */ |
if (ir->type->is_scalar() || ir->type->is_vector() || ir->type->is_matrix()) |
src.swizzle = swizzle_for_size(ir->type->vector_elements); |
else |
src.swizzle = BRW_SWIZZLE_NOOP; |
src.type = brw_type_for_base_type(ir->type); |
this->result = src; |
} |
void |
vec4_visitor::visit(ir_dereference_record *ir) |
{ |
unsigned int i; |
const glsl_type *struct_type = ir->record->type; |
int offset = 0; |
ir->record->accept(this); |
for (i = 0; i < struct_type->length; i++) { |
if (strcmp(struct_type->fields.structure[i].name, ir->field) == 0) |
break; |
offset += type_size(struct_type->fields.structure[i].type); |
} |
/* If the type is smaller than a vec4, replicate the last channel out. */ |
if (ir->type->is_scalar() || ir->type->is_vector() || ir->type->is_matrix()) |
this->result.swizzle = swizzle_for_size(ir->type->vector_elements); |
else |
this->result.swizzle = BRW_SWIZZLE_NOOP; |
this->result.type = brw_type_for_base_type(ir->type); |
this->result.reg_offset += offset; |
} |
/** |
* We want to be careful in assignment setup to hit the actual storage |
* instead of potentially using a temporary like we might with the |
* ir_dereference handler. |
*/ |
static dst_reg |
get_assignment_lhs(ir_dereference *ir, vec4_visitor *v) |
{ |
/* The LHS must be a dereference. If the LHS is a variable indexed array |
* access of a vector, it must be separated into a series conditional moves |
* before reaching this point (see ir_vec_index_to_cond_assign). |
*/ |
assert(ir->as_dereference()); |
ir_dereference_array *deref_array = ir->as_dereference_array(); |
if (deref_array) { |
assert(!deref_array->array->type->is_vector()); |
} |
/* Use the rvalue deref handler for the most part. We'll ignore |
* swizzles in it and write swizzles using writemask, though. |
*/ |
ir->accept(v); |
return dst_reg(v->result); |
} |
void |
vec4_visitor::emit_block_move(dst_reg *dst, src_reg *src, |
const struct glsl_type *type, uint32_t predicate) |
{ |
if (type->base_type == GLSL_TYPE_STRUCT) { |
for (unsigned int i = 0; i < type->length; i++) { |
emit_block_move(dst, src, type->fields.structure[i].type, predicate); |
} |
return; |
} |
if (type->is_array()) { |
for (unsigned int i = 0; i < type->length; i++) { |
emit_block_move(dst, src, type->fields.array, predicate); |
} |
return; |
} |
if (type->is_matrix()) { |
const struct glsl_type *vec_type; |
vec_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, |
type->vector_elements, 1); |
for (int i = 0; i < type->matrix_columns; i++) { |
emit_block_move(dst, src, vec_type, predicate); |
} |
return; |
} |
assert(type->is_scalar() || type->is_vector()); |
dst->type = brw_type_for_base_type(type); |
src->type = dst->type; |
dst->writemask = (1 << type->vector_elements) - 1; |
src->swizzle = swizzle_for_size(type->vector_elements); |
vec4_instruction *inst = emit(MOV(*dst, *src)); |
inst->predicate = predicate; |
dst->reg_offset++; |
src->reg_offset++; |
} |
/* If the RHS processing resulted in an instruction generating a |
* temporary value, and it would be easy to rewrite the instruction to |
* generate its result right into the LHS instead, do so. This ends |
* up reliably removing instructions where it can be tricky to do so |
* later without real UD chain information. |
*/ |
bool |
vec4_visitor::try_rewrite_rhs_to_dst(ir_assignment *ir, |
dst_reg dst, |
src_reg src, |
vec4_instruction *pre_rhs_inst, |
vec4_instruction *last_rhs_inst) |
{ |
/* This could be supported, but it would take more smarts. */ |
if (ir->condition) |
return false; |
if (pre_rhs_inst == last_rhs_inst) |
return false; /* No instructions generated to work with. */ |
/* Make sure the last instruction generated our source reg. */ |
if (src.file != GRF || |
src.file != last_rhs_inst->dst.file || |
src.reg != last_rhs_inst->dst.reg || |
src.reg_offset != last_rhs_inst->dst.reg_offset || |
src.reladdr || |
src.abs || |
src.negate || |
last_rhs_inst->predicate != BRW_PREDICATE_NONE) |
return false; |
/* Check that that last instruction fully initialized the channels |
* we want to use, in the order we want to use them. We could |
* potentially reswizzle the operands of many instructions so that |
* we could handle out of order channels, but don't yet. |
*/ |
for (unsigned i = 0; i < 4; i++) { |
if (dst.writemask & (1 << i)) { |
if (!(last_rhs_inst->dst.writemask & (1 << i))) |
return false; |
if (BRW_GET_SWZ(src.swizzle, i) != i) |
return false; |
} |
} |
/* Success! Rewrite the instruction. */ |
last_rhs_inst->dst.file = dst.file; |
last_rhs_inst->dst.reg = dst.reg; |
last_rhs_inst->dst.reg_offset = dst.reg_offset; |
last_rhs_inst->dst.reladdr = dst.reladdr; |
last_rhs_inst->dst.writemask &= dst.writemask; |
return true; |
} |
void |
vec4_visitor::visit(ir_assignment *ir) |
{ |
dst_reg dst = get_assignment_lhs(ir->lhs, this); |
uint32_t predicate = BRW_PREDICATE_NONE; |
if (!ir->lhs->type->is_scalar() && |
!ir->lhs->type->is_vector()) { |
ir->rhs->accept(this); |
src_reg src = this->result; |
if (ir->condition) { |
emit_bool_to_cond_code(ir->condition, &predicate); |
} |
/* emit_block_move doesn't account for swizzles in the source register. |
* This should be ok, since the source register is a structure or an |
* array, and those can't be swizzled. But double-check to be sure. |
*/ |
assert(src.swizzle == |
(ir->rhs->type->is_matrix() |
? swizzle_for_size(ir->rhs->type->vector_elements) |
: BRW_SWIZZLE_NOOP)); |
emit_block_move(&dst, &src, ir->rhs->type, predicate); |
return; |
} |
/* Now we're down to just a scalar/vector with writemasks. */ |
int i; |
vec4_instruction *pre_rhs_inst, *last_rhs_inst; |
pre_rhs_inst = (vec4_instruction *)this->instructions.get_tail(); |
ir->rhs->accept(this); |
last_rhs_inst = (vec4_instruction *)this->instructions.get_tail(); |
src_reg src = this->result; |
int swizzles[4]; |
int first_enabled_chan = 0; |
int src_chan = 0; |
assert(ir->lhs->type->is_vector() || |
ir->lhs->type->is_scalar()); |
dst.writemask = ir->write_mask; |
for (int i = 0; i < 4; i++) { |
if (dst.writemask & (1 << i)) { |
first_enabled_chan = BRW_GET_SWZ(src.swizzle, i); |
break; |
} |
} |
/* Swizzle a small RHS vector into the channels being written. |
* |
* glsl ir treats write_mask as dictating how many channels are |
* present on the RHS while in our instructions we need to make |
* those channels appear in the slots of the vec4 they're written to. |
*/ |
for (int i = 0; i < 4; i++) { |
if (dst.writemask & (1 << i)) |
swizzles[i] = BRW_GET_SWZ(src.swizzle, src_chan++); |
else |
swizzles[i] = first_enabled_chan; |
} |
src.swizzle = BRW_SWIZZLE4(swizzles[0], swizzles[1], |
swizzles[2], swizzles[3]); |
if (try_rewrite_rhs_to_dst(ir, dst, src, pre_rhs_inst, last_rhs_inst)) { |
return; |
} |
if (ir->condition) { |
emit_bool_to_cond_code(ir->condition, &predicate); |
} |
for (i = 0; i < type_size(ir->lhs->type); i++) { |
vec4_instruction *inst = emit(MOV(dst, src)); |
inst->predicate = predicate; |
dst.reg_offset++; |
src.reg_offset++; |
} |
} |
void |
vec4_visitor::emit_constant_values(dst_reg *dst, ir_constant *ir) |
{ |
if (ir->type->base_type == GLSL_TYPE_STRUCT) { |
foreach_list(node, &ir->components) { |
ir_constant *field_value = (ir_constant *)node; |
emit_constant_values(dst, field_value); |
} |
return; |
} |
if (ir->type->is_array()) { |
for (unsigned int i = 0; i < ir->type->length; i++) { |
emit_constant_values(dst, ir->array_elements[i]); |
} |
return; |
} |
if (ir->type->is_matrix()) { |
for (int i = 0; i < ir->type->matrix_columns; i++) { |
float *vec = &ir->value.f[i * ir->type->vector_elements]; |
for (int j = 0; j < ir->type->vector_elements; j++) { |
dst->writemask = 1 << j; |
dst->type = BRW_REGISTER_TYPE_F; |
emit(MOV(*dst, src_reg(vec[j]))); |
} |
dst->reg_offset++; |
} |
return; |
} |
int remaining_writemask = (1 << ir->type->vector_elements) - 1; |
for (int i = 0; i < ir->type->vector_elements; i++) { |
if (!(remaining_writemask & (1 << i))) |
continue; |
dst->writemask = 1 << i; |
dst->type = brw_type_for_base_type(ir->type); |
/* Find other components that match the one we're about to |
* write. Emits fewer instructions for things like vec4(0.5, |
* 1.5, 1.5, 1.5). |
*/ |
for (int j = i + 1; j < ir->type->vector_elements; j++) { |
if (ir->type->base_type == GLSL_TYPE_BOOL) { |
if (ir->value.b[i] == ir->value.b[j]) |
dst->writemask |= (1 << j); |
} else { |
/* u, i, and f storage all line up, so no need for a |
* switch case for comparing each type. |
*/ |
if (ir->value.u[i] == ir->value.u[j]) |
dst->writemask |= (1 << j); |
} |
} |
switch (ir->type->base_type) { |
case GLSL_TYPE_FLOAT: |
emit(MOV(*dst, src_reg(ir->value.f[i]))); |
break; |
case GLSL_TYPE_INT: |
emit(MOV(*dst, src_reg(ir->value.i[i]))); |
break; |
case GLSL_TYPE_UINT: |
emit(MOV(*dst, src_reg(ir->value.u[i]))); |
break; |
case GLSL_TYPE_BOOL: |
emit(MOV(*dst, src_reg(ir->value.b[i]))); |
break; |
default: |
assert(!"Non-float/uint/int/bool constant"); |
break; |
} |
remaining_writemask &= ~dst->writemask; |
} |
dst->reg_offset++; |
} |
void |
vec4_visitor::visit(ir_constant *ir) |
{ |
dst_reg dst = dst_reg(this, ir->type); |
this->result = src_reg(dst); |
emit_constant_values(&dst, ir); |
} |
void |
vec4_visitor::visit(ir_call *ir) |
{ |
assert(!"not reached"); |
} |
void |
vec4_visitor::visit(ir_texture *ir) |
{ |
int sampler = |
_mesa_get_sampler_uniform_value(ir->sampler, shader_prog, prog); |
/* Should be lowered by do_lower_texture_projection */ |
assert(!ir->projector); |
/* Generate code to compute all the subexpression trees. This has to be |
* done before loading any values into MRFs for the sampler message since |
* generating these values may involve SEND messages that need the MRFs. |
*/ |
src_reg coordinate; |
if (ir->coordinate) { |
ir->coordinate->accept(this); |
coordinate = this->result; |
} |
src_reg shadow_comparitor; |
if (ir->shadow_comparitor) { |
ir->shadow_comparitor->accept(this); |
shadow_comparitor = this->result; |
} |
const glsl_type *lod_type = NULL, *sample_index_type = NULL; |
src_reg lod, dPdx, dPdy, sample_index; |
switch (ir->op) { |
case ir_tex: |
lod = src_reg(0.0f); |
lod_type = glsl_type::float_type; |
break; |
case ir_txf: |
case ir_txl: |
case ir_txs: |
ir->lod_info.lod->accept(this); |
lod = this->result; |
lod_type = ir->lod_info.lod->type; |
break; |
case ir_txf_ms: |
ir->lod_info.sample_index->accept(this); |
sample_index = this->result; |
sample_index_type = ir->lod_info.sample_index->type; |
break; |
case ir_txd: |
ir->lod_info.grad.dPdx->accept(this); |
dPdx = this->result; |
ir->lod_info.grad.dPdy->accept(this); |
dPdy = this->result; |
lod_type = ir->lod_info.grad.dPdx->type; |
break; |
case ir_txb: |
case ir_lod: |
break; |
} |
vec4_instruction *inst = NULL; |
switch (ir->op) { |
case ir_tex: |
case ir_txl: |
inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXL); |
break; |
case ir_txd: |
inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXD); |
break; |
case ir_txf: |
inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXF); |
break; |
case ir_txf_ms: |
inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXF_MS); |
break; |
case ir_txs: |
inst = new(mem_ctx) vec4_instruction(this, SHADER_OPCODE_TXS); |
break; |
case ir_txb: |
assert(!"TXB is not valid for vertex shaders."); |
break; |
case ir_lod: |
assert(!"LOD is not valid for vertex shaders."); |
break; |
} |
bool use_texture_offset = ir->offset != NULL && ir->op != ir_txf; |
/* Texel offsets go in the message header; Gen4 also requires headers. */ |
inst->header_present = use_texture_offset || brw->gen < 5; |
inst->base_mrf = 2; |
inst->mlen = inst->header_present + 1; /* always at least one */ |
inst->sampler = sampler; |
inst->dst = dst_reg(this, ir->type); |
inst->dst.writemask = WRITEMASK_XYZW; |
inst->shadow_compare = ir->shadow_comparitor != NULL; |
if (use_texture_offset) |
inst->texture_offset = brw_texture_offset(ir->offset->as_constant()); |
/* MRF for the first parameter */ |
int param_base = inst->base_mrf + inst->header_present; |
if (ir->op == ir_txs) { |
int writemask = brw->gen == 4 ? WRITEMASK_W : WRITEMASK_X; |
emit(MOV(dst_reg(MRF, param_base, lod_type, writemask), lod)); |
} else { |
int i, coord_mask = 0, zero_mask = 0; |
/* Load the coordinate */ |
/* FINISHME: gl_clamp_mask and saturate */ |
for (i = 0; i < ir->coordinate->type->vector_elements; i++) |
coord_mask |= (1 << i); |
for (; i < 4; i++) |
zero_mask |= (1 << i); |
if (ir->offset && ir->op == ir_txf) { |
/* It appears that the ld instruction used for txf does its |
* address bounds check before adding in the offset. To work |
* around this, just add the integer offset to the integer |
* texel coordinate, and don't put the offset in the header. |
*/ |
ir_constant *offset = ir->offset->as_constant(); |
assert(offset); |
for (int j = 0; j < ir->coordinate->type->vector_elements; j++) { |
src_reg src = coordinate; |
src.swizzle = BRW_SWIZZLE4(BRW_GET_SWZ(src.swizzle, j), |
BRW_GET_SWZ(src.swizzle, j), |
BRW_GET_SWZ(src.swizzle, j), |
BRW_GET_SWZ(src.swizzle, j)); |
emit(ADD(dst_reg(MRF, param_base, ir->coordinate->type, 1 << j), |
src, offset->value.i[j])); |
} |
} else { |
emit(MOV(dst_reg(MRF, param_base, ir->coordinate->type, coord_mask), |
coordinate)); |
} |
if (zero_mask != 0) { |
emit(MOV(dst_reg(MRF, param_base, ir->coordinate->type, zero_mask), |
src_reg(0))); |
} |
/* Load the shadow comparitor */ |
if (ir->shadow_comparitor && ir->op != ir_txd) { |
emit(MOV(dst_reg(MRF, param_base + 1, ir->shadow_comparitor->type, |
WRITEMASK_X), |
shadow_comparitor)); |
inst->mlen++; |
} |
/* Load the LOD info */ |
if (ir->op == ir_tex || ir->op == ir_txl) { |
int mrf, writemask; |
if (brw->gen >= 5) { |
mrf = param_base + 1; |
if (ir->shadow_comparitor) { |
writemask = WRITEMASK_Y; |
/* mlen already incremented */ |
} else { |
writemask = WRITEMASK_X; |
inst->mlen++; |
} |
} else /* brw->gen == 4 */ { |
mrf = param_base; |
writemask = WRITEMASK_W; |
} |
emit(MOV(dst_reg(MRF, mrf, lod_type, writemask), lod)); |
} else if (ir->op == ir_txf) { |
emit(MOV(dst_reg(MRF, param_base, lod_type, WRITEMASK_W), lod)); |
} else if (ir->op == ir_txf_ms) { |
emit(MOV(dst_reg(MRF, param_base + 1, sample_index_type, WRITEMASK_X), |
sample_index)); |
inst->mlen++; |
/* on Gen7, there is an additional MCS parameter here after SI, |
* but we don't bother to emit it since it's always zero. If |
* we start supporting texturing from CMS surfaces, this will have |
* to change |
*/ |
} else if (ir->op == ir_txd) { |
const glsl_type *type = lod_type; |
if (brw->gen >= 5) { |
dPdx.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y); |
dPdy.swizzle = BRW_SWIZZLE4(SWIZZLE_X,SWIZZLE_X,SWIZZLE_Y,SWIZZLE_Y); |
emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XZ), dPdx)); |
emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_YW), dPdy)); |
inst->mlen++; |
if (ir->type->vector_elements == 3 || ir->shadow_comparitor) { |
dPdx.swizzle = BRW_SWIZZLE_ZZZZ; |
dPdy.swizzle = BRW_SWIZZLE_ZZZZ; |
emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_X), dPdx)); |
emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_Y), dPdy)); |
inst->mlen++; |
if (ir->shadow_comparitor) { |
emit(MOV(dst_reg(MRF, param_base + 2, |
ir->shadow_comparitor->type, WRITEMASK_Z), |
shadow_comparitor)); |
} |
} |
} else /* brw->gen == 4 */ { |
emit(MOV(dst_reg(MRF, param_base + 1, type, WRITEMASK_XYZ), dPdx)); |
emit(MOV(dst_reg(MRF, param_base + 2, type, WRITEMASK_XYZ), dPdy)); |
inst->mlen += 2; |
} |
} |
} |
emit(inst); |
/* fixup num layers (z) for cube arrays: hardware returns faces * layers; |
* spec requires layers. |
*/ |
if (ir->op == ir_txs) { |
glsl_type const *type = ir->sampler->type; |
if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE && |
type->sampler_array) { |
emit_math(SHADER_OPCODE_INT_QUOTIENT, |
with_writemask(inst->dst, WRITEMASK_Z), |
src_reg(inst->dst), src_reg(6)); |
} |
} |
swizzle_result(ir, src_reg(inst->dst), sampler); |
} |
void |
vec4_visitor::swizzle_result(ir_texture *ir, src_reg orig_val, int sampler) |
{ |
int s = key->tex.swizzles[sampler]; |
this->result = src_reg(this, ir->type); |
dst_reg swizzled_result(this->result); |
if (ir->op == ir_txs || ir->type == glsl_type::float_type |
|| s == SWIZZLE_NOOP) { |
emit(MOV(swizzled_result, orig_val)); |
return; |
} |
int zero_mask = 0, one_mask = 0, copy_mask = 0; |
int swizzle[4] = {0}; |
for (int i = 0; i < 4; i++) { |
switch (GET_SWZ(s, i)) { |
case SWIZZLE_ZERO: |
zero_mask |= (1 << i); |
break; |
case SWIZZLE_ONE: |
one_mask |= (1 << i); |
break; |
default: |
copy_mask |= (1 << i); |
swizzle[i] = GET_SWZ(s, i); |
break; |
} |
} |
if (copy_mask) { |
orig_val.swizzle = BRW_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]); |
swizzled_result.writemask = copy_mask; |
emit(MOV(swizzled_result, orig_val)); |
} |
if (zero_mask) { |
swizzled_result.writemask = zero_mask; |
emit(MOV(swizzled_result, src_reg(0.0f))); |
} |
if (one_mask) { |
swizzled_result.writemask = one_mask; |
emit(MOV(swizzled_result, src_reg(1.0f))); |
} |
} |
void |
vec4_visitor::visit(ir_return *ir) |
{ |
assert(!"not reached"); |
} |
void |
vec4_visitor::visit(ir_discard *ir) |
{ |
assert(!"not reached"); |
} |
void |
vec4_visitor::visit(ir_if *ir) |
{ |
/* Don't point the annotation at the if statement, because then it plus |
* the then and else blocks get printed. |
*/ |
this->base_ir = ir->condition; |
if (brw->gen == 6) { |
emit_if_gen6(ir); |
} else { |
uint32_t predicate; |
emit_bool_to_cond_code(ir->condition, &predicate); |
emit(IF(predicate)); |
} |
visit_instructions(&ir->then_instructions); |
if (!ir->else_instructions.is_empty()) { |
this->base_ir = ir->condition; |
emit(BRW_OPCODE_ELSE); |
visit_instructions(&ir->else_instructions); |
} |
this->base_ir = ir->condition; |
emit(BRW_OPCODE_ENDIF); |
} |
void |
vec4_visitor::emit_ndc_computation() |
{ |
/* Get the position */ |
src_reg pos = src_reg(output_reg[VARYING_SLOT_POS]); |
/* Build ndc coords, which are (x/w, y/w, z/w, 1/w) */ |
dst_reg ndc = dst_reg(this, glsl_type::vec4_type); |
output_reg[BRW_VARYING_SLOT_NDC] = ndc; |
current_annotation = "NDC"; |
dst_reg ndc_w = ndc; |
ndc_w.writemask = WRITEMASK_W; |
src_reg pos_w = pos; |
pos_w.swizzle = BRW_SWIZZLE4(SWIZZLE_W, SWIZZLE_W, SWIZZLE_W, SWIZZLE_W); |
emit_math(SHADER_OPCODE_RCP, ndc_w, pos_w); |
dst_reg ndc_xyz = ndc; |
ndc_xyz.writemask = WRITEMASK_XYZ; |
emit(MUL(ndc_xyz, pos, src_reg(ndc_w))); |
} |
void |
vec4_visitor::emit_psiz_and_flags(struct brw_reg reg) |
{ |
if (brw->gen < 6 && |
((prog_data->vue_map.slots_valid & VARYING_BIT_PSIZ) || |
key->userclip_active || brw->has_negative_rhw_bug)) { |
dst_reg header1 = dst_reg(this, glsl_type::uvec4_type); |
dst_reg header1_w = header1; |
header1_w.writemask = WRITEMASK_W; |
GLuint i; |
emit(MOV(header1, 0u)); |
if (prog_data->vue_map.slots_valid & VARYING_BIT_PSIZ) { |
src_reg psiz = src_reg(output_reg[VARYING_SLOT_PSIZ]); |
current_annotation = "Point size"; |
emit(MUL(header1_w, psiz, src_reg((float)(1 << 11)))); |
emit(AND(header1_w, src_reg(header1_w), 0x7ff << 8)); |
} |
current_annotation = "Clipping flags"; |
for (i = 0; i < key->nr_userclip_plane_consts; i++) { |
vec4_instruction *inst; |
gl_varying_slot slot = (prog_data->vue_map.slots_valid & VARYING_BIT_CLIP_VERTEX) |
? VARYING_SLOT_CLIP_VERTEX : VARYING_SLOT_POS; |
inst = emit(DP4(dst_null_f(), src_reg(output_reg[slot]), |
src_reg(this->userplane[i]))); |
inst->conditional_mod = BRW_CONDITIONAL_L; |
inst = emit(OR(header1_w, src_reg(header1_w), 1u << i)); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
/* i965 clipping workaround: |
* 1) Test for -ve rhw |
* 2) If set, |
* set ndc = (0,0,0,0) |
* set ucp[6] = 1 |
* |
* Later, clipping will detect ucp[6] and ensure the primitive is |
* clipped against all fixed planes. |
*/ |
if (brw->has_negative_rhw_bug) { |
src_reg ndc_w = src_reg(output_reg[BRW_VARYING_SLOT_NDC]); |
ndc_w.swizzle = BRW_SWIZZLE_WWWW; |
emit(CMP(dst_null_f(), ndc_w, src_reg(0.0f), BRW_CONDITIONAL_L)); |
vec4_instruction *inst; |
inst = emit(OR(header1_w, src_reg(header1_w), src_reg(1u << 6))); |
inst->predicate = BRW_PREDICATE_NORMAL; |
inst = emit(MOV(output_reg[BRW_VARYING_SLOT_NDC], src_reg(0.0f))); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
emit(MOV(retype(reg, BRW_REGISTER_TYPE_UD), src_reg(header1))); |
} else if (brw->gen < 6) { |
emit(MOV(retype(reg, BRW_REGISTER_TYPE_UD), 0u)); |
} else { |
emit(MOV(retype(reg, BRW_REGISTER_TYPE_D), src_reg(0))); |
if (prog_data->vue_map.slots_valid & VARYING_BIT_PSIZ) { |
emit(MOV(brw_writemask(reg, WRITEMASK_W), |
src_reg(output_reg[VARYING_SLOT_PSIZ]))); |
} |
if (prog_data->vue_map.slots_valid & VARYING_BIT_LAYER) { |
emit(MOV(retype(brw_writemask(reg, WRITEMASK_Y), BRW_REGISTER_TYPE_D), |
src_reg(output_reg[VARYING_SLOT_LAYER]))); |
} |
} |
} |
void |
vec4_visitor::emit_clip_distances(struct brw_reg reg, int offset) |
{ |
if (brw->gen < 6) { |
/* Clip distance slots are set aside in gen5, but they are not used. It |
* is not clear whether we actually need to set aside space for them, |
* but the performance cost is negligible. |
*/ |
return; |
} |
/* From the GLSL 1.30 spec, section 7.1 (Vertex Shader Special Variables): |
* |
* "If a linked set of shaders forming the vertex stage contains no |
* static write to gl_ClipVertex or gl_ClipDistance, but the |
* application has requested clipping against user clip planes through |
* the API, then the coordinate written to gl_Position is used for |
* comparison against the user clip planes." |
* |
* This function is only called if the shader didn't write to |
* gl_ClipDistance. Accordingly, we use gl_ClipVertex to perform clipping |
* if the user wrote to it; otherwise we use gl_Position. |
*/ |
gl_varying_slot clip_vertex = VARYING_SLOT_CLIP_VERTEX; |
if (!(prog_data->vue_map.slots_valid & VARYING_BIT_CLIP_VERTEX)) { |
clip_vertex = VARYING_SLOT_POS; |
} |
for (int i = 0; i + offset < key->nr_userclip_plane_consts && i < 4; |
++i) { |
emit(DP4(dst_reg(brw_writemask(reg, 1 << i)), |
src_reg(output_reg[clip_vertex]), |
src_reg(this->userplane[i + offset]))); |
} |
} |
void |
vec4_visitor::emit_generic_urb_slot(dst_reg reg, int varying) |
{ |
assert (varying < VARYING_SLOT_MAX); |
reg.type = output_reg[varying].type; |
current_annotation = output_reg_annotation[varying]; |
/* Copy the register, saturating if necessary */ |
vec4_instruction *inst = emit(MOV(reg, |
src_reg(output_reg[varying]))); |
if ((varying == VARYING_SLOT_COL0 || |
varying == VARYING_SLOT_COL1 || |
varying == VARYING_SLOT_BFC0 || |
varying == VARYING_SLOT_BFC1) && |
key->clamp_vertex_color) { |
inst->saturate = true; |
} |
} |
void |
vec4_visitor::emit_urb_slot(int mrf, int varying) |
{ |
struct brw_reg hw_reg = brw_message_reg(mrf); |
dst_reg reg = dst_reg(MRF, mrf); |
reg.type = BRW_REGISTER_TYPE_F; |
switch (varying) { |
case VARYING_SLOT_PSIZ: |
/* PSIZ is always in slot 0, and is coupled with other flags. */ |
current_annotation = "indices, point width, clip flags"; |
emit_psiz_and_flags(hw_reg); |
break; |
case BRW_VARYING_SLOT_NDC: |
current_annotation = "NDC"; |
emit(MOV(reg, src_reg(output_reg[BRW_VARYING_SLOT_NDC]))); |
break; |
case VARYING_SLOT_POS: |
current_annotation = "gl_Position"; |
emit(MOV(reg, src_reg(output_reg[VARYING_SLOT_POS]))); |
break; |
case VARYING_SLOT_CLIP_DIST0: |
case VARYING_SLOT_CLIP_DIST1: |
if (this->key->uses_clip_distance) { |
emit_generic_urb_slot(reg, varying); |
} else { |
current_annotation = "user clip distances"; |
emit_clip_distances(hw_reg, (varying - VARYING_SLOT_CLIP_DIST0) * 4); |
} |
break; |
case VARYING_SLOT_EDGE: |
/* This is present when doing unfilled polygons. We're supposed to copy |
* the edge flag from the user-provided vertex array |
* (glEdgeFlagPointer), or otherwise we'll copy from the current value |
* of that attribute (starts as 1.0f). This is then used in clipping to |
* determine which edges should be drawn as wireframe. |
*/ |
current_annotation = "edge flag"; |
emit(MOV(reg, src_reg(dst_reg(ATTR, VERT_ATTRIB_EDGEFLAG, |
glsl_type::float_type, WRITEMASK_XYZW)))); |
break; |
case BRW_VARYING_SLOT_PAD: |
/* No need to write to this slot */ |
break; |
default: |
emit_generic_urb_slot(reg, varying); |
break; |
} |
} |
static int |
align_interleaved_urb_mlen(struct brw_context *brw, int mlen) |
{ |
if (brw->gen >= 6) { |
/* URB data written (does not include the message header reg) must |
* be a multiple of 256 bits, or 2 VS registers. See vol5c.5, |
* section 5.4.3.2.2: URB_INTERLEAVED. |
* |
* URB entries are allocated on a multiple of 1024 bits, so an |
* extra 128 bits written here to make the end align to 256 is |
* no problem. |
*/ |
if ((mlen % 2) != 1) |
mlen++; |
} |
return mlen; |
} |
void |
vec4_vs_visitor::emit_urb_write_header(int mrf) |
{ |
/* No need to do anything for VS; an implied write to this MRF will be |
* performed by VS_OPCODE_URB_WRITE. |
*/ |
(void) mrf; |
} |
vec4_instruction * |
vec4_vs_visitor::emit_urb_write_opcode(bool complete) |
{ |
/* For VS, the URB writes end the thread. */ |
if (complete) { |
if (INTEL_DEBUG & DEBUG_SHADER_TIME) |
emit_shader_time_end(); |
} |
vec4_instruction *inst = emit(VS_OPCODE_URB_WRITE); |
inst->eot = complete; |
return inst; |
} |
/** |
* Generates the VUE payload plus the necessary URB write instructions to |
* output it. |
* |
* The VUE layout is documented in Volume 2a. |
*/ |
void |
vec4_visitor::emit_vertex() |
{ |
/* MRF 0 is reserved for the debugger, so start with message header |
* in MRF 1. |
*/ |
int base_mrf = 1; |
int mrf = base_mrf; |
/* In the process of generating our URB write message contents, we |
* may need to unspill a register or load from an array. Those |
* reads would use MRFs 14-15. |
*/ |
int max_usable_mrf = 13; |
/* The following assertion verifies that max_usable_mrf causes an |
* even-numbered amount of URB write data, which will meet gen6's |
* requirements for length alignment. |
*/ |
assert ((max_usable_mrf - base_mrf) % 2 == 0); |
/* First mrf is the g0-based message header containing URB handles and |
* such. |
*/ |
emit_urb_write_header(mrf++); |
if (brw->gen < 6) { |
emit_ndc_computation(); |
} |
/* Set up the VUE data for the first URB write */ |
int slot; |
for (slot = 0; slot < prog_data->vue_map.num_slots; ++slot) { |
emit_urb_slot(mrf++, prog_data->vue_map.slot_to_varying[slot]); |
/* If this was max_usable_mrf, we can't fit anything more into this URB |
* WRITE. |
*/ |
if (mrf > max_usable_mrf) { |
slot++; |
break; |
} |
} |
bool complete = slot >= prog_data->vue_map.num_slots; |
current_annotation = "URB write"; |
vec4_instruction *inst = emit_urb_write_opcode(complete); |
inst->base_mrf = base_mrf; |
inst->mlen = align_interleaved_urb_mlen(brw, mrf - base_mrf); |
/* Optional second URB write */ |
if (!complete) { |
mrf = base_mrf + 1; |
for (; slot < prog_data->vue_map.num_slots; ++slot) { |
assert(mrf < max_usable_mrf); |
emit_urb_slot(mrf++, prog_data->vue_map.slot_to_varying[slot]); |
} |
current_annotation = "URB write"; |
inst = emit_urb_write_opcode(true /* complete */); |
inst->base_mrf = base_mrf; |
inst->mlen = align_interleaved_urb_mlen(brw, mrf - base_mrf); |
/* URB destination offset. In the previous write, we got MRFs |
* 2-13 minus the one header MRF, so 12 regs. URB offset is in |
* URB row increments, and each of our MRFs is half of one of |
* those, since we're doing interleaved writes. |
*/ |
inst->offset = (max_usable_mrf - base_mrf) / 2; |
} |
} |
void |
vec4_vs_visitor::emit_thread_end() |
{ |
/* For VS, we always end the thread by emitting a single vertex. |
* emit_urb_write_opcode() will take care of setting the eot flag on the |
* SEND instruction. |
*/ |
emit_vertex(); |
} |
src_reg |
vec4_visitor::get_scratch_offset(vec4_instruction *inst, |
src_reg *reladdr, int reg_offset) |
{ |
/* Because we store the values to scratch interleaved like our |
* vertex data, we need to scale the vec4 index by 2. |
*/ |
int message_header_scale = 2; |
/* Pre-gen6, the message header uses byte offsets instead of vec4 |
* (16-byte) offset units. |
*/ |
if (brw->gen < 6) |
message_header_scale *= 16; |
if (reladdr) { |
src_reg index = src_reg(this, glsl_type::int_type); |
emit_before(inst, ADD(dst_reg(index), *reladdr, src_reg(reg_offset))); |
emit_before(inst, MUL(dst_reg(index), |
index, src_reg(message_header_scale))); |
return index; |
} else { |
return src_reg(reg_offset * message_header_scale); |
} |
} |
src_reg |
vec4_visitor::get_pull_constant_offset(vec4_instruction *inst, |
src_reg *reladdr, int reg_offset) |
{ |
if (reladdr) { |
src_reg index = src_reg(this, glsl_type::int_type); |
emit_before(inst, ADD(dst_reg(index), *reladdr, src_reg(reg_offset))); |
/* Pre-gen6, the message header uses byte offsets instead of vec4 |
* (16-byte) offset units. |
*/ |
if (brw->gen < 6) { |
emit_before(inst, MUL(dst_reg(index), index, src_reg(16))); |
} |
return index; |
} else { |
int message_header_scale = brw->gen < 6 ? 16 : 1; |
return src_reg(reg_offset * message_header_scale); |
} |
} |
/** |
* Emits an instruction before @inst to load the value named by @orig_src |
* from scratch space at @base_offset to @temp. |
* |
* @base_offset is measured in 32-byte units (the size of a register). |
*/ |
void |
vec4_visitor::emit_scratch_read(vec4_instruction *inst, |
dst_reg temp, src_reg orig_src, |
int base_offset) |
{ |
int reg_offset = base_offset + orig_src.reg_offset; |
src_reg index = get_scratch_offset(inst, orig_src.reladdr, reg_offset); |
emit_before(inst, SCRATCH_READ(temp, index)); |
} |
/** |
* Emits an instruction after @inst to store the value to be written |
* to @orig_dst to scratch space at @base_offset, from @temp. |
* |
* @base_offset is measured in 32-byte units (the size of a register). |
*/ |
void |
vec4_visitor::emit_scratch_write(vec4_instruction *inst, int base_offset) |
{ |
int reg_offset = base_offset + inst->dst.reg_offset; |
src_reg index = get_scratch_offset(inst, inst->dst.reladdr, reg_offset); |
/* Create a temporary register to store *inst's result in. |
* |
* We have to be careful in MOVing from our temporary result register in |
* the scratch write. If we swizzle from channels of the temporary that |
* weren't initialized, it will confuse live interval analysis, which will |
* make spilling fail to make progress. |
*/ |
src_reg temp = src_reg(this, glsl_type::vec4_type); |
temp.type = inst->dst.type; |
int first_writemask_chan = ffs(inst->dst.writemask) - 1; |
int swizzles[4]; |
for (int i = 0; i < 4; i++) |
if (inst->dst.writemask & (1 << i)) |
swizzles[i] = i; |
else |
swizzles[i] = first_writemask_chan; |
temp.swizzle = BRW_SWIZZLE4(swizzles[0], swizzles[1], |
swizzles[2], swizzles[3]); |
dst_reg dst = dst_reg(brw_writemask(brw_vec8_grf(0, 0), |
inst->dst.writemask)); |
vec4_instruction *write = SCRATCH_WRITE(dst, temp, index); |
write->predicate = inst->predicate; |
write->ir = inst->ir; |
write->annotation = inst->annotation; |
inst->insert_after(write); |
inst->dst.file = temp.file; |
inst->dst.reg = temp.reg; |
inst->dst.reg_offset = temp.reg_offset; |
inst->dst.reladdr = NULL; |
} |
/** |
* We can't generally support array access in GRF space, because a |
* single instruction's destination can only span 2 contiguous |
* registers. So, we send all GRF arrays that get variable index |
* access to scratch space. |
*/ |
void |
vec4_visitor::move_grf_array_access_to_scratch() |
{ |
int scratch_loc[this->virtual_grf_count]; |
for (int i = 0; i < this->virtual_grf_count; i++) { |
scratch_loc[i] = -1; |
} |
/* First, calculate the set of virtual GRFs that need to be punted |
* to scratch due to having any array access on them, and where in |
* scratch. |
*/ |
foreach_list(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
if (inst->dst.file == GRF && inst->dst.reladdr && |
scratch_loc[inst->dst.reg] == -1) { |
scratch_loc[inst->dst.reg] = c->last_scratch; |
c->last_scratch += this->virtual_grf_sizes[inst->dst.reg]; |
} |
for (int i = 0 ; i < 3; i++) { |
src_reg *src = &inst->src[i]; |
if (src->file == GRF && src->reladdr && |
scratch_loc[src->reg] == -1) { |
scratch_loc[src->reg] = c->last_scratch; |
c->last_scratch += this->virtual_grf_sizes[src->reg]; |
} |
} |
} |
/* Now, for anything that will be accessed through scratch, rewrite |
* it to load/store. Note that this is a _safe list walk, because |
* we may generate a new scratch_write instruction after the one |
* we're processing. |
*/ |
foreach_list_safe(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
/* Set up the annotation tracking for new generated instructions. */ |
base_ir = inst->ir; |
current_annotation = inst->annotation; |
if (inst->dst.file == GRF && scratch_loc[inst->dst.reg] != -1) { |
emit_scratch_write(inst, scratch_loc[inst->dst.reg]); |
} |
for (int i = 0 ; i < 3; i++) { |
if (inst->src[i].file != GRF || scratch_loc[inst->src[i].reg] == -1) |
continue; |
dst_reg temp = dst_reg(this, glsl_type::vec4_type); |
emit_scratch_read(inst, temp, inst->src[i], |
scratch_loc[inst->src[i].reg]); |
inst->src[i].file = temp.file; |
inst->src[i].reg = temp.reg; |
inst->src[i].reg_offset = temp.reg_offset; |
inst->src[i].reladdr = NULL; |
} |
} |
} |
/** |
* Emits an instruction before @inst to load the value named by @orig_src |
* from the pull constant buffer (surface) at @base_offset to @temp. |
*/ |
void |
vec4_visitor::emit_pull_constant_load(vec4_instruction *inst, |
dst_reg temp, src_reg orig_src, |
int base_offset) |
{ |
int reg_offset = base_offset + orig_src.reg_offset; |
src_reg index = src_reg((unsigned)SURF_INDEX_VERT_CONST_BUFFER); |
src_reg offset = get_pull_constant_offset(inst, orig_src.reladdr, reg_offset); |
vec4_instruction *load; |
if (brw->gen >= 7) { |
dst_reg grf_offset = dst_reg(this, glsl_type::int_type); |
grf_offset.type = offset.type; |
emit_before(inst, MOV(grf_offset, offset)); |
load = new(mem_ctx) vec4_instruction(this, |
VS_OPCODE_PULL_CONSTANT_LOAD_GEN7, |
temp, index, src_reg(grf_offset)); |
} else { |
load = new(mem_ctx) vec4_instruction(this, VS_OPCODE_PULL_CONSTANT_LOAD, |
temp, index, offset); |
load->base_mrf = 14; |
load->mlen = 1; |
} |
emit_before(inst, load); |
} |
/** |
* Implements array access of uniforms by inserting a |
* PULL_CONSTANT_LOAD instruction. |
* |
* Unlike temporary GRF array access (where we don't support it due to |
* the difficulty of doing relative addressing on instruction |
* destinations), we could potentially do array access of uniforms |
* that were loaded in GRF space as push constants. In real-world |
* usage we've seen, though, the arrays being used are always larger |
* than we could load as push constants, so just always move all |
* uniform array access out to a pull constant buffer. |
*/ |
void |
vec4_visitor::move_uniform_array_access_to_pull_constants() |
{ |
int pull_constant_loc[this->uniforms]; |
for (int i = 0; i < this->uniforms; i++) { |
pull_constant_loc[i] = -1; |
} |
/* Walk through and find array access of uniforms. Put a copy of that |
* uniform in the pull constant buffer. |
* |
* Note that we don't move constant-indexed accesses to arrays. No |
* testing has been done of the performance impact of this choice. |
*/ |
foreach_list_safe(node, &this->instructions) { |
vec4_instruction *inst = (vec4_instruction *)node; |
for (int i = 0 ; i < 3; i++) { |
if (inst->src[i].file != UNIFORM || !inst->src[i].reladdr) |
continue; |
int uniform = inst->src[i].reg; |
/* If this array isn't already present in the pull constant buffer, |
* add it. |
*/ |
if (pull_constant_loc[uniform] == -1) { |
const float **values = &prog_data->param[uniform * 4]; |
pull_constant_loc[uniform] = prog_data->nr_pull_params / 4; |
for (int j = 0; j < uniform_size[uniform] * 4; j++) { |
prog_data->pull_param[prog_data->nr_pull_params++] |
= values[j]; |
} |
} |
/* Set up the annotation tracking for new generated instructions. */ |
base_ir = inst->ir; |
current_annotation = inst->annotation; |
dst_reg temp = dst_reg(this, glsl_type::vec4_type); |
emit_pull_constant_load(inst, temp, inst->src[i], |
pull_constant_loc[uniform]); |
inst->src[i].file = temp.file; |
inst->src[i].reg = temp.reg; |
inst->src[i].reg_offset = temp.reg_offset; |
inst->src[i].reladdr = NULL; |
} |
} |
/* Now there are no accesses of the UNIFORM file with a reladdr, so |
* no need to track them as larger-than-vec4 objects. This will be |
* relied on in cutting out unused uniform vectors from push |
* constants. |
*/ |
split_uniform_registers(); |
} |
void |
vec4_visitor::resolve_ud_negate(src_reg *reg) |
{ |
if (reg->type != BRW_REGISTER_TYPE_UD || |
!reg->negate) |
return; |
src_reg temp = src_reg(this, glsl_type::uvec4_type); |
emit(BRW_OPCODE_MOV, dst_reg(temp), *reg); |
*reg = temp; |
} |
vec4_visitor::vec4_visitor(struct brw_context *brw, |
struct brw_vec4_compile *c, |
struct gl_program *prog, |
const struct brw_vec4_prog_key *key, |
struct brw_vec4_prog_data *prog_data, |
struct gl_shader_program *shader_prog, |
struct brw_shader *shader, |
void *mem_ctx, |
bool debug_flag) |
: debug_flag(debug_flag) |
{ |
this->brw = brw; |
this->ctx = &brw->ctx; |
this->shader_prog = shader_prog; |
this->shader = shader; |
this->mem_ctx = mem_ctx; |
this->failed = false; |
this->base_ir = NULL; |
this->current_annotation = NULL; |
memset(this->output_reg_annotation, 0, sizeof(this->output_reg_annotation)); |
this->c = c; |
this->prog = prog; |
this->key = key; |
this->prog_data = prog_data; |
this->variable_ht = hash_table_ctor(0, |
hash_table_pointer_hash, |
hash_table_pointer_compare); |
this->virtual_grf_start = NULL; |
this->virtual_grf_end = NULL; |
this->virtual_grf_sizes = NULL; |
this->virtual_grf_count = 0; |
this->virtual_grf_reg_map = NULL; |
this->virtual_grf_reg_count = 0; |
this->virtual_grf_array_size = 0; |
this->live_intervals_valid = false; |
this->max_grf = brw->gen >= 7 ? GEN7_MRF_HACK_START : BRW_MAX_GRF; |
this->uniforms = 0; |
} |
vec4_visitor::~vec4_visitor() |
{ |
hash_table_dtor(this->variable_ht); |
} |
vec4_vs_visitor::vec4_vs_visitor(struct brw_context *brw, |
struct brw_vs_compile *vs_compile, |
struct brw_vs_prog_data *vs_prog_data, |
struct gl_shader_program *prog, |
struct brw_shader *shader, |
void *mem_ctx) |
: vec4_visitor(brw, &vs_compile->base, &vs_compile->vp->program.Base, |
&vs_compile->key.base, &vs_prog_data->base, prog, shader, |
mem_ctx, INTEL_DEBUG & DEBUG_VS), |
vs_compile(vs_compile), |
vs_prog_data(vs_prog_data) |
{ |
} |
void |
vec4_visitor::fail(const char *format, ...) |
{ |
va_list va; |
char *msg; |
if (failed) |
return; |
failed = true; |
va_start(va, format); |
msg = ralloc_vasprintf(mem_ctx, format, va); |
va_end(va); |
msg = ralloc_asprintf(mem_ctx, "VS compile failed: %s\n", msg); |
this->fail_msg = msg; |
if (debug_flag) { |
fprintf(stderr, "%s", msg); |
} |
} |
} /* namespace brw */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vec4_vp.cpp |
---|
0,0 → 1,671 |
/* |
* 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. |
*/ |
/** @file brw_vec4_vp.cpp |
* |
* A translator from Mesa IR to the i965 driver's Vec4 IR, used to implement |
* ARB_vertex_program and fixed-function vertex processing. |
*/ |
#include "brw_context.h" |
#include "brw_vec4.h" |
extern "C" { |
#include "program/prog_parameter.h" |
#include "program/prog_print.h" |
} |
using namespace brw; |
void |
vec4_visitor::emit_vp_sop(uint32_t conditional_mod, |
dst_reg dst, src_reg src0, src_reg src1, |
src_reg one) |
{ |
vec4_instruction *inst; |
inst = emit(BRW_OPCODE_CMP, dst_null_d(), src0, src1); |
inst->conditional_mod = conditional_mod; |
inst = emit(BRW_OPCODE_SEL, dst, one, src_reg(0.0f)); |
inst->predicate = BRW_PREDICATE_NORMAL; |
} |
/** |
* Reswizzle a given source register. |
* \sa brw_swizzle(). |
*/ |
static inline src_reg |
reswizzle(src_reg orig, unsigned x, unsigned y, unsigned z, unsigned w) |
{ |
src_reg t = orig; |
t.swizzle = BRW_SWIZZLE4(BRW_GET_SWZ(orig.swizzle, x), |
BRW_GET_SWZ(orig.swizzle, y), |
BRW_GET_SWZ(orig.swizzle, z), |
BRW_GET_SWZ(orig.swizzle, w)); |
return t; |
} |
void |
vec4_vs_visitor::emit_program_code() |
{ |
this->need_all_constants_in_pull_buffer = false; |
setup_vp_regs(); |
/* Keep a reg with 1.0 around, for reuse by emit_vs_sop so that it can just |
* be: |
* |
* sel.f0 dst 1.0 0.0 |
* |
* instead of |
* |
* mov dst 0.0 |
* mov.f0 dst 1.0 |
*/ |
src_reg one = src_reg(this, glsl_type::float_type); |
emit(MOV(dst_reg(one), src_reg(1.0f))); |
for (unsigned int insn = 0; insn < prog->NumInstructions; insn++) { |
const struct prog_instruction *vpi = &prog->Instructions[insn]; |
base_ir = vpi; |
dst_reg dst; |
src_reg src[3]; |
/* We always emit into a temporary destination register to avoid |
* aliasing issues. |
*/ |
dst = dst_reg(this, glsl_type::vec4_type); |
for (int i = 0; i < 3; i++) |
src[i] = get_vp_src_reg(vpi->SrcReg[i]); |
switch (vpi->Opcode) { |
case OPCODE_ABS: |
src[0].abs = true; |
src[0].negate = false; |
emit(MOV(dst, src[0])); |
break; |
case OPCODE_ADD: |
emit(ADD(dst, src[0], src[1])); |
break; |
case OPCODE_ARL: |
if (brw->gen >= 6) { |
dst.writemask = WRITEMASK_X; |
dst_reg dst_f = dst; |
dst_f.type = BRW_REGISTER_TYPE_F; |
emit(RNDD(dst_f, src[0])); |
emit(MOV(dst, src_reg(dst_f))); |
} else { |
emit(RNDD(dst, src[0])); |
} |
break; |
case OPCODE_DP3: |
emit(DP3(dst, src[0], src[1])); |
break; |
case OPCODE_DP4: |
emit(DP4(dst, src[0], src[1])); |
break; |
case OPCODE_DPH: |
emit(DPH(dst, src[0], src[1])); |
break; |
case OPCODE_DST: { |
dst_reg t = dst; |
if (vpi->DstReg.WriteMask & WRITEMASK_X) { |
t.writemask = WRITEMASK_X; |
emit(MOV(t, src_reg(1.0f))); |
} |
if (vpi->DstReg.WriteMask & WRITEMASK_Y) { |
t.writemask = WRITEMASK_Y; |
emit(MUL(t, src[0], src[1])); |
} |
if (vpi->DstReg.WriteMask & WRITEMASK_Z) { |
t.writemask = WRITEMASK_Z; |
emit(MOV(t, src[0])); |
} |
if (vpi->DstReg.WriteMask & WRITEMASK_W) { |
t.writemask = WRITEMASK_W; |
emit(MOV(t, src[1])); |
} |
break; |
} |
case OPCODE_EXP: { |
dst_reg result = dst; |
if (vpi->DstReg.WriteMask & WRITEMASK_X) { |
/* tmp_d = floor(src[0].x) */ |
src_reg tmp_d = src_reg(this, glsl_type::ivec4_type); |
assert(tmp_d.type == BRW_REGISTER_TYPE_D); |
emit(RNDD(dst_reg(tmp_d), reswizzle(src[0], 0, 0, 0, 0))); |
/* result[0] = 2.0 ^ tmp */ |
/* Adjust exponent for floating point: exp += 127 */ |
dst_reg tmp_d_x(GRF, tmp_d.reg, glsl_type::int_type, WRITEMASK_X); |
emit(ADD(tmp_d_x, tmp_d, src_reg(127))); |
/* Install exponent and sign. Excess drops off the edge: */ |
dst_reg res_d_x(GRF, result.reg, glsl_type::int_type, WRITEMASK_X); |
emit(BRW_OPCODE_SHL, res_d_x, tmp_d, src_reg(23)); |
} |
if (vpi->DstReg.WriteMask & WRITEMASK_Y) { |
result.writemask = WRITEMASK_Y; |
emit(FRC(result, src[0])); |
} |
if (vpi->DstReg.WriteMask & WRITEMASK_Z) { |
result.writemask = WRITEMASK_Z; |
emit_math(SHADER_OPCODE_EXP2, result, src[0]); |
} |
if (vpi->DstReg.WriteMask & WRITEMASK_W) { |
result.writemask = WRITEMASK_W; |
emit(MOV(result, src_reg(1.0f))); |
} |
break; |
} |
case OPCODE_EX2: |
emit_math(SHADER_OPCODE_EXP2, dst, src[0]); |
break; |
case OPCODE_FLR: |
emit(RNDD(dst, src[0])); |
break; |
case OPCODE_FRC: |
emit(FRC(dst, src[0])); |
break; |
case OPCODE_LG2: |
emit_math(SHADER_OPCODE_LOG2, dst, src[0]); |
break; |
case OPCODE_LIT: { |
dst_reg result = dst; |
/* From the ARB_vertex_program spec: |
* |
* tmp = VectorLoad(op0); |
* if (tmp.x < 0) tmp.x = 0; |
* if (tmp.y < 0) tmp.y = 0; |
* if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon); |
* else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon; |
* result.x = 1.0; |
* result.y = tmp.x; |
* result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0; |
* result.w = 1.0; |
* |
* Note that we don't do the clamping to +/- 128. We didn't in |
* brw_vs_emit.c either. |
*/ |
if (vpi->DstReg.WriteMask & WRITEMASK_XW) { |
result.writemask = WRITEMASK_XW; |
emit(MOV(result, src_reg(1.0f))); |
} |
if (vpi->DstReg.WriteMask & WRITEMASK_YZ) { |
result.writemask = WRITEMASK_YZ; |
emit(MOV(result, src_reg(0.0f))); |
src_reg tmp_x = reswizzle(src[0], 0, 0, 0, 0); |
emit(CMP(dst_null_d(), tmp_x, src_reg(0.0f), BRW_CONDITIONAL_G)); |
emit(IF(BRW_PREDICATE_NORMAL)); |
if (vpi->DstReg.WriteMask & WRITEMASK_Y) { |
result.writemask = WRITEMASK_Y; |
emit(MOV(result, tmp_x)); |
} |
if (vpi->DstReg.WriteMask & WRITEMASK_Z) { |
/* if (tmp.y < 0) tmp.y = 0; */ |
src_reg tmp_y = reswizzle(src[0], 1, 1, 1, 1); |
result.writemask = WRITEMASK_Z; |
emit_minmax(BRW_CONDITIONAL_G, result, tmp_y, src_reg(0.0f)); |
src_reg clamped_y(result); |
clamped_y.swizzle = BRW_SWIZZLE_ZZZZ; |
src_reg tmp_w = reswizzle(src[0], 3, 3, 3, 3); |
emit_math(SHADER_OPCODE_POW, result, clamped_y, tmp_w); |
} |
emit(BRW_OPCODE_ENDIF); |
} |
break; |
} |
case OPCODE_LOG: { |
dst_reg result = dst; |
result.type = BRW_REGISTER_TYPE_UD; |
src_reg result_src = src_reg(result); |
src_reg arg0_ud = reswizzle(src[0], 0, 0, 0, 0); |
arg0_ud.type = BRW_REGISTER_TYPE_UD; |
/* Perform mant = frexpf(fabsf(x), &exp), adjust exp and mnt |
* according to spec: |
* |
* These almost look likey they could be joined up, but not really |
* practical: |
* |
* result[0].f = (x.i & ((1<<31)-1) >> 23) - 127 |
* result[1].i = (x.i & ((1<<23)-1) + (127<<23) |
*/ |
if (vpi->DstReg.WriteMask & WRITEMASK_XZ) { |
result.writemask = WRITEMASK_X; |
emit(AND(result, arg0_ud, src_reg((1u << 31) - 1))); |
emit(BRW_OPCODE_SHR, result, result_src, src_reg(23u)); |
src_reg result_d(result_src); |
result_d.type = BRW_REGISTER_TYPE_D; /* does it matter? */ |
result.type = BRW_REGISTER_TYPE_F; |
emit(ADD(result, result_d, src_reg(-127))); |
} |
if (vpi->DstReg.WriteMask & WRITEMASK_YZ) { |
result.writemask = WRITEMASK_Y; |
result.type = BRW_REGISTER_TYPE_UD; |
emit(AND(result, arg0_ud, src_reg((1u << 23) - 1))); |
emit(OR(result, result_src, src_reg(127u << 23))); |
} |
if (vpi->DstReg.WriteMask & WRITEMASK_Z) { |
/* result[2] = result[0] + LOG2(result[1]); */ |
/* Why bother? The above is just a hint how to do this with a |
* taylor series. Maybe we *should* use a taylor series as by |
* the time all the above has been done it's almost certainly |
* quicker than calling the mathbox, even with low precision. |
* |
* Options are: |
* - result[0] + mathbox.LOG2(result[1]) |
* - mathbox.LOG2(arg0.x) |
* - result[0] + inline_taylor_approx(result[1]) |
*/ |
result.type = BRW_REGISTER_TYPE_F; |
result.writemask = WRITEMASK_Z; |
src_reg result_x(result), result_y(result), result_z(result); |
result_x.swizzle = BRW_SWIZZLE_XXXX; |
result_y.swizzle = BRW_SWIZZLE_YYYY; |
result_z.swizzle = BRW_SWIZZLE_ZZZZ; |
emit_math(SHADER_OPCODE_LOG2, result, result_y); |
emit(ADD(result, result_z, result_x)); |
} |
if (vpi->DstReg.WriteMask & WRITEMASK_W) { |
result.type = BRW_REGISTER_TYPE_F; |
result.writemask = WRITEMASK_W; |
emit(MOV(result, src_reg(1.0f))); |
} |
break; |
} |
case OPCODE_MAD: { |
src_reg temp = src_reg(this, glsl_type::vec4_type); |
emit(MUL(dst_reg(temp), src[0], src[1])); |
emit(ADD(dst, temp, src[2])); |
break; |
} |
case OPCODE_MAX: |
emit_minmax(BRW_CONDITIONAL_G, dst, src[0], src[1]); |
break; |
case OPCODE_MIN: |
emit_minmax(BRW_CONDITIONAL_L, dst, src[0], src[1]); |
break; |
case OPCODE_MOV: |
emit(MOV(dst, src[0])); |
break; |
case OPCODE_MUL: |
emit(MUL(dst, src[0], src[1])); |
break; |
case OPCODE_POW: |
emit_math(SHADER_OPCODE_POW, dst, src[0], src[1]); |
break; |
case OPCODE_RCP: |
emit_math(SHADER_OPCODE_RCP, dst, src[0]); |
break; |
case OPCODE_RSQ: |
emit_math(SHADER_OPCODE_RSQ, dst, src[0]); |
break; |
case OPCODE_SGE: |
emit_vp_sop(BRW_CONDITIONAL_GE, dst, src[0], src[1], one); |
break; |
case OPCODE_SLT: |
emit_vp_sop(BRW_CONDITIONAL_L, dst, src[0], src[1], one); |
break; |
case OPCODE_SUB: { |
src_reg neg_src1 = src[1]; |
neg_src1.negate = !src[1].negate; |
emit(ADD(dst, src[0], neg_src1)); |
break; |
} |
case OPCODE_SWZ: |
/* Note that SWZ's extended swizzles are handled in the general |
* get_src_reg() code. |
*/ |
emit(MOV(dst, src[0])); |
break; |
case OPCODE_XPD: { |
src_reg t1 = src_reg(this, glsl_type::vec4_type); |
src_reg t2 = src_reg(this, glsl_type::vec4_type); |
emit(MUL(dst_reg(t1), |
reswizzle(src[0], 1, 2, 0, 3), |
reswizzle(src[1], 2, 0, 1, 3))); |
emit(MUL(dst_reg(t2), |
reswizzle(src[0], 2, 0, 1, 3), |
reswizzle(src[1], 1, 2, 0, 3))); |
t2.negate = true; |
emit(ADD(dst, t1, t2)); |
break; |
} |
case OPCODE_END: |
break; |
default: |
_mesa_problem(ctx, "Unsupported opcode %s in vertex program\n", |
_mesa_opcode_string(vpi->Opcode)); |
} |
/* Copy the temporary back into the actual destination register. */ |
if (vpi->Opcode != OPCODE_END) { |
emit(MOV(get_vp_dst_reg(vpi->DstReg), src_reg(dst))); |
} |
} |
/* If we used relative addressing, we need to upload all constants as |
* pull constants. Do that now. |
*/ |
if (this->need_all_constants_in_pull_buffer) { |
const struct gl_program_parameter_list *params = |
vs_compile->vp->program.Base.Parameters; |
unsigned i; |
for (i = 0; i < params->NumParameters * 4; i++) { |
prog_data->pull_param[i] = |
¶ms->ParameterValues[i / 4][i % 4].f; |
} |
prog_data->nr_pull_params = i; |
} |
} |
void |
vec4_vs_visitor::setup_vp_regs() |
{ |
/* PROGRAM_TEMPORARY */ |
int num_temp = prog->NumTemporaries; |
vp_temp_regs = rzalloc_array(mem_ctx, src_reg, num_temp); |
for (int i = 0; i < num_temp; i++) |
vp_temp_regs[i] = src_reg(this, glsl_type::vec4_type); |
/* PROGRAM_STATE_VAR etc. */ |
struct gl_program_parameter_list *plist = |
vs_compile->vp->program.Base.Parameters; |
for (unsigned p = 0; p < plist->NumParameters; p++) { |
unsigned components = plist->Parameters[p].Size; |
/* Parameters should be either vec4 uniforms or single component |
* constants; matrices and other larger types should have been broken |
* down earlier. |
*/ |
assert(components <= 4); |
this->uniform_size[this->uniforms] = 1; /* 1 vec4 */ |
this->uniform_vector_size[this->uniforms] = components; |
for (unsigned i = 0; i < 4; i++) { |
prog_data->param[this->uniforms * 4 + i] = i >= components |
? 0 : &plist->ParameterValues[p][i].f; |
} |
this->uniforms++; /* counted in vec4 units */ |
} |
/* PROGRAM_OUTPUT */ |
for (int slot = 0; slot < prog_data->vue_map.num_slots; slot++) { |
int varying = prog_data->vue_map.slot_to_varying[slot]; |
if (varying == VARYING_SLOT_PSIZ) |
output_reg[varying] = dst_reg(this, glsl_type::float_type); |
else |
output_reg[varying] = dst_reg(this, glsl_type::vec4_type); |
assert(output_reg[varying].type == BRW_REGISTER_TYPE_F); |
} |
/* PROGRAM_ADDRESS */ |
this->vp_addr_reg = src_reg(this, glsl_type::int_type); |
assert(this->vp_addr_reg.type == BRW_REGISTER_TYPE_D); |
} |
dst_reg |
vec4_vs_visitor::get_vp_dst_reg(const prog_dst_register &dst) |
{ |
dst_reg result; |
assert(!dst.RelAddr); |
switch (dst.File) { |
case PROGRAM_TEMPORARY: |
result = dst_reg(vp_temp_regs[dst.Index]); |
break; |
case PROGRAM_OUTPUT: |
result = output_reg[dst.Index]; |
break; |
case PROGRAM_ADDRESS: { |
assert(dst.Index == 0); |
result = dst_reg(this->vp_addr_reg); |
break; |
} |
case PROGRAM_UNDEFINED: |
return dst_null_f(); |
default: |
assert("vec4_vp: bad destination register file"); |
return dst_reg(this, glsl_type::vec4_type); |
} |
result.writemask = dst.WriteMask; |
return result; |
} |
src_reg |
vec4_vs_visitor::get_vp_src_reg(const prog_src_register &src) |
{ |
struct gl_program_parameter_list *plist = |
vs_compile->vp->program.Base.Parameters; |
src_reg result; |
assert(!src.Abs); |
switch (src.File) { |
case PROGRAM_UNDEFINED: |
return src_reg(brw_null_reg()); |
case PROGRAM_TEMPORARY: |
result = vp_temp_regs[src.Index]; |
break; |
case PROGRAM_INPUT: |
result = src_reg(ATTR, src.Index, glsl_type::vec4_type); |
result.type = BRW_REGISTER_TYPE_F; |
break; |
case PROGRAM_ADDRESS: { |
assert(src.Index == 0); |
result = this->vp_addr_reg; |
break; |
} |
case PROGRAM_STATE_VAR: |
case PROGRAM_CONSTANT: |
/* From the ARB_vertex_program specification: |
* "Relative addressing can only be used for accessing program |
* parameter arrays." |
*/ |
if (src.RelAddr) { |
/* Since we have no idea what the base of the array is, we need to |
* upload ALL constants as push constants. |
*/ |
this->need_all_constants_in_pull_buffer = true; |
/* Add the small constant index to the address register */ |
src_reg reladdr = src_reg(this, glsl_type::int_type); |
dst_reg dst_reladdr = dst_reg(reladdr); |
dst_reladdr.writemask = WRITEMASK_X; |
emit(ADD(dst_reladdr, this->vp_addr_reg, src_reg(src.Index))); |
if (brw->gen < 6) |
emit(MUL(dst_reladdr, reladdr, src_reg(16))); |
#if 0 |
assert(src.Index < this->uniforms); |
result = src_reg(dst_reg(UNIFORM, 0)); |
result.type = BRW_REGISTER_TYPE_F; |
result.reladdr = new(mem_ctx) src_reg(); |
memcpy(result.reladdr, &reladdr, sizeof(src_reg)); |
#endif |
result = src_reg(this, glsl_type::vec4_type); |
src_reg surf_index = src_reg(unsigned(SURF_INDEX_VERT_CONST_BUFFER)); |
vec4_instruction *load = |
new(mem_ctx) vec4_instruction(this, VS_OPCODE_PULL_CONSTANT_LOAD, |
dst_reg(result), surf_index, reladdr); |
load->base_mrf = 14; |
load->mlen = 1; |
emit(load); |
break; |
} |
/* We actually want to look at the type in the Parameters list for this, |
* because this lets us upload constant builtin uniforms as actual |
* constants. |
*/ |
switch (plist->Parameters[src.Index].Type) { |
case PROGRAM_CONSTANT: |
result = src_reg(this, glsl_type::vec4_type); |
for (int i = 0; i < 4; i++) { |
dst_reg t = dst_reg(result); |
t.writemask = 1 << i; |
emit(MOV(t, src_reg(plist->ParameterValues[src.Index][i].f))); |
} |
break; |
case PROGRAM_STATE_VAR: |
assert(src.Index < this->uniforms); |
result = src_reg(dst_reg(UNIFORM, src.Index)); |
result.type = BRW_REGISTER_TYPE_F; |
break; |
default: |
_mesa_problem(ctx, "bad uniform src register file: %s\n", |
_mesa_register_file_name((gl_register_file)src.File)); |
return src_reg(this, glsl_type::vec4_type); |
} |
break; |
default: |
_mesa_problem(ctx, "bad src register file: %s\n", |
_mesa_register_file_name((gl_register_file)src.File)); |
return src_reg(this, glsl_type::vec4_type); |
} |
if (src.Swizzle != SWIZZLE_NOOP || src.Negate) { |
unsigned short zeros_mask = 0; |
unsigned short ones_mask = 0; |
unsigned short src_mask = 0; |
unsigned short src_swiz[4]; |
for (int i = 0; i < 4; i++) { |
src_swiz[i] = 0; /* initialize for safety */ |
/* The ZERO, ONE, and Negate options are only used for OPCODE_SWZ, |
* but it's simplest to handle it here. |
*/ |
int s = GET_SWZ(src.Swizzle, i); |
switch (s) { |
case SWIZZLE_X: |
case SWIZZLE_Y: |
case SWIZZLE_Z: |
case SWIZZLE_W: |
src_mask |= 1 << i; |
src_swiz[i] = s; |
break; |
case SWIZZLE_ZERO: |
zeros_mask |= 1 << i; |
break; |
case SWIZZLE_ONE: |
ones_mask |= 1 << i; |
break; |
} |
} |
result.swizzle = |
BRW_SWIZZLE4(src_swiz[0], src_swiz[1], src_swiz[2], src_swiz[3]); |
/* The hardware doesn't natively handle the SWZ instruction's zero/one |
* swizzles or per-component negation, so we need to use a temporary. |
*/ |
if (zeros_mask || ones_mask || src.Negate) { |
src_reg temp_src(this, glsl_type::vec4_type); |
dst_reg temp(temp_src); |
if (src_mask) { |
temp.writemask = src_mask; |
emit(MOV(temp, result)); |
} |
if (zeros_mask) { |
temp.writemask = zeros_mask; |
emit(MOV(temp, src_reg(0.0f))); |
} |
if (ones_mask) { |
temp.writemask = ones_mask; |
emit(MOV(temp, src_reg(1.0f))); |
} |
if (src.Negate) { |
temp.writemask = src.Negate; |
src_reg neg(temp_src); |
neg.negate = true; |
emit(MOV(temp, neg)); |
} |
result = temp_src; |
} |
} |
return result; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vs.c |
---|
0,0 → 1,581 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/compiler.h" |
#include "brw_context.h" |
#include "brw_vs.h" |
#include "brw_util.h" |
#include "brw_state.h" |
#include "program/prog_print.h" |
#include "program/prog_parameter.h" |
#include "glsl/ralloc.h" |
static inline void assign_vue_slot(struct brw_vue_map *vue_map, |
int varying) |
{ |
/* Make sure this varying hasn't been assigned a slot already */ |
assert (vue_map->varying_to_slot[varying] == -1); |
vue_map->varying_to_slot[varying] = vue_map->num_slots; |
vue_map->slot_to_varying[vue_map->num_slots++] = varying; |
} |
/** |
* Compute the VUE map for vertex shader program. |
* |
* Note that consumers of this map using cache keys must include |
* prog_data->userclip and prog_data->outputs_written in their key |
* (generated by CACHE_NEW_VS_PROG). |
*/ |
void |
brw_compute_vue_map(struct brw_context *brw, struct brw_vue_map *vue_map, |
GLbitfield64 slots_valid, bool userclip_active) |
{ |
vue_map->slots_valid = slots_valid; |
int i; |
/* Make sure that the values we store in vue_map->varying_to_slot and |
* vue_map->slot_to_varying won't overflow the signed chars that are used |
* to store them. Note that since vue_map->slot_to_varying sometimes holds |
* values equal to BRW_VARYING_SLOT_COUNT, we need to ensure that |
* BRW_VARYING_SLOT_COUNT is <= 127, not 128. |
*/ |
STATIC_ASSERT(BRW_VARYING_SLOT_COUNT <= 127); |
vue_map->num_slots = 0; |
for (i = 0; i < BRW_VARYING_SLOT_COUNT; ++i) { |
vue_map->varying_to_slot[i] = -1; |
vue_map->slot_to_varying[i] = BRW_VARYING_SLOT_COUNT; |
} |
/* VUE header: format depends on chip generation and whether clipping is |
* enabled. |
*/ |
switch (brw->gen) { |
case 4: |
case 5: |
/* There are 8 dwords in VUE header pre-Ironlake: |
* dword 0-3 is indices, point width, clip flags. |
* dword 4-7 is ndc position |
* dword 8-11 is the first vertex data. |
* |
* On Ironlake the VUE header is nominally 20 dwords, but the hardware |
* will accept the same header layout as Gen4 [and should be a bit faster] |
*/ |
assign_vue_slot(vue_map, VARYING_SLOT_PSIZ); |
assign_vue_slot(vue_map, BRW_VARYING_SLOT_NDC); |
assign_vue_slot(vue_map, VARYING_SLOT_POS); |
break; |
case 6: |
case 7: |
/* There are 8 or 16 DWs (D0-D15) in VUE header on Sandybridge: |
* dword 0-3 of the header is indices, point width, clip flags. |
* dword 4-7 is the 4D space position |
* dword 8-15 of the vertex header is the user clip distance if |
* enabled. |
* dword 8-11 or 16-19 is the first vertex element data we fill. |
*/ |
assign_vue_slot(vue_map, VARYING_SLOT_PSIZ); |
assign_vue_slot(vue_map, VARYING_SLOT_POS); |
if (userclip_active) { |
assign_vue_slot(vue_map, VARYING_SLOT_CLIP_DIST0); |
assign_vue_slot(vue_map, VARYING_SLOT_CLIP_DIST1); |
} |
/* front and back colors need to be consecutive so that we can use |
* ATTRIBUTE_SWIZZLE_INPUTATTR_FACING to swizzle them when doing |
* two-sided color. |
*/ |
if (slots_valid & BITFIELD64_BIT(VARYING_SLOT_COL0)) |
assign_vue_slot(vue_map, VARYING_SLOT_COL0); |
if (slots_valid & BITFIELD64_BIT(VARYING_SLOT_BFC0)) |
assign_vue_slot(vue_map, VARYING_SLOT_BFC0); |
if (slots_valid & BITFIELD64_BIT(VARYING_SLOT_COL1)) |
assign_vue_slot(vue_map, VARYING_SLOT_COL1); |
if (slots_valid & BITFIELD64_BIT(VARYING_SLOT_BFC1)) |
assign_vue_slot(vue_map, VARYING_SLOT_BFC1); |
break; |
default: |
assert (!"VUE map not known for this chip generation"); |
break; |
} |
/* The hardware doesn't care about the rest of the vertex outputs, so just |
* assign them contiguously. Don't reassign outputs that already have a |
* slot. |
* |
* We generally don't need to assign a slot for VARYING_SLOT_CLIP_VERTEX, |
* since it's encoded as the clip distances by emit_clip_distances(). |
* However, it may be output by transform feedback, and we'd rather not |
* recompute state when TF changes, so we just always include it. |
*/ |
for (int i = 0; i < VARYING_SLOT_MAX; ++i) { |
if ((slots_valid & BITFIELD64_BIT(i)) && |
vue_map->varying_to_slot[i] == -1) { |
assign_vue_slot(vue_map, i); |
} |
} |
} |
/** |
* Decide which set of clip planes should be used when clipping via |
* gl_Position or gl_ClipVertex. |
*/ |
gl_clip_plane *brw_select_clip_planes(struct gl_context *ctx) |
{ |
if (ctx->Shader.CurrentVertexProgram) { |
/* There is currently a GLSL vertex shader, so clip according to GLSL |
* rules, which means compare gl_ClipVertex (or gl_Position, if |
* gl_ClipVertex wasn't assigned) against the eye-coordinate clip planes |
* that were stored in EyeUserPlane at the time the clip planes were |
* specified. |
*/ |
return ctx->Transform.EyeUserPlane; |
} else { |
/* Either we are using fixed function or an ARB vertex program. In |
* either case the clip planes are going to be compared against |
* gl_Position (which is in clip coordinates) so we have to clip using |
* _ClipUserPlane, which was transformed into clip coordinates by Mesa |
* core. |
*/ |
return ctx->Transform._ClipUserPlane; |
} |
} |
bool |
brw_vec4_prog_data_compare(const struct brw_vec4_prog_data *a, |
const struct brw_vec4_prog_data *b) |
{ |
/* Compare all the struct up to the pointers. */ |
if (memcmp(a, b, offsetof(struct brw_vec4_prog_data, param))) |
return false; |
if (memcmp(a->param, b->param, a->nr_params * sizeof(void *))) |
return false; |
if (memcmp(a->pull_param, b->pull_param, a->nr_pull_params * sizeof(void *))) |
return false; |
return true; |
} |
bool |
brw_vs_prog_data_compare(const void *in_a, const void *in_b, |
int aux_size, const void *in_key) |
{ |
const struct brw_vs_prog_data *a = in_a; |
const struct brw_vs_prog_data *b = in_b; |
/* Compare the base vec4 structure. */ |
if (!brw_vec4_prog_data_compare(&a->base, &b->base)) |
return false; |
/* Compare the rest of the struct. */ |
const unsigned offset = sizeof(struct brw_vec4_prog_data); |
if (memcmp(((char *) a) + offset, ((char *) b) + offset, |
sizeof(struct brw_vs_prog_data) - offset)) { |
return false; |
} |
return true; |
} |
static bool |
do_vs_prog(struct brw_context *brw, |
struct gl_shader_program *prog, |
struct brw_vertex_program *vp, |
struct brw_vs_prog_key *key) |
{ |
GLuint program_size; |
const GLuint *program; |
struct brw_vs_compile c; |
struct brw_vs_prog_data prog_data; |
void *mem_ctx; |
int i; |
struct gl_shader *vs = NULL; |
if (prog) |
vs = prog->_LinkedShaders[MESA_SHADER_VERTEX]; |
memset(&c, 0, sizeof(c)); |
memcpy(&c.key, key, sizeof(*key)); |
memset(&prog_data, 0, sizeof(prog_data)); |
mem_ctx = ralloc_context(NULL); |
c.vp = vp; |
/* Allocate the references to the uniforms that will end up in the |
* prog_data associated with the compiled program, and which will be freed |
* by the state cache. |
*/ |
int param_count; |
if (vs) { |
/* We add padding around uniform values below vec4 size, with the worst |
* case being a float value that gets blown up to a vec4, so be |
* conservative here. |
*/ |
param_count = vs->num_uniform_components * 4; |
} else { |
param_count = vp->program.Base.Parameters->NumParameters * 4; |
} |
/* We also upload clip plane data as uniforms */ |
param_count += MAX_CLIP_PLANES * 4; |
prog_data.base.param = rzalloc_array(NULL, const float *, param_count); |
prog_data.base.pull_param = rzalloc_array(NULL, const float *, param_count); |
GLbitfield64 outputs_written = vp->program.Base.OutputsWritten; |
prog_data.inputs_read = vp->program.Base.InputsRead; |
if (c.key.copy_edgeflag) { |
outputs_written |= BITFIELD64_BIT(VARYING_SLOT_EDGE); |
prog_data.inputs_read |= VERT_BIT_EDGEFLAG; |
} |
if (brw->gen < 6) { |
/* Put dummy slots into the VUE for the SF to put the replaced |
* point sprite coords in. We shouldn't need these dummy slots, |
* which take up precious URB space, but it would mean that the SF |
* doesn't get nice aligned pairs of input coords into output |
* coords, which would be a pain to handle. |
*/ |
for (i = 0; i < 8; i++) { |
if (c.key.point_coord_replace & (1 << i)) |
outputs_written |= BITFIELD64_BIT(VARYING_SLOT_TEX0 + i); |
} |
/* if back colors are written, allocate slots for front colors too */ |
if (outputs_written & BITFIELD64_BIT(VARYING_SLOT_BFC0)) |
outputs_written |= BITFIELD64_BIT(VARYING_SLOT_COL0); |
if (outputs_written & BITFIELD64_BIT(VARYING_SLOT_BFC1)) |
outputs_written |= BITFIELD64_BIT(VARYING_SLOT_COL1); |
} |
brw_compute_vue_map(brw, &prog_data.base.vue_map, outputs_written, |
c.key.base.userclip_active); |
if (0) { |
_mesa_fprint_program_opt(stdout, &c.vp->program.Base, PROG_PRINT_DEBUG, |
true); |
} |
/* Emit GEN4 code. |
*/ |
program = brw_vs_emit(brw, prog, &c, &prog_data, mem_ctx, &program_size); |
if (program == NULL) { |
ralloc_free(mem_ctx); |
return false; |
} |
if (prog_data.base.nr_pull_params) |
prog_data.base.num_surfaces = 1; |
if (c.vp->program.Base.SamplersUsed) |
prog_data.base.num_surfaces = SURF_INDEX_VS_TEXTURE(BRW_MAX_TEX_UNIT); |
if (prog && |
prog->_LinkedShaders[MESA_SHADER_VERTEX]->NumUniformBlocks) { |
prog_data.base.num_surfaces = |
SURF_INDEX_VS_UBO(prog->_LinkedShaders[MESA_SHADER_VERTEX]->NumUniformBlocks); |
} |
/* Scratch space is used for register spilling */ |
if (c.base.last_scratch) { |
perf_debug("Vertex shader triggered register spilling. " |
"Try reducing the number of live vec4 values to " |
"improve performance.\n"); |
prog_data.base.total_scratch |
= brw_get_scratch_size(c.base.last_scratch*REG_SIZE); |
brw_get_scratch_bo(brw, &brw->vs.scratch_bo, |
prog_data.base.total_scratch * brw->max_vs_threads); |
} |
brw_upload_cache(&brw->cache, BRW_VS_PROG, |
&c.key, sizeof(c.key), |
program, program_size, |
&prog_data, sizeof(prog_data), |
&brw->vs.prog_offset, &brw->vs.prog_data); |
ralloc_free(mem_ctx); |
return true; |
} |
static bool |
key_debug(struct brw_context *brw, const char *name, int a, int b) |
{ |
if (a != b) { |
perf_debug(" %s %d->%d\n", name, a, b); |
return true; |
} |
return false; |
} |
void |
brw_vs_debug_recompile(struct brw_context *brw, |
struct gl_shader_program *prog, |
const struct brw_vs_prog_key *key) |
{ |
struct brw_cache_item *c = NULL; |
const struct brw_vs_prog_key *old_key = NULL; |
bool found = false; |
perf_debug("Recompiling vertex shader for program %d\n", prog->Name); |
for (unsigned int i = 0; i < brw->cache.size; i++) { |
for (c = brw->cache.items[i]; c; c = c->next) { |
if (c->cache_id == BRW_VS_PROG) { |
old_key = c->key; |
if (old_key->base.program_string_id == key->base.program_string_id) |
break; |
} |
} |
if (c) |
break; |
} |
if (!c) { |
perf_debug(" Didn't find previous compile in the shader cache for " |
"debug\n"); |
return; |
} |
for (unsigned int i = 0; i < VERT_ATTRIB_MAX; i++) { |
found |= key_debug(brw, "Vertex attrib w/a flags", |
old_key->gl_attrib_wa_flags[i], |
key->gl_attrib_wa_flags[i]); |
} |
found |= key_debug(brw, "user clip flags", |
old_key->base.userclip_active, key->base.userclip_active); |
found |= key_debug(brw, "user clipping planes as push constants", |
old_key->base.nr_userclip_plane_consts, |
key->base.nr_userclip_plane_consts); |
found |= key_debug(brw, "clip distance enable", |
old_key->base.uses_clip_distance, key->base.uses_clip_distance); |
found |= key_debug(brw, "clip plane enable bitfield", |
old_key->base.userclip_planes_enabled_gen_4_5, |
key->base.userclip_planes_enabled_gen_4_5); |
found |= key_debug(brw, "copy edgeflag", |
old_key->copy_edgeflag, key->copy_edgeflag); |
found |= key_debug(brw, "PointCoord replace", |
old_key->point_coord_replace, key->point_coord_replace); |
found |= key_debug(brw, "vertex color clamping", |
old_key->base.clamp_vertex_color, key->base.clamp_vertex_color); |
found |= brw_debug_recompile_sampler_key(brw, &old_key->base.tex, |
&key->base.tex); |
if (!found) { |
perf_debug(" Something else\n"); |
} |
} |
static void brw_upload_vs_prog(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_vs_prog_key key; |
/* BRW_NEW_VERTEX_PROGRAM */ |
struct brw_vertex_program *vp = |
(struct brw_vertex_program *)brw->vertex_program; |
struct gl_program *prog = (struct gl_program *) brw->vertex_program; |
int i; |
memset(&key, 0, sizeof(key)); |
/* Just upload the program verbatim for now. Always send it all |
* the inputs it asks for, whether they are varying or not. |
*/ |
key.base.program_string_id = vp->id; |
key.base.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); |
key.base.uses_clip_distance = vp->program.UsesClipDistance; |
if (key.base.userclip_active && !key.base.uses_clip_distance) { |
if (brw->gen < 6) { |
key.base.nr_userclip_plane_consts |
= _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); |
key.base.userclip_planes_enabled_gen_4_5 |
= ctx->Transform.ClipPlanesEnabled; |
} else { |
key.base.nr_userclip_plane_consts |
= _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; |
} |
} |
/* _NEW_POLYGON */ |
if (brw->gen < 6) { |
key.copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL); |
} |
/* _NEW_LIGHT | _NEW_BUFFERS */ |
key.base.clamp_vertex_color = ctx->Light._ClampVertexColor; |
/* _NEW_POINT */ |
if (brw->gen < 6 && ctx->Point.PointSprite) { |
for (i = 0; i < 8; i++) { |
if (ctx->Point.CoordReplace[i]) |
key.point_coord_replace |= (1 << i); |
} |
} |
/* _NEW_TEXTURE */ |
brw_populate_sampler_prog_key_data(ctx, prog, &key.base.tex); |
/* BRW_NEW_VERTICES */ |
if (brw->gen < 8 && !brw->is_haswell) { |
/* Prior to Haswell, the hardware can't natively support GL_FIXED or |
* 2_10_10_10_REV vertex formats. Set appropriate workaround flags. |
*/ |
for (i = 0; i < VERT_ATTRIB_MAX; i++) { |
if (!(vp->program.Base.InputsRead & BITFIELD64_BIT(i))) |
continue; |
uint8_t wa_flags = 0; |
switch (brw->vb.inputs[i].glarray->Type) { |
case GL_FIXED: |
wa_flags = brw->vb.inputs[i].glarray->Size; |
break; |
case GL_INT_2_10_10_10_REV: |
wa_flags |= BRW_ATTRIB_WA_SIGN; |
/* fallthough */ |
case GL_UNSIGNED_INT_2_10_10_10_REV: |
if (brw->vb.inputs[i].glarray->Format == GL_BGRA) |
wa_flags |= BRW_ATTRIB_WA_BGRA; |
if (brw->vb.inputs[i].glarray->Normalized) |
wa_flags |= BRW_ATTRIB_WA_NORMALIZE; |
else if (!brw->vb.inputs[i].glarray->Integer) |
wa_flags |= BRW_ATTRIB_WA_SCALE; |
break; |
} |
key.gl_attrib_wa_flags[i] = wa_flags; |
} |
} |
if (!brw_search_cache(&brw->cache, BRW_VS_PROG, |
&key, sizeof(key), |
&brw->vs.prog_offset, &brw->vs.prog_data)) { |
bool success = do_vs_prog(brw, ctx->Shader.CurrentVertexProgram, |
vp, &key); |
assert(success); |
} |
if (memcmp(&brw->vs.prog_data->base.vue_map, &brw->vue_map_geom_out, |
sizeof(brw->vue_map_geom_out)) != 0) { |
brw->vue_map_geom_out = brw->vs.prog_data->base.vue_map; |
brw->state.dirty.brw |= BRW_NEW_VUE_MAP_GEOM_OUT; |
} |
} |
/* See brw_vs.c: |
*/ |
const struct brw_tracked_state brw_vs_prog = { |
.dirty = { |
.mesa = (_NEW_TRANSFORM | _NEW_POLYGON | _NEW_POINT | _NEW_LIGHT | |
_NEW_TEXTURE | |
_NEW_BUFFERS), |
.brw = (BRW_NEW_VERTEX_PROGRAM | |
BRW_NEW_VERTICES), |
.cache = 0 |
}, |
.emit = brw_upload_vs_prog |
}; |
bool |
brw_vs_precompile(struct gl_context *ctx, struct gl_shader_program *prog) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct brw_vs_prog_key key; |
uint32_t old_prog_offset = brw->vs.prog_offset; |
struct brw_vs_prog_data *old_prog_data = brw->vs.prog_data; |
bool success; |
if (!prog->_LinkedShaders[MESA_SHADER_VERTEX]) |
return true; |
struct gl_vertex_program *vp = (struct gl_vertex_program *) |
prog->_LinkedShaders[MESA_SHADER_VERTEX]->Program; |
struct brw_vertex_program *bvp = brw_vertex_program(vp); |
memset(&key, 0, sizeof(key)); |
key.base.program_string_id = bvp->id; |
key.base.clamp_vertex_color = ctx->API == API_OPENGL_COMPAT; |
for (int i = 0; i < MAX_SAMPLERS; i++) { |
if (vp->Base.ShadowSamplers & (1 << i)) { |
/* Assume DEPTH_TEXTURE_MODE is the default: X, X, X, 1 */ |
key.base.tex.swizzles[i] = |
MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); |
} else { |
/* Color sampler: assume no swizzling. */ |
key.base.tex.swizzles[i] = SWIZZLE_XYZW; |
} |
} |
success = do_vs_prog(brw, prog, bvp, &key); |
brw->vs.prog_offset = old_prog_offset; |
brw->vs.prog_data = old_prog_data; |
return success; |
} |
void |
brw_vec4_prog_data_free(const struct brw_vec4_prog_data *prog_data) |
{ |
ralloc_free((void *)prog_data->param); |
ralloc_free((void *)prog_data->pull_param); |
} |
void |
brw_vs_prog_data_free(const void *in_prog_data) |
{ |
const struct brw_vs_prog_data *prog_data = in_prog_data; |
brw_vec4_prog_data_free(&prog_data->base); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vs.h |
---|
0,0 → 1,140 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 BRW_VS_H |
#define BRW_VS_H |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_program.h" |
#include "program/program.h" |
/** |
* The VF can't natively handle certain types of attributes, such as GL_FIXED |
* or most 10_10_10_2 types. These flags enable various VS workarounds to |
* "fix" attributes at the beginning of shaders. |
*/ |
#define BRW_ATTRIB_WA_COMPONENT_MASK 7 /* mask for GL_FIXED scale channel count */ |
#define BRW_ATTRIB_WA_NORMALIZE 8 /* normalize in shader */ |
#define BRW_ATTRIB_WA_BGRA 16 /* swap r/b channels in shader */ |
#define BRW_ATTRIB_WA_SIGN 32 /* interpret as signed in shader */ |
#define BRW_ATTRIB_WA_SCALE 64 /* interpret as scaled in shader */ |
struct brw_vec4_prog_key { |
GLuint program_string_id; |
/** |
* True if at least one clip flag is enabled, regardless of whether the |
* shader uses clip planes or gl_ClipDistance. |
*/ |
GLuint userclip_active:1; |
/** |
* How many user clipping planes are being uploaded to the vertex shader as |
* push constants. |
*/ |
GLuint nr_userclip_plane_consts:4; |
/** |
* True if the shader uses gl_ClipDistance, regardless of whether any clip |
* flags are enabled. |
*/ |
GLuint uses_clip_distance:1; |
/** |
* For pre-Gen6 hardware, a bitfield indicating which clipping planes are |
* enabled. This is used to compact clip planes. |
* |
* For Gen6 and later hardware, clip planes are not compacted, so this |
* value is zero to avoid provoking unnecessary shader recompiles. |
*/ |
GLuint userclip_planes_enabled_gen_4_5:MAX_CLIP_PLANES; |
GLuint clamp_vertex_color:1; |
struct brw_sampler_prog_key_data tex; |
}; |
struct brw_vs_prog_key { |
struct brw_vec4_prog_key base; |
/* |
* Per-attribute workaround flags |
*/ |
uint8_t gl_attrib_wa_flags[VERT_ATTRIB_MAX]; |
GLuint copy_edgeflag:1; |
/** |
* For pre-Gen6 hardware, a bitfield indicating which texture coordinates |
* are going to be replaced with point coordinates (as a consequence of a |
* call to glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE)). Because |
* our SF thread requires exact matching between VS outputs and FS inputs, |
* these texture coordinates will need to be unconditionally included in |
* the VUE, even if they aren't written by the vertex shader. |
*/ |
GLuint point_coord_replace:8; |
}; |
struct brw_vec4_compile { |
GLuint last_scratch; /**< measured in 32-byte (register size) units */ |
}; |
struct brw_vs_compile { |
struct brw_vec4_compile base; |
struct brw_vs_prog_key key; |
struct brw_vertex_program *vp; |
}; |
const unsigned *brw_vs_emit(struct brw_context *brw, |
struct gl_shader_program *prog, |
struct brw_vs_compile *c, |
struct brw_vs_prog_data *prog_data, |
void *mem_ctx, |
unsigned *program_size); |
bool brw_vs_precompile(struct gl_context *ctx, struct gl_shader_program *prog); |
void brw_vs_debug_recompile(struct brw_context *brw, |
struct gl_shader_program *prog, |
const struct brw_vs_prog_key *key); |
bool brw_vec4_prog_data_compare(const struct brw_vec4_prog_data *a, |
const struct brw_vec4_prog_data *b); |
bool brw_vs_prog_data_compare(const void *a, const void *b, |
int aux_size, const void *key); |
void brw_vec4_prog_data_free(const struct brw_vec4_prog_data *prog_data); |
void brw_vs_prog_data_free(const void *in_prog_data); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vs_state.c |
---|
0,0 → 1,193 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "main/macros.h" |
static void |
brw_upload_vs_unit(struct brw_context *brw) |
{ |
struct brw_vs_unit_state *vs; |
vs = brw_state_batch(brw, AUB_TRACE_VS_STATE, |
sizeof(*vs), 32, &brw->vs.state_offset); |
memset(vs, 0, sizeof(*vs)); |
/* BRW_NEW_PROGRAM_CACHE | CACHE_NEW_VS_PROG */ |
vs->thread0.grf_reg_count = |
ALIGN(brw->vs.prog_data->base.total_grf, 16) / 16 - 1; |
vs->thread0.kernel_start_pointer = |
brw_program_reloc(brw, |
brw->vs.state_offset + |
offsetof(struct brw_vs_unit_state, thread0), |
brw->vs.prog_offset + |
(vs->thread0.grf_reg_count << 1)) >> 6; |
/* Use ALT floating point mode for ARB vertex programs, because they |
* require 0^0 == 1. |
*/ |
if (brw->ctx.Shader.CurrentVertexProgram == NULL) |
vs->thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754; |
else |
vs->thread1.floating_point_mode = BRW_FLOATING_POINT_IEEE_754; |
/* Choosing multiple program flow means that we may get 2-vertex threads, |
* which will have the channel mask for dwords 4-7 enabled in the thread, |
* and those dwords will be written to the second URB handle when we |
* brw_urb_WRITE() results. |
*/ |
/* Force single program flow on Ironlake. We cannot reliably get |
* all applications working without it. See: |
* https://bugs.freedesktop.org/show_bug.cgi?id=29172 |
* |
* The most notable and reliably failing application is the Humus |
* demo "CelShading" |
*/ |
vs->thread1.single_program_flow = (brw->gen == 5); |
vs->thread1.binding_table_entry_count = 0; |
if (brw->vs.prog_data->base.total_scratch != 0) { |
vs->thread2.scratch_space_base_pointer = |
brw->vs.scratch_bo->offset >> 10; /* reloc */ |
vs->thread2.per_thread_scratch_space = |
ffs(brw->vs.prog_data->base.total_scratch) - 11; |
} else { |
vs->thread2.scratch_space_base_pointer = 0; |
vs->thread2.per_thread_scratch_space = 0; |
} |
vs->thread3.urb_entry_read_length = brw->vs.prog_data->base.urb_read_length; |
vs->thread3.const_urb_entry_read_length |
= brw->vs.prog_data->base.curb_read_length; |
vs->thread3.dispatch_grf_start_reg = 1; |
vs->thread3.urb_entry_read_offset = 0; |
/* BRW_NEW_CURBE_OFFSETS, _NEW_TRANSFORM, BRW_NEW_VERTEX_PROGRAM */ |
vs->thread3.const_urb_entry_read_offset = brw->curbe.vs_start * 2; |
/* BRW_NEW_URB_FENCE */ |
if (brw->gen == 5) { |
switch (brw->urb.nr_vs_entries) { |
case 8: |
case 12: |
case 16: |
case 32: |
case 64: |
case 96: |
case 128: |
case 168: |
case 192: |
case 224: |
case 256: |
vs->thread4.nr_urb_entries = brw->urb.nr_vs_entries >> 2; |
break; |
default: |
assert(0); |
} |
} else { |
switch (brw->urb.nr_vs_entries) { |
case 8: |
case 12: |
case 16: |
case 32: |
break; |
case 64: |
assert(brw->is_g4x); |
break; |
default: |
assert(0); |
} |
vs->thread4.nr_urb_entries = brw->urb.nr_vs_entries; |
} |
vs->thread4.urb_entry_allocation_size = brw->urb.vsize - 1; |
vs->thread4.max_threads = CLAMP(brw->urb.nr_vs_entries / 2, |
1, brw->max_vs_threads) - 1; |
if (brw->gen == 5) |
vs->vs5.sampler_count = 0; /* hardware requirement */ |
else { |
/* CACHE_NEW_SAMPLER */ |
vs->vs5.sampler_count = (brw->sampler.count + 3) / 4; |
} |
if (unlikely(INTEL_DEBUG & DEBUG_STATS)) |
vs->thread4.stats_enable = 1; |
/* Vertex program always enabled: |
*/ |
vs->vs6.vs_enable = 1; |
/* Set the sampler state pointer, and its reloc |
*/ |
if (brw->sampler.count) { |
vs->vs5.sampler_state_pointer = |
(brw->batch.bo->offset + brw->sampler.offset) >> 5; |
drm_intel_bo_emit_reloc(brw->batch.bo, |
brw->vs.state_offset + |
offsetof(struct brw_vs_unit_state, vs5), |
brw->batch.bo, |
brw->sampler.offset | vs->vs5.sampler_count, |
I915_GEM_DOMAIN_INSTRUCTION, 0); |
} |
/* Emit scratch space relocation */ |
if (brw->vs.prog_data->base.total_scratch != 0) { |
drm_intel_bo_emit_reloc(brw->batch.bo, |
brw->vs.state_offset + |
offsetof(struct brw_vs_unit_state, thread2), |
brw->vs.scratch_bo, |
vs->thread2.per_thread_scratch_space, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); |
} |
brw->state.dirty.cache |= CACHE_NEW_VS_UNIT; |
} |
const struct brw_tracked_state brw_vs_unit = { |
.dirty = { |
.mesa = _NEW_TRANSFORM, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_PROGRAM_CACHE | |
BRW_NEW_CURBE_OFFSETS | |
BRW_NEW_URB_FENCE | |
BRW_NEW_VERTEX_PROGRAM), |
.cache = CACHE_NEW_VS_PROG | CACHE_NEW_SAMPLER |
}, |
.emit = brw_upload_vs_unit, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vs_surface_state.c |
---|
0,0 → 1,184 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/mtypes.h" |
#include "program/prog_parameter.h" |
#include "brw_context.h" |
#include "brw_state.h" |
/* Creates a new VS constant buffer reflecting the current VS program's |
* constants, if needed by the VS program. |
* |
* Otherwise, constants go through the CURBEs using the brw_constant_buffer |
* state atom. |
*/ |
static void |
brw_upload_vs_pull_constants(struct brw_context *brw) |
{ |
/* BRW_NEW_VERTEX_PROGRAM */ |
struct brw_vertex_program *vp = |
(struct brw_vertex_program *) brw->vertex_program; |
int i; |
/* Updates the ParamaterValues[i] pointers for all parameters of the |
* basic type of PROGRAM_STATE_VAR. |
*/ |
_mesa_load_state_parameters(&brw->ctx, vp->program.Base.Parameters); |
/* CACHE_NEW_VS_PROG */ |
if (!brw->vs.prog_data->base.nr_pull_params) { |
if (brw->vs.const_bo) { |
drm_intel_bo_unreference(brw->vs.const_bo); |
brw->vs.const_bo = NULL; |
brw->vs.surf_offset[SURF_INDEX_VERT_CONST_BUFFER] = 0; |
brw->state.dirty.brw |= BRW_NEW_VS_CONSTBUF; |
} |
return; |
} |
/* _NEW_PROGRAM_CONSTANTS */ |
drm_intel_bo_unreference(brw->vs.const_bo); |
uint32_t size = brw->vs.prog_data->base.nr_pull_params * 4; |
brw->vs.const_bo = drm_intel_bo_alloc(brw->bufmgr, "vp_const_buffer", |
size, 64); |
drm_intel_gem_bo_map_gtt(brw->vs.const_bo); |
for (i = 0; i < brw->vs.prog_data->base.nr_pull_params; i++) { |
memcpy(brw->vs.const_bo->virtual + i * 4, |
brw->vs.prog_data->base.pull_param[i], |
4); |
} |
if (0) { |
for (i = 0; i < ALIGN(brw->vs.prog_data->base.nr_pull_params, 4) / 4; |
i++) { |
float *row = (float *)brw->vs.const_bo->virtual + i * 4; |
printf("vs const surface %3d: %4.3f %4.3f %4.3f %4.3f\n", |
i, row[0], row[1], row[2], row[3]); |
} |
} |
drm_intel_gem_bo_unmap_gtt(brw->vs.const_bo); |
const int surf = SURF_INDEX_VERT_CONST_BUFFER; |
brw->vtbl.create_constant_surface(brw, brw->vs.const_bo, 0, size, |
&brw->vs.surf_offset[surf], false); |
brw->state.dirty.brw |= BRW_NEW_VS_CONSTBUF; |
} |
const struct brw_tracked_state brw_vs_pull_constants = { |
.dirty = { |
.mesa = (_NEW_PROGRAM_CONSTANTS), |
.brw = (BRW_NEW_BATCH | BRW_NEW_VERTEX_PROGRAM), |
.cache = CACHE_NEW_VS_PROG, |
}, |
.emit = brw_upload_vs_pull_constants, |
}; |
static void |
brw_upload_vs_ubo_surfaces(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* _NEW_PROGRAM */ |
struct gl_shader_program *prog = ctx->Shader.CurrentVertexProgram; |
if (!prog) |
return; |
brw_upload_ubo_surfaces(brw, prog->_LinkedShaders[MESA_SHADER_VERTEX], |
&brw->vs.surf_offset[SURF_INDEX_VS_UBO(0)]); |
} |
const struct brw_tracked_state brw_vs_ubo_surfaces = { |
.dirty = { |
.mesa = _NEW_PROGRAM, |
.brw = BRW_NEW_BATCH | BRW_NEW_UNIFORM_BUFFER, |
.cache = 0, |
}, |
.emit = brw_upload_vs_ubo_surfaces, |
}; |
/** |
* Constructs the binding table for the WM surface state, which maps unit |
* numbers to surface state objects. |
*/ |
static void |
brw_vs_upload_binding_table(struct brw_context *brw) |
{ |
uint32_t *bind; |
int i; |
if (INTEL_DEBUG & DEBUG_SHADER_TIME) { |
gen7_create_shader_time_surface(brw, &brw->vs.surf_offset[SURF_INDEX_VS_SHADER_TIME]); |
assert(brw->vs.prog_data->base.num_surfaces |
<= SURF_INDEX_VS_SHADER_TIME); |
brw->vs.prog_data->base.num_surfaces = SURF_INDEX_VS_SHADER_TIME; |
} |
/* CACHE_NEW_VS_PROG: Skip making a binding table if we don't use textures or |
* pull constants. |
*/ |
if (brw->vs.prog_data->base.num_surfaces == 0) { |
if (brw->vs.bind_bo_offset != 0) { |
brw->state.dirty.brw |= BRW_NEW_VS_BINDING_TABLE; |
brw->vs.bind_bo_offset = 0; |
} |
return; |
} |
/* Might want to calculate nr_surfaces first, to avoid taking up so much |
* space for the binding table. |
*/ |
bind = brw_state_batch(brw, AUB_TRACE_BINDING_TABLE, |
sizeof(uint32_t) * BRW_MAX_VS_SURFACES, |
32, &brw->vs.bind_bo_offset); |
/* BRW_NEW_SURFACES and BRW_NEW_VS_CONSTBUF */ |
for (i = 0; i < BRW_MAX_VS_SURFACES; i++) { |
bind[i] = brw->vs.surf_offset[i]; |
} |
brw->state.dirty.brw |= BRW_NEW_VS_BINDING_TABLE; |
} |
const struct brw_tracked_state brw_vs_binding_table = { |
.dirty = { |
.mesa = 0, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_VS_CONSTBUF | |
BRW_NEW_SURFACES), |
.cache = CACHE_NEW_VS_PROG |
}, |
.emit = brw_vs_upload_binding_table, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_vtbl.c |
---|
0,0 → 1,169 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/mtypes.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "main/colormac.h" |
#include "main/renderbuffer.h" |
#include "main/framebuffer.h" |
#include "intel_batchbuffer.h" |
#include "intel_regions.h" |
#include "intel_fbo.h" |
#include "brw_context.h" |
#include "brw_program.h" |
#include "brw_defines.h" |
#include "brw_state.h" |
#include "brw_draw.h" |
#include "brw_vs.h" |
#include "brw_wm.h" |
#include "gen6_blorp.h" |
#include "gen7_blorp.h" |
#include "glsl/ralloc.h" |
static void |
dri_bo_release(drm_intel_bo **bo) |
{ |
drm_intel_bo_unreference(*bo); |
*bo = NULL; |
} |
/** |
* called from intelDestroyContext() |
*/ |
static void |
brw_destroy_context(struct brw_context *brw) |
{ |
if (INTEL_DEBUG & DEBUG_SHADER_TIME) { |
/* Force a report. */ |
brw->shader_time.report_time = 0; |
brw_collect_and_report_shader_time(brw); |
brw_destroy_shader_time(brw); |
} |
brw_destroy_state(brw); |
brw_draw_destroy( brw ); |
dri_bo_release(&brw->curbe.curbe_bo); |
dri_bo_release(&brw->vs.const_bo); |
dri_bo_release(&brw->wm.const_bo); |
free(brw->curbe.last_buf); |
free(brw->curbe.next_buf); |
drm_intel_gem_context_destroy(brw->hw_ctx); |
} |
/** |
* called from intel_batchbuffer_flush and children before sending a |
* batchbuffer off. |
* |
* Note that ALL state emitted here must fit in the reserved space |
* at the end of a batchbuffer. If you add more GPU state, increase |
* the BATCH_RESERVED macro. |
*/ |
static void |
brw_finish_batch(struct brw_context *brw) |
{ |
brw_emit_query_end(brw); |
if (brw->curbe.curbe_bo) { |
drm_intel_gem_bo_unmap_gtt(brw->curbe.curbe_bo); |
drm_intel_bo_unreference(brw->curbe.curbe_bo); |
brw->curbe.curbe_bo = NULL; |
} |
} |
/** |
* called from intelFlushBatchLocked |
*/ |
static void |
brw_new_batch(struct brw_context *brw) |
{ |
/* If the kernel supports hardware contexts, then most hardware state is |
* preserved between batches; we only need to re-emit state that is required |
* to be in every batch. Otherwise we need to re-emit all the state that |
* would otherwise be stored in the context (which for all intents and |
* purposes means everything). |
*/ |
if (brw->hw_ctx == NULL) |
brw->state.dirty.brw |= BRW_NEW_CONTEXT; |
brw->state.dirty.brw |= BRW_NEW_BATCH; |
/* Assume that the last command before the start of our batch was a |
* primitive, for safety. |
*/ |
brw->batch.need_workaround_flush = true; |
brw->state_batch_count = 0; |
brw->ib.type = -1; |
/* Mark that the current program cache BO has been used by the GPU. |
* It will be reallocated if we need to put new programs in for the |
* next batch. |
*/ |
brw->cache.bo_used_by_gpu = true; |
/* We need to periodically reap the shader time results, because rollover |
* happens every few seconds. We also want to see results every once in a |
* while, because many programs won't cleanly destroy our context, so the |
* end-of-run printout may not happen. |
*/ |
if (INTEL_DEBUG & DEBUG_SHADER_TIME) |
brw_collect_and_report_shader_time(brw); |
} |
void brwInitVtbl( struct brw_context *brw ) |
{ |
brw->vtbl.new_batch = brw_new_batch; |
brw->vtbl.finish_batch = brw_finish_batch; |
brw->vtbl.destroy = brw_destroy_context; |
assert(brw->gen >= 4); |
if (brw->gen >= 7) { |
gen7_init_vtable_surface_functions(brw); |
brw->vtbl.emit_depth_stencil_hiz = gen7_emit_depth_stencil_hiz; |
} else if (brw->gen >= 4) { |
gen4_init_vtable_surface_functions(brw); |
brw->vtbl.emit_depth_stencil_hiz = brw_emit_depth_stencil_hiz; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_wm.c |
---|
0,0 → 1,515 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "brw_context.h" |
#include "brw_wm.h" |
#include "brw_state.h" |
#include "main/formats.h" |
#include "main/fbobject.h" |
#include "main/samplerobj.h" |
#include "program/prog_parameter.h" |
#include "glsl/ralloc.h" |
/** |
* Return a bitfield where bit n is set if barycentric interpolation mode n |
* (see enum brw_wm_barycentric_interp_mode) is needed by the fragment shader. |
*/ |
static unsigned |
brw_compute_barycentric_interp_modes(struct brw_context *brw, |
bool shade_model_flat, |
const struct gl_fragment_program *fprog) |
{ |
unsigned barycentric_interp_modes = 0; |
int attr; |
/* Loop through all fragment shader inputs to figure out what interpolation |
* modes are in use, and set the appropriate bits in |
* barycentric_interp_modes. |
*/ |
for (attr = 0; attr < VARYING_SLOT_MAX; ++attr) { |
enum glsl_interp_qualifier interp_qualifier = |
fprog->InterpQualifier[attr]; |
bool is_centroid = fprog->IsCentroid & BITFIELD64_BIT(attr); |
bool is_gl_Color = attr == VARYING_SLOT_COL0 || attr == VARYING_SLOT_COL1; |
/* Ignore unused inputs. */ |
if (!(fprog->Base.InputsRead & BITFIELD64_BIT(attr))) |
continue; |
/* Ignore WPOS and FACE, because they don't require interpolation. */ |
if (attr == VARYING_SLOT_POS || attr == VARYING_SLOT_FACE) |
continue; |
/* Determine the set (or sets) of barycentric coordinates needed to |
* interpolate this variable. Note that when |
* brw->needs_unlit_centroid_workaround is set, centroid interpolation |
* uses PIXEL interpolation for unlit pixels and CENTROID interpolation |
* for lit pixels, so we need both sets of barycentric coordinates. |
*/ |
if (interp_qualifier == INTERP_QUALIFIER_NOPERSPECTIVE) { |
if (is_centroid) { |
barycentric_interp_modes |= |
1 << BRW_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC; |
} |
if (!is_centroid || brw->needs_unlit_centroid_workaround) { |
barycentric_interp_modes |= |
1 << BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC; |
} |
} else if (interp_qualifier == INTERP_QUALIFIER_SMOOTH || |
(!(shade_model_flat && is_gl_Color) && |
interp_qualifier == INTERP_QUALIFIER_NONE)) { |
if (is_centroid) { |
barycentric_interp_modes |= |
1 << BRW_WM_PERSPECTIVE_CENTROID_BARYCENTRIC; |
} |
if (!is_centroid || brw->needs_unlit_centroid_workaround) { |
barycentric_interp_modes |= |
1 << BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC; |
} |
} |
} |
return barycentric_interp_modes; |
} |
bool |
brw_wm_prog_data_compare(const void *in_a, const void *in_b, |
int aux_size, const void *in_key) |
{ |
const struct brw_wm_prog_data *a = in_a; |
const struct brw_wm_prog_data *b = in_b; |
/* Compare all the struct up to the pointers. */ |
if (memcmp(a, b, offsetof(struct brw_wm_prog_data, param))) |
return false; |
if (memcmp(a->param, b->param, a->nr_params * sizeof(void *))) |
return false; |
if (memcmp(a->pull_param, b->pull_param, a->nr_pull_params * sizeof(void *))) |
return false; |
return true; |
} |
void |
brw_wm_prog_data_free(const void *in_prog_data) |
{ |
const struct brw_wm_prog_data *prog_data = in_prog_data; |
ralloc_free((void *)prog_data->param); |
ralloc_free((void *)prog_data->pull_param); |
} |
/** |
* All Mesa program -> GPU code generation goes through this function. |
* Depending on the instructions used (i.e. flow control instructions) |
* we'll use one of two code generators. |
*/ |
bool do_wm_prog(struct brw_context *brw, |
struct gl_shader_program *prog, |
struct brw_fragment_program *fp, |
struct brw_wm_prog_key *key) |
{ |
struct brw_wm_compile *c; |
const GLuint *program; |
struct gl_shader *fs = NULL; |
GLuint program_size; |
if (prog) |
fs = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; |
c = rzalloc(NULL, struct brw_wm_compile); |
/* Allocate the references to the uniforms that will end up in the |
* prog_data associated with the compiled program, and which will be freed |
* by the state cache. |
*/ |
int param_count; |
if (fs) { |
param_count = fs->num_uniform_components; |
} else { |
param_count = fp->program.Base.Parameters->NumParameters * 4; |
} |
/* The backend also sometimes adds params for texture size. */ |
param_count += 2 * BRW_MAX_TEX_UNIT; |
c->prog_data.param = rzalloc_array(NULL, const float *, param_count); |
c->prog_data.pull_param = rzalloc_array(NULL, const float *, param_count); |
memcpy(&c->key, key, sizeof(*key)); |
c->prog_data.barycentric_interp_modes = |
brw_compute_barycentric_interp_modes(brw, c->key.flat_shade, |
&fp->program); |
program = brw_wm_fs_emit(brw, c, &fp->program, prog, &program_size); |
if (program == NULL) |
return false; |
/* Scratch space is used for register spilling */ |
if (c->last_scratch) { |
perf_debug("Fragment shader triggered register spilling. " |
"Try reducing the number of live scalar values to " |
"improve performance.\n"); |
c->prog_data.total_scratch = brw_get_scratch_size(c->last_scratch); |
brw_get_scratch_bo(brw, &brw->wm.scratch_bo, |
c->prog_data.total_scratch * brw->max_wm_threads); |
} |
if (unlikely(INTEL_DEBUG & DEBUG_WM)) |
fprintf(stderr, "\n"); |
brw_upload_cache(&brw->cache, BRW_WM_PROG, |
&c->key, sizeof(c->key), |
program, program_size, |
&c->prog_data, sizeof(c->prog_data), |
&brw->wm.prog_offset, &brw->wm.prog_data); |
ralloc_free(c); |
return true; |
} |
static bool |
key_debug(struct brw_context *brw, const char *name, int a, int b) |
{ |
if (a != b) { |
perf_debug(" %s %d->%d\n", name, a, b); |
return true; |
} else { |
return false; |
} |
} |
bool |
brw_debug_recompile_sampler_key(struct brw_context *brw, |
const struct brw_sampler_prog_key_data *old_key, |
const struct brw_sampler_prog_key_data *key) |
{ |
bool found = false; |
for (unsigned int i = 0; i < MAX_SAMPLERS; i++) { |
found |= key_debug(brw, "EXT_texture_swizzle or DEPTH_TEXTURE_MODE", |
old_key->swizzles[i], key->swizzles[i]); |
} |
found |= key_debug(brw, "GL_CLAMP enabled on any texture unit's 1st coordinate", |
old_key->gl_clamp_mask[0], key->gl_clamp_mask[0]); |
found |= key_debug(brw, "GL_CLAMP enabled on any texture unit's 2nd coordinate", |
old_key->gl_clamp_mask[1], key->gl_clamp_mask[1]); |
found |= key_debug(brw, "GL_CLAMP enabled on any texture unit's 3rd coordinate", |
old_key->gl_clamp_mask[2], key->gl_clamp_mask[2]); |
found |= key_debug(brw, "GL_MESA_ycbcr texturing\n", |
old_key->yuvtex_mask, key->yuvtex_mask); |
found |= key_debug(brw, "GL_MESA_ycbcr UV swapping\n", |
old_key->yuvtex_swap_mask, key->yuvtex_swap_mask); |
return found; |
} |
void |
brw_wm_debug_recompile(struct brw_context *brw, |
struct gl_shader_program *prog, |
const struct brw_wm_prog_key *key) |
{ |
struct brw_cache_item *c = NULL; |
const struct brw_wm_prog_key *old_key = NULL; |
bool found = false; |
perf_debug("Recompiling fragment shader for program %d\n", prog->Name); |
for (unsigned int i = 0; i < brw->cache.size; i++) { |
for (c = brw->cache.items[i]; c; c = c->next) { |
if (c->cache_id == BRW_WM_PROG) { |
old_key = c->key; |
if (old_key->program_string_id == key->program_string_id) |
break; |
} |
} |
if (c) |
break; |
} |
if (!c) { |
perf_debug(" Didn't find previous compile in the shader cache for debug\n"); |
return; |
} |
found |= key_debug(brw, "alphatest, computed depth, depth test, or " |
"depth write", |
old_key->iz_lookup, key->iz_lookup); |
found |= key_debug(brw, "depth statistics", |
old_key->stats_wm, key->stats_wm); |
found |= key_debug(brw, "flat shading", |
old_key->flat_shade, key->flat_shade); |
found |= key_debug(brw, "number of color buffers", |
old_key->nr_color_regions, key->nr_color_regions); |
found |= key_debug(brw, "MRT alpha test or alpha-to-coverage", |
old_key->replicate_alpha, key->replicate_alpha); |
found |= key_debug(brw, "rendering to FBO", |
old_key->render_to_fbo, key->render_to_fbo); |
found |= key_debug(brw, "fragment color clamping", |
old_key->clamp_fragment_color, key->clamp_fragment_color); |
found |= key_debug(brw, "line smoothing", |
old_key->line_aa, key->line_aa); |
found |= key_debug(brw, "renderbuffer height", |
old_key->drawable_height, key->drawable_height); |
found |= key_debug(brw, "input slots valid", |
old_key->input_slots_valid, key->input_slots_valid); |
found |= brw_debug_recompile_sampler_key(brw, &old_key->tex, &key->tex); |
if (!found) { |
perf_debug(" Something else\n"); |
} |
} |
void |
brw_populate_sampler_prog_key_data(struct gl_context *ctx, |
const struct gl_program *prog, |
struct brw_sampler_prog_key_data *key) |
{ |
struct brw_context *brw = brw_context(ctx); |
for (int s = 0; s < MAX_SAMPLERS; s++) { |
key->swizzles[s] = SWIZZLE_NOOP; |
if (!(prog->SamplersUsed & (1 << s))) |
continue; |
int unit_id = prog->SamplerUnits[s]; |
const struct gl_texture_unit *unit = &ctx->Texture.Unit[unit_id]; |
if (unit->_ReallyEnabled && unit->_Current->Target != GL_TEXTURE_BUFFER) { |
const struct gl_texture_object *t = unit->_Current; |
const struct gl_texture_image *img = t->Image[0][t->BaseLevel]; |
struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit_id); |
const bool alpha_depth = t->DepthMode == GL_ALPHA && |
(img->_BaseFormat == GL_DEPTH_COMPONENT || |
img->_BaseFormat == GL_DEPTH_STENCIL); |
/* Haswell handles texture swizzling as surface format overrides |
* (except for GL_ALPHA); all other platforms need MOVs in the shader. |
*/ |
if (!brw->is_haswell || alpha_depth) |
key->swizzles[s] = brw_get_texture_swizzle(ctx, t); |
if (img->InternalFormat == GL_YCBCR_MESA) { |
key->yuvtex_mask |= 1 << s; |
if (img->TexFormat == MESA_FORMAT_YCBCR) |
key->yuvtex_swap_mask |= 1 << s; |
} |
if (sampler->MinFilter != GL_NEAREST && |
sampler->MagFilter != GL_NEAREST) { |
if (sampler->WrapS == GL_CLAMP) |
key->gl_clamp_mask[0] |= 1 << s; |
if (sampler->WrapT == GL_CLAMP) |
key->gl_clamp_mask[1] |= 1 << s; |
if (sampler->WrapR == GL_CLAMP) |
key->gl_clamp_mask[2] |= 1 << s; |
} |
} |
} |
} |
static void brw_wm_populate_key( struct brw_context *brw, |
struct brw_wm_prog_key *key ) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_FRAGMENT_PROGRAM */ |
const struct brw_fragment_program *fp = |
(struct brw_fragment_program *)brw->fragment_program; |
const struct gl_program *prog = (struct gl_program *) brw->fragment_program; |
GLuint lookup = 0; |
GLuint line_aa; |
bool program_uses_dfdy = fp->program.UsesDFdy; |
memset(key, 0, sizeof(*key)); |
/* Build the index for table lookup |
*/ |
if (brw->gen < 6) { |
/* _NEW_COLOR */ |
if (fp->program.UsesKill || ctx->Color.AlphaEnabled) |
lookup |= IZ_PS_KILL_ALPHATEST_BIT; |
if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) |
lookup |= IZ_PS_COMPUTES_DEPTH_BIT; |
/* _NEW_DEPTH */ |
if (ctx->Depth.Test) |
lookup |= IZ_DEPTH_TEST_ENABLE_BIT; |
if (ctx->Depth.Test && ctx->Depth.Mask) /* ?? */ |
lookup |= IZ_DEPTH_WRITE_ENABLE_BIT; |
/* _NEW_STENCIL | _NEW_BUFFERS */ |
if (ctx->Stencil._Enabled) { |
lookup |= IZ_STENCIL_TEST_ENABLE_BIT; |
if (ctx->Stencil.WriteMask[0] || |
ctx->Stencil.WriteMask[ctx->Stencil._BackFace]) |
lookup |= IZ_STENCIL_WRITE_ENABLE_BIT; |
} |
key->iz_lookup = lookup; |
} |
line_aa = AA_NEVER; |
/* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */ |
if (ctx->Line.SmoothFlag) { |
if (brw->reduced_primitive == GL_LINES) { |
line_aa = AA_ALWAYS; |
} |
else if (brw->reduced_primitive == GL_TRIANGLES) { |
if (ctx->Polygon.FrontMode == GL_LINE) { |
line_aa = AA_SOMETIMES; |
if (ctx->Polygon.BackMode == GL_LINE || |
(ctx->Polygon.CullFlag && |
ctx->Polygon.CullFaceMode == GL_BACK)) |
line_aa = AA_ALWAYS; |
} |
else if (ctx->Polygon.BackMode == GL_LINE) { |
line_aa = AA_SOMETIMES; |
if ((ctx->Polygon.CullFlag && |
ctx->Polygon.CullFaceMode == GL_FRONT)) |
line_aa = AA_ALWAYS; |
} |
} |
} |
key->line_aa = line_aa; |
if (brw->gen < 6) |
key->stats_wm = brw->stats_wm; |
/* _NEW_LIGHT */ |
key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT); |
/* _NEW_FRAG_CLAMP | _NEW_BUFFERS */ |
key->clamp_fragment_color = ctx->Color._ClampFragmentColor; |
/* _NEW_TEXTURE */ |
brw_populate_sampler_prog_key_data(ctx, prog, &key->tex); |
/* _NEW_BUFFERS */ |
/* |
* Include the draw buffer origin and height so that we can calculate |
* fragment position values relative to the bottom left of the drawable, |
* from the incoming screen origin relative position we get as part of our |
* payload. |
* |
* This is only needed for the WM_WPOSXY opcode when the fragment program |
* uses the gl_FragCoord input. |
* |
* We could avoid recompiling by including this as a constant referenced by |
* our program, but if we were to do that it would also be nice to handle |
* getting that constant updated at batchbuffer submit time (when we |
* hold the lock and know where the buffer really is) rather than at emit |
* time when we don't hold the lock and are just guessing. We could also |
* just avoid using this as key data if the program doesn't use |
* fragment.position. |
* |
* For DRI2 the origin_x/y will always be (0,0) but we still need the |
* drawable height in order to invert the Y axis. |
*/ |
if (fp->program.Base.InputsRead & VARYING_BIT_POS) { |
key->drawable_height = ctx->DrawBuffer->Height; |
} |
if ((fp->program.Base.InputsRead & VARYING_BIT_POS) || program_uses_dfdy) { |
key->render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
} |
/* _NEW_BUFFERS */ |
key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers; |
/* _NEW_MULTISAMPLE, _NEW_COLOR, _NEW_BUFFERS */ |
key->replicate_alpha = ctx->DrawBuffer->_NumColorDrawBuffers > 1 && |
(ctx->Multisample.SampleAlphaToCoverage || ctx->Color.AlphaEnabled); |
/* BRW_NEW_VUE_MAP_GEOM_OUT */ |
if (brw->gen < 6) |
key->input_slots_valid = brw->vue_map_geom_out.slots_valid; |
/* The unique fragment program ID */ |
key->program_string_id = fp->id; |
} |
static void |
brw_upload_wm_prog(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_wm_prog_key key; |
struct brw_fragment_program *fp = (struct brw_fragment_program *) |
brw->fragment_program; |
brw_wm_populate_key(brw, &key); |
if (!brw_search_cache(&brw->cache, BRW_WM_PROG, |
&key, sizeof(key), |
&brw->wm.prog_offset, &brw->wm.prog_data)) { |
bool success = do_wm_prog(brw, ctx->Shader._CurrentFragmentProgram, fp, |
&key); |
(void) success; |
assert(success); |
} |
} |
const struct brw_tracked_state brw_wm_prog = { |
.dirty = { |
.mesa = (_NEW_COLOR | |
_NEW_DEPTH | |
_NEW_STENCIL | |
_NEW_POLYGON | |
_NEW_LINE | |
_NEW_LIGHT | |
_NEW_FRAG_CLAMP | |
_NEW_BUFFERS | |
_NEW_TEXTURE | |
_NEW_MULTISAMPLE), |
.brw = (BRW_NEW_FRAGMENT_PROGRAM | |
BRW_NEW_REDUCED_PRIMITIVE | |
BRW_NEW_VUE_MAP_GEOM_OUT | |
BRW_NEW_STATS_WM) |
}, |
.emit = brw_upload_wm_prog |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_wm.h |
---|
0,0 → 1,120 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 BRW_WM_H |
#define BRW_WM_H |
#include <stdbool.h> |
#include "program/prog_instruction.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
#include "brw_program.h" |
/* A big lookup table is used to figure out which and how many |
* additional regs will inserted before the main payload in the WM |
* program execution. These mainly relate to depth and stencil |
* processing and the early-depth-test optimization. |
*/ |
#define IZ_PS_KILL_ALPHATEST_BIT 0x1 |
#define IZ_PS_COMPUTES_DEPTH_BIT 0x2 |
#define IZ_DEPTH_WRITE_ENABLE_BIT 0x4 |
#define IZ_DEPTH_TEST_ENABLE_BIT 0x8 |
#define IZ_STENCIL_WRITE_ENABLE_BIT 0x10 |
#define IZ_STENCIL_TEST_ENABLE_BIT 0x20 |
#define IZ_BIT_MAX 0x40 |
#define AA_NEVER 0 |
#define AA_SOMETIMES 1 |
#define AA_ALWAYS 2 |
struct brw_wm_prog_key { |
uint8_t iz_lookup; |
GLuint stats_wm:1; |
GLuint flat_shade:1; |
GLuint nr_color_regions:5; |
GLuint replicate_alpha:1; |
GLuint render_to_fbo:1; |
GLuint clamp_fragment_color:1; |
GLuint line_aa:2; |
GLushort drawable_height; |
GLbitfield64 input_slots_valid; |
GLuint program_string_id:32; |
struct brw_sampler_prog_key_data tex; |
}; |
struct brw_wm_compile { |
struct brw_wm_prog_key key; |
struct brw_wm_prog_data prog_data; |
uint8_t source_depth_reg; |
uint8_t source_w_reg; |
uint8_t aa_dest_stencil_reg; |
uint8_t dest_depth_reg; |
uint8_t barycentric_coord_reg[BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT]; |
uint8_t nr_payload_regs; |
GLuint source_depth_to_render_target:1; |
GLuint runtime_check_aads_emit:1; |
GLuint last_scratch; |
}; |
/** |
* Compile a fragment shader. |
* |
* Returns the final assembly and the program's size. |
*/ |
const unsigned *brw_wm_fs_emit(struct brw_context *brw, |
struct brw_wm_compile *c, |
struct gl_fragment_program *fp, |
struct gl_shader_program *prog, |
unsigned *final_assembly_size); |
GLboolean brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog); |
struct gl_shader *brw_new_shader(struct gl_context *ctx, GLuint name, GLuint type); |
struct gl_shader_program *brw_new_shader_program(struct gl_context *ctx, GLuint name); |
bool brw_color_buffer_write_enabled(struct brw_context *brw); |
bool do_wm_prog(struct brw_context *brw, |
struct gl_shader_program *prog, |
struct brw_fragment_program *fp, |
struct brw_wm_prog_key *key); |
void brw_wm_debug_recompile(struct brw_context *brw, |
struct gl_shader_program *prog, |
const struct brw_wm_prog_key *key); |
bool brw_wm_prog_data_compare(const void *a, const void *b, |
int aux_size, const void *key); |
void brw_wm_prog_data_free(const void *in_prog_data); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_wm_iz.cpp |
---|
0,0 → 1,167 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/mtypes.h" |
#include "brw_fs.h" |
#undef P /* prompted depth */ |
#undef C /* computed */ |
#undef N /* non-promoted? */ |
#define P 0 |
#define C 1 |
#define N 2 |
static const struct { |
GLuint mode:2; |
GLuint sd_present:1; |
GLuint sd_to_rt:1; |
GLuint dd_present:1; |
GLuint ds_present:1; |
} wm_iz_table[IZ_BIT_MAX] = |
{ |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ N, 1, 1, 0, 0 }, |
{ N, 0, 1, 0, 0 }, |
{ N, 0, 1, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ C, 0, 1, 1, 0 }, |
{ C, 0, 1, 1, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ N, 1, 1, 0, 0 }, |
{ C, 0, 1, 1, 0 }, |
{ C, 0, 1, 1, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ N, 1, 1, 0, 0 }, |
{ N, 0, 1, 0, 0 }, |
{ N, 0, 1, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ C, 0, 1, 1, 0 }, |
{ C, 0, 1, 1, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ N, 1, 1, 0, 0 }, |
{ C, 0, 1, 1, 0 }, |
{ C, 0, 1, 1, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ N, 1, 1, 0, 1 }, |
{ N, 0, 1, 0, 1 }, |
{ N, 0, 1, 0, 1 }, |
{ P, 0, 0, 0, 0 }, |
{ P, 0, 0, 0, 0 }, |
{ C, 0, 1, 1, 1 }, |
{ C, 0, 1, 1, 1 }, |
{ P, 0, 0, 0, 0 }, |
{ N, 1, 1, 0, 1 }, |
{ C, 0, 1, 1, 1 }, |
{ C, 0, 1, 1, 1 }, |
{ P, 0, 0, 0, 0 }, |
{ C, 0, 0, 0, 1 }, |
{ P, 0, 0, 0, 0 }, |
{ C, 0, 1, 0, 1 }, |
{ P, 0, 0, 0, 0 }, |
{ C, 1, 1, 0, 1 }, |
{ C, 0, 1, 0, 1 }, |
{ C, 0, 1, 0, 1 }, |
{ P, 0, 0, 0, 0 }, |
{ C, 1, 1, 1, 1 }, |
{ C, 0, 1, 1, 1 }, |
{ C, 0, 1, 1, 1 }, |
{ P, 0, 0, 0, 0 }, |
{ C, 1, 1, 1, 1 }, |
{ C, 0, 1, 1, 1 }, |
{ C, 0, 1, 1, 1 } |
}; |
/** |
* \param line_aa AA_NEVER, AA_ALWAYS or AA_SOMETIMES |
* \param lookup bitmask of IZ_* flags |
*/ |
void fs_visitor::setup_payload_gen4() |
{ |
GLuint reg = 2; |
bool kill_stats_promoted_workaround = false; |
int lookup = c->key.iz_lookup; |
bool uses_depth = |
(fp->Base.InputsRead & (1 << VARYING_SLOT_POS)) != 0; |
assert(lookup < IZ_BIT_MAX); |
/* Crazy workaround in the windowizer, which we need to track in |
* our register allocation and render target writes. See the "If |
* statistics are enabled..." paragraph of 11.5.3.2: Early Depth |
* Test Cases [Pre-DevGT] of the 3D Pipeline - Windower B-Spec. |
*/ |
if (c->key.stats_wm && |
(lookup & IZ_PS_KILL_ALPHATEST_BIT) && |
wm_iz_table[lookup].mode == P) { |
kill_stats_promoted_workaround = true; |
} |
if (wm_iz_table[lookup].sd_present || uses_depth || |
kill_stats_promoted_workaround) { |
c->source_depth_reg = reg; |
reg += 2; |
} |
if (wm_iz_table[lookup].sd_to_rt || kill_stats_promoted_workaround) |
c->source_depth_to_render_target = 1; |
if (wm_iz_table[lookup].ds_present || c->key.line_aa != AA_NEVER) { |
c->aa_dest_stencil_reg = reg; |
c->runtime_check_aads_emit = (!wm_iz_table[lookup].ds_present && |
c->key.line_aa == AA_SOMETIMES); |
reg++; |
} |
if (wm_iz_table[lookup].dd_present) { |
c->dest_depth_reg = reg; |
reg+=2; |
} |
c->nr_payload_regs = reg; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_wm_sampler_state.c |
---|
0,0 → 1,413 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "main/macros.h" |
#include "main/samplerobj.h" |
/* Samplers aren't strictly wm state from the hardware's perspective, |
* but that is the only situation in which we use them in this driver. |
*/ |
uint32_t |
translate_wrap_mode(GLenum wrap, bool using_nearest) |
{ |
switch( wrap ) { |
case GL_REPEAT: |
return BRW_TEXCOORDMODE_WRAP; |
case GL_CLAMP: |
/* GL_CLAMP is the weird mode where coordinates are clamped to |
* [0.0, 1.0], so linear filtering of coordinates outside of |
* [0.0, 1.0] give you half edge texel value and half border |
* color. The fragment shader will clamp the coordinates, and |
* we set clamp_border here, which gets the result desired. We |
* just use clamp(_to_edge) for nearest, because for nearest |
* clamping to 1.0 gives border color instead of the desired |
* edge texels. |
*/ |
if (using_nearest) |
return BRW_TEXCOORDMODE_CLAMP; |
else |
return BRW_TEXCOORDMODE_CLAMP_BORDER; |
case GL_CLAMP_TO_EDGE: |
return BRW_TEXCOORDMODE_CLAMP; |
case GL_CLAMP_TO_BORDER: |
return BRW_TEXCOORDMODE_CLAMP_BORDER; |
case GL_MIRRORED_REPEAT: |
return BRW_TEXCOORDMODE_MIRROR; |
default: |
return BRW_TEXCOORDMODE_WRAP; |
} |
} |
/** |
* Upload SAMPLER_BORDER_COLOR_STATE. |
*/ |
void |
upload_default_color(struct brw_context *brw, struct gl_sampler_object *sampler, |
int unit, int ss_index) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
struct gl_texture_object *texObj = texUnit->_Current; |
struct gl_texture_image *firstImage = texObj->Image[0][texObj->BaseLevel]; |
float color[4]; |
switch (firstImage->_BaseFormat) { |
case GL_DEPTH_COMPONENT: |
/* GL specs that border color for depth textures is taken from the |
* R channel, while the hardware uses A. Spam R into all the |
* channels for safety. |
*/ |
color[0] = sampler->BorderColor.f[0]; |
color[1] = sampler->BorderColor.f[0]; |
color[2] = sampler->BorderColor.f[0]; |
color[3] = sampler->BorderColor.f[0]; |
break; |
case GL_ALPHA: |
color[0] = 0.0; |
color[1] = 0.0; |
color[2] = 0.0; |
color[3] = sampler->BorderColor.f[3]; |
break; |
case GL_INTENSITY: |
color[0] = sampler->BorderColor.f[0]; |
color[1] = sampler->BorderColor.f[0]; |
color[2] = sampler->BorderColor.f[0]; |
color[3] = sampler->BorderColor.f[0]; |
break; |
case GL_LUMINANCE: |
color[0] = sampler->BorderColor.f[0]; |
color[1] = sampler->BorderColor.f[0]; |
color[2] = sampler->BorderColor.f[0]; |
color[3] = 1.0; |
break; |
case GL_LUMINANCE_ALPHA: |
color[0] = sampler->BorderColor.f[0]; |
color[1] = sampler->BorderColor.f[0]; |
color[2] = sampler->BorderColor.f[0]; |
color[3] = sampler->BorderColor.f[3]; |
break; |
default: |
color[0] = sampler->BorderColor.f[0]; |
color[1] = sampler->BorderColor.f[1]; |
color[2] = sampler->BorderColor.f[2]; |
color[3] = sampler->BorderColor.f[3]; |
break; |
} |
/* In some cases we use an RGBA surface format for GL RGB textures, |
* where we've initialized the A channel to 1.0. We also have to set |
* the border color alpha to 1.0 in that case. |
*/ |
if (firstImage->_BaseFormat == GL_RGB) |
color[3] = 1.0; |
if (brw->gen == 5 || brw->gen == 6) { |
struct gen5_sampler_default_color *sdc; |
sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR, |
sizeof(*sdc), 32, &brw->wm.sdc_offset[ss_index]); |
memset(sdc, 0, sizeof(*sdc)); |
UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[0], color[0]); |
UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[1], color[1]); |
UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[2], color[2]); |
UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[3], color[3]); |
UNCLAMPED_FLOAT_TO_USHORT(sdc->us[0], color[0]); |
UNCLAMPED_FLOAT_TO_USHORT(sdc->us[1], color[1]); |
UNCLAMPED_FLOAT_TO_USHORT(sdc->us[2], color[2]); |
UNCLAMPED_FLOAT_TO_USHORT(sdc->us[3], color[3]); |
UNCLAMPED_FLOAT_TO_SHORT(sdc->s[0], color[0]); |
UNCLAMPED_FLOAT_TO_SHORT(sdc->s[1], color[1]); |
UNCLAMPED_FLOAT_TO_SHORT(sdc->s[2], color[2]); |
UNCLAMPED_FLOAT_TO_SHORT(sdc->s[3], color[3]); |
sdc->hf[0] = _mesa_float_to_half(color[0]); |
sdc->hf[1] = _mesa_float_to_half(color[1]); |
sdc->hf[2] = _mesa_float_to_half(color[2]); |
sdc->hf[3] = _mesa_float_to_half(color[3]); |
sdc->b[0] = sdc->s[0] >> 8; |
sdc->b[1] = sdc->s[1] >> 8; |
sdc->b[2] = sdc->s[2] >> 8; |
sdc->b[3] = sdc->s[3] >> 8; |
sdc->f[0] = color[0]; |
sdc->f[1] = color[1]; |
sdc->f[2] = color[2]; |
sdc->f[3] = color[3]; |
} else { |
struct brw_sampler_default_color *sdc; |
sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR, |
sizeof(*sdc), 32, &brw->wm.sdc_offset[ss_index]); |
COPY_4V(sdc->color, color); |
} |
} |
/** |
* Sets the sampler state for a single unit based off of the sampler key |
* entry. |
*/ |
static void brw_update_sampler_state(struct brw_context *brw, |
int unit, |
int ss_index, |
struct brw_sampler_state *sampler) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
struct gl_texture_object *texObj = texUnit->_Current; |
struct gl_sampler_object *gl_sampler = _mesa_get_samplerobj(ctx, unit); |
bool using_nearest = false; |
/* These don't use samplers at all. */ |
if (texObj->Target == GL_TEXTURE_BUFFER) |
return; |
switch (gl_sampler->MinFilter) { |
case GL_NEAREST: |
sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; |
sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; |
using_nearest = true; |
break; |
case GL_LINEAR: |
sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; |
sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; |
break; |
case GL_NEAREST_MIPMAP_NEAREST: |
sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; |
sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST; |
break; |
case GL_LINEAR_MIPMAP_NEAREST: |
sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; |
sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST; |
break; |
case GL_NEAREST_MIPMAP_LINEAR: |
sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; |
sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR; |
break; |
case GL_LINEAR_MIPMAP_LINEAR: |
sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; |
sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR; |
break; |
default: |
break; |
} |
/* Set Anisotropy: |
*/ |
if (gl_sampler->MaxAnisotropy > 1.0) { |
sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC; |
sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC; |
if (gl_sampler->MaxAnisotropy > 2.0) { |
sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2, |
BRW_ANISORATIO_16); |
} |
} |
else { |
switch (gl_sampler->MagFilter) { |
case GL_NEAREST: |
sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST; |
using_nearest = true; |
break; |
case GL_LINEAR: |
sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; |
break; |
default: |
break; |
} |
} |
sampler->ss1.r_wrap_mode = translate_wrap_mode(gl_sampler->WrapR, |
using_nearest); |
sampler->ss1.s_wrap_mode = translate_wrap_mode(gl_sampler->WrapS, |
using_nearest); |
sampler->ss1.t_wrap_mode = translate_wrap_mode(gl_sampler->WrapT, |
using_nearest); |
if (brw->gen >= 6 && |
sampler->ss0.min_filter != sampler->ss0.mag_filter) |
sampler->ss0.min_mag_neq = 1; |
/* Cube-maps on 965 and later must use the same wrap mode for all 3 |
* coordinate dimensions. Futher, only CUBE and CLAMP are valid. |
*/ |
if (texObj->Target == GL_TEXTURE_CUBE_MAP || |
texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) { |
if (ctx->Texture.CubeMapSeamless && |
(gl_sampler->MinFilter != GL_NEAREST || |
gl_sampler->MagFilter != GL_NEAREST)) { |
sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE; |
sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE; |
sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE; |
} else { |
sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
} |
} else if (texObj->Target == GL_TEXTURE_1D) { |
/* There's a bug in 1D texture sampling - it actually pays |
* attention to the wrap_t value, though it should not. |
* Override the wrap_t value here to GL_REPEAT to keep |
* any nonexistent border pixels from floating in. |
*/ |
sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP; |
} |
/* Set shadow function: |
*/ |
if (gl_sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) { |
/* Shadowing is "enabled" by emitting a particular sampler |
* message (sample_c). So need to recompile WM program when |
* shadow comparison is enabled on each/any texture unit. |
*/ |
sampler->ss0.shadow_function = |
intel_translate_shadow_compare_func(gl_sampler->CompareFunc); |
} |
/* Set LOD bias: |
*/ |
sampler->ss0.lod_bias = S_FIXED(CLAMP(texUnit->LodBias + |
gl_sampler->LodBias, -16, 15), 6); |
sampler->ss0.lod_preclamp = 1; /* OpenGL mode */ |
sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */ |
/* Set BaseMipLevel, MaxLOD, MinLOD: |
* |
* XXX: I don't think that using firstLevel, lastLevel works, |
* because we always setup the surface state as if firstLevel == |
* level zero. Probably have to subtract firstLevel from each of |
* these: |
*/ |
sampler->ss0.base_level = U_FIXED(0, 1); |
sampler->ss1.max_lod = U_FIXED(CLAMP(gl_sampler->MaxLod, 0, 13), 6); |
sampler->ss1.min_lod = U_FIXED(CLAMP(gl_sampler->MinLod, 0, 13), 6); |
/* On Gen6+, the sampler can handle non-normalized texture |
* rectangle coordinates natively |
*/ |
if (brw->gen >= 6 && texObj->Target == GL_TEXTURE_RECTANGLE) { |
sampler->ss3.non_normalized_coord = 1; |
} |
upload_default_color(brw, gl_sampler, unit, ss_index); |
if (brw->gen >= 6) { |
sampler->ss2.default_color_pointer = brw->wm.sdc_offset[ss_index] >> 5; |
} else { |
/* reloc */ |
sampler->ss2.default_color_pointer = (brw->batch.bo->offset + |
brw->wm.sdc_offset[ss_index]) >> 5; |
drm_intel_bo_emit_reloc(brw->batch.bo, |
brw->sampler.offset + |
ss_index * sizeof(struct brw_sampler_state) + |
offsetof(struct brw_sampler_state, ss2), |
brw->batch.bo, brw->wm.sdc_offset[ss_index], |
I915_GEM_DOMAIN_SAMPLER, 0); |
} |
if (sampler->ss0.min_filter != BRW_MAPFILTER_NEAREST) |
sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN | |
BRW_ADDRESS_ROUNDING_ENABLE_V_MIN | |
BRW_ADDRESS_ROUNDING_ENABLE_R_MIN; |
if (sampler->ss0.mag_filter != BRW_MAPFILTER_NEAREST) |
sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG | |
BRW_ADDRESS_ROUNDING_ENABLE_V_MAG | |
BRW_ADDRESS_ROUNDING_ENABLE_R_MAG; |
} |
static void |
brw_upload_samplers(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_sampler_state *samplers; |
/* BRW_NEW_VERTEX_PROGRAM and BRW_NEW_FRAGMENT_PROGRAM */ |
struct gl_program *vs = (struct gl_program *) brw->vertex_program; |
struct gl_program *fs = (struct gl_program *) brw->fragment_program; |
GLbitfield SamplersUsed = vs->SamplersUsed | fs->SamplersUsed; |
/* ARB programs use the texture unit number as the sampler index, so we |
* need to find the highest unit used. A bit-count will not work. |
*/ |
brw->sampler.count = _mesa_fls(SamplersUsed); |
if (brw->sampler.count == 0) |
return; |
samplers = brw_state_batch(brw, AUB_TRACE_SAMPLER_STATE, |
brw->sampler.count * sizeof(*samplers), |
32, &brw->sampler.offset); |
memset(samplers, 0, brw->sampler.count * sizeof(*samplers)); |
for (unsigned s = 0; s < brw->sampler.count; s++) { |
if (SamplersUsed & (1 << s)) { |
const unsigned unit = (fs->SamplersUsed & (1 << s)) ? |
fs->SamplerUnits[s] : vs->SamplerUnits[s]; |
if (ctx->Texture.Unit[unit]._ReallyEnabled) |
brw_update_sampler_state(brw, unit, s, &samplers[s]); |
} |
} |
brw->state.dirty.cache |= CACHE_NEW_SAMPLER; |
} |
const struct brw_tracked_state brw_samplers = { |
.dirty = { |
.mesa = _NEW_TEXTURE, |
.brw = BRW_NEW_BATCH | |
BRW_NEW_VERTEX_PROGRAM | |
BRW_NEW_FRAGMENT_PROGRAM, |
.cache = 0 |
}, |
.emit = brw_upload_samplers, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_wm_state.c |
---|
0,0 → 1,260 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "intel_fbo.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_wm.h" |
/*********************************************************************** |
* WM unit - fragment programs and rasterization |
*/ |
bool |
brw_color_buffer_write_enabled(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
const struct gl_fragment_program *fp = brw->fragment_program; |
int i; |
/* _NEW_BUFFERS */ |
for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { |
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i]; |
/* _NEW_COLOR */ |
if (rb && |
(fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR) || |
fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DATA0 + i)) && |
(ctx->Color.ColorMask[i][0] || |
ctx->Color.ColorMask[i][1] || |
ctx->Color.ColorMask[i][2] || |
ctx->Color.ColorMask[i][3])) { |
return true; |
} |
} |
return false; |
} |
/** |
* Setup wm hardware state. See page 225 of Volume 2 |
*/ |
static void |
brw_upload_wm_unit(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
const struct gl_fragment_program *fp = brw->fragment_program; |
struct brw_wm_unit_state *wm; |
wm = brw_state_batch(brw, AUB_TRACE_WM_STATE, |
sizeof(*wm), 32, &brw->wm.state_offset); |
memset(wm, 0, sizeof(*wm)); |
if (brw->wm.prog_data->prog_offset_16) { |
/* These two fields should be the same pre-gen6, which is why we |
* only have one hardware field to program for both dispatch |
* widths. |
*/ |
assert(brw->wm.prog_data->first_curbe_grf == |
brw->wm.prog_data->first_curbe_grf_16); |
} |
/* BRW_NEW_PROGRAM_CACHE | CACHE_NEW_WM_PROG */ |
wm->thread0.grf_reg_count = brw->wm.prog_data->reg_blocks; |
wm->wm9.grf_reg_count_2 = brw->wm.prog_data->reg_blocks_16; |
wm->thread0.kernel_start_pointer = |
brw_program_reloc(brw, |
brw->wm.state_offset + |
offsetof(struct brw_wm_unit_state, thread0), |
brw->wm.prog_offset + |
(wm->thread0.grf_reg_count << 1)) >> 6; |
wm->wm9.kernel_start_pointer_2 = |
brw_program_reloc(brw, |
brw->wm.state_offset + |
offsetof(struct brw_wm_unit_state, wm9), |
brw->wm.prog_offset + |
brw->wm.prog_data->prog_offset_16 + |
(wm->wm9.grf_reg_count_2 << 1)) >> 6; |
wm->thread1.depth_coef_urb_read_offset = 1; |
/* Use ALT floating point mode for ARB fragment programs, because they |
* require 0^0 == 1. Even though _CurrentFragmentProgram is used for |
* rendering, CurrentFragmentProgram is used for this check to |
* differentiate between the GLSL and non-GLSL cases. |
*/ |
if (ctx->Shader.CurrentFragmentProgram == NULL) |
wm->thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754; |
else |
wm->thread1.floating_point_mode = BRW_FLOATING_POINT_IEEE_754; |
wm->thread1.binding_table_entry_count = 0; |
if (brw->wm.prog_data->total_scratch != 0) { |
wm->thread2.scratch_space_base_pointer = |
brw->wm.scratch_bo->offset >> 10; /* reloc */ |
wm->thread2.per_thread_scratch_space = |
ffs(brw->wm.prog_data->total_scratch) - 11; |
} else { |
wm->thread2.scratch_space_base_pointer = 0; |
wm->thread2.per_thread_scratch_space = 0; |
} |
wm->thread3.dispatch_grf_start_reg = brw->wm.prog_data->first_curbe_grf; |
wm->thread3.urb_entry_read_length = brw->wm.prog_data->urb_read_length; |
wm->thread3.urb_entry_read_offset = 0; |
wm->thread3.const_urb_entry_read_length = |
brw->wm.prog_data->curb_read_length; |
/* BRW_NEW_CURBE_OFFSETS */ |
wm->thread3.const_urb_entry_read_offset = brw->curbe.wm_start * 2; |
if (brw->gen == 5) |
wm->wm4.sampler_count = 0; /* hardware requirement */ |
else { |
/* CACHE_NEW_SAMPLER */ |
wm->wm4.sampler_count = (brw->sampler.count + 1) / 4; |
} |
if (brw->sampler.count) { |
/* reloc */ |
wm->wm4.sampler_state_pointer = (brw->batch.bo->offset + |
brw->sampler.offset) >> 5; |
} else { |
wm->wm4.sampler_state_pointer = 0; |
} |
/* BRW_NEW_FRAGMENT_PROGRAM */ |
wm->wm5.program_uses_depth = (fp->Base.InputsRead & |
(1 << VARYING_SLOT_POS)) != 0; |
wm->wm5.program_computes_depth = (fp->Base.OutputsWritten & |
BITFIELD64_BIT(FRAG_RESULT_DEPTH)) != 0; |
/* _NEW_BUFFERS |
* Override for NULL depthbuffer case, required by the Pixel Shader Computed |
* Depth field. |
*/ |
if (!intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH)) |
wm->wm5.program_computes_depth = 0; |
/* _NEW_COLOR */ |
wm->wm5.program_uses_killpixel = fp->UsesKill || ctx->Color.AlphaEnabled; |
wm->wm5.enable_8_pix = 1; |
if (brw->wm.prog_data->prog_offset_16) |
wm->wm5.enable_16_pix = 1; |
wm->wm5.max_threads = brw->max_wm_threads - 1; |
/* _NEW_BUFFERS | _NEW_COLOR */ |
if (brw_color_buffer_write_enabled(brw) || |
wm->wm5.program_uses_killpixel || |
wm->wm5.program_computes_depth) { |
wm->wm5.thread_dispatch_enable = 1; |
} |
wm->wm5.legacy_line_rast = 0; |
wm->wm5.legacy_global_depth_bias = 0; |
wm->wm5.early_depth_test = 1; /* never need to disable */ |
wm->wm5.line_aa_region_width = 0; |
wm->wm5.line_endcap_aa_region_width = 1; |
/* _NEW_POLYGONSTIPPLE */ |
wm->wm5.polygon_stipple = ctx->Polygon.StippleFlag; |
/* _NEW_POLYGON */ |
if (ctx->Polygon.OffsetFill) { |
wm->wm5.depth_offset = 1; |
/* Something wierd going on with legacy_global_depth_bias, |
* offset_constant, scaling and MRD. This value passes glean |
* but gives some odd results elsewere (eg. the |
* quad-offset-units test). |
*/ |
wm->global_depth_offset_constant = ctx->Polygon.OffsetUnits * 2; |
/* This is the only value that passes glean: |
*/ |
wm->global_depth_offset_scale = ctx->Polygon.OffsetFactor; |
} |
/* _NEW_LINE */ |
wm->wm5.line_stipple = ctx->Line.StippleFlag; |
/* BRW_NEW_STATS_WM */ |
if (unlikely(INTEL_DEBUG & DEBUG_STATS) || brw->stats_wm) |
wm->wm4.stats_enable = 1; |
/* Emit scratch space relocation */ |
if (brw->wm.prog_data->total_scratch != 0) { |
drm_intel_bo_emit_reloc(brw->batch.bo, |
brw->wm.state_offset + |
offsetof(struct brw_wm_unit_state, thread2), |
brw->wm.scratch_bo, |
wm->thread2.per_thread_scratch_space, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); |
} |
/* Emit sampler state relocation */ |
if (brw->sampler.count != 0) { |
drm_intel_bo_emit_reloc(brw->batch.bo, |
brw->wm.state_offset + |
offsetof(struct brw_wm_unit_state, wm4), |
brw->batch.bo, (brw->sampler.offset | |
wm->wm4.stats_enable | |
(wm->wm4.sampler_count << 2)), |
I915_GEM_DOMAIN_INSTRUCTION, 0); |
} |
brw->state.dirty.cache |= CACHE_NEW_WM_UNIT; |
} |
const struct brw_tracked_state brw_wm_unit = { |
.dirty = { |
.mesa = (_NEW_POLYGON | |
_NEW_POLYGONSTIPPLE | |
_NEW_LINE | |
_NEW_COLOR | |
_NEW_BUFFERS), |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_PROGRAM_CACHE | |
BRW_NEW_FRAGMENT_PROGRAM | |
BRW_NEW_CURBE_OFFSETS | |
BRW_NEW_STATS_WM), |
.cache = (CACHE_NEW_WM_PROG | |
CACHE_NEW_SAMPLER) |
}, |
.emit = brw_upload_wm_unit, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/brw_wm_surface_state.c |
---|
0,0 → 1,918 |
/* |
Copyright (C) Intel Corp. 2006. All Rights Reserved. |
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
develop this 3D driver. |
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 COPYRIGHT OWNER(S) 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 "main/context.h" |
#include "main/blend.h" |
#include "main/mtypes.h" |
#include "main/samplerobj.h" |
#include "program/prog_parameter.h" |
#include "intel_mipmap_tree.h" |
#include "intel_batchbuffer.h" |
#include "intel_tex.h" |
#include "intel_fbo.h" |
#include "intel_buffer_objects.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_wm.h" |
GLuint |
translate_tex_target(GLenum target) |
{ |
switch (target) { |
case GL_TEXTURE_1D: |
case GL_TEXTURE_1D_ARRAY_EXT: |
return BRW_SURFACE_1D; |
case GL_TEXTURE_RECTANGLE_NV: |
return BRW_SURFACE_2D; |
case GL_TEXTURE_2D: |
case GL_TEXTURE_2D_ARRAY_EXT: |
case GL_TEXTURE_EXTERNAL_OES: |
case GL_TEXTURE_2D_MULTISAMPLE: |
case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: |
return BRW_SURFACE_2D; |
case GL_TEXTURE_3D: |
return BRW_SURFACE_3D; |
case GL_TEXTURE_CUBE_MAP: |
case GL_TEXTURE_CUBE_MAP_ARRAY: |
return BRW_SURFACE_CUBE; |
default: |
assert(0); |
return 0; |
} |
} |
uint32_t |
brw_get_surface_tiling_bits(uint32_t tiling) |
{ |
switch (tiling) { |
case I915_TILING_X: |
return BRW_SURFACE_TILED; |
case I915_TILING_Y: |
return BRW_SURFACE_TILED | BRW_SURFACE_TILED_Y; |
default: |
return 0; |
} |
} |
uint32_t |
brw_get_surface_num_multisamples(unsigned num_samples) |
{ |
if (num_samples > 1) |
return BRW_SURFACE_MULTISAMPLECOUNT_4; |
else |
return BRW_SURFACE_MULTISAMPLECOUNT_1; |
} |
/** |
* Compute the combination of DEPTH_TEXTURE_MODE and EXT_texture_swizzle |
* swizzling. |
*/ |
int |
brw_get_texture_swizzle(const struct gl_context *ctx, |
const struct gl_texture_object *t) |
{ |
const struct gl_texture_image *img = t->Image[0][t->BaseLevel]; |
int swizzles[SWIZZLE_NIL + 1] = { |
SWIZZLE_X, |
SWIZZLE_Y, |
SWIZZLE_Z, |
SWIZZLE_W, |
SWIZZLE_ZERO, |
SWIZZLE_ONE, |
SWIZZLE_NIL |
}; |
if (img->_BaseFormat == GL_DEPTH_COMPONENT || |
img->_BaseFormat == GL_DEPTH_STENCIL) { |
GLenum depth_mode = t->DepthMode; |
/* In ES 3.0, DEPTH_TEXTURE_MODE is expected to be GL_RED for textures |
* with depth component data specified with a sized internal format. |
* Otherwise, it's left at the old default, GL_LUMINANCE. |
*/ |
if (_mesa_is_gles3(ctx) && |
img->InternalFormat != GL_DEPTH_COMPONENT && |
img->InternalFormat != GL_DEPTH_STENCIL) { |
depth_mode = GL_RED; |
} |
switch (depth_mode) { |
case GL_ALPHA: |
swizzles[0] = SWIZZLE_ZERO; |
swizzles[1] = SWIZZLE_ZERO; |
swizzles[2] = SWIZZLE_ZERO; |
swizzles[3] = SWIZZLE_X; |
break; |
case GL_LUMINANCE: |
swizzles[0] = SWIZZLE_X; |
swizzles[1] = SWIZZLE_X; |
swizzles[2] = SWIZZLE_X; |
swizzles[3] = SWIZZLE_ONE; |
break; |
case GL_INTENSITY: |
swizzles[0] = SWIZZLE_X; |
swizzles[1] = SWIZZLE_X; |
swizzles[2] = SWIZZLE_X; |
swizzles[3] = SWIZZLE_X; |
break; |
case GL_RED: |
swizzles[0] = SWIZZLE_X; |
swizzles[1] = SWIZZLE_ZERO; |
swizzles[2] = SWIZZLE_ZERO; |
swizzles[3] = SWIZZLE_ONE; |
break; |
} |
} |
/* If the texture's format is alpha-only, force R, G, and B to |
* 0.0. Similarly, if the texture's format has no alpha channel, |
* force the alpha value read to 1.0. This allows for the |
* implementation to use an RGBA texture for any of these formats |
* without leaking any unexpected values. |
*/ |
switch (img->_BaseFormat) { |
case GL_ALPHA: |
swizzles[0] = SWIZZLE_ZERO; |
swizzles[1] = SWIZZLE_ZERO; |
swizzles[2] = SWIZZLE_ZERO; |
break; |
case GL_RED: |
case GL_RG: |
case GL_RGB: |
if (_mesa_get_format_bits(img->TexFormat, GL_ALPHA_BITS) > 0) |
swizzles[3] = SWIZZLE_ONE; |
break; |
} |
return MAKE_SWIZZLE4(swizzles[GET_SWZ(t->_Swizzle, 0)], |
swizzles[GET_SWZ(t->_Swizzle, 1)], |
swizzles[GET_SWZ(t->_Swizzle, 2)], |
swizzles[GET_SWZ(t->_Swizzle, 3)]); |
} |
static void |
brw_update_buffer_texture_surface(struct gl_context *ctx, |
unsigned unit, |
uint32_t *binding_table, |
unsigned surf_index) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; |
uint32_t *surf; |
struct intel_buffer_object *intel_obj = |
intel_buffer_object(tObj->BufferObject); |
drm_intel_bo *bo = intel_obj ? intel_obj->buffer : NULL; |
gl_format format = tObj->_BufferObjectFormat; |
uint32_t brw_format = brw_format_for_mesa_format(format); |
int texel_size = _mesa_get_format_bytes(format); |
if (brw_format == 0 && format != MESA_FORMAT_RGBA_FLOAT32) { |
_mesa_problem(NULL, "bad format %s for texture buffer\n", |
_mesa_get_format_name(format)); |
} |
surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, |
6 * 4, 32, &binding_table[surf_index]); |
surf[0] = (BRW_SURFACE_BUFFER << BRW_SURFACE_TYPE_SHIFT | |
(brw_format_for_mesa_format(format) << BRW_SURFACE_FORMAT_SHIFT)); |
if (brw->gen >= 6) |
surf[0] |= BRW_SURFACE_RC_READ_WRITE; |
if (bo) { |
surf[1] = bo->offset; /* reloc */ |
/* Emit relocation to surface contents. */ |
drm_intel_bo_emit_reloc(brw->batch.bo, |
binding_table[surf_index] + 4, |
bo, 0, I915_GEM_DOMAIN_SAMPLER, 0); |
int w = intel_obj->Base.Size / texel_size; |
surf[2] = ((w & 0x7f) << BRW_SURFACE_WIDTH_SHIFT | |
((w >> 7) & 0x1fff) << BRW_SURFACE_HEIGHT_SHIFT); |
surf[3] = (((w >> 20) & 0x7f) << BRW_SURFACE_DEPTH_SHIFT | |
(texel_size - 1) << BRW_SURFACE_PITCH_SHIFT); |
} else { |
surf[1] = 0; |
surf[2] = 0; |
surf[3] = 0; |
} |
surf[4] = 0; |
surf[5] = 0; |
} |
static void |
brw_update_texture_surface(struct gl_context *ctx, |
unsigned unit, |
uint32_t *binding_table, |
unsigned surf_index) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; |
struct intel_texture_object *intelObj = intel_texture_object(tObj); |
struct intel_mipmap_tree *mt = intelObj->mt; |
struct gl_texture_image *firstImage = tObj->Image[0][tObj->BaseLevel]; |
struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); |
uint32_t *surf; |
uint32_t tile_x, tile_y; |
if (tObj->Target == GL_TEXTURE_BUFFER) { |
brw_update_buffer_texture_surface(ctx, unit, binding_table, surf_index); |
return; |
} |
surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, |
6 * 4, 32, &binding_table[surf_index]); |
surf[0] = (translate_tex_target(tObj->Target) << BRW_SURFACE_TYPE_SHIFT | |
BRW_SURFACE_MIPMAPLAYOUT_BELOW << BRW_SURFACE_MIPLAYOUT_SHIFT | |
BRW_SURFACE_CUBEFACE_ENABLES | |
(translate_tex_format(brw, |
mt->format, |
tObj->DepthMode, |
sampler->sRGBDecode) << |
BRW_SURFACE_FORMAT_SHIFT)); |
surf[1] = intelObj->mt->region->bo->offset + intelObj->mt->offset; /* reloc */ |
surf[1] += intel_miptree_get_tile_offsets(intelObj->mt, firstImage->Level, 0, |
&tile_x, &tile_y); |
surf[2] = ((intelObj->_MaxLevel - tObj->BaseLevel) << BRW_SURFACE_LOD_SHIFT | |
(mt->logical_width0 - 1) << BRW_SURFACE_WIDTH_SHIFT | |
(mt->logical_height0 - 1) << BRW_SURFACE_HEIGHT_SHIFT); |
surf[3] = (brw_get_surface_tiling_bits(intelObj->mt->region->tiling) | |
(mt->logical_depth0 - 1) << BRW_SURFACE_DEPTH_SHIFT | |
(intelObj->mt->region->pitch - 1) << |
BRW_SURFACE_PITCH_SHIFT); |
surf[4] = brw_get_surface_num_multisamples(intelObj->mt->num_samples); |
assert(brw->has_surface_tile_offset || (tile_x == 0 && tile_y == 0)); |
/* Note that the low bits of these fields are missing, so |
* there's the possibility of getting in trouble. |
*/ |
assert(tile_x % 4 == 0); |
assert(tile_y % 2 == 0); |
surf[5] = ((tile_x / 4) << BRW_SURFACE_X_OFFSET_SHIFT | |
(tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT | |
(mt->align_h == 4 ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0)); |
/* Emit relocation to surface contents */ |
drm_intel_bo_emit_reloc(brw->batch.bo, |
binding_table[surf_index] + 4, |
intelObj->mt->region->bo, |
surf[1] - intelObj->mt->region->bo->offset, |
I915_GEM_DOMAIN_SAMPLER, 0); |
} |
/** |
* Create the constant buffer surface. Vertex/fragment shader constants will be |
* read from this buffer with Data Port Read instructions/messages. |
*/ |
static void |
brw_create_constant_surface(struct brw_context *brw, |
drm_intel_bo *bo, |
uint32_t offset, |
uint32_t size, |
uint32_t *out_offset, |
bool dword_pitch) |
{ |
uint32_t stride = dword_pitch ? 4 : 16; |
uint32_t elements = ALIGN(size, stride) / stride; |
const GLint w = elements - 1; |
uint32_t *surf; |
surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, |
6 * 4, 32, out_offset); |
surf[0] = (BRW_SURFACE_BUFFER << BRW_SURFACE_TYPE_SHIFT | |
BRW_SURFACE_MIPMAPLAYOUT_BELOW << BRW_SURFACE_MIPLAYOUT_SHIFT | |
BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_SURFACE_FORMAT_SHIFT); |
if (brw->gen >= 6) |
surf[0] |= BRW_SURFACE_RC_READ_WRITE; |
surf[1] = bo->offset + offset; /* reloc */ |
surf[2] = ((w & 0x7f) << BRW_SURFACE_WIDTH_SHIFT | |
((w >> 7) & 0x1fff) << BRW_SURFACE_HEIGHT_SHIFT); |
surf[3] = (((w >> 20) & 0x7f) << BRW_SURFACE_DEPTH_SHIFT | |
(stride - 1) << BRW_SURFACE_PITCH_SHIFT); |
surf[4] = 0; |
surf[5] = 0; |
/* Emit relocation to surface contents. The 965 PRM, Volume 4, section |
* 5.1.2 "Data Cache" says: "the data cache does not exist as a separate |
* physical cache. It is mapped in hardware to the sampler cache." |
*/ |
drm_intel_bo_emit_reloc(brw->batch.bo, |
*out_offset + 4, |
bo, offset, |
I915_GEM_DOMAIN_SAMPLER, 0); |
} |
/** |
* Set up a binding table entry for use by stream output logic (transform |
* feedback). |
* |
* buffer_size_minus_1 must me less than BRW_MAX_NUM_BUFFER_ENTRIES. |
*/ |
void |
brw_update_sol_surface(struct brw_context *brw, |
struct gl_buffer_object *buffer_obj, |
uint32_t *out_offset, unsigned num_vector_components, |
unsigned stride_dwords, unsigned offset_dwords) |
{ |
struct intel_buffer_object *intel_bo = intel_buffer_object(buffer_obj); |
drm_intel_bo *bo = intel_bufferobj_buffer(brw, intel_bo, INTEL_WRITE_PART); |
uint32_t *surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, 6 * 4, 32, |
out_offset); |
uint32_t pitch_minus_1 = 4*stride_dwords - 1; |
uint32_t offset_bytes = 4 * offset_dwords; |
size_t size_dwords = buffer_obj->Size / 4; |
uint32_t buffer_size_minus_1, width, height, depth, surface_format; |
/* FIXME: can we rely on core Mesa to ensure that the buffer isn't |
* too big to map using a single binding table entry? |
*/ |
assert((size_dwords - offset_dwords) / stride_dwords |
<= BRW_MAX_NUM_BUFFER_ENTRIES); |
if (size_dwords > offset_dwords + num_vector_components) { |
/* There is room for at least 1 transform feedback output in the buffer. |
* Compute the number of additional transform feedback outputs the |
* buffer has room for. |
*/ |
buffer_size_minus_1 = |
(size_dwords - offset_dwords - num_vector_components) / stride_dwords; |
} else { |
/* There isn't even room for a single transform feedback output in the |
* buffer. We can't configure the binding table entry to prevent output |
* entirely; we'll have to rely on the geometry shader to detect |
* overflow. But to minimize the damage in case of a bug, set up the |
* binding table entry to just allow a single output. |
*/ |
buffer_size_minus_1 = 0; |
} |
width = buffer_size_minus_1 & 0x7f; |
height = (buffer_size_minus_1 & 0xfff80) >> 7; |
depth = (buffer_size_minus_1 & 0x7f00000) >> 20; |
switch (num_vector_components) { |
case 1: |
surface_format = BRW_SURFACEFORMAT_R32_FLOAT; |
break; |
case 2: |
surface_format = BRW_SURFACEFORMAT_R32G32_FLOAT; |
break; |
case 3: |
surface_format = BRW_SURFACEFORMAT_R32G32B32_FLOAT; |
break; |
case 4: |
surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT; |
break; |
default: |
assert(!"Invalid vector size for transform feedback output"); |
surface_format = BRW_SURFACEFORMAT_R32_FLOAT; |
break; |
} |
surf[0] = BRW_SURFACE_BUFFER << BRW_SURFACE_TYPE_SHIFT | |
BRW_SURFACE_MIPMAPLAYOUT_BELOW << BRW_SURFACE_MIPLAYOUT_SHIFT | |
surface_format << BRW_SURFACE_FORMAT_SHIFT | |
BRW_SURFACE_RC_READ_WRITE; |
surf[1] = bo->offset + offset_bytes; /* reloc */ |
surf[2] = (width << BRW_SURFACE_WIDTH_SHIFT | |
height << BRW_SURFACE_HEIGHT_SHIFT); |
surf[3] = (depth << BRW_SURFACE_DEPTH_SHIFT | |
pitch_minus_1 << BRW_SURFACE_PITCH_SHIFT); |
surf[4] = 0; |
surf[5] = 0; |
/* Emit relocation to surface contents. */ |
drm_intel_bo_emit_reloc(brw->batch.bo, |
*out_offset + 4, |
bo, offset_bytes, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); |
} |
/* Creates a new WM constant buffer reflecting the current fragment program's |
* constants, if needed by the fragment program. |
* |
* Otherwise, constants go through the CURBEs using the brw_constant_buffer |
* state atom. |
*/ |
static void |
brw_upload_wm_pull_constants(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_FRAGMENT_PROGRAM */ |
struct brw_fragment_program *fp = |
(struct brw_fragment_program *) brw->fragment_program; |
struct gl_program_parameter_list *params = fp->program.Base.Parameters; |
const int size = brw->wm.prog_data->nr_pull_params * sizeof(float); |
const int surf_index = SURF_INDEX_FRAG_CONST_BUFFER; |
float *constants; |
unsigned int i; |
_mesa_load_state_parameters(ctx, params); |
/* CACHE_NEW_WM_PROG */ |
if (brw->wm.prog_data->nr_pull_params == 0) { |
if (brw->wm.const_bo) { |
drm_intel_bo_unreference(brw->wm.const_bo); |
brw->wm.const_bo = NULL; |
brw->wm.surf_offset[surf_index] = 0; |
brw->state.dirty.brw |= BRW_NEW_SURFACES; |
} |
return; |
} |
drm_intel_bo_unreference(brw->wm.const_bo); |
brw->wm.const_bo = drm_intel_bo_alloc(brw->bufmgr, "WM const bo", |
size, 64); |
/* _NEW_PROGRAM_CONSTANTS */ |
drm_intel_gem_bo_map_gtt(brw->wm.const_bo); |
constants = brw->wm.const_bo->virtual; |
for (i = 0; i < brw->wm.prog_data->nr_pull_params; i++) { |
constants[i] = *brw->wm.prog_data->pull_param[i]; |
} |
drm_intel_gem_bo_unmap_gtt(brw->wm.const_bo); |
brw->vtbl.create_constant_surface(brw, brw->wm.const_bo, 0, size, |
&brw->wm.surf_offset[surf_index], |
true); |
brw->state.dirty.brw |= BRW_NEW_SURFACES; |
} |
const struct brw_tracked_state brw_wm_pull_constants = { |
.dirty = { |
.mesa = (_NEW_PROGRAM_CONSTANTS), |
.brw = (BRW_NEW_BATCH | BRW_NEW_FRAGMENT_PROGRAM), |
.cache = CACHE_NEW_WM_PROG, |
}, |
.emit = brw_upload_wm_pull_constants, |
}; |
static void |
brw_update_null_renderbuffer_surface(struct brw_context *brw, unsigned int unit) |
{ |
/* From the Sandy bridge PRM, Vol4 Part1 p71 (Surface Type: Programming |
* Notes): |
* |
* A null surface will be used in instances where an actual surface is |
* not bound. When a write message is generated to a null surface, no |
* actual surface is written to. When a read message (including any |
* sampling engine message) is generated to a null surface, the result |
* is all zeros. Note that a null surface type is allowed to be used |
* with all messages, even if it is not specificially indicated as |
* supported. All of the remaining fields in surface state are ignored |
* for null surfaces, with the following exceptions: |
* |
* - [DevSNB+]: Width, Height, Depth, and LOD fields must match the |
* depth buffer’s corresponding state for all render target surfaces, |
* including null. |
* |
* - Surface Format must be R8G8B8A8_UNORM. |
*/ |
struct gl_context *ctx = &brw->ctx; |
uint32_t *surf; |
unsigned surface_type = BRW_SURFACE_NULL; |
drm_intel_bo *bo = NULL; |
unsigned pitch_minus_1 = 0; |
uint32_t multisampling_state = 0; |
/* _NEW_BUFFERS */ |
const struct gl_framebuffer *fb = ctx->DrawBuffer; |
surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, |
6 * 4, 32, &brw->wm.surf_offset[unit]); |
if (fb->Visual.samples > 1) { |
/* On Gen6, null render targets seem to cause GPU hangs when |
* multisampling. So work around this problem by rendering into dummy |
* color buffer. |
* |
* To decrease the amount of memory needed by the workaround buffer, we |
* set its pitch to 128 bytes (the width of a Y tile). This means that |
* the amount of memory needed for the workaround buffer is |
* (width_in_tiles + height_in_tiles - 1) tiles. |
* |
* Note that since the workaround buffer will be interpreted by the |
* hardware as an interleaved multisampled buffer, we need to compute |
* width_in_tiles and height_in_tiles by dividing the width and height |
* by 16 rather than the normal Y-tile size of 32. |
*/ |
unsigned width_in_tiles = ALIGN(fb->Width, 16) / 16; |
unsigned height_in_tiles = ALIGN(fb->Height, 16) / 16; |
unsigned size_needed = (width_in_tiles + height_in_tiles - 1) * 4096; |
brw_get_scratch_bo(brw, &brw->wm.multisampled_null_render_target_bo, |
size_needed); |
bo = brw->wm.multisampled_null_render_target_bo; |
surface_type = BRW_SURFACE_2D; |
pitch_minus_1 = 127; |
multisampling_state = |
brw_get_surface_num_multisamples(fb->Visual.samples); |
} |
surf[0] = (surface_type << BRW_SURFACE_TYPE_SHIFT | |
BRW_SURFACEFORMAT_B8G8R8A8_UNORM << BRW_SURFACE_FORMAT_SHIFT); |
if (brw->gen < 6) { |
surf[0] |= (1 << BRW_SURFACE_WRITEDISABLE_R_SHIFT | |
1 << BRW_SURFACE_WRITEDISABLE_G_SHIFT | |
1 << BRW_SURFACE_WRITEDISABLE_B_SHIFT | |
1 << BRW_SURFACE_WRITEDISABLE_A_SHIFT); |
} |
surf[1] = bo ? bo->offset : 0; |
surf[2] = ((fb->Width - 1) << BRW_SURFACE_WIDTH_SHIFT | |
(fb->Height - 1) << BRW_SURFACE_HEIGHT_SHIFT); |
/* From Sandy bridge PRM, Vol4 Part1 p82 (Tiled Surface: Programming |
* Notes): |
* |
* If Surface Type is SURFTYPE_NULL, this field must be TRUE |
*/ |
surf[3] = (BRW_SURFACE_TILED | BRW_SURFACE_TILED_Y | |
pitch_minus_1 << BRW_SURFACE_PITCH_SHIFT); |
surf[4] = multisampling_state; |
surf[5] = 0; |
if (bo) { |
drm_intel_bo_emit_reloc(brw->batch.bo, |
brw->wm.surf_offset[unit] + 4, |
bo, 0, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); |
} |
} |
/** |
* Sets up a surface state structure to point at the given region. |
* While it is only used for the front/back buffer currently, it should be |
* usable for further buffers when doing ARB_draw_buffer support. |
*/ |
static void |
brw_update_renderbuffer_surface(struct brw_context *brw, |
struct gl_renderbuffer *rb, |
bool layered, |
unsigned int unit) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
struct intel_mipmap_tree *mt = irb->mt; |
struct intel_region *region; |
uint32_t *surf; |
uint32_t tile_x, tile_y; |
uint32_t format = 0; |
/* _NEW_BUFFERS */ |
gl_format rb_format = _mesa_get_render_format(ctx, intel_rb_format(irb)); |
assert(!layered); |
if (rb->TexImage && !brw->has_surface_tile_offset) { |
intel_renderbuffer_get_tile_offsets(irb, &tile_x, &tile_y); |
if (tile_x != 0 || tile_y != 0) { |
/* Original gen4 hardware couldn't draw to a non-tile-aligned |
* destination in a miptree unless you actually setup your renderbuffer |
* as a miptree and used the fragile lod/array_index/etc. controls to |
* select the image. So, instead, we just make a new single-level |
* miptree and render into that. |
*/ |
intel_renderbuffer_move_to_temp(brw, irb, false); |
mt = irb->mt; |
} |
} |
intel_miptree_used_for_rendering(irb->mt); |
region = irb->mt->region; |
surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, |
6 * 4, 32, &brw->wm.surf_offset[unit]); |
format = brw->render_target_format[rb_format]; |
if (unlikely(!brw->format_supported_as_render_target[rb_format])) { |
_mesa_problem(ctx, "%s: renderbuffer format %s unsupported\n", |
__FUNCTION__, _mesa_get_format_name(rb_format)); |
} |
surf[0] = (BRW_SURFACE_2D << BRW_SURFACE_TYPE_SHIFT | |
format << BRW_SURFACE_FORMAT_SHIFT); |
/* reloc */ |
surf[1] = (intel_renderbuffer_get_tile_offsets(irb, &tile_x, &tile_y) + |
region->bo->offset); |
surf[2] = ((rb->Width - 1) << BRW_SURFACE_WIDTH_SHIFT | |
(rb->Height - 1) << BRW_SURFACE_HEIGHT_SHIFT); |
surf[3] = (brw_get_surface_tiling_bits(region->tiling) | |
(region->pitch - 1) << BRW_SURFACE_PITCH_SHIFT); |
surf[4] = brw_get_surface_num_multisamples(mt->num_samples); |
assert(brw->has_surface_tile_offset || (tile_x == 0 && tile_y == 0)); |
/* Note that the low bits of these fields are missing, so |
* there's the possibility of getting in trouble. |
*/ |
assert(tile_x % 4 == 0); |
assert(tile_y % 2 == 0); |
surf[5] = ((tile_x / 4) << BRW_SURFACE_X_OFFSET_SHIFT | |
(tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT | |
(mt->align_h == 4 ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0)); |
if (brw->gen < 6) { |
/* _NEW_COLOR */ |
if (!ctx->Color.ColorLogicOpEnabled && |
(ctx->Color.BlendEnabled & (1 << unit))) |
surf[0] |= BRW_SURFACE_BLEND_ENABLED; |
if (!ctx->Color.ColorMask[unit][0]) |
surf[0] |= 1 << BRW_SURFACE_WRITEDISABLE_R_SHIFT; |
if (!ctx->Color.ColorMask[unit][1]) |
surf[0] |= 1 << BRW_SURFACE_WRITEDISABLE_G_SHIFT; |
if (!ctx->Color.ColorMask[unit][2]) |
surf[0] |= 1 << BRW_SURFACE_WRITEDISABLE_B_SHIFT; |
/* As mentioned above, disable writes to the alpha component when the |
* renderbuffer is XRGB. |
*/ |
if (ctx->DrawBuffer->Visual.alphaBits == 0 || |
!ctx->Color.ColorMask[unit][3]) { |
surf[0] |= 1 << BRW_SURFACE_WRITEDISABLE_A_SHIFT; |
} |
} |
#if 0 |
printf("brw_update_renderbuffer_surface\n" |
"bind bo(handle=%d format=%d width=%d height=%d\n" |
"pitch=%d, tiling=%d\n" |
"ss[0] %x ss[1] %x ss[2] %x ss[3] %x ss[4] %x ss[5] %x\n", |
region->bo->handle, format, rb->Width, rb->Height, |
region->pitch, region->tiling, |
surf[0],surf[1],surf[2],surf[3], surf[4],surf[5]); |
#endif |
drm_intel_bo_emit_reloc(brw->batch.bo, |
brw->wm.surf_offset[unit] + 4, |
region->bo, |
surf[1] - region->bo->offset, |
I915_GEM_DOMAIN_RENDER, |
I915_GEM_DOMAIN_RENDER); |
} |
/** |
* Construct SURFACE_STATE objects for renderbuffers/draw buffers. |
*/ |
static void |
brw_update_renderbuffer_surfaces(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
GLuint i; |
/* _NEW_BUFFERS | _NEW_COLOR */ |
/* Update surfaces for drawing buffers */ |
if (ctx->DrawBuffer->_NumColorDrawBuffers >= 1) { |
for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { |
if (intel_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[i])) { |
brw->vtbl.update_renderbuffer_surface(brw, ctx->DrawBuffer->_ColorDrawBuffers[i], |
ctx->DrawBuffer->Layered, i); |
} else { |
brw->vtbl.update_null_renderbuffer_surface(brw, i); |
} |
} |
} else { |
brw->vtbl.update_null_renderbuffer_surface(brw, 0); |
} |
brw->state.dirty.brw |= BRW_NEW_SURFACES; |
} |
const struct brw_tracked_state brw_renderbuffer_surfaces = { |
.dirty = { |
.mesa = (_NEW_COLOR | |
_NEW_BUFFERS), |
.brw = BRW_NEW_BATCH, |
.cache = 0 |
}, |
.emit = brw_update_renderbuffer_surfaces, |
}; |
const struct brw_tracked_state gen6_renderbuffer_surfaces = { |
.dirty = { |
.mesa = _NEW_BUFFERS, |
.brw = BRW_NEW_BATCH, |
.cache = 0 |
}, |
.emit = brw_update_renderbuffer_surfaces, |
}; |
/** |
* Construct SURFACE_STATE objects for enabled textures. |
*/ |
static void |
brw_update_texture_surfaces(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_VERTEX_PROGRAM and BRW_NEW_FRAGMENT_PROGRAM: |
* Unfortunately, we're stuck using the gl_program structs until the |
* ARB_fragment_program front-end gets converted to GLSL IR. These |
* have the downside that SamplerUnits is split and only contains the |
* mappings for samplers active in that stage. |
*/ |
struct gl_program *vs = (struct gl_program *) brw->vertex_program; |
struct gl_program *fs = (struct gl_program *) brw->fragment_program; |
unsigned num_samplers = _mesa_fls(vs->SamplersUsed | fs->SamplersUsed); |
for (unsigned s = 0; s < num_samplers; s++) { |
brw->vs.surf_offset[SURF_INDEX_VS_TEXTURE(s)] = 0; |
brw->wm.surf_offset[SURF_INDEX_TEXTURE(s)] = 0; |
if (vs->SamplersUsed & (1 << s)) { |
const unsigned unit = vs->SamplerUnits[s]; |
/* _NEW_TEXTURE */ |
if (ctx->Texture.Unit[unit]._ReallyEnabled) { |
brw->vtbl.update_texture_surface(ctx, unit, |
brw->vs.surf_offset, |
SURF_INDEX_VS_TEXTURE(s)); |
} |
} |
if (fs->SamplersUsed & (1 << s)) { |
const unsigned unit = fs->SamplerUnits[s]; |
/* _NEW_TEXTURE */ |
if (ctx->Texture.Unit[unit]._ReallyEnabled) { |
brw->vtbl.update_texture_surface(ctx, unit, |
brw->wm.surf_offset, |
SURF_INDEX_TEXTURE(s)); |
} |
} |
} |
brw->state.dirty.brw |= BRW_NEW_SURFACES; |
} |
const struct brw_tracked_state brw_texture_surfaces = { |
.dirty = { |
.mesa = _NEW_TEXTURE, |
.brw = BRW_NEW_BATCH | |
BRW_NEW_VERTEX_PROGRAM | |
BRW_NEW_FRAGMENT_PROGRAM, |
.cache = 0 |
}, |
.emit = brw_update_texture_surfaces, |
}; |
void |
brw_upload_ubo_surfaces(struct brw_context *brw, |
struct gl_shader *shader, |
uint32_t *surf_offsets) |
{ |
struct gl_context *ctx = &brw->ctx; |
if (!shader) |
return; |
for (int i = 0; i < shader->NumUniformBlocks; i++) { |
struct gl_uniform_buffer_binding *binding; |
struct intel_buffer_object *intel_bo; |
binding = &ctx->UniformBufferBindings[shader->UniformBlocks[i].Binding]; |
intel_bo = intel_buffer_object(binding->BufferObject); |
drm_intel_bo *bo = intel_bufferobj_buffer(brw, intel_bo, INTEL_READ); |
/* Because behavior for referencing outside of the binding's size in the |
* glBindBufferRange case is undefined, we can just bind the whole buffer |
* glBindBufferBase wants and be a correct implementation. |
*/ |
brw->vtbl.create_constant_surface(brw, bo, binding->Offset, |
bo->size - binding->Offset, |
&surf_offsets[i], |
shader->Type == GL_FRAGMENT_SHADER); |
} |
if (shader->NumUniformBlocks) |
brw->state.dirty.brw |= BRW_NEW_SURFACES; |
} |
static void |
brw_upload_wm_ubo_surfaces(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* _NEW_PROGRAM */ |
struct gl_shader_program *prog = ctx->Shader._CurrentFragmentProgram; |
if (!prog) |
return; |
brw_upload_ubo_surfaces(brw, prog->_LinkedShaders[MESA_SHADER_FRAGMENT], |
&brw->wm.surf_offset[SURF_INDEX_WM_UBO(0)]); |
} |
const struct brw_tracked_state brw_wm_ubo_surfaces = { |
.dirty = { |
.mesa = _NEW_PROGRAM, |
.brw = BRW_NEW_BATCH | BRW_NEW_UNIFORM_BUFFER, |
.cache = 0, |
}, |
.emit = brw_upload_wm_ubo_surfaces, |
}; |
/** |
* Constructs the binding table for the WM surface state, which maps unit |
* numbers to surface state objects. |
*/ |
static void |
brw_upload_wm_binding_table(struct brw_context *brw) |
{ |
uint32_t *bind; |
int i; |
if (INTEL_DEBUG & DEBUG_SHADER_TIME) { |
gen7_create_shader_time_surface(brw, &brw->wm.surf_offset[SURF_INDEX_WM_SHADER_TIME]); |
} |
/* Might want to calculate nr_surfaces first, to avoid taking up so much |
* space for the binding table. |
*/ |
bind = brw_state_batch(brw, AUB_TRACE_BINDING_TABLE, |
sizeof(uint32_t) * BRW_MAX_WM_SURFACES, |
32, &brw->wm.bind_bo_offset); |
/* BRW_NEW_SURFACES */ |
for (i = 0; i < BRW_MAX_WM_SURFACES; i++) { |
bind[i] = brw->wm.surf_offset[i]; |
} |
brw->state.dirty.brw |= BRW_NEW_PS_BINDING_TABLE; |
} |
const struct brw_tracked_state brw_wm_binding_table = { |
.dirty = { |
.mesa = 0, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_SURFACES), |
.cache = 0 |
}, |
.emit = brw_upload_wm_binding_table, |
}; |
void |
gen4_init_vtable_surface_functions(struct brw_context *brw) |
{ |
brw->vtbl.update_texture_surface = brw_update_texture_surface; |
brw->vtbl.update_renderbuffer_surface = brw_update_renderbuffer_surface; |
brw->vtbl.update_null_renderbuffer_surface = |
brw_update_null_renderbuffer_surface; |
brw->vtbl.create_constant_surface = brw_create_constant_surface; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_blorp.cpp |
---|
0,0 → 1,1083 |
/* |
* Copyright © 2011 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 <assert.h> |
#include "intel_batchbuffer.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
#include "brw_state.h" |
#include "brw_blorp.h" |
#include "gen6_blorp.h" |
/** |
* \name Constants for BLORP VBO |
* \{ |
*/ |
#define GEN6_BLORP_NUM_VERTICES 3 |
#define GEN6_BLORP_NUM_VUE_ELEMS 8 |
#define GEN6_BLORP_VBO_SIZE (GEN6_BLORP_NUM_VERTICES \ |
* GEN6_BLORP_NUM_VUE_ELEMS \ |
* sizeof(float)) |
/** \} */ |
void |
gen6_blorp_emit_batch_head(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* To ensure that the batch contains only the resolve, flush the batch |
* before beginning and after finishing emitting the resolve packets. |
*/ |
intel_flush(ctx); |
} |
/** |
* CMD_STATE_BASE_ADDRESS |
* |
* From the Sandy Bridge PRM, Volume 1, Part 1, Table STATE_BASE_ADDRESS: |
* The following commands must be reissued following any change to the |
* base addresses: |
* 3DSTATE_CC_POINTERS |
* 3DSTATE_BINDING_TABLE_POINTERS |
* 3DSTATE_SAMPLER_STATE_POINTERS |
* 3DSTATE_VIEWPORT_STATE_POINTERS |
* MEDIA_STATE_POINTERS |
*/ |
void |
gen6_blorp_emit_state_base_address(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(10); |
OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (10 - 2)); |
OUT_BATCH(1); /* GeneralStateBaseAddressModifyEnable */ |
/* SurfaceStateBaseAddress */ |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_SAMPLER, 0, 1); |
/* DynamicStateBaseAddress */ |
OUT_RELOC(brw->batch.bo, (I915_GEM_DOMAIN_RENDER | |
I915_GEM_DOMAIN_INSTRUCTION), 0, 1); |
OUT_BATCH(1); /* IndirectObjectBaseAddress */ |
if (params->use_wm_prog) { |
OUT_RELOC(brw->cache.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, |
1); /* Instruction base address: shader kernels */ |
} else { |
OUT_BATCH(1); /* InstructionBaseAddress */ |
} |
OUT_BATCH(1); /* GeneralStateUpperBound */ |
/* Dynamic state upper bound. Although the documentation says that |
* programming it to zero will cause it to be ignored, that is a lie. |
* If this isn't programmed to a real bound, the sampler border color |
* pointer is rejected, causing border color to mysteriously fail. |
*/ |
OUT_BATCH(0xfffff001); |
OUT_BATCH(1); /* IndirectObjectUpperBound*/ |
OUT_BATCH(1); /* InstructionAccessUpperBound */ |
ADVANCE_BATCH(); |
} |
void |
gen6_blorp_emit_vertices(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
uint32_t vertex_offset; |
/* Setup VBO for the rectangle primitive.. |
* |
* A rectangle primitive (3DPRIM_RECTLIST) consists of only three |
* vertices. The vertices reside in screen space with DirectX coordinates |
* (that is, (0, 0) is the upper left corner). |
* |
* v2 ------ implied |
* | | |
* | | |
* v0 ----- v1 |
* |
* Since the VS is disabled, the clipper loads each VUE directly from |
* the URB. This is controlled by the 3DSTATE_VERTEX_BUFFERS and |
* 3DSTATE_VERTEX_ELEMENTS packets below. The VUE contents are as follows: |
* dw0: Reserved, MBZ. |
* dw1: Render Target Array Index. The HiZ op does not use indexed |
* vertices, so set the dword to 0. |
* dw2: Viewport Index. The HiZ op disables viewport mapping and |
* scissoring, so set the dword to 0. |
* dw3: Point Width: The HiZ op does not emit the POINTLIST primitive, so |
* set the dword to 0. |
* dw4: Vertex Position X. |
* dw5: Vertex Position Y. |
* dw6: Vertex Position Z. |
* dw7: Vertex Position W. |
* |
* For details, see the Sandybridge PRM, Volume 2, Part 1, Section 1.5.1 |
* "Vertex URB Entry (VUE) Formats". |
*/ |
{ |
float *vertex_data; |
const float vertices[GEN6_BLORP_VBO_SIZE] = { |
/* v0 */ 0, 0, 0, 0, (float) params->x0, (float) params->y1, 0, 1, |
/* v1 */ 0, 0, 0, 0, (float) params->x1, (float) params->y1, 0, 1, |
/* v2 */ 0, 0, 0, 0, (float) params->x0, (float) params->y0, 0, 1, |
}; |
vertex_data = (float *) brw_state_batch(brw, AUB_TRACE_VERTEX_BUFFER, |
GEN6_BLORP_VBO_SIZE, 32, |
&vertex_offset); |
memcpy(vertex_data, vertices, GEN6_BLORP_VBO_SIZE); |
} |
/* 3DSTATE_VERTEX_BUFFERS */ |
{ |
const int num_buffers = 1; |
const int batch_length = 1 + 4 * num_buffers; |
uint32_t dw0 = GEN6_VB0_ACCESS_VERTEXDATA | |
(GEN6_BLORP_NUM_VUE_ELEMS * sizeof(float)) << BRW_VB0_PITCH_SHIFT; |
if (brw->gen >= 7) |
dw0 |= GEN7_VB0_ADDRESS_MODIFYENABLE; |
if (brw->is_haswell) |
dw0 |= GEN7_MOCS_L3 << 16; |
BEGIN_BATCH(batch_length); |
OUT_BATCH((_3DSTATE_VERTEX_BUFFERS << 16) | (batch_length - 2)); |
OUT_BATCH(dw0); |
/* start address */ |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_VERTEX, 0, |
vertex_offset); |
/* end address */ |
OUT_RELOC(brw->batch.bo, I915_GEM_DOMAIN_VERTEX, 0, |
vertex_offset + GEN6_BLORP_VBO_SIZE - 1); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_VERTEX_ELEMENTS |
* |
* Fetch dwords 0 - 7 from each VUE. See the comments above where |
* the vertex_bo is filled with data. |
*/ |
{ |
const int num_elements = 2; |
const int batch_length = 1 + 2 * num_elements; |
BEGIN_BATCH(batch_length); |
OUT_BATCH((_3DSTATE_VERTEX_ELEMENTS << 16) | (batch_length - 2)); |
/* Element 0 */ |
OUT_BATCH(GEN6_VE0_VALID | |
BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT | |
0 << BRW_VE0_SRC_OFFSET_SHIFT); |
OUT_BATCH(BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT | |
BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_1_SHIFT | |
BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_2_SHIFT | |
BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_3_SHIFT); |
/* Element 1 */ |
OUT_BATCH(GEN6_VE0_VALID | |
BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_VE0_FORMAT_SHIFT | |
16 << BRW_VE0_SRC_OFFSET_SHIFT); |
OUT_BATCH(BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_0_SHIFT | |
BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_1_SHIFT | |
BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_2_SHIFT | |
BRW_VE1_COMPONENT_STORE_SRC << BRW_VE1_COMPONENT_3_SHIFT); |
ADVANCE_BATCH(); |
} |
} |
/* 3DSTATE_URB |
* |
* Assign the entire URB to the VS. Even though the VS disabled, URB space |
* is still needed because the clipper loads the VUE's from the URB. From |
* the Sandybridge PRM, Volume 2, Part 1, Section 3DSTATE, |
* Dword 1.15:0 "VS Number of URB Entries": |
* This field is always used (even if VS Function Enable is DISABLED). |
* |
* The warning below appears in the PRM (Section 3DSTATE_URB), but we can |
* safely ignore it because this batch contains only one draw call. |
* Because of URB corruption caused by allocating a previous GS unit |
* URB entry to the VS unit, software is required to send a “GS NULL |
* Fence” (Send URB fence with VS URB size == 1 and GS URB size == 0) |
* plus a dummy DRAW call before any case where VS will be taking over |
* GS URB space. |
*/ |
static void |
gen6_blorp_emit_urb_config(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(3); |
OUT_BATCH(_3DSTATE_URB << 16 | (3 - 2)); |
OUT_BATCH(brw->urb.max_vs_entries << GEN6_URB_VS_ENTRIES_SHIFT); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* BLEND_STATE */ |
uint32_t |
gen6_blorp_emit_blend_state(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
uint32_t cc_blend_state_offset; |
struct gen6_blend_state *blend = (struct gen6_blend_state *) |
brw_state_batch(brw, AUB_TRACE_BLEND_STATE, |
sizeof(struct gen6_blend_state), 64, |
&cc_blend_state_offset); |
memset(blend, 0, sizeof(*blend)); |
blend->blend1.pre_blend_clamp_enable = 1; |
blend->blend1.post_blend_clamp_enable = 1; |
blend->blend1.clamp_range = BRW_RENDERTARGET_CLAMPRANGE_FORMAT; |
blend->blend1.write_disable_r = params->color_write_disable[0]; |
blend->blend1.write_disable_g = params->color_write_disable[1]; |
blend->blend1.write_disable_b = params->color_write_disable[2]; |
blend->blend1.write_disable_a = params->color_write_disable[3]; |
/* When blitting from an XRGB source to a ARGB destination, we need to |
* interpret the missing channel as 1.0. Blending can do that for us: |
* we simply use the RGB values from the fragment shader ("source RGB"), |
* but smash the alpha channel to 1. |
*/ |
if (params->src.mt && |
_mesa_get_format_bits(params->dst.mt->format, GL_ALPHA_BITS) > 0 && |
_mesa_get_format_bits(params->src.mt->format, GL_ALPHA_BITS) == 0) { |
blend->blend0.blend_enable = 1; |
blend->blend0.ia_blend_enable = 1; |
blend->blend0.blend_func = BRW_BLENDFUNCTION_ADD; |
blend->blend0.ia_blend_func = BRW_BLENDFUNCTION_ADD; |
blend->blend0.source_blend_factor = BRW_BLENDFACTOR_SRC_COLOR; |
blend->blend0.dest_blend_factor = BRW_BLENDFACTOR_ZERO; |
blend->blend0.ia_source_blend_factor = BRW_BLENDFACTOR_ONE; |
blend->blend0.ia_dest_blend_factor = BRW_BLENDFACTOR_ZERO; |
} |
return cc_blend_state_offset; |
} |
/* CC_STATE */ |
uint32_t |
gen6_blorp_emit_cc_state(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
uint32_t cc_state_offset; |
struct gen6_color_calc_state *cc = (struct gen6_color_calc_state *) |
brw_state_batch(brw, AUB_TRACE_CC_STATE, |
sizeof(gen6_color_calc_state), 64, |
&cc_state_offset); |
memset(cc, 0, sizeof(*cc)); |
return cc_state_offset; |
} |
/** |
* \param out_offset is relative to |
* CMD_STATE_BASE_ADDRESS.DynamicStateBaseAddress. |
*/ |
uint32_t |
gen6_blorp_emit_depth_stencil_state(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
uint32_t depthstencil_offset; |
struct gen6_depth_stencil_state *state; |
state = (struct gen6_depth_stencil_state *) |
brw_state_batch(brw, AUB_TRACE_DEPTH_STENCIL_STATE, |
sizeof(*state), 64, |
&depthstencil_offset); |
memset(state, 0, sizeof(*state)); |
/* See the following sections of the Sandy Bridge PRM, Volume 1, Part2: |
* - 7.5.3.1 Depth Buffer Clear |
* - 7.5.3.2 Depth Buffer Resolve |
* - 7.5.3.3 Hierarchical Depth Buffer Resolve |
*/ |
state->ds2.depth_write_enable = 1; |
if (params->hiz_op == GEN6_HIZ_OP_DEPTH_RESOLVE) { |
state->ds2.depth_test_enable = 1; |
state->ds2.depth_test_func = BRW_COMPAREFUNCTION_NEVER; |
} |
return depthstencil_offset; |
} |
/* 3DSTATE_CC_STATE_POINTERS |
* |
* The pointer offsets are relative to |
* CMD_STATE_BASE_ADDRESS.DynamicStateBaseAddress. |
* |
* The HiZ op doesn't use BLEND_STATE or COLOR_CALC_STATE. |
*/ |
static void |
gen6_blorp_emit_cc_state_pointers(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t cc_blend_state_offset, |
uint32_t depthstencil_offset, |
uint32_t cc_state_offset) |
{ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (4 - 2)); |
OUT_BATCH(cc_blend_state_offset | 1); /* BLEND_STATE offset */ |
OUT_BATCH(depthstencil_offset | 1); /* DEPTH_STENCIL_STATE offset */ |
OUT_BATCH(cc_state_offset | 1); /* COLOR_CALC_STATE offset */ |
ADVANCE_BATCH(); |
} |
/* WM push constants */ |
uint32_t |
gen6_blorp_emit_wm_constants(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
uint32_t wm_push_const_offset; |
void *constants = brw_state_batch(brw, AUB_TRACE_WM_CONSTANTS, |
sizeof(params->wm_push_consts), |
32, &wm_push_const_offset); |
memcpy(constants, ¶ms->wm_push_consts, |
sizeof(params->wm_push_consts)); |
return wm_push_const_offset; |
} |
/* SURFACE_STATE for renderbuffer or texture surface (see |
* brw_update_renderbuffer_surface and brw_update_texture_surface) |
*/ |
static uint32_t |
gen6_blorp_emit_surface_state(struct brw_context *brw, |
const brw_blorp_params *params, |
const brw_blorp_surface_info *surface, |
uint32_t read_domains, uint32_t write_domain) |
{ |
uint32_t wm_surf_offset; |
uint32_t width = surface->width; |
uint32_t height = surface->height; |
if (surface->num_samples > 1) { |
/* Since gen6 uses INTEL_MSAA_LAYOUT_IMS, width and height are measured |
* in samples. But SURFACE_STATE wants them in pixels, so we need to |
* divide them each by 2. |
*/ |
width /= 2; |
height /= 2; |
} |
struct intel_region *region = surface->mt->region; |
uint32_t tile_x, tile_y; |
uint32_t *surf = (uint32_t *) |
brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, 6 * 4, 32, |
&wm_surf_offset); |
surf[0] = (BRW_SURFACE_2D << BRW_SURFACE_TYPE_SHIFT | |
BRW_SURFACE_MIPMAPLAYOUT_BELOW << BRW_SURFACE_MIPLAYOUT_SHIFT | |
BRW_SURFACE_CUBEFACE_ENABLES | |
surface->brw_surfaceformat << BRW_SURFACE_FORMAT_SHIFT); |
/* reloc */ |
surf[1] = (surface->compute_tile_offsets(&tile_x, &tile_y) + |
region->bo->offset); |
surf[2] = (0 << BRW_SURFACE_LOD_SHIFT | |
(width - 1) << BRW_SURFACE_WIDTH_SHIFT | |
(height - 1) << BRW_SURFACE_HEIGHT_SHIFT); |
uint32_t tiling = surface->map_stencil_as_y_tiled |
? BRW_SURFACE_TILED | BRW_SURFACE_TILED_Y |
: brw_get_surface_tiling_bits(region->tiling); |
uint32_t pitch_bytes = region->pitch; |
if (surface->map_stencil_as_y_tiled) |
pitch_bytes *= 2; |
surf[3] = (tiling | |
0 << BRW_SURFACE_DEPTH_SHIFT | |
(pitch_bytes - 1) << BRW_SURFACE_PITCH_SHIFT); |
surf[4] = brw_get_surface_num_multisamples(surface->num_samples); |
/* Note that the low bits of these fields are missing, so |
* there's the possibility of getting in trouble. |
*/ |
assert(tile_x % 4 == 0); |
assert(tile_y % 2 == 0); |
surf[5] = ((tile_x / 4) << BRW_SURFACE_X_OFFSET_SHIFT | |
(tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT | |
(surface->mt->align_h == 4 ? |
BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0)); |
/* Emit relocation to surface contents */ |
drm_intel_bo_emit_reloc(brw->batch.bo, |
wm_surf_offset + 4, |
region->bo, |
surf[1] - region->bo->offset, |
read_domains, write_domain); |
return wm_surf_offset; |
} |
/* BINDING_TABLE. See brw_wm_binding_table(). */ |
uint32_t |
gen6_blorp_emit_binding_table(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t wm_surf_offset_renderbuffer, |
uint32_t wm_surf_offset_texture) |
{ |
uint32_t wm_bind_bo_offset; |
uint32_t *bind = (uint32_t *) |
brw_state_batch(brw, AUB_TRACE_BINDING_TABLE, |
sizeof(uint32_t) * |
BRW_BLORP_NUM_BINDING_TABLE_ENTRIES, |
32, /* alignment */ |
&wm_bind_bo_offset); |
bind[BRW_BLORP_RENDERBUFFER_BINDING_TABLE_INDEX] = |
wm_surf_offset_renderbuffer; |
bind[BRW_BLORP_TEXTURE_BINDING_TABLE_INDEX] = wm_surf_offset_texture; |
return wm_bind_bo_offset; |
} |
/** |
* SAMPLER_STATE. See brw_update_sampler_state(). |
*/ |
static uint32_t |
gen6_blorp_emit_sampler_state(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
uint32_t sampler_offset; |
struct brw_sampler_state *sampler = (struct brw_sampler_state *) |
brw_state_batch(brw, AUB_TRACE_SAMPLER_STATE, |
sizeof(struct brw_sampler_state), |
32, &sampler_offset); |
memset(sampler, 0, sizeof(*sampler)); |
sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; |
sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; |
sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; |
sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
sampler->ss0.min_mag_neq = 1; |
/* Set LOD bias: |
*/ |
sampler->ss0.lod_bias = 0; |
sampler->ss0.lod_preclamp = 1; /* OpenGL mode */ |
sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */ |
/* Set BaseMipLevel, MaxLOD, MinLOD: |
* |
* XXX: I don't think that using firstLevel, lastLevel works, |
* because we always setup the surface state as if firstLevel == |
* level zero. Probably have to subtract firstLevel from each of |
* these: |
*/ |
sampler->ss0.base_level = U_FIXED(0, 1); |
sampler->ss1.max_lod = U_FIXED(0, 6); |
sampler->ss1.min_lod = U_FIXED(0, 6); |
sampler->ss3.non_normalized_coord = 1; |
sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN | |
BRW_ADDRESS_ROUNDING_ENABLE_V_MIN | |
BRW_ADDRESS_ROUNDING_ENABLE_R_MIN; |
sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG | |
BRW_ADDRESS_ROUNDING_ENABLE_V_MAG | |
BRW_ADDRESS_ROUNDING_ENABLE_R_MAG; |
return sampler_offset; |
} |
/** |
* 3DSTATE_SAMPLER_STATE_POINTERS. See upload_sampler_state_pointers(). |
*/ |
static void |
gen6_blorp_emit_sampler_state_pointers(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t sampler_offset) |
{ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_SAMPLER_STATE_POINTERS << 16 | |
VS_SAMPLER_STATE_CHANGE | |
GS_SAMPLER_STATE_CHANGE | |
PS_SAMPLER_STATE_CHANGE | |
(4 - 2)); |
OUT_BATCH(0); /* VS */ |
OUT_BATCH(0); /* GS */ |
OUT_BATCH(sampler_offset); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_VS |
* |
* Disable vertex shader. |
*/ |
void |
gen6_blorp_emit_vs_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
if (brw->gen == 6) { |
/* From the BSpec, 3D Pipeline > Geometry > Vertex Shader > State, |
* 3DSTATE_VS, Dword 5.0 "VS Function Enable": |
* |
* [DevSNB] A pipeline flush must be programmed prior to a |
* 3DSTATE_VS command that causes the VS Function Enable to |
* toggle. Pipeline flush can be executed by sending a PIPE_CONTROL |
* command with CS stall bit set and a post sync operation. |
*/ |
intel_emit_post_sync_nonzero_flush(brw); |
} |
/* Disable the push constant buffers. */ |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 | (5 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(6); |
OUT_BATCH(_3DSTATE_VS << 16 | (6 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_GS |
* |
* Disable the geometry shader. |
*/ |
void |
gen6_blorp_emit_gs_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
/* Disable all the constant buffers. */ |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_CONSTANT_GS << 16 | (5 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_GS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_CLIP |
* |
* Disable the clipper. |
* |
* The BLORP op emits a rectangle primitive, which requires clipping to |
* be disabled. From page 10 of the Sandy Bridge PRM Volume 2 Part 1 |
* Section 1.3 "3D Primitives Overview": |
* RECTLIST: |
* Either the CLIP unit should be DISABLED, or the CLIP unit's Clip |
* Mode should be set to a value other than CLIPMODE_NORMAL. |
* |
* Also disable perspective divide. This doesn't change the clipper's |
* output, but does spare a few electrons. |
*/ |
void |
gen6_blorp_emit_clip_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(GEN6_CLIP_PERSPECTIVE_DIVIDE_DISABLE); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_SF |
* |
* Disable ViewportTransformEnable (dw2.1) |
* |
* From the SandyBridge PRM, Volume 2, Part 1, Section 1.3, "3D |
* Primitives Overview": |
* RECTLIST: Viewport Mapping must be DISABLED (as is typical with the |
* use of screen- space coordinates). |
* |
* A solid rectangle must be rendered, so set FrontFaceFillMode (dw2.4:3) |
* and BackFaceFillMode (dw2.5:6) to SOLID(0). |
* |
* From the Sandy Bridge PRM, Volume 2, Part 1, Section |
* 6.4.1.1 3DSTATE_SF, Field FrontFaceFillMode: |
* SOLID: Any triangle or rectangle object found to be front-facing |
* is rendered as a solid object. This setting is required when |
* (rendering rectangle (RECTLIST) objects. |
*/ |
static void |
gen6_blorp_emit_sf_config(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(20); |
OUT_BATCH(_3DSTATE_SF << 16 | (20 - 2)); |
OUT_BATCH((1 - 1) << GEN6_SF_NUM_OUTPUTS_SHIFT | /* only position */ |
1 << GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT | |
0 << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT); |
OUT_BATCH(0); /* dw2 */ |
OUT_BATCH(params->num_samples > 1 ? GEN6_SF_MSRAST_ON_PATTERN : 0); |
for (int i = 0; i < 16; ++i) |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/** |
* Enable or disable thread dispatch and set the HiZ op appropriately. |
*/ |
static void |
gen6_blorp_emit_wm_config(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t prog_offset, |
brw_blorp_prog_data *prog_data) |
{ |
uint32_t dw2, dw4, dw5, dw6; |
/* Even when thread dispatch is disabled, max threads (dw5.25:31) must be |
* nonzero to prevent the GPU from hanging. While the documentation doesn't |
* mention this explicitly, it notes that the valid range for the field is |
* [1,39] = [2,40] threads, which excludes zero. |
* |
* To be safe (and to minimize extraneous code) we go ahead and fully |
* configure the WM state whether or not there is a WM program. |
*/ |
dw2 = dw4 = dw5 = dw6 = 0; |
switch (params->hiz_op) { |
case GEN6_HIZ_OP_DEPTH_CLEAR: |
dw4 |= GEN6_WM_DEPTH_CLEAR; |
break; |
case GEN6_HIZ_OP_DEPTH_RESOLVE: |
dw4 |= GEN6_WM_DEPTH_RESOLVE; |
break; |
case GEN6_HIZ_OP_HIZ_RESOLVE: |
dw4 |= GEN6_WM_HIERARCHICAL_DEPTH_RESOLVE; |
break; |
case GEN6_HIZ_OP_NONE: |
break; |
default: |
assert(0); |
break; |
} |
dw5 |= GEN6_WM_LINE_AA_WIDTH_1_0; |
dw5 |= GEN6_WM_LINE_END_CAP_AA_WIDTH_0_5; |
dw5 |= (brw->max_wm_threads - 1) << GEN6_WM_MAX_THREADS_SHIFT; |
dw6 |= 0 << GEN6_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT; /* No interp */ |
dw6 |= 0 << GEN6_WM_NUM_SF_OUTPUTS_SHIFT; /* No inputs from SF */ |
if (params->use_wm_prog) { |
dw2 |= 1 << GEN6_WM_SAMPLER_COUNT_SHIFT; /* Up to 4 samplers */ |
dw4 |= prog_data->first_curbe_grf << GEN6_WM_DISPATCH_START_GRF_SHIFT_0; |
dw5 |= GEN6_WM_16_DISPATCH_ENABLE; |
dw5 |= GEN6_WM_KILL_ENABLE; /* TODO: temporarily smash on */ |
dw5 |= GEN6_WM_DISPATCH_ENABLE; /* We are rendering */ |
} |
if (params->num_samples > 1) { |
dw6 |= GEN6_WM_MSRAST_ON_PATTERN; |
if (prog_data && prog_data->persample_msaa_dispatch) |
dw6 |= GEN6_WM_MSDISPMODE_PERSAMPLE; |
else |
dw6 |= GEN6_WM_MSDISPMODE_PERPIXEL; |
} else { |
dw6 |= GEN6_WM_MSRAST_OFF_PIXEL; |
dw6 |= GEN6_WM_MSDISPMODE_PERSAMPLE; |
} |
BEGIN_BATCH(9); |
OUT_BATCH(_3DSTATE_WM << 16 | (9 - 2)); |
OUT_BATCH(params->use_wm_prog ? prog_offset : 0); |
OUT_BATCH(dw2); |
OUT_BATCH(0); /* No scratch needed */ |
OUT_BATCH(dw4); |
OUT_BATCH(dw5); |
OUT_BATCH(dw6); |
OUT_BATCH(0); /* No other programs */ |
OUT_BATCH(0); /* No other programs */ |
ADVANCE_BATCH(); |
} |
static void |
gen6_blorp_emit_constant_ps(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t wm_push_const_offset) |
{ |
/* Make sure the push constants fill an exact integer number of |
* registers. |
*/ |
assert(sizeof(brw_blorp_wm_push_constants) % 32 == 0); |
/* There must be at least one register worth of push constant data. */ |
assert(BRW_BLORP_NUM_PUSH_CONST_REGS > 0); |
/* Enable push constant buffer 0. */ |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_CONSTANT_PS << 16 | |
GEN6_CONSTANT_BUFFER_0_ENABLE | |
(5 - 2)); |
OUT_BATCH(wm_push_const_offset + (BRW_BLORP_NUM_PUSH_CONST_REGS - 1)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
static void |
gen6_blorp_emit_constant_ps_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
/* Disable the push constant buffers. */ |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_CONSTANT_PS << 16 | (5 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/** |
* 3DSTATE_BINDING_TABLE_POINTERS |
*/ |
static void |
gen6_blorp_emit_binding_table_pointers(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t wm_bind_bo_offset) |
{ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS << 16 | |
GEN6_BINDING_TABLE_MODIFY_PS | |
(4 - 2)); |
OUT_BATCH(0); /* vs -- ignored */ |
OUT_BATCH(0); /* gs -- ignored */ |
OUT_BATCH(wm_bind_bo_offset); /* wm/ps */ |
ADVANCE_BATCH(); |
} |
static void |
gen6_blorp_emit_depth_stencil_config(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
struct gl_context *ctx = &brw->ctx; |
uint32_t draw_x = params->depth.x_offset; |
uint32_t draw_y = params->depth.y_offset; |
uint32_t tile_mask_x, tile_mask_y; |
brw_get_depthstencil_tile_masks(params->depth.mt, |
params->depth.level, |
params->depth.layer, |
NULL, |
&tile_mask_x, &tile_mask_y); |
/* 3DSTATE_DEPTH_BUFFER */ |
{ |
uint32_t tile_x = draw_x & tile_mask_x; |
uint32_t tile_y = draw_y & tile_mask_y; |
uint32_t offset = |
intel_region_get_aligned_offset(params->depth.mt->region, |
draw_x & ~tile_mask_x, |
draw_y & ~tile_mask_y, false); |
/* According to the Sandy Bridge PRM, volume 2 part 1, pp326-327 |
* (3DSTATE_DEPTH_BUFFER dw5), in the documentation for "Depth |
* Coordinate Offset X/Y": |
* |
* "The 3 LSBs of both offsets must be zero to ensure correct |
* alignment" |
* |
* We have no guarantee that tile_x and tile_y are correctly aligned, |
* since they are determined by the mipmap layout, which is only aligned |
* to multiples of 4. |
* |
* So, to avoid hanging the GPU, just smash the low order 3 bits of |
* tile_x and tile_y to 0. This is a temporary workaround until we come |
* up with a better solution. |
*/ |
WARN_ONCE((tile_x & 7) || (tile_y & 7), |
"Depth/stencil buffer needs alignment to 8-pixel boundaries.\n" |
"Truncating offset, bad rendering may occur.\n"); |
tile_x &= ~7; |
tile_y &= ~7; |
intel_emit_post_sync_nonzero_flush(brw); |
intel_emit_depth_stall_flushes(brw); |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2)); |
OUT_BATCH((params->depth.mt->region->pitch - 1) | |
params->depth_format << 18 | |
1 << 21 | /* separate stencil enable */ |
1 << 22 | /* hiz enable */ |
BRW_TILEWALK_YMAJOR << 26 | |
1 << 27 | /* y-tiled */ |
BRW_SURFACE_2D << 29); |
OUT_RELOC(params->depth.mt->region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
offset); |
OUT_BATCH(BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1 | |
(params->depth.width + tile_x - 1) << 6 | |
(params->depth.height + tile_y - 1) << 19); |
OUT_BATCH(0); |
OUT_BATCH(tile_x | |
tile_y << 16); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_HIER_DEPTH_BUFFER */ |
{ |
struct intel_region *hiz_region = params->depth.mt->hiz_mt->region; |
uint32_t hiz_offset = |
intel_region_get_aligned_offset(hiz_region, |
draw_x & ~tile_mask_x, |
(draw_y & ~tile_mask_y) / 2, false); |
BEGIN_BATCH(3); |
OUT_BATCH((_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2)); |
OUT_BATCH(hiz_region->pitch - 1); |
OUT_RELOC(hiz_region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
hiz_offset); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_STENCIL_BUFFER */ |
{ |
BEGIN_BATCH(3); |
OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
} |
static void |
gen6_blorp_emit_depth_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2)); |
OUT_BATCH((BRW_DEPTHFORMAT_D32_FLOAT << 18) | |
(BRW_SURFACE_NULL << 29)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_CLEAR_PARAMS |
* |
* From the Sandybridge PRM, Volume 2, Part 1, Section 3DSTATE_CLEAR_PARAMS: |
* [DevSNB] 3DSTATE_CLEAR_PARAMS packet must follow the DEPTH_BUFFER_STATE |
* packet when HiZ is enabled and the DEPTH_BUFFER_STATE changes. |
*/ |
static void |
gen6_blorp_emit_clear_params(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_CLEAR_PARAMS << 16 | |
GEN5_DEPTH_CLEAR_VALID | |
(2 - 2)); |
OUT_BATCH(params->depth.mt ? params->depth.mt->depth_clear_value : 0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_DRAWING_RECTANGLE */ |
void |
gen6_blorp_emit_drawing_rectangle(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_DRAWING_RECTANGLE << 16 | (4 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(((params->x1 - 1) & 0xffff) | |
((params->y1 - 1) << 16)); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_VIEWPORT_STATE_POINTERS */ |
void |
gen6_blorp_emit_viewport_state(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
struct brw_cc_viewport *ccv; |
uint32_t cc_vp_offset; |
ccv = (struct brw_cc_viewport *)brw_state_batch(brw, AUB_TRACE_CC_VP_STATE, |
sizeof(*ccv), 32, |
&cc_vp_offset); |
ccv->min_depth = 0.0; |
ccv->max_depth = 1.0; |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_VIEWPORT_STATE_POINTERS << 16 | (4 - 2) | |
GEN6_CC_VIEWPORT_MODIFY); |
OUT_BATCH(0); /* clip VP */ |
OUT_BATCH(0); /* SF VP */ |
OUT_BATCH(cc_vp_offset); |
ADVANCE_BATCH(); |
} |
/* 3DPRIMITIVE */ |
static void |
gen6_blorp_emit_primitive(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(6); |
OUT_BATCH(CMD_3D_PRIM << 16 | (6 - 2) | |
_3DPRIM_RECTLIST << GEN4_3DPRIM_TOPOLOGY_TYPE_SHIFT | |
GEN4_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL); |
OUT_BATCH(3); /* vertex count per instance */ |
OUT_BATCH(0); |
OUT_BATCH(1); /* instance count */ |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/** |
* \brief Execute a blit or render pass operation. |
* |
* To execute the operation, this function manually constructs and emits a |
* batch to draw a rectangle primitive. The batchbuffer is flushed before |
* constructing and after emitting the batch. |
* |
* This function alters no GL state. |
*/ |
void |
gen6_blorp_exec(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
brw_blorp_prog_data *prog_data = NULL; |
uint32_t cc_blend_state_offset = 0; |
uint32_t cc_state_offset = 0; |
uint32_t depthstencil_offset; |
uint32_t wm_push_const_offset = 0; |
uint32_t wm_bind_bo_offset = 0; |
uint32_t prog_offset = params->get_wm_prog(brw, &prog_data); |
gen6_blorp_emit_batch_head(brw, params); |
gen6_emit_3dstate_multisample(brw, params->num_samples); |
gen6_emit_3dstate_sample_mask(brw, params->num_samples, 1.0, false, ~0u); |
gen6_blorp_emit_state_base_address(brw, params); |
gen6_blorp_emit_vertices(brw, params); |
gen6_blorp_emit_urb_config(brw, params); |
if (params->use_wm_prog) { |
cc_blend_state_offset = gen6_blorp_emit_blend_state(brw, params); |
cc_state_offset = gen6_blorp_emit_cc_state(brw, params); |
} |
depthstencil_offset = gen6_blorp_emit_depth_stencil_state(brw, params); |
gen6_blorp_emit_cc_state_pointers(brw, params, cc_blend_state_offset, |
depthstencil_offset, cc_state_offset); |
if (params->use_wm_prog) { |
uint32_t wm_surf_offset_renderbuffer; |
uint32_t wm_surf_offset_texture = 0; |
uint32_t sampler_offset; |
wm_push_const_offset = gen6_blorp_emit_wm_constants(brw, params); |
intel_miptree_used_for_rendering(params->dst.mt); |
wm_surf_offset_renderbuffer = |
gen6_blorp_emit_surface_state(brw, params, ¶ms->dst, |
I915_GEM_DOMAIN_RENDER, |
I915_GEM_DOMAIN_RENDER); |
if (params->src.mt) { |
wm_surf_offset_texture = |
gen6_blorp_emit_surface_state(brw, params, ¶ms->src, |
I915_GEM_DOMAIN_SAMPLER, 0); |
} |
wm_bind_bo_offset = |
gen6_blorp_emit_binding_table(brw, params, |
wm_surf_offset_renderbuffer, |
wm_surf_offset_texture); |
sampler_offset = gen6_blorp_emit_sampler_state(brw, params); |
gen6_blorp_emit_sampler_state_pointers(brw, params, sampler_offset); |
} |
gen6_blorp_emit_vs_disable(brw, params); |
gen6_blorp_emit_gs_disable(brw, params); |
gen6_blorp_emit_clip_disable(brw, params); |
gen6_blorp_emit_sf_config(brw, params); |
if (params->use_wm_prog) |
gen6_blorp_emit_constant_ps(brw, params, wm_push_const_offset); |
else |
gen6_blorp_emit_constant_ps_disable(brw, params); |
gen6_blorp_emit_wm_config(brw, params, prog_offset, prog_data); |
if (params->use_wm_prog) |
gen6_blorp_emit_binding_table_pointers(brw, params, wm_bind_bo_offset); |
gen6_blorp_emit_viewport_state(brw, params); |
if (params->depth.mt) |
gen6_blorp_emit_depth_stencil_config(brw, params); |
else |
gen6_blorp_emit_depth_disable(brw, params); |
gen6_blorp_emit_clear_params(brw, params); |
gen6_blorp_emit_drawing_rectangle(brw, params); |
gen6_blorp_emit_primitive(brw, params); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_blorp.h |
---|
0,0 → 1,41 |
/* |
* Copyright © 2011 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. |
*/ |
#pragma once |
#include <stdint.h> |
#ifdef __cplusplus |
extern "C" { |
#endif |
struct intel_mipmap_tree; |
#ifdef __cplusplus |
} |
void |
gen6_blorp_exec(struct brw_context *brw, |
const brw_blorp_params *params); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_cc.c |
---|
0,0 → 1,300 |
/* |
* Copyright © 2009 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_util.h" |
#include "intel_batchbuffer.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "main/glformats.h" |
#include "main/stencil.h" |
static void |
gen6_upload_blend_state(struct brw_context *brw) |
{ |
bool is_buffer_zero_integer_format = false; |
struct gl_context *ctx = &brw->ctx; |
struct gen6_blend_state *blend; |
int b; |
int nr_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers; |
int size; |
/* We need at least one BLEND_STATE written, because we might do |
* thread dispatch even if _NumColorDrawBuffers is 0 (for example |
* for computed depth or alpha test), which will do an FB write |
* with render target 0, which will reference BLEND_STATE[0] for |
* alpha test enable. |
*/ |
if (nr_draw_buffers == 0 && ctx->Color.AlphaEnabled) |
nr_draw_buffers = 1; |
size = sizeof(*blend) * nr_draw_buffers; |
blend = brw_state_batch(brw, AUB_TRACE_BLEND_STATE, |
size, 64, &brw->cc.blend_state_offset); |
memset(blend, 0, size); |
for (b = 0; b < nr_draw_buffers; b++) { |
/* _NEW_BUFFERS */ |
struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[b]; |
GLenum rb_type; |
bool integer; |
if (rb) |
rb_type = _mesa_get_format_datatype(rb->Format); |
else |
rb_type = GL_UNSIGNED_NORMALIZED; |
/* Used for implementing the following bit of GL_EXT_texture_integer: |
* "Per-fragment operations that require floating-point color |
* components, including multisample alpha operations, alpha test, |
* blending, and dithering, have no effect when the corresponding |
* colors are written to an integer color buffer." |
*/ |
integer = (rb_type == GL_INT || rb_type == GL_UNSIGNED_INT); |
if(b == 0 && integer) |
is_buffer_zero_integer_format = true; |
/* _NEW_COLOR */ |
if (ctx->Color.ColorLogicOpEnabled) { |
/* Floating point RTs should have no effect from LogicOp, |
* except for disabling of blending, but other types should. |
* |
* However, from the Sandy Bridge PRM, Vol 2 Par 1, Section 8.1.11, |
* "Logic Ops", |
* |
* "Logic Ops are only supported on *_UNORM surfaces (excluding |
* _SRGB variants), otherwise Logic Ops must be DISABLED." |
*/ |
WARN_ONCE(ctx->Color.LogicOp != GL_COPY && |
rb_type != GL_UNSIGNED_NORMALIZED && |
rb_type != GL_FLOAT, "Ignoring %s logic op on %s " |
"renderbuffer\n", |
_mesa_lookup_enum_by_nr(ctx->Color.LogicOp), |
_mesa_lookup_enum_by_nr(rb_type)); |
if (rb_type == GL_UNSIGNED_NORMALIZED) { |
blend[b].blend1.logic_op_enable = 1; |
blend[b].blend1.logic_op_func = |
intel_translate_logic_op(ctx->Color.LogicOp); |
} |
} else if (ctx->Color.BlendEnabled & (1 << b) && !integer) { |
GLenum eqRGB = ctx->Color.Blend[b].EquationRGB; |
GLenum eqA = ctx->Color.Blend[b].EquationA; |
GLenum srcRGB = ctx->Color.Blend[b].SrcRGB; |
GLenum dstRGB = ctx->Color.Blend[b].DstRGB; |
GLenum srcA = ctx->Color.Blend[b].SrcA; |
GLenum dstA = ctx->Color.Blend[b].DstA; |
if (eqRGB == GL_MIN || eqRGB == GL_MAX) { |
srcRGB = dstRGB = GL_ONE; |
} |
if (eqA == GL_MIN || eqA == GL_MAX) { |
srcA = dstA = GL_ONE; |
} |
/* Due to hardware limitations, the destination may have information |
* in an alpha channel even when the format specifies no alpha |
* channel. In order to avoid getting any incorrect blending due to |
* that alpha channel, coerce the blend factors to values that will |
* not read the alpha channel, but will instead use the correct |
* implicit value for alpha. |
*/ |
if (rb && !_mesa_base_format_has_channel(rb->_BaseFormat, GL_TEXTURE_ALPHA_TYPE)) |
{ |
srcRGB = brw_fix_xRGB_alpha(srcRGB); |
srcA = brw_fix_xRGB_alpha(srcA); |
dstRGB = brw_fix_xRGB_alpha(dstRGB); |
dstA = brw_fix_xRGB_alpha(dstA); |
} |
blend[b].blend0.dest_blend_factor = brw_translate_blend_factor(dstRGB); |
blend[b].blend0.source_blend_factor = brw_translate_blend_factor(srcRGB); |
blend[b].blend0.blend_func = brw_translate_blend_equation(eqRGB); |
blend[b].blend0.ia_dest_blend_factor = brw_translate_blend_factor(dstA); |
blend[b].blend0.ia_source_blend_factor = brw_translate_blend_factor(srcA); |
blend[b].blend0.ia_blend_func = brw_translate_blend_equation(eqA); |
blend[b].blend0.blend_enable = 1; |
blend[b].blend0.ia_blend_enable = (srcA != srcRGB || |
dstA != dstRGB || |
eqA != eqRGB); |
} |
/* See section 8.1.6 "Pre-Blend Color Clamping" of the |
* SandyBridge PRM Volume 2 Part 1 for HW requirements. |
* |
* We do our ARB_color_buffer_float CLAMP_FRAGMENT_COLOR |
* clamping in the fragment shader. For its clamping of |
* blending, the spec says: |
* |
* "RESOLVED: For fixed-point color buffers, the inputs and |
* the result of the blending equation are clamped. For |
* floating-point color buffers, no clamping occurs." |
* |
* So, generally, we want clamping to the render target's range. |
* And, good news, the hardware tables for both pre- and |
* post-blend color clamping are either ignored, or any are |
* allowed, or clamping is required but RT range clamping is a |
* valid option. |
*/ |
blend[b].blend1.pre_blend_clamp_enable = 1; |
blend[b].blend1.post_blend_clamp_enable = 1; |
blend[b].blend1.clamp_range = BRW_RENDERTARGET_CLAMPRANGE_FORMAT; |
/* _NEW_COLOR */ |
if (ctx->Color.AlphaEnabled && !integer) { |
blend[b].blend1.alpha_test_enable = 1; |
blend[b].blend1.alpha_test_func = |
intel_translate_compare_func(ctx->Color.AlphaFunc); |
} |
/* _NEW_COLOR */ |
if (ctx->Color.DitherFlag && !integer) { |
blend[b].blend1.dither_enable = 1; |
blend[b].blend1.y_dither_offset = 0; |
blend[b].blend1.x_dither_offset = 0; |
} |
blend[b].blend1.write_disable_r = !ctx->Color.ColorMask[b][0]; |
blend[b].blend1.write_disable_g = !ctx->Color.ColorMask[b][1]; |
blend[b].blend1.write_disable_b = !ctx->Color.ColorMask[b][2]; |
blend[b].blend1.write_disable_a = !ctx->Color.ColorMask[b][3]; |
/* OpenGL specification 3.3 (page 196), section 4.1.3 says: |
* "If drawbuffer zero is not NONE and the buffer it references has an |
* integer format, the SAMPLE_ALPHA_TO_COVERAGE and SAMPLE_ALPHA_TO_ONE |
* operations are skipped." |
*/ |
if(!is_buffer_zero_integer_format) { |
/* _NEW_MULTISAMPLE */ |
blend[b].blend1.alpha_to_coverage = |
ctx->Multisample._Enabled && ctx->Multisample.SampleAlphaToCoverage; |
/* From SandyBridge PRM, volume 2 Part 1, section 8.2.3, BLEND_STATE: |
* DWord 1, Bit 30 (AlphaToOne Enable): |
* "If Dual Source Blending is enabled, this bit must be disabled" |
*/ |
WARN_ONCE(ctx->Color.Blend[b]._UsesDualSrc && |
ctx->Multisample._Enabled && |
ctx->Multisample.SampleAlphaToOne, |
"HW workaround: disabling alpha to one with dual src " |
"blending\n"); |
if (ctx->Color.Blend[b]._UsesDualSrc) |
blend[b].blend1.alpha_to_one = false; |
else |
blend[b].blend1.alpha_to_one = |
ctx->Multisample._Enabled && ctx->Multisample.SampleAlphaToOne; |
blend[b].blend1.alpha_to_coverage_dither = (brw->gen >= 7); |
} |
else { |
blend[b].blend1.alpha_to_coverage = false; |
blend[b].blend1.alpha_to_one = false; |
} |
} |
/* Point the GPU at the new indirect state. */ |
if (brw->gen == 6) { |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (4 - 2)); |
OUT_BATCH(brw->cc.blend_state_offset | 1); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} else { |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_BLEND_STATE_POINTERS << 16 | (2 - 2)); |
OUT_BATCH(brw->cc.blend_state_offset | 1); |
ADVANCE_BATCH(); |
} |
} |
const struct brw_tracked_state gen6_blend_state = { |
.dirty = { |
.mesa = (_NEW_COLOR | |
_NEW_BUFFERS | |
_NEW_MULTISAMPLE), |
.brw = BRW_NEW_BATCH | BRW_NEW_STATE_BASE_ADDRESS, |
.cache = 0, |
}, |
.emit = gen6_upload_blend_state, |
}; |
static void |
gen6_upload_color_calc_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gen6_color_calc_state *cc; |
cc = brw_state_batch(brw, AUB_TRACE_CC_STATE, |
sizeof(*cc), 64, &brw->cc.state_offset); |
memset(cc, 0, sizeof(*cc)); |
/* _NEW_COLOR */ |
cc->cc0.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8; |
UNCLAMPED_FLOAT_TO_UBYTE(cc->cc1.alpha_ref_fi.ui, ctx->Color.AlphaRef); |
/* _NEW_STENCIL */ |
cc->cc0.stencil_ref = _mesa_get_stencil_ref(ctx, 0); |
cc->cc0.bf_stencil_ref = _mesa_get_stencil_ref(ctx, ctx->Stencil._BackFace); |
/* _NEW_COLOR */ |
cc->constant_r = ctx->Color.BlendColorUnclamped[0]; |
cc->constant_g = ctx->Color.BlendColorUnclamped[1]; |
cc->constant_b = ctx->Color.BlendColorUnclamped[2]; |
cc->constant_a = ctx->Color.BlendColorUnclamped[3]; |
/* Point the GPU at the new indirect state. */ |
if (brw->gen == 6) { |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (4 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(brw->cc.state_offset | 1); |
ADVANCE_BATCH(); |
} else { |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (2 - 2)); |
OUT_BATCH(brw->cc.state_offset | 1); |
ADVANCE_BATCH(); |
} |
} |
const struct brw_tracked_state gen6_color_calc_state = { |
.dirty = { |
.mesa = _NEW_COLOR | _NEW_STENCIL, |
.brw = BRW_NEW_BATCH | BRW_NEW_STATE_BASE_ADDRESS, |
.cache = 0, |
}, |
.emit = gen6_upload_color_calc_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_clip_state.c |
---|
0,0 → 1,108 |
/* |
* Copyright © 2009 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_util.h" |
#include "intel_batchbuffer.h" |
#include "main/fbobject.h" |
static void |
upload_clip_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
uint32_t dw1 = brw->meta_in_progress ? 0 : GEN6_CLIP_STATISTICS_ENABLE; |
uint32_t dw2 = 0; |
/* _NEW_BUFFERS */ |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
/* CACHE_NEW_WM_PROG */ |
if (brw->wm.prog_data->barycentric_interp_modes & |
BRW_WM_NONPERSPECTIVE_BARYCENTRIC_BITS) { |
dw2 |= GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE; |
} |
if (!ctx->Transform.DepthClamp) |
dw2 |= GEN6_CLIP_Z_TEST; |
/* _NEW_LIGHT */ |
if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION) { |
dw2 |= |
(0 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | |
(1 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | |
(0 << GEN6_CLIP_LINE_PROVOKE_SHIFT); |
} else { |
dw2 |= |
(2 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | |
(2 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | |
(1 << GEN6_CLIP_LINE_PROVOKE_SHIFT); |
} |
/* _NEW_TRANSFORM */ |
dw2 |= (ctx->Transform.ClipPlanesEnabled << |
GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT); |
if (ctx->Viewport.X == 0 && |
ctx->Viewport.Y == 0 && |
ctx->Viewport.Width == fb->Width && |
ctx->Viewport.Height == fb->Height) { |
dw2 |= GEN6_CLIP_GB_TEST; |
} |
/* BRW_NEW_RASTERIZER_DISCARD */ |
if (ctx->RasterDiscard) { |
dw2 |= GEN6_CLIP_MODE_REJECT_ALL; |
perf_debug("Rasterizer discard is currently implemented via the clipper; " |
"having the GS not write primitives would likely be faster."); |
} |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); |
OUT_BATCH(dw1); |
OUT_BATCH(GEN6_CLIP_ENABLE | |
GEN6_CLIP_API_OGL | |
GEN6_CLIP_MODE_NORMAL | |
GEN6_CLIP_XY_TEST | |
dw2); |
OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT | |
U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT | |
GEN6_CLIP_FORCE_ZERO_RTAINDEX); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen6_clip_state = { |
.dirty = { |
.mesa = _NEW_TRANSFORM | _NEW_LIGHT | _NEW_BUFFERS, |
.brw = BRW_NEW_CONTEXT | |
BRW_NEW_META_IN_PROGRESS | |
BRW_NEW_RASTERIZER_DISCARD, |
.cache = CACHE_NEW_WM_PROG |
}, |
.emit = upload_clip_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_depthstencil.c |
---|
0,0 → 1,112 |
/* |
* Copyright © 2009 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "intel_batchbuffer.h" |
#include "intel_fbo.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
#include "brw_state.h" |
static void |
gen6_upload_depth_stencil_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gen6_depth_stencil_state *ds; |
struct intel_renderbuffer *depth_irb; |
/* _NEW_BUFFERS */ |
depth_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH); |
ds = brw_state_batch(brw, AUB_TRACE_DEPTH_STENCIL_STATE, |
sizeof(*ds), 64, |
&brw->cc.depth_stencil_state_offset); |
memset(ds, 0, sizeof(*ds)); |
/* _NEW_STENCIL | _NEW_BUFFERS */ |
if (ctx->Stencil._Enabled) { |
int back = ctx->Stencil._BackFace; |
ds->ds0.stencil_enable = 1; |
ds->ds0.stencil_func = |
intel_translate_compare_func(ctx->Stencil.Function[0]); |
ds->ds0.stencil_fail_op = |
intel_translate_stencil_op(ctx->Stencil.FailFunc[0]); |
ds->ds0.stencil_pass_depth_fail_op = |
intel_translate_stencil_op(ctx->Stencil.ZFailFunc[0]); |
ds->ds0.stencil_pass_depth_pass_op = |
intel_translate_stencil_op(ctx->Stencil.ZPassFunc[0]); |
ds->ds1.stencil_write_mask = ctx->Stencil.WriteMask[0]; |
ds->ds1.stencil_test_mask = ctx->Stencil.ValueMask[0]; |
if (ctx->Stencil._TestTwoSide) { |
ds->ds0.bf_stencil_enable = 1; |
ds->ds0.bf_stencil_func = |
intel_translate_compare_func(ctx->Stencil.Function[back]); |
ds->ds0.bf_stencil_fail_op = |
intel_translate_stencil_op(ctx->Stencil.FailFunc[back]); |
ds->ds0.bf_stencil_pass_depth_fail_op = |
intel_translate_stencil_op(ctx->Stencil.ZFailFunc[back]); |
ds->ds0.bf_stencil_pass_depth_pass_op = |
intel_translate_stencil_op(ctx->Stencil.ZPassFunc[back]); |
ds->ds1.bf_stencil_write_mask = ctx->Stencil.WriteMask[back]; |
ds->ds1.bf_stencil_test_mask = ctx->Stencil.ValueMask[back]; |
} |
ds->ds0.stencil_write_enable = ctx->Stencil._WriteEnabled; |
} |
/* _NEW_DEPTH */ |
if (ctx->Depth.Test && depth_irb) { |
ds->ds2.depth_test_enable = ctx->Depth.Test; |
ds->ds2.depth_test_func = intel_translate_compare_func(ctx->Depth.Func); |
ds->ds2.depth_write_enable = ctx->Depth.Mask; |
} |
/* Point the GPU at the new indirect state. */ |
if (brw->gen == 6) { |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (4 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(brw->cc.depth_stencil_state_offset | 1); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} else { |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_DEPTH_STENCIL_STATE_POINTERS << 16 | (2 - 2)); |
OUT_BATCH(brw->cc.depth_stencil_state_offset | 1); |
ADVANCE_BATCH(); |
} |
} |
const struct brw_tracked_state gen6_depth_stencil_state = { |
.dirty = { |
.mesa = _NEW_DEPTH | _NEW_STENCIL | _NEW_BUFFERS, |
.brw = BRW_NEW_BATCH | BRW_NEW_STATE_BASE_ADDRESS, |
.cache = 0, |
}, |
.emit = gen6_upload_depth_stencil_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_gs_state.c |
---|
0,0 → 1,88 |
/* |
* Copyright © 2009 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "intel_batchbuffer.h" |
static void |
upload_gs_state(struct brw_context *brw) |
{ |
/* Disable all the constant buffers. */ |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_CONSTANT_GS << 16 | (5 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
if (brw->gs.prog_active) { |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_GS << 16 | (7 - 2)); |
OUT_BATCH(brw->gs.prog_offset); |
OUT_BATCH(GEN6_GS_SPF_MODE | GEN6_GS_VECTOR_MASK_ENABLE); |
OUT_BATCH(0); /* no scratch space */ |
OUT_BATCH((2 << GEN6_GS_DISPATCH_START_GRF_SHIFT) | |
(brw->gs.prog_data->urb_read_length << GEN6_GS_URB_READ_LENGTH_SHIFT)); |
OUT_BATCH(((brw->max_gs_threads - 1) << GEN6_GS_MAX_THREADS_SHIFT) | |
GEN6_GS_STATISTICS_ENABLE | |
GEN6_GS_SO_STATISTICS_ENABLE | |
GEN6_GS_RENDERING_ENABLE); |
OUT_BATCH(GEN6_GS_SVBI_PAYLOAD_ENABLE | |
GEN6_GS_SVBI_POSTINCREMENT_ENABLE | |
(brw->gs.prog_data->svbi_postincrement_value << |
GEN6_GS_SVBI_POSTINCREMENT_VALUE_SHIFT) | |
GEN6_GS_ENABLE); |
ADVANCE_BATCH(); |
} else { |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_GS << 16 | (7 - 2)); |
OUT_BATCH(0); /* prog_bo */ |
OUT_BATCH((0 << GEN6_GS_SAMPLER_COUNT_SHIFT) | |
(0 << GEN6_GS_BINDING_TABLE_ENTRY_COUNT_SHIFT)); |
OUT_BATCH(0); /* scratch space base offset */ |
OUT_BATCH((1 << GEN6_GS_DISPATCH_START_GRF_SHIFT) | |
(0 << GEN6_GS_URB_READ_LENGTH_SHIFT) | |
(0 << GEN6_GS_URB_ENTRY_READ_OFFSET_SHIFT)); |
OUT_BATCH((0 << GEN6_GS_MAX_THREADS_SHIFT) | |
GEN6_GS_STATISTICS_ENABLE | |
GEN6_GS_RENDERING_ENABLE); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
} |
const struct brw_tracked_state gen6_gs_state = { |
.dirty = { |
.mesa = _NEW_TRANSFORM, |
.brw = BRW_NEW_CONTEXT, |
.cache = CACHE_NEW_GS_PROG |
}, |
.emit = upload_gs_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_multisample_state.c |
---|
0,0 → 1,203 |
/* |
* 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 "intel_batchbuffer.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
/* Sample positions: |
* 2 6 a e |
* 2 0 |
* 6 1 |
* a 2 |
* e 3 |
*/ |
static uint32_t |
sample_positions_4x[] = { 0xae2ae662 }; |
/* Sample positions are based on a solution to the "8 queens" puzzle. |
* Rationale: in a solution to the 8 queens puzzle, no two queens share |
* a row, column, or diagonal. This is a desirable property for samples |
* in a multisampling pattern, because it ensures that the samples are |
* relatively uniformly distributed through the pixel. |
* |
* There are several solutions to the 8 queens puzzle (see |
* http://en.wikipedia.org/wiki/Eight_queens_puzzle). This solution was |
* chosen because it has a queen close to the center; this should |
* improve the accuracy of centroid interpolation, since the hardware |
* implements centroid interpolation by choosing the centermost sample |
* that overlaps with the primitive being drawn. |
* |
* Note: from the Ivy Bridge PRM, Vol2 Part1 p304 (3DSTATE_MULTISAMPLE: |
* Programming Notes): |
* |
* "When programming the sample offsets (for NUMSAMPLES_4 or _8 and |
* MSRASTMODE_xxx_PATTERN), the order of the samples 0 to 3 (or 7 |
* for 8X) must have monotonically increasing distance from the |
* pixel center. This is required to get the correct centroid |
* computation in the device." |
* |
* Sample positions: |
* 1 3 5 7 9 b d f |
* 1 5 |
* 3 2 |
* 5 6 |
* 7 4 |
* 9 0 |
* b 3 |
* d 1 |
* f 7 |
*/ |
static uint32_t |
sample_positions_8x[] = { 0xdbb39d79, 0x3ff55117 }; |
void |
gen6_get_sample_position(struct gl_context *ctx, |
struct gl_framebuffer *fb, |
GLuint index, GLfloat *result) |
{ |
switch (fb->Visual.samples) { |
case 1: |
result[0] = result[1] = 0.5f; |
break; |
case 4: { |
uint8_t val = (uint8_t)(sample_positions_4x[0] >> (8*index)); |
result[0] = ((val >> 4) & 0xf) / 16.0f; |
result[1] = (val & 0xf) / 16.0f; |
break; |
} |
case 8: { |
uint8_t val = (uint8_t)(sample_positions_8x[index>>2] >> (8*(index & 3))); |
result[0] = ((val >> 4) & 0xf) / 16.0f; |
result[1] = (val & 0xf) / 16.0f; |
break; |
} |
default: |
assert(!"Not implemented"); |
} |
} |
/** |
* 3DSTATE_MULTISAMPLE |
*/ |
void |
gen6_emit_3dstate_multisample(struct brw_context *brw, |
unsigned num_samples) |
{ |
uint32_t number_of_multisamples = 0; |
uint32_t sample_positions_3210 = 0; |
uint32_t sample_positions_7654 = 0; |
switch (num_samples) { |
case 0: |
case 1: |
number_of_multisamples = MS_NUMSAMPLES_1; |
break; |
case 4: |
number_of_multisamples = MS_NUMSAMPLES_4; |
sample_positions_3210 = sample_positions_4x[0]; |
break; |
case 8: |
number_of_multisamples = MS_NUMSAMPLES_8; |
sample_positions_3210 = sample_positions_8x[0]; |
sample_positions_7654 = sample_positions_8x[1]; |
break; |
default: |
assert(!"Unrecognized num_samples in gen6_emit_3dstate_multisample"); |
break; |
} |
int len = brw->gen >= 7 ? 4 : 3; |
BEGIN_BATCH(len); |
OUT_BATCH(_3DSTATE_MULTISAMPLE << 16 | (len - 2)); |
OUT_BATCH(MS_PIXEL_LOCATION_CENTER | number_of_multisamples); |
OUT_BATCH(sample_positions_3210); |
if (brw->gen >= 7) |
OUT_BATCH(sample_positions_7654); |
ADVANCE_BATCH(); |
} |
/** |
* 3DSTATE_SAMPLE_MASK |
*/ |
void |
gen6_emit_3dstate_sample_mask(struct brw_context *brw, |
unsigned num_samples, float coverage, |
bool coverage_invert, unsigned sample_mask) |
{ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_SAMPLE_MASK << 16 | (2 - 2)); |
if (num_samples > 1) { |
int coverage_int = (int) (num_samples * coverage + 0.5); |
uint32_t coverage_bits = (1 << coverage_int) - 1; |
if (coverage_invert) |
coverage_bits ^= (1 << num_samples) - 1; |
OUT_BATCH(coverage_bits & sample_mask); |
} else { |
OUT_BATCH(1); |
} |
ADVANCE_BATCH(); |
} |
static void upload_multisample_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
float coverage = 1.0; |
float coverage_invert = false; |
unsigned sample_mask = ~0u; |
/* _NEW_BUFFERS */ |
unsigned num_samples = ctx->DrawBuffer->Visual.samples; |
/* _NEW_MULTISAMPLE */ |
if (ctx->Multisample._Enabled) { |
if (ctx->Multisample.SampleCoverage) { |
coverage = ctx->Multisample.SampleCoverageValue; |
coverage_invert = ctx->Multisample.SampleCoverageInvert; |
} |
if (ctx->Multisample.SampleMask) { |
sample_mask = ctx->Multisample.SampleMaskValue; |
} |
} |
/* 3DSTATE_MULTISAMPLE is nonpipelined. */ |
intel_emit_post_sync_nonzero_flush(brw); |
gen6_emit_3dstate_multisample(brw, num_samples); |
gen6_emit_3dstate_sample_mask(brw, num_samples, coverage, |
coverage_invert, sample_mask); |
} |
const struct brw_tracked_state gen6_multisample_state = { |
.dirty = { |
.mesa = _NEW_BUFFERS | |
_NEW_MULTISAMPLE, |
.brw = BRW_NEW_CONTEXT, |
.cache = 0 |
}, |
.emit = upload_multisample_state |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_queryobj.c |
---|
0,0 → 1,384 |
/* |
* Copyright © 2008 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* Kenneth Graunke <kenneth@whitecape.org> |
*/ |
/** @file gen6_queryobj.c |
* |
* Support for query objects (GL_ARB_occlusion_query, GL_ARB_timer_query, |
* GL_EXT_transform_feedback, and friends) on platforms that support |
* hardware contexts (Gen6+). |
*/ |
#include "main/imports.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
#include "brw_state.h" |
#include "intel_batchbuffer.h" |
#include "intel_reg.h" |
/** |
* Emit PIPE_CONTROLs to write the current GPU timestamp into a buffer. |
*/ |
static void |
write_timestamp(struct brw_context *brw, drm_intel_bo *query_bo, int idx) |
{ |
/* Emit workaround flushes: */ |
if (brw->gen == 6) { |
/* The timestamp write below is a non-zero post-sync op, which on |
* Gen6 necessitates a CS stall. CS stalls need stall at scoreboard |
* set. See the comments for intel_emit_post_sync_nonzero_flush(). |
*/ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2)); |
OUT_BATCH(PIPE_CONTROL_CS_STALL | PIPE_CONTROL_STALL_AT_SCOREBOARD); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (5 - 2)); |
OUT_BATCH(PIPE_CONTROL_WRITE_TIMESTAMP); |
OUT_RELOC(query_bo, |
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, |
PIPE_CONTROL_GLOBAL_GTT_WRITE | |
idx * sizeof(uint64_t)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/** |
* Emit PIPE_CONTROLs to write the PS_DEPTH_COUNT register into a buffer. |
*/ |
static void |
write_depth_count(struct brw_context *brw, drm_intel_bo *query_bo, int idx) |
{ |
/* Emit Sandybridge workaround flush: */ |
if (brw->gen == 6) |
intel_emit_post_sync_nonzero_flush(brw); |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (5 - 2)); |
OUT_BATCH(PIPE_CONTROL_DEPTH_STALL | |
PIPE_CONTROL_WRITE_DEPTH_COUNT); |
OUT_RELOC(query_bo, |
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, |
PIPE_CONTROL_GLOBAL_GTT_WRITE | |
(idx * sizeof(uint64_t))); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* |
* Write an arbitrary 64-bit register to a buffer via MI_STORE_REGISTER_MEM. |
* |
* Only TIMESTAMP and PS_DEPTH_COUNT have special PIPE_CONTROL support; other |
* counters have to be read via the generic MI_STORE_REGISTER_MEM. This |
* function also performs a pipeline flush for proper synchronization. |
*/ |
static void |
write_reg(struct brw_context *brw, |
drm_intel_bo *query_bo, uint32_t reg, int idx) |
{ |
assert(brw->gen >= 6); |
intel_batchbuffer_emit_mi_flush(brw); |
/* MI_STORE_REGISTER_MEM only stores a single 32-bit value, so to |
* read a full 64-bit register, we need to do two of them. |
*/ |
BEGIN_BATCH(3); |
OUT_BATCH(MI_STORE_REGISTER_MEM | (3 - 2)); |
OUT_BATCH(reg); |
OUT_RELOC(query_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
idx * sizeof(uint64_t)); |
ADVANCE_BATCH(); |
BEGIN_BATCH(3); |
OUT_BATCH(MI_STORE_REGISTER_MEM | (3 - 2)); |
OUT_BATCH(reg + sizeof(uint32_t)); |
OUT_RELOC(query_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
sizeof(uint32_t) + idx * sizeof(uint64_t)); |
ADVANCE_BATCH(); |
} |
static void |
write_primitives_generated(struct brw_context *brw, |
drm_intel_bo *query_bo, int idx) |
{ |
write_reg(brw, query_bo, CL_INVOCATION_COUNT, idx); |
} |
static void |
write_xfb_primitives_written(struct brw_context *brw, |
drm_intel_bo *query_bo, int idx) |
{ |
if (brw->gen >= 7) { |
write_reg(brw, query_bo, SO_NUM_PRIMS_WRITTEN0_IVB, idx); |
} else { |
write_reg(brw, query_bo, SO_NUM_PRIMS_WRITTEN, idx); |
} |
} |
/** |
* Wait on the query object's BO and calculate the final result. |
*/ |
static void |
gen6_queryobj_get_results(struct gl_context *ctx, |
struct brw_query_object *query) |
{ |
struct brw_context *brw = brw_context(ctx); |
if (query->bo == NULL) |
return; |
/* If the application has requested the query result, but this batch is |
* still contributing to it, flush it now so the results will be present |
* when mapped. |
*/ |
if (drm_intel_bo_references(brw->batch.bo, query->bo)) |
intel_batchbuffer_flush(brw); |
if (unlikely(brw->perf_debug)) { |
if (drm_intel_bo_busy(query->bo)) { |
perf_debug("Stalling on the GPU waiting for a query object.\n"); |
} |
} |
drm_intel_bo_map(query->bo, false); |
uint64_t *results = query->bo->virtual; |
switch (query->Base.Target) { |
case GL_TIME_ELAPSED: |
/* The query BO contains the starting and ending timestamps. |
* Subtract the two and convert to nanoseconds. |
*/ |
query->Base.Result += 80 * (results[1] - results[0]); |
break; |
case GL_TIMESTAMP: |
/* Our timer is a clock that increments every 80ns (regardless of |
* other clock scaling in the system). The timestamp register we can |
* read for glGetTimestamp() masks out the top 32 bits, so we do that |
* here too to let the two counters be compared against each other. |
* |
* If we just multiplied that 32 bits of data by 80, it would roll |
* over at a non-power-of-two, so an application couldn't use |
* GL_QUERY_COUNTER_BITS to handle rollover correctly. Instead, we |
* report 36 bits and truncate at that (rolling over 5 times as often |
* as the HW counter), and when the 32-bit counter rolls over, it |
* happens to also be at a rollover in the reported value from near |
* (1<<36) to 0. |
* |
* The low 32 bits rolls over in ~343 seconds. Our 36-bit result |
* rolls over every ~69 seconds. |
* |
* The query BO contains a single timestamp value in results[0]. |
*/ |
query->Base.Result = 80 * (results[0] & 0xffffffff); |
query->Base.Result &= (1ull << 36) - 1; |
break; |
case GL_SAMPLES_PASSED_ARB: |
/* We need to use += rather than = here since some BLT-based operations |
* may have added additional samples to our occlusion query value. |
*/ |
query->Base.Result += results[1] - results[0]; |
break; |
case GL_ANY_SAMPLES_PASSED: |
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: |
if (results[0] != results[1]) |
query->Base.Result = true; |
break; |
case GL_PRIMITIVES_GENERATED: |
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: |
query->Base.Result = results[1] - results[0]; |
break; |
default: |
assert(!"Unrecognized query target in brw_queryobj_get_results()"); |
break; |
} |
drm_intel_bo_unmap(query->bo); |
/* Now that we've processed the data stored in the query's buffer object, |
* we can release it. |
*/ |
drm_intel_bo_unreference(query->bo); |
query->bo = NULL; |
} |
/** |
* Driver hook for glBeginQuery(). |
* |
* Initializes driver structures and emits any GPU commands required to begin |
* recording data for the query. |
*/ |
static void |
gen6_begin_query(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct brw_query_object *query = (struct brw_query_object *)q; |
/* Since we're starting a new query, we need to throw away old results. */ |
drm_intel_bo_unreference(query->bo); |
query->bo = drm_intel_bo_alloc(brw->bufmgr, "query results", 4096, 4096); |
switch (query->Base.Target) { |
case GL_TIME_ELAPSED: |
/* For timestamp queries, we record the starting time right away so that |
* we measure the full time between BeginQuery and EndQuery. There's |
* some debate about whether this is the right thing to do. Our decision |
* is based on the following text from the ARB_timer_query extension: |
* |
* "(5) Should the extension measure total time elapsed between the full |
* completion of the BeginQuery and EndQuery commands, or just time |
* spent in the graphics library? |
* |
* RESOLVED: This extension will measure the total time elapsed |
* between the full completion of these commands. Future extensions |
* may implement a query to determine time elapsed at different stages |
* of the graphics pipeline." |
* |
* We write a starting timestamp now (at index 0). At EndQuery() time, |
* we'll write a second timestamp (at index 1), and subtract the two to |
* obtain the time elapsed. Notably, this includes time elapsed while |
* the system was doing other work, such as running other applications. |
*/ |
write_timestamp(brw, query->bo, 0); |
break; |
case GL_ANY_SAMPLES_PASSED: |
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: |
case GL_SAMPLES_PASSED_ARB: |
write_depth_count(brw, query->bo, 0); |
break; |
case GL_PRIMITIVES_GENERATED: |
write_primitives_generated(brw, query->bo, 0); |
break; |
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: |
write_xfb_primitives_written(brw, query->bo, 0); |
break; |
default: |
assert(!"Unrecognized query target in brw_begin_query()"); |
break; |
} |
} |
/** |
* Driver hook for glEndQuery(). |
* |
* Emits GPU commands to record a final query value, ending any data capturing. |
* However, the final result isn't necessarily available until the GPU processes |
* those commands. brw_queryobj_get_results() processes the captured data to |
* produce the final result. |
*/ |
static void |
gen6_end_query(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct brw_query_object *query = (struct brw_query_object *)q; |
switch (query->Base.Target) { |
case GL_TIME_ELAPSED: |
write_timestamp(brw, query->bo, 1); |
break; |
case GL_ANY_SAMPLES_PASSED: |
case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: |
case GL_SAMPLES_PASSED_ARB: |
write_depth_count(brw, query->bo, 1); |
break; |
case GL_PRIMITIVES_GENERATED: |
write_primitives_generated(brw, query->bo, 1); |
break; |
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: |
write_xfb_primitives_written(brw, query->bo, 1); |
break; |
default: |
assert(!"Unrecognized query target in brw_end_query()"); |
break; |
} |
} |
/** |
* The WaitQuery() driver hook. |
* |
* Wait for a query result to become available and return it. This is the |
* backing for glGetQueryObjectiv() with the GL_QUERY_RESULT pname. |
*/ |
static void gen6_wait_query(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct brw_query_object *query = (struct brw_query_object *)q; |
gen6_queryobj_get_results(ctx, query); |
query->Base.Ready = true; |
} |
/** |
* The CheckQuery() driver hook. |
* |
* Checks whether a query result is ready yet. If not, flushes. |
* This is the backing for glGetQueryObjectiv()'s QUERY_RESULT_AVAILABLE pname. |
*/ |
static void gen6_check_query(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct brw_query_object *query = (struct brw_query_object *)q; |
/* From the GL_ARB_occlusion_query spec: |
* |
* "Instead of allowing for an infinite loop, performing a |
* QUERY_RESULT_AVAILABLE_ARB will perform a flush if the result is |
* not ready yet on the first time it is queried. This ensures that |
* the async query will return true in finite time. |
*/ |
if (query->bo && drm_intel_bo_references(brw->batch.bo, query->bo)) |
intel_batchbuffer_flush(brw); |
if (query->bo == NULL || !drm_intel_bo_busy(query->bo)) { |
gen6_queryobj_get_results(ctx, query); |
query->Base.Ready = true; |
} |
} |
/* Initialize Gen6+-specific query object functions. */ |
void gen6_init_queryobj_functions(struct dd_function_table *functions) |
{ |
functions->BeginQuery = gen6_begin_query; |
functions->EndQuery = gen6_end_query; |
functions->CheckQuery = gen6_check_query; |
functions->WaitQuery = gen6_wait_query; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_sampler_state.c |
---|
0,0 → 1,56 |
/* |
* Copyright © 2010 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "intel_batchbuffer.h" |
static void |
upload_sampler_state_pointers(struct brw_context *brw) |
{ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_SAMPLER_STATE_POINTERS << 16 | |
VS_SAMPLER_STATE_CHANGE | |
GS_SAMPLER_STATE_CHANGE | |
PS_SAMPLER_STATE_CHANGE | |
(4 - 2)); |
OUT_BATCH(brw->sampler.offset); /* VS */ |
OUT_BATCH(0); /* GS */ |
OUT_BATCH(brw->sampler.offset); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen6_sampler_state = { |
.dirty = { |
.mesa = 0, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_STATE_BASE_ADDRESS), |
.cache = CACHE_NEW_SAMPLER |
}, |
.emit = upload_sampler_state_pointers, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_scissor_state.c |
---|
0,0 → 1,94 |
/* |
* Copyright © 2009 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "intel_batchbuffer.h" |
#include "main/fbobject.h" |
static void |
gen6_upload_scissor_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
const bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
struct gen6_scissor_rect *scissor; |
uint32_t scissor_state_offset; |
scissor = brw_state_batch(brw, AUB_TRACE_SCISSOR_STATE, |
sizeof(*scissor), 32, &scissor_state_offset); |
/* _NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT */ |
/* The scissor only needs to handle the intersection of drawable and |
* scissor rect. Clipping to the boundaries of static shared buffers |
* for front/back/depth is covered by looping over cliprects in brw_draw.c. |
* |
* Note that the hardware's coordinates are inclusive, while Mesa's min is |
* inclusive but max is exclusive. |
*/ |
if (ctx->DrawBuffer->_Xmin == ctx->DrawBuffer->_Xmax || |
ctx->DrawBuffer->_Ymin == ctx->DrawBuffer->_Ymax) { |
/* If the scissor was out of bounds and got clamped to 0 |
* width/height at the bounds, the subtraction of 1 from |
* maximums could produce a negative number and thus not clip |
* anything. Instead, just provide a min > max scissor inside |
* the bounds, which produces the expected no rendering. |
*/ |
scissor->xmin = 1; |
scissor->xmax = 0; |
scissor->ymin = 1; |
scissor->ymax = 0; |
} else if (render_to_fbo) { |
/* texmemory: Y=0=bottom */ |
scissor->xmin = ctx->DrawBuffer->_Xmin; |
scissor->xmax = ctx->DrawBuffer->_Xmax - 1; |
scissor->ymin = ctx->DrawBuffer->_Ymin; |
scissor->ymax = ctx->DrawBuffer->_Ymax - 1; |
} |
else { |
/* memory: Y=0=top */ |
scissor->xmin = ctx->DrawBuffer->_Xmin; |
scissor->xmax = ctx->DrawBuffer->_Xmax - 1; |
scissor->ymin = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymax; |
scissor->ymax = ctx->DrawBuffer->Height - ctx->DrawBuffer->_Ymin - 1; |
} |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_SCISSOR_STATE_POINTERS << 16 | (2 - 2)); |
OUT_BATCH(scissor_state_offset); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen6_scissor_state = { |
.dirty = { |
.mesa = _NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT, |
.brw = BRW_NEW_BATCH, |
.cache = 0, |
}, |
.emit = gen6_upload_scissor_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_sf_state.c |
---|
0,0 → 1,376 |
/* |
* Copyright © 2009 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_util.h" |
#include "main/macros.h" |
#include "main/fbobject.h" |
#include "intel_batchbuffer.h" |
/** |
* Determine the appropriate attribute override value to store into the |
* 3DSTATE_SF structure for a given fragment shader attribute. The attribute |
* override value contains two pieces of information: the location of the |
* attribute in the VUE (relative to urb_entry_read_offset, see below), and a |
* flag indicating whether to "swizzle" the attribute based on the direction |
* the triangle is facing. |
* |
* If an attribute is "swizzled", then the given VUE location is used for |
* front-facing triangles, and the VUE location that immediately follows is |
* used for back-facing triangles. We use this to implement the mapping from |
* gl_FrontColor/gl_BackColor to gl_Color. |
* |
* urb_entry_read_offset is the offset into the VUE at which the SF unit is |
* being instructed to begin reading attribute data. It can be set to a |
* nonzero value to prevent the SF unit from wasting time reading elements of |
* the VUE that are not needed by the fragment shader. It is measured in |
* 256-bit increments. |
*/ |
uint32_t |
get_attr_override(const struct brw_vue_map *vue_map, int urb_entry_read_offset, |
int fs_attr, bool two_side_color, uint32_t *max_source_attr) |
{ |
if (fs_attr == VARYING_SLOT_POS) { |
/* This attribute will be overwritten by the fragment shader's |
* interpolation code (see emit_interp() in brw_wm_fp.c), so just let it |
* reference the first available attribute. |
*/ |
return 0; |
} |
/* Find the VUE slot for this attribute. */ |
int slot = vue_map->varying_to_slot[fs_attr]; |
/* If there was only a back color written but not front, use back |
* as the color instead of undefined |
*/ |
if (slot == -1 && fs_attr == VARYING_SLOT_COL0) |
slot = vue_map->varying_to_slot[VARYING_SLOT_BFC0]; |
if (slot == -1 && fs_attr == VARYING_SLOT_COL1) |
slot = vue_map->varying_to_slot[VARYING_SLOT_BFC1]; |
if (slot == -1) { |
/* This attribute does not exist in the VUE--that means that the vertex |
* shader did not write to it. This means that either: |
* |
* (a) This attribute is a texture coordinate, and it is going to be |
* replaced with point coordinates (as a consequence of a call to |
* glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE)), so the |
* hardware will ignore whatever attribute override we supply. |
* |
* (b) This attribute is read by the fragment shader but not written by |
* the vertex shader, so its value is undefined. Therefore the |
* attribute override we supply doesn't matter. |
* |
* In either case the attribute override we supply doesn't matter, so |
* just reference the first available attribute. |
*/ |
return 0; |
} |
/* Compute the location of the attribute relative to urb_entry_read_offset. |
* Each increment of urb_entry_read_offset represents a 256-bit value, so |
* it counts for two 128-bit VUE slots. |
*/ |
int source_attr = slot - 2 * urb_entry_read_offset; |
assert(source_attr >= 0 && source_attr < 32); |
/* If we are doing two-sided color, and the VUE slot following this one |
* represents a back-facing color, then we need to instruct the SF unit to |
* do back-facing swizzling. |
*/ |
bool swizzling = two_side_color && |
((vue_map->slot_to_varying[slot] == VARYING_SLOT_COL0 && |
vue_map->slot_to_varying[slot+1] == VARYING_SLOT_BFC0) || |
(vue_map->slot_to_varying[slot] == VARYING_SLOT_COL1 && |
vue_map->slot_to_varying[slot+1] == VARYING_SLOT_BFC1)); |
/* Update max_source_attr. If swizzling, the SF will read this slot + 1. */ |
if (*max_source_attr < source_attr + swizzling) |
*max_source_attr = source_attr + swizzling; |
if (swizzling) { |
return source_attr | |
(ATTRIBUTE_SWIZZLE_INPUTATTR_FACING << ATTRIBUTE_SWIZZLE_SHIFT); |
} |
return source_attr; |
} |
static void |
upload_sf_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_FRAGMENT_PROGRAM */ |
uint32_t num_outputs = _mesa_bitcount_64(brw->fragment_program->Base.InputsRead); |
/* _NEW_LIGHT */ |
bool shade_model_flat = ctx->Light.ShadeModel == GL_FLAT; |
uint32_t dw1, dw2, dw3, dw4, dw16, dw17; |
int i; |
/* _NEW_BUFFER */ |
bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
bool multisampled_fbo = ctx->DrawBuffer->Visual.samples > 1; |
int attr = 0, input_index = 0; |
int urb_entry_read_offset = 1; |
float point_size; |
uint16_t attr_overrides[VARYING_SLOT_MAX]; |
uint32_t point_sprite_origin; |
dw1 = GEN6_SF_SWIZZLE_ENABLE | num_outputs << GEN6_SF_NUM_OUTPUTS_SHIFT; |
dw2 = GEN6_SF_STATISTICS_ENABLE | |
GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; |
dw3 = 0; |
dw4 = 0; |
dw16 = 0; |
dw17 = 0; |
/* _NEW_POLYGON */ |
if ((ctx->Polygon.FrontFace == GL_CCW) ^ render_to_fbo) |
dw2 |= GEN6_SF_WINDING_CCW; |
if (ctx->Polygon.OffsetFill) |
dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID; |
if (ctx->Polygon.OffsetLine) |
dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME; |
if (ctx->Polygon.OffsetPoint) |
dw2 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT; |
switch (ctx->Polygon.FrontMode) { |
case GL_FILL: |
dw2 |= GEN6_SF_FRONT_SOLID; |
break; |
case GL_LINE: |
dw2 |= GEN6_SF_FRONT_WIREFRAME; |
break; |
case GL_POINT: |
dw2 |= GEN6_SF_FRONT_POINT; |
break; |
default: |
assert(0); |
break; |
} |
switch (ctx->Polygon.BackMode) { |
case GL_FILL: |
dw2 |= GEN6_SF_BACK_SOLID; |
break; |
case GL_LINE: |
dw2 |= GEN6_SF_BACK_WIREFRAME; |
break; |
case GL_POINT: |
dw2 |= GEN6_SF_BACK_POINT; |
break; |
default: |
assert(0); |
break; |
} |
/* _NEW_SCISSOR */ |
if (ctx->Scissor.Enabled) |
dw3 |= GEN6_SF_SCISSOR_ENABLE; |
/* _NEW_POLYGON */ |
if (ctx->Polygon.CullFlag) { |
switch (ctx->Polygon.CullFaceMode) { |
case GL_FRONT: |
dw3 |= GEN6_SF_CULL_FRONT; |
break; |
case GL_BACK: |
dw3 |= GEN6_SF_CULL_BACK; |
break; |
case GL_FRONT_AND_BACK: |
dw3 |= GEN6_SF_CULL_BOTH; |
break; |
default: |
assert(0); |
break; |
} |
} else { |
dw3 |= GEN6_SF_CULL_NONE; |
} |
/* _NEW_LINE */ |
{ |
uint32_t line_width_u3_7 = U_FIXED(CLAMP(ctx->Line.Width, 0.0, 7.99), 7); |
/* TODO: line width of 0 is not allowed when MSAA enabled */ |
if (line_width_u3_7 == 0) |
line_width_u3_7 = 1; |
dw3 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT; |
} |
if (ctx->Line.SmoothFlag) { |
dw3 |= GEN6_SF_LINE_AA_ENABLE; |
dw3 |= GEN6_SF_LINE_AA_MODE_TRUE; |
dw3 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; |
} |
/* _NEW_MULTISAMPLE */ |
if (multisampled_fbo && ctx->Multisample.Enabled) |
dw3 |= GEN6_SF_MSRAST_ON_PATTERN; |
/* _NEW_PROGRAM | _NEW_POINT */ |
if (!(ctx->VertexProgram.PointSizeEnabled || |
ctx->Point._Attenuated)) |
dw4 |= GEN6_SF_USE_STATE_POINT_WIDTH; |
/* Clamp to ARB_point_parameters user limits */ |
point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); |
/* Clamp to the hardware limits and convert to fixed point */ |
dw4 |= U_FIXED(CLAMP(point_size, 0.125, 255.875), 3); |
/* |
* Window coordinates in an FBO are inverted, which means point |
* sprite origin must be inverted, too. |
*/ |
if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) { |
point_sprite_origin = GEN6_SF_POINT_SPRITE_LOWERLEFT; |
} else { |
point_sprite_origin = GEN6_SF_POINT_SPRITE_UPPERLEFT; |
} |
dw1 |= point_sprite_origin; |
/* _NEW_LIGHT */ |
if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { |
dw4 |= |
(2 << GEN6_SF_TRI_PROVOKE_SHIFT) | |
(2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | |
(1 << GEN6_SF_LINE_PROVOKE_SHIFT); |
} else { |
dw4 |= |
(1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); |
} |
/* Create the mapping from the FS inputs we produce to the VS outputs |
* they source from. |
*/ |
uint32_t max_source_attr = 0; |
for (; attr < VARYING_SLOT_MAX; attr++) { |
enum glsl_interp_qualifier interp_qualifier = |
brw->fragment_program->InterpQualifier[attr]; |
bool is_gl_Color = attr == VARYING_SLOT_COL0 || attr == VARYING_SLOT_COL1; |
if (!(brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(attr))) |
continue; |
/* _NEW_POINT */ |
if (ctx->Point.PointSprite && |
(attr >= VARYING_SLOT_TEX0 && attr <= VARYING_SLOT_TEX7) && |
ctx->Point.CoordReplace[attr - VARYING_SLOT_TEX0]) { |
dw16 |= (1 << input_index); |
} |
if (attr == VARYING_SLOT_PNTC) |
dw16 |= (1 << input_index); |
/* flat shading */ |
if (interp_qualifier == INTERP_QUALIFIER_FLAT || |
(shade_model_flat && is_gl_Color && |
interp_qualifier == INTERP_QUALIFIER_NONE)) |
dw17 |= (1 << input_index); |
/* The hardware can only do the overrides on 16 overrides at a |
* time, and the other up to 16 have to be lined up so that the |
* input index = the output index. We'll need to do some |
* tweaking to make sure that's the case. |
*/ |
assert(input_index < 16 || attr == input_index); |
/* BRW_NEW_VUE_MAP_GEOM_OUT | _NEW_LIGHT | _NEW_PROGRAM */ |
attr_overrides[input_index++] = |
get_attr_override(&brw->vue_map_geom_out, |
urb_entry_read_offset, attr, |
ctx->VertexProgram._TwoSideEnabled, |
&max_source_attr); |
} |
for (; input_index < VARYING_SLOT_MAX; input_index++) |
attr_overrides[input_index] = 0; |
/* From the Sandy Bridge PRM, Volume 2, Part 1, documentation for |
* 3DSTATE_SF DWord 1 bits 15:11, "Vertex URB Entry Read Length": |
* |
* "This field should be set to the minimum length required to read the |
* maximum source attribute. The maximum source attribute is indicated |
* by the maximum value of the enabled Attribute # Source Attribute if |
* Attribute Swizzle Enable is set, Number of Output Attributes-1 if |
* enable is not set. |
* read_length = ceiling((max_source_attr + 1) / 2) |
* |
* [errata] Corruption/Hang possible if length programmed larger than |
* recommended" |
*/ |
uint32_t urb_entry_read_length = ALIGN(max_source_attr + 1, 2) / 2; |
dw1 |= urb_entry_read_length << GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT | |
urb_entry_read_offset << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT; |
BEGIN_BATCH(20); |
OUT_BATCH(_3DSTATE_SF << 16 | (20 - 2)); |
OUT_BATCH(dw1); |
OUT_BATCH(dw2); |
OUT_BATCH(dw3); |
OUT_BATCH(dw4); |
OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */ |
OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */ |
OUT_BATCH_F(0.0); /* XXX: global depth offset clamp */ |
for (i = 0; i < 8; i++) { |
OUT_BATCH(attr_overrides[i * 2] | attr_overrides[i * 2 + 1] << 16); |
} |
OUT_BATCH(dw16); /* point sprite texcoord bitmask */ |
OUT_BATCH(dw17); /* constant interp bitmask */ |
OUT_BATCH(0); /* wrapshortest enables 0-7 */ |
OUT_BATCH(0); /* wrapshortest enables 8-15 */ |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen6_sf_state = { |
.dirty = { |
.mesa = (_NEW_LIGHT | |
_NEW_PROGRAM | |
_NEW_POLYGON | |
_NEW_LINE | |
_NEW_SCISSOR | |
_NEW_BUFFERS | |
_NEW_POINT | |
_NEW_MULTISAMPLE), |
.brw = (BRW_NEW_CONTEXT | |
BRW_NEW_FRAGMENT_PROGRAM | |
BRW_NEW_VUE_MAP_GEOM_OUT) |
}, |
.emit = upload_sf_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_sol.c |
---|
0,0 → 1,190 |
/* |
* Copyright © 2011 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. |
*/ |
/** \file gen6_sol.c |
* |
* Code to initialize the binding table entries used by transform feedback. |
*/ |
#include "main/macros.h" |
#include "brw_context.h" |
#include "intel_batchbuffer.h" |
#include "brw_defines.h" |
#include "brw_state.h" |
#include "main/transformfeedback.h" |
static void |
gen6_update_sol_surfaces(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_TRANSFORM_FEEDBACK */ |
struct gl_transform_feedback_object *xfb_obj = |
ctx->TransformFeedback.CurrentObject; |
/* BRW_NEW_VERTEX_PROGRAM */ |
const struct gl_shader_program *shaderprog = |
ctx->Shader.CurrentVertexProgram; |
const struct gl_transform_feedback_info *linked_xfb_info = |
&shaderprog->LinkedTransformFeedback; |
int i; |
for (i = 0; i < BRW_MAX_SOL_BINDINGS; ++i) { |
const int surf_index = SURF_INDEX_SOL_BINDING(i); |
if (_mesa_is_xfb_active_and_unpaused(ctx) && |
i < linked_xfb_info->NumOutputs) { |
unsigned buffer = linked_xfb_info->Outputs[i].OutputBuffer; |
unsigned buffer_offset = |
xfb_obj->Offset[buffer] / 4 + |
linked_xfb_info->Outputs[i].DstOffset; |
brw_update_sol_surface( |
brw, xfb_obj->Buffers[buffer], &brw->gs.surf_offset[surf_index], |
linked_xfb_info->Outputs[i].NumComponents, |
linked_xfb_info->BufferStride[buffer], buffer_offset); |
} else { |
brw->gs.surf_offset[surf_index] = 0; |
} |
} |
brw->state.dirty.brw |= BRW_NEW_SURFACES; |
} |
const struct brw_tracked_state gen6_sol_surface = { |
.dirty = { |
.mesa = 0, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_VERTEX_PROGRAM | |
BRW_NEW_TRANSFORM_FEEDBACK), |
.cache = 0 |
}, |
.emit = gen6_update_sol_surfaces, |
}; |
/** |
* Constructs the binding table for the WM surface state, which maps unit |
* numbers to surface state objects. |
*/ |
static void |
brw_gs_upload_binding_table(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_VERTEX_PROGRAM */ |
const struct gl_shader_program *shaderprog = |
ctx->Shader.CurrentVertexProgram; |
bool has_surfaces = false; |
uint32_t *bind; |
if (shaderprog) { |
const struct gl_transform_feedback_info *linked_xfb_info = |
&shaderprog->LinkedTransformFeedback; |
/* Currently we only ever upload surfaces for SOL. */ |
has_surfaces = linked_xfb_info->NumOutputs != 0; |
} |
/* Skip making a binding table if we don't have anything to put in it. */ |
if (!has_surfaces) { |
if (brw->gs.bind_bo_offset != 0) { |
brw->state.dirty.brw |= BRW_NEW_GS_BINDING_TABLE; |
brw->gs.bind_bo_offset = 0; |
} |
return; |
} |
/* Might want to calculate nr_surfaces first, to avoid taking up so much |
* space for the binding table. |
*/ |
bind = brw_state_batch(brw, AUB_TRACE_BINDING_TABLE, |
sizeof(uint32_t) * BRW_MAX_GS_SURFACES, |
32, &brw->gs.bind_bo_offset); |
/* BRW_NEW_SURFACES */ |
memcpy(bind, brw->gs.surf_offset, BRW_MAX_GS_SURFACES * sizeof(uint32_t)); |
brw->state.dirty.brw |= BRW_NEW_GS_BINDING_TABLE; |
} |
const struct brw_tracked_state gen6_gs_binding_table = { |
.dirty = { |
.mesa = 0, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_VERTEX_PROGRAM | |
BRW_NEW_SURFACES), |
.cache = 0 |
}, |
.emit = brw_gs_upload_binding_table, |
}; |
void |
brw_begin_transform_feedback(struct gl_context *ctx, GLenum mode, |
struct gl_transform_feedback_object *obj) |
{ |
struct brw_context *brw = brw_context(ctx); |
const struct gl_shader_program *vs_prog = |
ctx->Shader.CurrentVertexProgram; |
const struct gl_transform_feedback_info *linked_xfb_info = |
&vs_prog->LinkedTransformFeedback; |
struct gl_transform_feedback_object *xfb_obj = |
ctx->TransformFeedback.CurrentObject; |
assert(brw->gen == 6); |
/* Compute the maximum number of vertices that we can write without |
* overflowing any of the buffers currently being used for feedback. |
*/ |
unsigned max_index |
= _mesa_compute_max_transform_feedback_vertices(xfb_obj, |
linked_xfb_info); |
/* Initialize the SVBI 0 register to zero and set the maximum index. */ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_GS_SVB_INDEX << 16 | (4 - 2)); |
OUT_BATCH(0); /* SVBI 0 */ |
OUT_BATCH(0); /* starting index */ |
OUT_BATCH(max_index); |
ADVANCE_BATCH(); |
/* Initialize the rest of the unused streams to sane values. Otherwise, |
* they may indicate that there is no room to write data and prevent |
* anything from happening at all. |
*/ |
for (int i = 1; i < 4; i++) { |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_GS_SVB_INDEX << 16 | (4 - 2)); |
OUT_BATCH(i << SVB_INDEX_SHIFT); |
OUT_BATCH(0); /* starting index */ |
OUT_BATCH(0xffffffff); |
ADVANCE_BATCH(); |
} |
} |
void |
brw_end_transform_feedback(struct gl_context *ctx, |
struct gl_transform_feedback_object *obj) |
{ |
/* After EndTransformFeedback, it's likely that the client program will try |
* to draw using the contents of the transform feedback buffer as vertex |
* input. In order for this to work, we need to flush the data through at |
* least the GS stage of the pipeline, and flush out the render cache. For |
* simplicity, just do a full flush. |
*/ |
struct brw_context *brw = brw_context(ctx); |
intel_batchbuffer_emit_mi_flush(brw); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_urb.c |
---|
0,0 → 1,124 |
/* |
* Copyright © 2009 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "main/macros.h" |
#include "intel_batchbuffer.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
/** |
* When the GS is not in use, we assign the entire URB space to the VS. When |
* the GS is in use, we split the URB space evenly between the VS and the GS. |
* This is not ideal, but it's simple. |
* |
* URB size / 2 URB size / 2 |
* _____________-______________ _____________-______________ |
* / \ / \ |
* +-------------------------------------------------------------+ |
* | Vertex Shader Entries | Geometry Shader Entries | |
* +-------------------------------------------------------------+ |
* |
* Sandybridge GT1 has 32kB of URB space, while GT2 has 64kB. |
* (See the Sandybridge PRM, Volume 2, Part 1, Section 1.4.7: 3DSTATE_URB.) |
*/ |
static void |
gen6_upload_urb( struct brw_context *brw ) |
{ |
int nr_vs_entries, nr_gs_entries; |
int total_urb_size = brw->urb.size * 1024; /* in bytes */ |
/* CACHE_NEW_VS_PROG */ |
unsigned vs_size = MAX2(brw->vs.prog_data->base.urb_entry_size, 1); |
/* We use the same VUE layout for VS outputs and GS outputs (as it's what |
* the SF and Clipper expect), so we can simply make the GS URB entry size |
* the same as for the VS. This may technically be too large in cases |
* where we have few vertex attributes and a lot of varyings, since the VS |
* size is determined by the larger of the two. For now, it's safe. |
*/ |
unsigned gs_size = vs_size; |
/* Calculate how many entries fit in each stage's section of the URB */ |
if (brw->gs.prog_active) { |
nr_vs_entries = (total_urb_size/2) / (vs_size * 128); |
nr_gs_entries = (total_urb_size/2) / (gs_size * 128); |
} else { |
nr_vs_entries = total_urb_size / (vs_size * 128); |
nr_gs_entries = 0; |
} |
/* Then clamp to the maximum allowed by the hardware */ |
if (nr_vs_entries > brw->urb.max_vs_entries) |
nr_vs_entries = brw->urb.max_vs_entries; |
if (nr_gs_entries > brw->urb.max_gs_entries) |
nr_gs_entries = brw->urb.max_gs_entries; |
/* Finally, both must be a multiple of 4 (see 3DSTATE_URB in the PRM). */ |
brw->urb.nr_vs_entries = ROUND_DOWN_TO(nr_vs_entries, 4); |
brw->urb.nr_gs_entries = ROUND_DOWN_TO(nr_gs_entries, 4); |
assert(brw->urb.nr_vs_entries >= 24); |
assert(brw->urb.nr_vs_entries % 4 == 0); |
assert(brw->urb.nr_gs_entries % 4 == 0); |
assert(vs_size < 5); |
assert(gs_size < 5); |
BEGIN_BATCH(3); |
OUT_BATCH(_3DSTATE_URB << 16 | (3 - 2)); |
OUT_BATCH(((vs_size - 1) << GEN6_URB_VS_SIZE_SHIFT) | |
((brw->urb.nr_vs_entries) << GEN6_URB_VS_ENTRIES_SHIFT)); |
OUT_BATCH(((gs_size - 1) << GEN6_URB_GS_SIZE_SHIFT) | |
((brw->urb.nr_gs_entries) << GEN6_URB_GS_ENTRIES_SHIFT)); |
ADVANCE_BATCH(); |
/* From the PRM Volume 2 part 1, section 1.4.7: |
* |
* Because of a urb corruption caused by allocating a previous gsunit’s |
* urb entry to vsunit software is required to send a "GS NULL |
* Fence"(Send URB fence with VS URB size == 1 and GS URB size == 0) plus |
* a dummy DRAW call before any case where VS will be taking over GS URB |
* space. |
* |
* It is not clear exactly what this means ("URB fence" is a command that |
* doesn't exist on Gen6). So for now we just do a full pipeline flush as |
* a workaround. |
*/ |
if (brw->urb.gen6_gs_previously_active && !brw->gs.prog_active) |
intel_batchbuffer_emit_mi_flush(brw); |
brw->urb.gen6_gs_previously_active = brw->gs.prog_active; |
} |
const struct brw_tracked_state gen6_urb = { |
.dirty = { |
.mesa = 0, |
.brw = BRW_NEW_CONTEXT, |
.cache = (CACHE_NEW_VS_PROG | CACHE_NEW_GS_PROG), |
}, |
.emit = gen6_upload_urb, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_viewport_state.c |
---|
0,0 → 1,144 |
/* |
* Copyright © 2009 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "intel_batchbuffer.h" |
#include "main/fbobject.h" |
/* The clip VP defines the guardband region where expensive clipping is skipped |
* and fragments are allowed to be generated and clipped out cheaply by the SF. |
*/ |
static void |
gen6_upload_clip_vp(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct brw_clipper_viewport *vp; |
vp = brw_state_batch(brw, AUB_TRACE_CLIP_VP_STATE, |
sizeof(*vp), 32, &brw->clip.vp_offset); |
/* According to the "Vertex X,Y Clamping and Quantization" section of the |
* Strips and Fans documentation, objects must not have a screen-space |
* extents of over 8192 pixels, or they may be mis-rasterized. The maximum |
* screen space coordinates of a small object may larger, but we have no |
* way to enforce the object size other than through clipping. |
* |
* If you're surprised that we set clip to -gbx to +gbx and it seems like |
* we'll end up with 16384 wide, note that for a 8192-wide render target, |
* we'll end up with a normal (-1, 1) clip volume that just covers the |
* drawable. |
*/ |
const float maximum_post_clamp_delta = 8192; |
float gbx = maximum_post_clamp_delta / (float) ctx->Viewport.Width; |
float gby = maximum_post_clamp_delta / (float) ctx->Viewport.Height; |
vp->xmin = -gbx; |
vp->xmax = gbx; |
vp->ymin = -gby; |
vp->ymax = gby; |
brw->state.dirty.cache |= CACHE_NEW_CLIP_VP; |
} |
const struct brw_tracked_state gen6_clip_vp = { |
.dirty = { |
.mesa = _NEW_VIEWPORT, |
.brw = BRW_NEW_BATCH, |
.cache = 0, |
}, |
.emit = gen6_upload_clip_vp, |
}; |
static void |
gen6_upload_sf_vp(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
const GLfloat depth_scale = 1.0F / ctx->DrawBuffer->_DepthMaxF; |
struct brw_sf_viewport *sfv; |
GLfloat y_scale, y_bias; |
const bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
const GLfloat *v = ctx->Viewport._WindowMap.m; |
sfv = brw_state_batch(brw, AUB_TRACE_SF_VP_STATE, |
sizeof(*sfv), 32, &brw->sf.vp_offset); |
memset(sfv, 0, sizeof(*sfv)); |
/* _NEW_BUFFERS */ |
if (render_to_fbo) { |
y_scale = 1.0; |
y_bias = 0; |
} else { |
y_scale = -1.0; |
y_bias = ctx->DrawBuffer->Height; |
} |
/* _NEW_VIEWPORT */ |
sfv->viewport.m00 = v[MAT_SX]; |
sfv->viewport.m11 = v[MAT_SY] * y_scale; |
sfv->viewport.m22 = v[MAT_SZ] * depth_scale; |
sfv->viewport.m30 = v[MAT_TX]; |
sfv->viewport.m31 = v[MAT_TY] * y_scale + y_bias; |
sfv->viewport.m32 = v[MAT_TZ] * depth_scale; |
brw->state.dirty.cache |= CACHE_NEW_SF_VP; |
} |
const struct brw_tracked_state gen6_sf_vp = { |
.dirty = { |
.mesa = _NEW_VIEWPORT | _NEW_BUFFERS, |
.brw = BRW_NEW_BATCH, |
.cache = 0, |
}, |
.emit = gen6_upload_sf_vp, |
}; |
static void upload_viewport_state_pointers(struct brw_context *brw) |
{ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_VIEWPORT_STATE_POINTERS << 16 | (4 - 2) | |
GEN6_CC_VIEWPORT_MODIFY | |
GEN6_SF_VIEWPORT_MODIFY | |
GEN6_CLIP_VIEWPORT_MODIFY); |
OUT_BATCH(brw->clip.vp_offset); |
OUT_BATCH(brw->sf.vp_offset); |
OUT_BATCH(brw->cc.vp_offset); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen6_viewport_state = { |
.dirty = { |
.mesa = 0, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_STATE_BASE_ADDRESS), |
.cache = (CACHE_NEW_CLIP_VP | |
CACHE_NEW_SF_VP | |
CACHE_NEW_CC_VP) |
}, |
.emit = upload_viewport_state_pointers, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_vs_state.c |
---|
0,0 → 1,209 |
/* |
* Copyright © 2009 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_util.h" |
#include "program/prog_parameter.h" |
#include "program/prog_statevars.h" |
#include "intel_batchbuffer.h" |
static void |
gen6_upload_vs_push_constants(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* _BRW_NEW_VERTEX_PROGRAM */ |
const struct brw_vertex_program *vp = |
brw_vertex_program_const(brw->vertex_program); |
/* Updates the ParamaterValues[i] pointers for all parameters of the |
* basic type of PROGRAM_STATE_VAR. |
*/ |
/* XXX: Should this happen somewhere before to get our state flag set? */ |
_mesa_load_state_parameters(ctx, vp->program.Base.Parameters); |
/* CACHE_NEW_VS_PROG */ |
if (brw->vs.prog_data->base.nr_params == 0) { |
brw->vs.push_const_size = 0; |
} else { |
int params_uploaded; |
float *param; |
int i; |
param = brw_state_batch(brw, AUB_TRACE_VS_CONSTANTS, |
brw->vs.prog_data->base.nr_params * sizeof(float), |
32, &brw->vs.push_const_offset); |
/* _NEW_PROGRAM_CONSTANTS |
* |
* Also _NEW_TRANSFORM -- we may reference clip planes other than as a |
* side effect of dereferencing uniforms, so _NEW_PROGRAM_CONSTANTS |
* wouldn't be set for them. |
*/ |
for (i = 0; i < brw->vs.prog_data->base.nr_params; i++) { |
param[i] = *brw->vs.prog_data->base.param[i]; |
} |
params_uploaded = brw->vs.prog_data->base.nr_params / 4; |
if (0) { |
printf("VS constant buffer:\n"); |
for (i = 0; i < params_uploaded; i++) { |
float *buf = param + i * 4; |
printf("%d: %f %f %f %f\n", |
i, buf[0], buf[1], buf[2], buf[3]); |
} |
} |
brw->vs.push_const_size = (params_uploaded + 1) / 2; |
/* We can only push 32 registers of constants at a time. */ |
assert(brw->vs.push_const_size <= 32); |
} |
} |
const struct brw_tracked_state gen6_vs_push_constants = { |
.dirty = { |
.mesa = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_VERTEX_PROGRAM), |
.cache = CACHE_NEW_VS_PROG, |
}, |
.emit = gen6_upload_vs_push_constants, |
}; |
static void |
upload_vs_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
uint32_t floating_point_mode = 0; |
/* From the BSpec, 3D Pipeline > Geometry > Vertex Shader > State, |
* 3DSTATE_VS, Dword 5.0 "VS Function Enable": |
* |
* [DevSNB] A pipeline flush must be programmed prior to a 3DSTATE_VS |
* command that causes the VS Function Enable to toggle. Pipeline |
* flush can be executed by sending a PIPE_CONTROL command with CS |
* stall bit set and a post sync operation. |
* |
* Although we don't disable the VS during normal drawing, BLORP sometimes |
* disables it. To be safe, do the flush here just in case. |
*/ |
intel_emit_post_sync_nonzero_flush(brw); |
if (brw->vs.push_const_size == 0) { |
/* Disable the push constant buffers. */ |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 | (5 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} else { |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 | |
GEN6_CONSTANT_BUFFER_0_ENABLE | |
(5 - 2)); |
/* Pointer to the VS constant buffer. Covered by the set of |
* state flags from gen6_upload_vs_constants |
*/ |
OUT_BATCH(brw->vs.push_const_offset + |
brw->vs.push_const_size - 1); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* Use ALT floating point mode for ARB vertex programs, because they |
* require 0^0 == 1. |
*/ |
if (ctx->Shader.CurrentVertexProgram == NULL) |
floating_point_mode = GEN6_VS_FLOATING_POINT_MODE_ALT; |
BEGIN_BATCH(6); |
OUT_BATCH(_3DSTATE_VS << 16 | (6 - 2)); |
OUT_BATCH(brw->vs.prog_offset); |
OUT_BATCH(floating_point_mode | |
((ALIGN(brw->sampler.count, 4)/4) << GEN6_VS_SAMPLER_COUNT_SHIFT)); |
if (brw->vs.prog_data->base.total_scratch) { |
OUT_RELOC(brw->vs.scratch_bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
ffs(brw->vs.prog_data->base.total_scratch) - 11); |
} else { |
OUT_BATCH(0); |
} |
OUT_BATCH((1 << GEN6_VS_DISPATCH_START_GRF_SHIFT) | |
(brw->vs.prog_data->base.urb_read_length << GEN6_VS_URB_READ_LENGTH_SHIFT) | |
(0 << GEN6_VS_URB_ENTRY_READ_OFFSET_SHIFT)); |
OUT_BATCH(((brw->max_vs_threads - 1) << GEN6_VS_MAX_THREADS_SHIFT) | |
GEN6_VS_STATISTICS_ENABLE | |
GEN6_VS_ENABLE); |
ADVANCE_BATCH(); |
/* Based on my reading of the simulator, the VS constants don't get |
* pulled into the VS FF unit until an appropriate pipeline flush |
* happens, and instead the 3DSTATE_CONSTANT_VS packet just adds |
* references to them into a little FIFO. The flushes are common, |
* but don't reliably happen between this and a 3DPRIMITIVE, causing |
* the primitive to use the wrong constants. Then the FIFO |
* containing the constant setup gets added to again on the next |
* constants change, and eventually when a flush does happen the |
* unit is overwhelmed by constant changes and dies. |
* |
* To avoid this, send a PIPE_CONTROL down the line that will |
* update the unit immediately loading the constants. The flush |
* type bits here were those set by the STATE_BASE_ADDRESS whose |
* move in a82a43e8d99e1715dd11c9c091b5ab734079b6a6 triggered the |
* bug reports that led to this workaround, and may be more than |
* what is strictly required to avoid the issue. |
*/ |
intel_emit_post_sync_nonzero_flush(brw); |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2)); |
OUT_BATCH(PIPE_CONTROL_DEPTH_STALL | |
PIPE_CONTROL_INSTRUCTION_FLUSH | |
PIPE_CONTROL_STATE_CACHE_INVALIDATE); |
OUT_BATCH(0); /* address */ |
OUT_BATCH(0); /* write data */ |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen6_vs_state = { |
.dirty = { |
.mesa = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS, |
.brw = (BRW_NEW_CONTEXT | |
BRW_NEW_VERTEX_PROGRAM | |
BRW_NEW_BATCH), |
.cache = CACHE_NEW_VS_PROG | CACHE_NEW_SAMPLER |
}, |
.emit = upload_vs_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen6_wm_state.c |
---|
0,0 → 1,237 |
/* |
* Copyright © 2009 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_util.h" |
#include "brw_wm.h" |
#include "program/prog_parameter.h" |
#include "program/prog_statevars.h" |
#include "intel_batchbuffer.h" |
static void |
gen6_upload_wm_push_constants(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_FRAGMENT_PROGRAM */ |
const struct brw_fragment_program *fp = |
brw_fragment_program_const(brw->fragment_program); |
/* Updates the ParameterValues[i] pointers for all parameters of the |
* basic type of PROGRAM_STATE_VAR. |
*/ |
/* XXX: Should this happen somewhere before to get our state flag set? */ |
_mesa_load_state_parameters(ctx, fp->program.Base.Parameters); |
/* CACHE_NEW_WM_PROG */ |
if (brw->wm.prog_data->nr_params != 0) { |
float *constants; |
unsigned int i; |
constants = brw_state_batch(brw, AUB_TRACE_WM_CONSTANTS, |
brw->wm.prog_data->nr_params * |
sizeof(float), |
32, &brw->wm.push_const_offset); |
for (i = 0; i < brw->wm.prog_data->nr_params; i++) { |
constants[i] = *brw->wm.prog_data->param[i]; |
} |
if (0) { |
printf("WM constants:\n"); |
for (i = 0; i < brw->wm.prog_data->nr_params; i++) { |
if ((i & 7) == 0) |
printf("g%d: ", brw->wm.prog_data->first_curbe_grf + i / 8); |
printf("%8f ", constants[i]); |
if ((i & 7) == 7) |
printf("\n"); |
} |
if ((i & 7) != 0) |
printf("\n"); |
printf("\n"); |
} |
} |
} |
const struct brw_tracked_state gen6_wm_push_constants = { |
.dirty = { |
.mesa = _NEW_PROGRAM_CONSTANTS, |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_FRAGMENT_PROGRAM), |
.cache = CACHE_NEW_WM_PROG, |
}, |
.emit = gen6_upload_wm_push_constants, |
}; |
static void |
upload_wm_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
const struct brw_fragment_program *fp = |
brw_fragment_program_const(brw->fragment_program); |
uint32_t dw2, dw4, dw5, dw6; |
/* _NEW_BUFFERS */ |
bool multisampled_fbo = ctx->DrawBuffer->Visual.samples > 1; |
/* CACHE_NEW_WM_PROG */ |
if (brw->wm.prog_data->nr_params == 0) { |
/* Disable the push constant buffers. */ |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_CONSTANT_PS << 16 | (5 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} else { |
BEGIN_BATCH(5); |
OUT_BATCH(_3DSTATE_CONSTANT_PS << 16 | |
GEN6_CONSTANT_BUFFER_0_ENABLE | |
(5 - 2)); |
/* Pointer to the WM constant buffer. Covered by the set of |
* state flags from gen6_upload_wm_push_constants. |
*/ |
OUT_BATCH(brw->wm.push_const_offset + |
ALIGN(brw->wm.prog_data->nr_params, |
brw->wm.prog_data->dispatch_width) / 8 - 1); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
dw2 = dw4 = dw5 = dw6 = 0; |
dw4 |= GEN6_WM_STATISTICS_ENABLE; |
dw5 |= GEN6_WM_LINE_AA_WIDTH_1_0; |
dw5 |= GEN6_WM_LINE_END_CAP_AA_WIDTH_0_5; |
/* Use ALT floating point mode for ARB fragment programs, because they |
* require 0^0 == 1. Even though _CurrentFragmentProgram is used for |
* rendering, CurrentFragmentProgram is used for this check to |
* differentiate between the GLSL and non-GLSL cases. |
*/ |
if (ctx->Shader.CurrentFragmentProgram == NULL) |
dw2 |= GEN6_WM_FLOATING_POINT_MODE_ALT; |
/* CACHE_NEW_SAMPLER */ |
dw2 |= (ALIGN(brw->sampler.count, 4) / 4) << GEN6_WM_SAMPLER_COUNT_SHIFT; |
dw4 |= (brw->wm.prog_data->first_curbe_grf << |
GEN6_WM_DISPATCH_START_GRF_SHIFT_0); |
dw4 |= (brw->wm.prog_data->first_curbe_grf_16 << |
GEN6_WM_DISPATCH_START_GRF_SHIFT_2); |
dw5 |= (brw->max_wm_threads - 1) << GEN6_WM_MAX_THREADS_SHIFT; |
/* CACHE_NEW_WM_PROG */ |
dw5 |= GEN6_WM_8_DISPATCH_ENABLE; |
if (brw->wm.prog_data->prog_offset_16) |
dw5 |= GEN6_WM_16_DISPATCH_ENABLE; |
/* CACHE_NEW_WM_PROG | _NEW_COLOR */ |
if (brw->wm.prog_data->dual_src_blend && |
(ctx->Color.BlendEnabled & 1) && |
ctx->Color.Blend[0]._UsesDualSrc) { |
dw5 |= GEN6_WM_DUAL_SOURCE_BLEND_ENABLE; |
} |
/* _NEW_LINE */ |
if (ctx->Line.StippleFlag) |
dw5 |= GEN6_WM_LINE_STIPPLE_ENABLE; |
/* _NEW_POLYGON */ |
if (ctx->Polygon.StippleFlag) |
dw5 |= GEN6_WM_POLYGON_STIPPLE_ENABLE; |
/* BRW_NEW_FRAGMENT_PROGRAM */ |
if (fp->program.Base.InputsRead & VARYING_BIT_POS) |
dw5 |= GEN6_WM_USES_SOURCE_DEPTH | GEN6_WM_USES_SOURCE_W; |
if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) |
dw5 |= GEN6_WM_COMPUTED_DEPTH; |
/* CACHE_NEW_WM_PROG */ |
dw6 |= brw->wm.prog_data->barycentric_interp_modes << |
GEN6_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT; |
/* _NEW_COLOR, _NEW_MULTISAMPLE */ |
if (fp->program.UsesKill || ctx->Color.AlphaEnabled || |
ctx->Multisample.SampleAlphaToCoverage) |
dw5 |= GEN6_WM_KILL_ENABLE; |
if (brw_color_buffer_write_enabled(brw) || |
dw5 & (GEN6_WM_KILL_ENABLE | GEN6_WM_COMPUTED_DEPTH)) { |
dw5 |= GEN6_WM_DISPATCH_ENABLE; |
} |
dw6 |= _mesa_bitcount_64(brw->fragment_program->Base.InputsRead) << |
GEN6_WM_NUM_SF_OUTPUTS_SHIFT; |
if (multisampled_fbo) { |
/* _NEW_MULTISAMPLE */ |
if (ctx->Multisample.Enabled) |
dw6 |= GEN6_WM_MSRAST_ON_PATTERN; |
else |
dw6 |= GEN6_WM_MSRAST_OFF_PIXEL; |
dw6 |= GEN6_WM_MSDISPMODE_PERPIXEL; |
} else { |
dw6 |= GEN6_WM_MSRAST_OFF_PIXEL; |
dw6 |= GEN6_WM_MSDISPMODE_PERSAMPLE; |
} |
BEGIN_BATCH(9); |
OUT_BATCH(_3DSTATE_WM << 16 | (9 - 2)); |
OUT_BATCH(brw->wm.prog_offset); |
OUT_BATCH(dw2); |
if (brw->wm.prog_data->total_scratch) { |
OUT_RELOC(brw->wm.scratch_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
ffs(brw->wm.prog_data->total_scratch) - 11); |
} else { |
OUT_BATCH(0); |
} |
OUT_BATCH(dw4); |
OUT_BATCH(dw5); |
OUT_BATCH(dw6); |
OUT_BATCH(0); /* kernel 1 pointer */ |
/* kernel 2 pointer */ |
OUT_BATCH(brw->wm.prog_offset + brw->wm.prog_data->prog_offset_16); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen6_wm_state = { |
.dirty = { |
.mesa = (_NEW_LINE | |
_NEW_COLOR | |
_NEW_BUFFERS | |
_NEW_PROGRAM_CONSTANTS | |
_NEW_POLYGON | |
_NEW_MULTISAMPLE), |
.brw = (BRW_NEW_FRAGMENT_PROGRAM | |
BRW_NEW_BATCH), |
.cache = (CACHE_NEW_SAMPLER | |
CACHE_NEW_WM_PROG) |
}, |
.emit = upload_wm_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_blorp.cpp |
---|
0,0 → 1,887 |
/* |
* Copyright © 2011 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 <assert.h> |
#include "intel_batchbuffer.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
#include "brw_state.h" |
#include "brw_blorp.h" |
#include "gen7_blorp.h" |
/* 3DSTATE_URB_VS |
* 3DSTATE_URB_HS |
* 3DSTATE_URB_DS |
* 3DSTATE_URB_GS |
* |
* If the 3DSTATE_URB_VS is emitted, than the others must be also. |
* From the Ivybridge PRM, Volume 2 Part 1, section 1.7.1 3DSTATE_URB_VS: |
* |
* 3DSTATE_URB_HS, 3DSTATE_URB_DS, and 3DSTATE_URB_GS must also be |
* programmed in order for the programming of this state to be |
* valid. |
*/ |
static void |
gen7_blorp_emit_urb_config(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
/* The minimum valid value is 32. See 3DSTATE_URB_VS, |
* Dword 1.15:0 "VS Number of URB Entries". |
*/ |
int num_vs_entries = 32; |
int vs_size = 2; |
int vs_start = 2; /* skip over push constants */ |
gen7_emit_urb_state(brw, num_vs_entries, vs_size, vs_start); |
} |
/* 3DSTATE_BLEND_STATE_POINTERS */ |
static void |
gen7_blorp_emit_blend_state_pointer(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t cc_blend_state_offset) |
{ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_BLEND_STATE_POINTERS << 16 | (2 - 2)); |
OUT_BATCH(cc_blend_state_offset | 1); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_CC_STATE_POINTERS */ |
static void |
gen7_blorp_emit_cc_state_pointer(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t cc_state_offset) |
{ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_CC_STATE_POINTERS << 16 | (2 - 2)); |
OUT_BATCH(cc_state_offset | 1); |
ADVANCE_BATCH(); |
} |
static void |
gen7_blorp_emit_cc_viewport(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
struct brw_cc_viewport *ccv; |
uint32_t cc_vp_offset; |
ccv = (struct brw_cc_viewport *)brw_state_batch(brw, AUB_TRACE_CC_VP_STATE, |
sizeof(*ccv), 32, |
&cc_vp_offset); |
ccv->min_depth = 0.0; |
ccv->max_depth = 1.0; |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_VIEWPORT_STATE_POINTERS_CC << 16 | (2 - 2)); |
OUT_BATCH(cc_vp_offset); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_DEPTH_STENCIL_STATE_POINTERS |
* |
* The offset is relative to CMD_STATE_BASE_ADDRESS.DynamicStateBaseAddress. |
*/ |
static void |
gen7_blorp_emit_depth_stencil_state_pointers(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t depthstencil_offset) |
{ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_DEPTH_STENCIL_STATE_POINTERS << 16 | (2 - 2)); |
OUT_BATCH(depthstencil_offset | 1); |
ADVANCE_BATCH(); |
} |
/* SURFACE_STATE for renderbuffer or texture surface (see |
* brw_update_renderbuffer_surface and brw_update_texture_surface) |
*/ |
static uint32_t |
gen7_blorp_emit_surface_state(struct brw_context *brw, |
const brw_blorp_params *params, |
const brw_blorp_surface_info *surface, |
uint32_t read_domains, uint32_t write_domain, |
bool is_render_target) |
{ |
uint32_t wm_surf_offset; |
uint32_t width = surface->width; |
uint32_t height = surface->height; |
/* Note: since gen7 uses INTEL_MSAA_LAYOUT_CMS or INTEL_MSAA_LAYOUT_UMS for |
* color surfaces, width and height are measured in pixels; we don't need |
* to divide them by 2 as we do for Gen6 (see |
* gen6_blorp_emit_surface_state). |
*/ |
struct intel_region *region = surface->mt->region; |
uint32_t tile_x, tile_y; |
uint8_t mocs = brw->is_haswell ? GEN7_MOCS_L3 : 0; |
uint32_t tiling = surface->map_stencil_as_y_tiled |
? I915_TILING_Y : region->tiling; |
uint32_t *surf = (uint32_t *) |
brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, 8 * 4, 32, &wm_surf_offset); |
memset(surf, 0, 8 * 4); |
surf[0] = BRW_SURFACE_2D << BRW_SURFACE_TYPE_SHIFT | |
surface->brw_surfaceformat << BRW_SURFACE_FORMAT_SHIFT | |
gen7_surface_tiling_mode(tiling); |
if (surface->mt->align_h == 4) |
surf[0] |= GEN7_SURFACE_VALIGN_4; |
if (surface->mt->align_w == 8) |
surf[0] |= GEN7_SURFACE_HALIGN_8; |
if (surface->array_spacing_lod0) |
surf[0] |= GEN7_SURFACE_ARYSPC_LOD0; |
else |
surf[0] |= GEN7_SURFACE_ARYSPC_FULL; |
/* reloc */ |
surf[1] = |
surface->compute_tile_offsets(&tile_x, &tile_y) + region->bo->offset; |
/* Note that the low bits of these fields are missing, so |
* there's the possibility of getting in trouble. |
*/ |
assert(tile_x % 4 == 0); |
assert(tile_y % 2 == 0); |
surf[5] = SET_FIELD(tile_x / 4, BRW_SURFACE_X_OFFSET) | |
SET_FIELD(tile_y / 2, BRW_SURFACE_Y_OFFSET) | |
SET_FIELD(mocs, GEN7_SURFACE_MOCS); |
surf[2] = SET_FIELD(width - 1, GEN7_SURFACE_WIDTH) | |
SET_FIELD(height - 1, GEN7_SURFACE_HEIGHT); |
uint32_t pitch_bytes = region->pitch; |
if (surface->map_stencil_as_y_tiled) |
pitch_bytes *= 2; |
surf[3] = pitch_bytes - 1; |
surf[4] = gen7_surface_msaa_bits(surface->num_samples, surface->msaa_layout); |
if (surface->mt->mcs_mt) { |
gen7_set_surface_mcs_info(brw, surf, wm_surf_offset, surface->mt->mcs_mt, |
is_render_target); |
} |
surf[7] = surface->mt->fast_clear_color_value; |
if (brw->is_haswell) { |
surf[7] |= (SET_FIELD(HSW_SCS_RED, GEN7_SURFACE_SCS_R) | |
SET_FIELD(HSW_SCS_GREEN, GEN7_SURFACE_SCS_G) | |
SET_FIELD(HSW_SCS_BLUE, GEN7_SURFACE_SCS_B) | |
SET_FIELD(HSW_SCS_ALPHA, GEN7_SURFACE_SCS_A)); |
} |
/* Emit relocation to surface contents */ |
drm_intel_bo_emit_reloc(brw->batch.bo, |
wm_surf_offset + 4, |
region->bo, |
surf[1] - region->bo->offset, |
read_domains, write_domain); |
gen7_check_surface_setup(surf, is_render_target); |
return wm_surf_offset; |
} |
/** |
* SAMPLER_STATE. See gen7_update_sampler_state(). |
*/ |
static uint32_t |
gen7_blorp_emit_sampler_state(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
uint32_t sampler_offset; |
struct gen7_sampler_state *sampler = (struct gen7_sampler_state *) |
brw_state_batch(brw, AUB_TRACE_SAMPLER_STATE, |
sizeof(struct gen7_sampler_state), |
32, &sampler_offset); |
memset(sampler, 0, sizeof(*sampler)); |
sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; |
sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; |
sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; |
sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
// sampler->ss0.min_mag_neq = 1; |
/* Set LOD bias: |
*/ |
sampler->ss0.lod_bias = 0; |
sampler->ss0.lod_preclamp = 1; /* OpenGL mode */ |
sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */ |
/* Set BaseMipLevel, MaxLOD, MinLOD: |
* |
* XXX: I don't think that using firstLevel, lastLevel works, |
* because we always setup the surface state as if firstLevel == |
* level zero. Probably have to subtract firstLevel from each of |
* these: |
*/ |
sampler->ss0.base_level = U_FIXED(0, 1); |
sampler->ss1.max_lod = U_FIXED(0, 8); |
sampler->ss1.min_lod = U_FIXED(0, 8); |
sampler->ss3.non_normalized_coord = 1; |
sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN | |
BRW_ADDRESS_ROUNDING_ENABLE_V_MIN | |
BRW_ADDRESS_ROUNDING_ENABLE_R_MIN; |
sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG | |
BRW_ADDRESS_ROUNDING_ENABLE_V_MAG | |
BRW_ADDRESS_ROUNDING_ENABLE_R_MAG; |
return sampler_offset; |
} |
/* 3DSTATE_VS |
* |
* Disable vertex shader. |
*/ |
static void |
gen7_blorp_emit_vs_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(6); |
OUT_BATCH(_3DSTATE_VS << 16 | (6 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_HS |
* |
* Disable the hull shader. |
*/ |
static void |
gen7_blorp_emit_hs_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_HS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_HS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_TE |
* |
* Disable the tesselation engine. |
*/ |
static void |
gen7_blorp_emit_te_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_TE << 16 | (4 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_DS |
* |
* Disable the domain shader. |
*/ |
static void |
gen7_blorp_emit_ds_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_DS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(6); |
OUT_BATCH(_3DSTATE_DS << 16 | (6 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_GS |
* |
* Disable the geometry shader. |
*/ |
static void |
gen7_blorp_emit_gs_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_GS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_GS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_STREAMOUT |
* |
* Disable streamout. |
*/ |
static void |
gen7_blorp_emit_streamout_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(3); |
OUT_BATCH(_3DSTATE_STREAMOUT << 16 | (3 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
static void |
gen7_blorp_emit_sf_config(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
/* 3DSTATE_SF |
* |
* Disable ViewportTransformEnable (dw1.1) |
* |
* From the SandyBridge PRM, Volume 2, Part 1, Section 1.3, "3D |
* Primitives Overview": |
* RECTLIST: Viewport Mapping must be DISABLED (as is typical with the |
* use of screen- space coordinates). |
* |
* A solid rectangle must be rendered, so set FrontFaceFillMode (dw1.6:5) |
* and BackFaceFillMode (dw1.4:3) to SOLID(0). |
* |
* From the Sandy Bridge PRM, Volume 2, Part 1, Section |
* 6.4.1.1 3DSTATE_SF, Field FrontFaceFillMode: |
* SOLID: Any triangle or rectangle object found to be front-facing |
* is rendered as a solid object. This setting is required when |
* (rendering rectangle (RECTLIST) objects. |
*/ |
{ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_SF << 16 | (7 - 2)); |
OUT_BATCH(params->depth_format << |
GEN7_SF_DEPTH_BUFFER_SURFACE_FORMAT_SHIFT); |
OUT_BATCH(params->num_samples > 1 ? GEN6_SF_MSRAST_ON_PATTERN : 0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_SBE */ |
{ |
BEGIN_BATCH(14); |
OUT_BATCH(_3DSTATE_SBE << 16 | (14 - 2)); |
OUT_BATCH((1 - 1) << GEN7_SBE_NUM_OUTPUTS_SHIFT | /* only position */ |
1 << GEN7_SBE_URB_ENTRY_READ_LENGTH_SHIFT | |
0 << GEN7_SBE_URB_ENTRY_READ_OFFSET_SHIFT); |
for (int i = 0; i < 12; ++i) |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
} |
/** |
* Disable thread dispatch (dw5.19) and enable the HiZ op. |
*/ |
static void |
gen7_blorp_emit_wm_config(struct brw_context *brw, |
const brw_blorp_params *params, |
brw_blorp_prog_data *prog_data) |
{ |
uint32_t dw1 = 0, dw2 = 0; |
switch (params->hiz_op) { |
case GEN6_HIZ_OP_DEPTH_CLEAR: |
dw1 |= GEN7_WM_DEPTH_CLEAR; |
break; |
case GEN6_HIZ_OP_DEPTH_RESOLVE: |
dw1 |= GEN7_WM_DEPTH_RESOLVE; |
break; |
case GEN6_HIZ_OP_HIZ_RESOLVE: |
dw1 |= GEN7_WM_HIERARCHICAL_DEPTH_RESOLVE; |
break; |
case GEN6_HIZ_OP_NONE: |
break; |
default: |
assert(0); |
break; |
} |
dw1 |= GEN7_WM_LINE_AA_WIDTH_1_0; |
dw1 |= GEN7_WM_LINE_END_CAP_AA_WIDTH_0_5; |
dw1 |= 0 << GEN7_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT; /* No interp */ |
if (params->use_wm_prog) { |
dw1 |= GEN7_WM_KILL_ENABLE; /* TODO: temporarily smash on */ |
dw1 |= GEN7_WM_DISPATCH_ENABLE; /* We are rendering */ |
} |
if (params->num_samples > 1) { |
dw1 |= GEN7_WM_MSRAST_ON_PATTERN; |
if (prog_data && prog_data->persample_msaa_dispatch) |
dw2 |= GEN7_WM_MSDISPMODE_PERSAMPLE; |
else |
dw2 |= GEN7_WM_MSDISPMODE_PERPIXEL; |
} else { |
dw1 |= GEN7_WM_MSRAST_OFF_PIXEL; |
dw2 |= GEN7_WM_MSDISPMODE_PERSAMPLE; |
} |
BEGIN_BATCH(3); |
OUT_BATCH(_3DSTATE_WM << 16 | (3 - 2)); |
OUT_BATCH(dw1); |
OUT_BATCH(dw2); |
ADVANCE_BATCH(); |
} |
/** |
* 3DSTATE_PS |
* |
* Pixel shader dispatch is disabled above in 3DSTATE_WM, dw1.29. Despite |
* that, thread dispatch info must still be specified. |
* - Maximum Number of Threads (dw4.24:31) must be nonzero, as the |
* valid range for this field is [0x3, 0x2f]. |
* - A dispatch mode must be given; that is, at least one of the |
* "N Pixel Dispatch Enable" (N=8,16,32) fields must be set. This was |
* discovered through simulator error messages. |
*/ |
static void |
gen7_blorp_emit_ps_config(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t prog_offset, |
brw_blorp_prog_data *prog_data) |
{ |
uint32_t dw2, dw4, dw5; |
const int max_threads_shift = brw->is_haswell ? |
HSW_PS_MAX_THREADS_SHIFT : IVB_PS_MAX_THREADS_SHIFT; |
dw2 = dw4 = dw5 = 0; |
dw4 |= (brw->max_wm_threads - 1) << max_threads_shift; |
/* If there's a WM program, we need to do 16-pixel dispatch since that's |
* what the program is compiled for. If there isn't, then it shouldn't |
* matter because no program is actually being run. However, the hardware |
* gets angry if we don't enable at least one dispatch mode, so just enable |
* 16-pixel dispatch unconditionally. |
*/ |
dw4 |= GEN7_PS_16_DISPATCH_ENABLE; |
if (brw->is_haswell) |
dw4 |= SET_FIELD(1, HSW_PS_SAMPLE_MASK); /* 1 sample for now */ |
if (params->use_wm_prog) { |
dw2 |= 1 << GEN7_PS_SAMPLER_COUNT_SHIFT; /* Up to 4 samplers */ |
dw4 |= GEN7_PS_PUSH_CONSTANT_ENABLE; |
dw5 |= prog_data->first_curbe_grf << GEN7_PS_DISPATCH_START_GRF_SHIFT_0; |
} |
switch (params->fast_clear_op) { |
case GEN7_FAST_CLEAR_OP_FAST_CLEAR: |
dw4 |= GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE; |
break; |
case GEN7_FAST_CLEAR_OP_RESOLVE: |
dw4 |= GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE; |
break; |
default: |
break; |
} |
BEGIN_BATCH(8); |
OUT_BATCH(_3DSTATE_PS << 16 | (8 - 2)); |
OUT_BATCH(params->use_wm_prog ? prog_offset : 0); |
OUT_BATCH(dw2); |
OUT_BATCH(0); |
OUT_BATCH(dw4); |
OUT_BATCH(dw5); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
static void |
gen7_blorp_emit_binding_table_pointers_ps(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t wm_bind_bo_offset) |
{ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_PS << 16 | (2 - 2)); |
OUT_BATCH(wm_bind_bo_offset); |
ADVANCE_BATCH(); |
} |
static void |
gen7_blorp_emit_sampler_state_pointers_ps(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t sampler_offset) |
{ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_SAMPLER_STATE_POINTERS_PS << 16 | (2 - 2)); |
OUT_BATCH(sampler_offset); |
ADVANCE_BATCH(); |
} |
static void |
gen7_blorp_emit_constant_ps(struct brw_context *brw, |
const brw_blorp_params *params, |
uint32_t wm_push_const_offset) |
{ |
uint8_t mocs = brw->is_haswell ? GEN7_MOCS_L3 : 0; |
/* Make sure the push constants fill an exact integer number of |
* registers. |
*/ |
assert(sizeof(brw_blorp_wm_push_constants) % 32 == 0); |
/* There must be at least one register worth of push constant data. */ |
assert(BRW_BLORP_NUM_PUSH_CONST_REGS > 0); |
/* Enable push constant buffer 0. */ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_PS << 16 | |
(7 - 2)); |
OUT_BATCH(BRW_BLORP_NUM_PUSH_CONST_REGS); |
OUT_BATCH(0); |
OUT_BATCH(wm_push_const_offset | mocs); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
static void |
gen7_blorp_emit_constant_ps_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_PS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
static void |
gen7_blorp_emit_depth_stencil_config(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
struct gl_context *ctx = &brw->ctx; |
uint32_t draw_x = params->depth.x_offset; |
uint32_t draw_y = params->depth.y_offset; |
uint32_t tile_mask_x, tile_mask_y; |
uint8_t mocs = brw->is_haswell ? GEN7_MOCS_L3 : 0; |
brw_get_depthstencil_tile_masks(params->depth.mt, |
params->depth.level, |
params->depth.layer, |
NULL, |
&tile_mask_x, &tile_mask_y); |
/* 3DSTATE_DEPTH_BUFFER */ |
{ |
uint32_t tile_x = draw_x & tile_mask_x; |
uint32_t tile_y = draw_y & tile_mask_y; |
uint32_t offset = |
intel_region_get_aligned_offset(params->depth.mt->region, |
draw_x & ~tile_mask_x, |
draw_y & ~tile_mask_y, false); |
/* According to the Sandy Bridge PRM, volume 2 part 1, pp326-327 |
* (3DSTATE_DEPTH_BUFFER dw5), in the documentation for "Depth |
* Coordinate Offset X/Y": |
* |
* "The 3 LSBs of both offsets must be zero to ensure correct |
* alignment" |
* |
* We have no guarantee that tile_x and tile_y are correctly aligned, |
* since they are determined by the mipmap layout, which is only aligned |
* to multiples of 4. |
* |
* So, to avoid hanging the GPU, just smash the low order 3 bits of |
* tile_x and tile_y to 0. This is a temporary workaround until we come |
* up with a better solution. |
*/ |
WARN_ONCE((tile_x & 7) || (tile_y & 7), |
"Depth/stencil buffer needs alignment to 8-pixel boundaries.\n" |
"Truncating offset, bad rendering may occur.\n"); |
tile_x &= ~7; |
tile_y &= ~7; |
intel_emit_depth_stall_flushes(brw); |
BEGIN_BATCH(7); |
OUT_BATCH(GEN7_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2)); |
OUT_BATCH((params->depth.mt->region->pitch - 1) | |
params->depth_format << 18 | |
1 << 22 | /* hiz enable */ |
1 << 28 | /* depth write */ |
BRW_SURFACE_2D << 29); |
OUT_RELOC(params->depth.mt->region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
offset); |
OUT_BATCH((params->depth.width + tile_x - 1) << 4 | |
(params->depth.height + tile_y - 1) << 18); |
OUT_BATCH(mocs); |
OUT_BATCH(tile_x | |
tile_y << 16); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_HIER_DEPTH_BUFFER */ |
{ |
struct intel_region *hiz_region = params->depth.mt->hiz_mt->region; |
uint32_t hiz_offset = |
intel_region_get_aligned_offset(hiz_region, |
draw_x & ~tile_mask_x, |
(draw_y & ~tile_mask_y) / 2, false); |
BEGIN_BATCH(3); |
OUT_BATCH((GEN7_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2)); |
OUT_BATCH((mocs << 25) | |
(hiz_region->pitch - 1)); |
OUT_RELOC(hiz_region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
hiz_offset); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_STENCIL_BUFFER */ |
{ |
BEGIN_BATCH(3); |
OUT_BATCH((GEN7_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
} |
static void |
gen7_blorp_emit_depth_disable(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(7); |
OUT_BATCH(GEN7_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2)); |
OUT_BATCH(BRW_DEPTHFORMAT_D32_FLOAT << 18 | (BRW_SURFACE_NULL << 29)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* 3DSTATE_CLEAR_PARAMS |
* |
* From the Ivybridge PRM, Volume 2 Part 1, Section 11.5.5.4 |
* 3DSTATE_CLEAR_PARAMS: |
* 3DSTATE_CLEAR_PARAMS must always be programmed in the along |
* with the other Depth/Stencil state commands(i.e. 3DSTATE_DEPTH_BUFFER, |
* 3DSTATE_STENCIL_BUFFER, or 3DSTATE_HIER_DEPTH_BUFFER). |
*/ |
static void |
gen7_blorp_emit_clear_params(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(3); |
OUT_BATCH(GEN7_3DSTATE_CLEAR_PARAMS << 16 | (3 - 2)); |
OUT_BATCH(params->depth.mt ? params->depth.mt->depth_clear_value : 0); |
OUT_BATCH(GEN7_DEPTH_CLEAR_VALID); |
ADVANCE_BATCH(); |
} |
/* 3DPRIMITIVE */ |
static void |
gen7_blorp_emit_primitive(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
BEGIN_BATCH(7); |
OUT_BATCH(CMD_3D_PRIM << 16 | (7 - 2)); |
OUT_BATCH(GEN7_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL | |
_3DPRIM_RECTLIST); |
OUT_BATCH(3); /* vertex count per instance */ |
OUT_BATCH(0); |
OUT_BATCH(1); /* instance count */ |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/** |
* \copydoc gen6_blorp_exec() |
*/ |
void |
gen7_blorp_exec(struct brw_context *brw, |
const brw_blorp_params *params) |
{ |
brw_blorp_prog_data *prog_data = NULL; |
uint32_t cc_blend_state_offset = 0; |
uint32_t cc_state_offset = 0; |
uint32_t depthstencil_offset; |
uint32_t wm_push_const_offset = 0; |
uint32_t wm_bind_bo_offset = 0; |
uint32_t sampler_offset = 0; |
uint32_t prog_offset = params->get_wm_prog(brw, &prog_data); |
gen6_blorp_emit_batch_head(brw, params); |
gen6_emit_3dstate_multisample(brw, params->num_samples); |
gen6_emit_3dstate_sample_mask(brw, params->num_samples, 1.0, false, ~0u); |
gen6_blorp_emit_state_base_address(brw, params); |
gen6_blorp_emit_vertices(brw, params); |
gen7_blorp_emit_urb_config(brw, params); |
if (params->use_wm_prog) { |
cc_blend_state_offset = gen6_blorp_emit_blend_state(brw, params); |
cc_state_offset = gen6_blorp_emit_cc_state(brw, params); |
gen7_blorp_emit_blend_state_pointer(brw, params, cc_blend_state_offset); |
gen7_blorp_emit_cc_state_pointer(brw, params, cc_state_offset); |
} |
depthstencil_offset = gen6_blorp_emit_depth_stencil_state(brw, params); |
gen7_blorp_emit_depth_stencil_state_pointers(brw, params, |
depthstencil_offset); |
if (params->use_wm_prog) { |
uint32_t wm_surf_offset_renderbuffer; |
uint32_t wm_surf_offset_texture = 0; |
wm_push_const_offset = gen6_blorp_emit_wm_constants(brw, params); |
intel_miptree_used_for_rendering(params->dst.mt); |
wm_surf_offset_renderbuffer = |
gen7_blorp_emit_surface_state(brw, params, ¶ms->dst, |
I915_GEM_DOMAIN_RENDER, |
I915_GEM_DOMAIN_RENDER, |
true /* is_render_target */); |
if (params->src.mt) { |
wm_surf_offset_texture = |
gen7_blorp_emit_surface_state(brw, params, ¶ms->src, |
I915_GEM_DOMAIN_SAMPLER, 0, |
false /* is_render_target */); |
} |
wm_bind_bo_offset = |
gen6_blorp_emit_binding_table(brw, params, |
wm_surf_offset_renderbuffer, |
wm_surf_offset_texture); |
sampler_offset = gen7_blorp_emit_sampler_state(brw, params); |
} |
gen7_blorp_emit_vs_disable(brw, params); |
gen7_blorp_emit_hs_disable(brw, params); |
gen7_blorp_emit_te_disable(brw, params); |
gen7_blorp_emit_ds_disable(brw, params); |
gen7_blorp_emit_gs_disable(brw, params); |
gen7_blorp_emit_streamout_disable(brw, params); |
gen6_blorp_emit_clip_disable(brw, params); |
gen7_blorp_emit_sf_config(brw, params); |
gen7_blorp_emit_wm_config(brw, params, prog_data); |
if (params->use_wm_prog) { |
gen7_blorp_emit_binding_table_pointers_ps(brw, params, |
wm_bind_bo_offset); |
gen7_blorp_emit_sampler_state_pointers_ps(brw, params, sampler_offset); |
gen7_blorp_emit_constant_ps(brw, params, wm_push_const_offset); |
} else { |
gen7_blorp_emit_constant_ps_disable(brw, params); |
} |
gen7_blorp_emit_ps_config(brw, params, prog_offset, prog_data); |
gen7_blorp_emit_cc_viewport(brw, params); |
if (params->depth.mt) |
gen7_blorp_emit_depth_stencil_config(brw, params); |
else |
gen7_blorp_emit_depth_disable(brw, params); |
gen7_blorp_emit_clear_params(brw, params); |
gen6_blorp_emit_drawing_rectangle(brw, params); |
gen7_blorp_emit_primitive(brw, params); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_blorp.h |
---|
0,0 → 1,41 |
/* |
* Copyright © 2011 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. |
*/ |
#pragma once |
#include <stdint.h> |
#ifdef __cplusplus |
extern "C" { |
#endif |
struct intel_mipmap_tree; |
#ifdef __cplusplus |
} |
void |
gen7_blorp_exec(struct brw_context *brw, |
const brw_blorp_params *params); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_clip_state.c |
---|
0,0 → 1,137 |
/* |
* Copyright © 2011 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 "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_util.h" |
#include "intel_batchbuffer.h" |
#include "main/fbobject.h" |
static void |
upload_clip_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
uint32_t dw1 = 0, dw2 = 0; |
/* _NEW_BUFFERS */ |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
bool render_to_fbo = _mesa_is_user_fbo(fb); |
/* BRW_NEW_META_IN_PROGRESS */ |
if (!brw->meta_in_progress) |
dw1 |= GEN6_CLIP_STATISTICS_ENABLE; |
/* CACHE_NEW_WM_PROG */ |
if (brw->wm.prog_data->barycentric_interp_modes & |
BRW_WM_NONPERSPECTIVE_BARYCENTRIC_BITS) { |
dw2 |= GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE; |
} |
dw1 |= GEN7_CLIP_EARLY_CULL; |
/* _NEW_POLYGON */ |
if ((ctx->Polygon.FrontFace == GL_CCW) ^ render_to_fbo) |
dw1 |= GEN7_CLIP_WINDING_CCW; |
if (ctx->Polygon.CullFlag) { |
switch (ctx->Polygon.CullFaceMode) { |
case GL_FRONT: |
dw1 |= GEN7_CLIP_CULLMODE_FRONT; |
break; |
case GL_BACK: |
dw1 |= GEN7_CLIP_CULLMODE_BACK; |
break; |
case GL_FRONT_AND_BACK: |
dw1 |= GEN7_CLIP_CULLMODE_BOTH; |
break; |
default: |
assert(!"Should not get here: invalid CullFlag"); |
break; |
} |
} else { |
dw1 |= GEN7_CLIP_CULLMODE_NONE; |
} |
/* _NEW_TRANSFORM */ |
if (!ctx->Transform.DepthClamp) |
dw2 |= GEN6_CLIP_Z_TEST; |
/* _NEW_LIGHT */ |
if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION) { |
dw2 |= |
(0 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | |
(1 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | |
(0 << GEN6_CLIP_LINE_PROVOKE_SHIFT); |
} else { |
dw2 |= |
(2 << GEN6_CLIP_TRI_PROVOKE_SHIFT) | |
(2 << GEN6_CLIP_TRIFAN_PROVOKE_SHIFT) | |
(1 << GEN6_CLIP_LINE_PROVOKE_SHIFT); |
} |
/* _NEW_TRANSFORM */ |
dw2 |= (ctx->Transform.ClipPlanesEnabled << |
GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT); |
if (ctx->Viewport.X == 0 && |
ctx->Viewport.Y == 0 && |
ctx->Viewport.Width == fb->Width && |
ctx->Viewport.Height == fb->Height) { |
dw2 |= GEN6_CLIP_GB_TEST; |
} |
/* BRW_NEW_RASTERIZER_DISCARD */ |
if (ctx->RasterDiscard) { |
dw2 |= GEN6_CLIP_MODE_REJECT_ALL; |
perf_debug("Rasterizer discard is currently implemented via the clipper; " |
"using the SOL unit may be faster."); |
} |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); |
OUT_BATCH(dw1); |
OUT_BATCH(GEN6_CLIP_ENABLE | |
GEN6_CLIP_API_OGL | |
GEN6_CLIP_MODE_NORMAL | |
GEN6_CLIP_XY_TEST | |
dw2); |
OUT_BATCH(U_FIXED(0.125, 3) << GEN6_CLIP_MIN_POINT_WIDTH_SHIFT | |
U_FIXED(255.875, 3) << GEN6_CLIP_MAX_POINT_WIDTH_SHIFT | |
GEN6_CLIP_FORCE_ZERO_RTAINDEX); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen7_clip_state = { |
.dirty = { |
.mesa = (_NEW_BUFFERS | |
_NEW_POLYGON | |
_NEW_LIGHT | |
_NEW_TRANSFORM), |
.brw = BRW_NEW_CONTEXT | |
BRW_NEW_META_IN_PROGRESS | |
BRW_NEW_RASTERIZER_DISCARD, |
.cache = CACHE_NEW_WM_PROG |
}, |
.emit = upload_clip_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_disable.c |
---|
0,0 → 1,132 |
/* |
* Copyright © 2011 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 "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "intel_batchbuffer.h" |
static void |
disable_stages(struct brw_context *brw) |
{ |
assert(!brw->gs.prog_active); |
/* Disable the Geometry Shader (GS) Unit */ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_GS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_GS << 16 | (7 - 2)); |
OUT_BATCH(0); /* prog_bo */ |
OUT_BATCH((0 << GEN6_GS_SAMPLER_COUNT_SHIFT) | |
(0 << GEN6_GS_BINDING_TABLE_ENTRY_COUNT_SHIFT)); |
OUT_BATCH(0); /* scratch space base offset */ |
OUT_BATCH((1 << GEN6_GS_DISPATCH_START_GRF_SHIFT) | |
(0 << GEN6_GS_URB_READ_LENGTH_SHIFT) | |
GEN7_GS_INCLUDE_VERTEX_HANDLES | |
(0 << GEN6_GS_URB_ENTRY_READ_OFFSET_SHIFT)); |
OUT_BATCH((0 << GEN6_GS_MAX_THREADS_SHIFT) | |
GEN6_GS_STATISTICS_ENABLE); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_GS << 16 | (2 - 2)); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
/* Disable the HS Unit */ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_HS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_HS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_HS << 16 | (2 - 2)); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
/* Disable the TE */ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_TE << 16 | (4 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
/* Disable the DS Unit */ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_DS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(6); |
OUT_BATCH(_3DSTATE_DS << 16 | (6 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_DS << 16 | (2 - 2)); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen7_disable_stages = { |
.dirty = { |
.mesa = 0, |
.brw = BRW_NEW_CONTEXT, |
.cache = 0, |
}, |
.emit = disable_stages, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_misc_state.c |
---|
0,0 → 1,138 |
/* |
* Copyright © 2011 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 "intel_batchbuffer.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_fbo.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
void |
gen7_emit_depth_stencil_hiz(struct brw_context *brw, |
struct intel_mipmap_tree *depth_mt, |
uint32_t depth_offset, uint32_t depthbuffer_format, |
uint32_t depth_surface_type, |
struct intel_mipmap_tree *stencil_mt, |
bool hiz, bool separate_stencil, |
uint32_t width, uint32_t height, |
uint32_t tile_x, uint32_t tile_y) |
{ |
struct gl_context *ctx = &brw->ctx; |
uint8_t mocs = brw->is_haswell ? GEN7_MOCS_L3 : 0; |
intel_emit_depth_stall_flushes(brw); |
/* _NEW_DEPTH, _NEW_STENCIL, _NEW_BUFFERS */ |
BEGIN_BATCH(7); |
OUT_BATCH(GEN7_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2)); |
OUT_BATCH((depth_mt ? depth_mt->region->pitch - 1 : 0) | |
(depthbuffer_format << 18) | |
((hiz ? 1 : 0) << 22) | |
((stencil_mt != NULL && ctx->Stencil._WriteEnabled) << 27) | |
((ctx->Depth.Mask != 0) << 28) | |
(depth_surface_type << 29)); |
if (depth_mt) { |
OUT_RELOC(depth_mt->region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
depth_offset); |
} else { |
OUT_BATCH(0); |
} |
OUT_BATCH(((width + tile_x - 1) << 4) | |
((height + tile_y - 1) << 18)); |
OUT_BATCH(mocs); |
OUT_BATCH(tile_x | (tile_y << 16)); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
if (!hiz) { |
BEGIN_BATCH(3); |
OUT_BATCH(GEN7_3DSTATE_HIER_DEPTH_BUFFER << 16 | (3 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} else { |
struct intel_mipmap_tree *hiz_mt = depth_mt->hiz_mt; |
BEGIN_BATCH(3); |
OUT_BATCH(GEN7_3DSTATE_HIER_DEPTH_BUFFER << 16 | (3 - 2)); |
OUT_BATCH((mocs << 25) | |
(hiz_mt->region->pitch - 1)); |
OUT_RELOC(hiz_mt->region->bo, |
I915_GEM_DOMAIN_RENDER, |
I915_GEM_DOMAIN_RENDER, |
brw->depthstencil.hiz_offset); |
ADVANCE_BATCH(); |
} |
if (stencil_mt == NULL) { |
BEGIN_BATCH(3); |
OUT_BATCH(GEN7_3DSTATE_STENCIL_BUFFER << 16 | (3 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} else { |
const int enabled = brw->is_haswell ? HSW_STENCIL_ENABLED : 0; |
BEGIN_BATCH(3); |
OUT_BATCH(GEN7_3DSTATE_STENCIL_BUFFER << 16 | (3 - 2)); |
/* The stencil buffer has quirky pitch requirements. From the |
* Sandybridge PRM, Volume 2 Part 1, page 329 (3DSTATE_STENCIL_BUFFER |
* dword 1 bits 16:0 - Surface Pitch): |
* |
* The pitch must be set to 2x the value computed based on width, as |
* the stencil buffer is stored with two rows interleaved. |
* |
* While the Ivybridge PRM lacks this comment, the BSpec contains the |
* same text, and experiments indicate that this is necessary. |
*/ |
OUT_BATCH(enabled | |
mocs << 25 | |
(2 * stencil_mt->region->pitch - 1)); |
OUT_RELOC(stencil_mt->region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
brw->depthstencil.stencil_offset); |
ADVANCE_BATCH(); |
} |
BEGIN_BATCH(3); |
OUT_BATCH(GEN7_3DSTATE_CLEAR_PARAMS << 16 | (3 - 2)); |
OUT_BATCH(depth_mt ? depth_mt->depth_clear_value : 0); |
OUT_BATCH(1); |
ADVANCE_BATCH(); |
} |
/** |
* \see brw_context.state.depth_region |
*/ |
const struct brw_tracked_state gen7_depthbuffer = { |
.dirty = { |
.mesa = (_NEW_BUFFERS | _NEW_DEPTH | _NEW_STENCIL), |
.brw = BRW_NEW_BATCH, |
.cache = 0, |
}, |
.emit = brw_emit_depthbuffer, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_sampler_state.c |
---|
0,0 → 1,229 |
/* |
* Copyright © 2011 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 "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "intel_batchbuffer.h" |
#include "main/macros.h" |
#include "main/samplerobj.h" |
/** |
* Sets the sampler state for a single unit. |
*/ |
static void |
gen7_update_sampler_state(struct brw_context *brw, int unit, int ss_index, |
struct gen7_sampler_state *sampler) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
struct gl_texture_object *texObj = texUnit->_Current; |
struct gl_sampler_object *gl_sampler = _mesa_get_samplerobj(ctx, unit); |
bool using_nearest = false; |
/* These don't use samplers at all. */ |
if (texObj->Target == GL_TEXTURE_BUFFER) |
return; |
switch (gl_sampler->MinFilter) { |
case GL_NEAREST: |
sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; |
sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; |
using_nearest = true; |
break; |
case GL_LINEAR: |
sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; |
sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; |
break; |
case GL_NEAREST_MIPMAP_NEAREST: |
sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; |
sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST; |
break; |
case GL_LINEAR_MIPMAP_NEAREST: |
sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; |
sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST; |
break; |
case GL_NEAREST_MIPMAP_LINEAR: |
sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; |
sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR; |
break; |
case GL_LINEAR_MIPMAP_LINEAR: |
sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; |
sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR; |
break; |
default: |
break; |
} |
/* Set Anisotropy: */ |
if (gl_sampler->MaxAnisotropy > 1.0) { |
sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC; |
sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC; |
if (gl_sampler->MaxAnisotropy > 2.0) { |
sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2, |
BRW_ANISORATIO_16); |
} |
} |
else { |
switch (gl_sampler->MagFilter) { |
case GL_NEAREST: |
sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST; |
using_nearest = true; |
break; |
case GL_LINEAR: |
sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; |
break; |
default: |
break; |
} |
} |
sampler->ss3.r_wrap_mode = translate_wrap_mode(gl_sampler->WrapR, |
using_nearest); |
sampler->ss3.s_wrap_mode = translate_wrap_mode(gl_sampler->WrapS, |
using_nearest); |
sampler->ss3.t_wrap_mode = translate_wrap_mode(gl_sampler->WrapT, |
using_nearest); |
/* Cube-maps on 965 and later must use the same wrap mode for all 3 |
* coordinate dimensions. Futher, only CUBE and CLAMP are valid. |
*/ |
if (texObj->Target == GL_TEXTURE_CUBE_MAP || |
texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) { |
if (ctx->Texture.CubeMapSeamless && |
(gl_sampler->MinFilter != GL_NEAREST || |
gl_sampler->MagFilter != GL_NEAREST)) { |
sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CUBE; |
sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CUBE; |
sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CUBE; |
} else { |
sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP; |
} |
} else if (texObj->Target == GL_TEXTURE_1D) { |
/* There's a bug in 1D texture sampling - it actually pays |
* attention to the wrap_t value, though it should not. |
* Override the wrap_t value here to GL_REPEAT to keep |
* any nonexistent border pixels from floating in. |
*/ |
sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_WRAP; |
} |
/* Set shadow function: */ |
if (gl_sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) { |
/* Shadowing is "enabled" by emitting a particular sampler |
* message (sample_c). So need to recompile WM program when |
* shadow comparison is enabled on each/any texture unit. |
*/ |
sampler->ss1.shadow_function = |
intel_translate_shadow_compare_func(gl_sampler->CompareFunc); |
} |
/* Set LOD bias: */ |
sampler->ss0.lod_bias = S_FIXED(CLAMP(texUnit->LodBias + |
gl_sampler->LodBias, -16, 15), 8); |
sampler->ss0.lod_preclamp = 1; /* OpenGL mode */ |
sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */ |
/* Set BaseMipLevel, MaxLOD, MinLOD: |
* |
* XXX: I don't think that using firstLevel, lastLevel works, |
* because we always setup the surface state as if firstLevel == |
* level zero. Probably have to subtract firstLevel from each of |
* these: |
*/ |
sampler->ss0.base_level = U_FIXED(0, 1); |
sampler->ss1.max_lod = U_FIXED(CLAMP(gl_sampler->MaxLod, 0, 13), 8); |
sampler->ss1.min_lod = U_FIXED(CLAMP(gl_sampler->MinLod, 0, 13), 8); |
/* The sampler can handle non-normalized texture rectangle coordinates |
* natively |
*/ |
if (texObj->Target == GL_TEXTURE_RECTANGLE) { |
sampler->ss3.non_normalized_coord = 1; |
} |
upload_default_color(brw, gl_sampler, unit, ss_index); |
sampler->ss2.default_color_pointer = brw->wm.sdc_offset[ss_index] >> 5; |
if (sampler->ss0.min_filter != BRW_MAPFILTER_NEAREST) |
sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN | |
BRW_ADDRESS_ROUNDING_ENABLE_V_MIN | |
BRW_ADDRESS_ROUNDING_ENABLE_R_MIN; |
if (sampler->ss0.mag_filter != BRW_MAPFILTER_NEAREST) |
sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG | |
BRW_ADDRESS_ROUNDING_ENABLE_V_MAG | |
BRW_ADDRESS_ROUNDING_ENABLE_R_MAG; |
} |
static void |
gen7_upload_samplers(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gen7_sampler_state *samplers; |
/* BRW_NEW_VERTEX_PROGRAM and BRW_NEW_FRAGMENT_PROGRAM */ |
struct gl_program *vs = (struct gl_program *) brw->vertex_program; |
struct gl_program *fs = (struct gl_program *) brw->fragment_program; |
GLbitfield SamplersUsed = vs->SamplersUsed | fs->SamplersUsed; |
brw->sampler.count = _mesa_fls(SamplersUsed); |
if (brw->sampler.count == 0) |
return; |
samplers = brw_state_batch(brw, AUB_TRACE_SAMPLER_STATE, |
brw->sampler.count * sizeof(*samplers), |
32, &brw->sampler.offset); |
memset(samplers, 0, brw->sampler.count * sizeof(*samplers)); |
for (unsigned s = 0; s < brw->sampler.count; s++) { |
if (SamplersUsed & (1 << s)) { |
const unsigned unit = (fs->SamplersUsed & (1 << s)) ? |
fs->SamplerUnits[s] : vs->SamplerUnits[s]; |
if (ctx->Texture.Unit[unit]._ReallyEnabled) |
gen7_update_sampler_state(brw, unit, s, &samplers[s]); |
} |
} |
brw->state.dirty.cache |= CACHE_NEW_SAMPLER; |
} |
const struct brw_tracked_state gen7_samplers = { |
.dirty = { |
.mesa = _NEW_TEXTURE, |
.brw = BRW_NEW_BATCH | |
BRW_NEW_VERTEX_PROGRAM | |
BRW_NEW_FRAGMENT_PROGRAM, |
.cache = 0 |
}, |
.emit = gen7_upload_samplers, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_sf_state.c |
---|
0,0 → 1,316 |
/* |
* Copyright © 2011 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 "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_util.h" |
#include "main/macros.h" |
#include "main/fbobject.h" |
#include "intel_batchbuffer.h" |
static void |
upload_sbe_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_FRAGMENT_PROGRAM */ |
uint32_t num_outputs = _mesa_bitcount_64(brw->fragment_program->Base.InputsRead); |
/* _NEW_LIGHT */ |
bool shade_model_flat = ctx->Light.ShadeModel == GL_FLAT; |
uint32_t dw1, dw10, dw11; |
int i; |
int attr = 0, input_index = 0; |
int urb_entry_read_offset = 1; |
uint16_t attr_overrides[VARYING_SLOT_MAX]; |
/* _NEW_BUFFERS */ |
bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
uint32_t point_sprite_origin; |
/* FINISHME: Attribute Swizzle Control Mode? */ |
dw1 = GEN7_SBE_SWIZZLE_ENABLE | num_outputs << GEN7_SBE_NUM_OUTPUTS_SHIFT; |
/* _NEW_POINT |
* |
* Window coordinates in an FBO are inverted, which means point |
* sprite origin must be inverted. |
*/ |
if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) { |
point_sprite_origin = GEN6_SF_POINT_SPRITE_LOWERLEFT; |
} else { |
point_sprite_origin = GEN6_SF_POINT_SPRITE_UPPERLEFT; |
} |
dw1 |= point_sprite_origin; |
dw10 = 0; |
dw11 = 0; |
/* Create the mapping from the FS inputs we produce to the VS outputs |
* they source from. |
*/ |
uint32_t max_source_attr = 0; |
for (; attr < VARYING_SLOT_MAX; attr++) { |
enum glsl_interp_qualifier interp_qualifier = |
brw->fragment_program->InterpQualifier[attr]; |
bool is_gl_Color = attr == VARYING_SLOT_COL0 || attr == VARYING_SLOT_COL1; |
if (!(brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(attr))) |
continue; |
if (ctx->Point.PointSprite && |
attr >= VARYING_SLOT_TEX0 && attr <= VARYING_SLOT_TEX7 && |
ctx->Point.CoordReplace[attr - VARYING_SLOT_TEX0]) { |
dw10 |= (1 << input_index); |
} |
if (attr == VARYING_SLOT_PNTC) |
dw10 |= (1 << input_index); |
/* flat shading */ |
if (interp_qualifier == INTERP_QUALIFIER_FLAT || |
(shade_model_flat && is_gl_Color && |
interp_qualifier == INTERP_QUALIFIER_NONE)) |
dw11 |= (1 << input_index); |
/* The hardware can only do the overrides on 16 overrides at a |
* time, and the other up to 16 have to be lined up so that the |
* input index = the output index. We'll need to do some |
* tweaking to make sure that's the case. |
*/ |
assert(input_index < 16 || attr == input_index); |
/* BRW_NEW_VUE_MAP_GEOM_OUT | _NEW_LIGHT | _NEW_PROGRAM */ |
attr_overrides[input_index++] = |
get_attr_override(&brw->vue_map_geom_out, |
urb_entry_read_offset, attr, |
ctx->VertexProgram._TwoSideEnabled, |
&max_source_attr); |
} |
/* From the Ivy Bridge PRM, Volume 2, Part 1, documentation for |
* 3DSTATE_SBE DWord 1 bits 15:11, "Vertex URB Entry Read Length": |
* |
* "This field should be set to the minimum length required to read the |
* maximum source attribute. The maximum source attribute is indicated |
* by the maximum value of the enabled Attribute # Source Attribute if |
* Attribute Swizzle Enable is set, Number of Output Attributes-1 if |
* enable is not set. |
* |
* read_length = ceiling((max_source_attr + 1) / 2)" |
*/ |
uint32_t urb_entry_read_length = ALIGN(max_source_attr + 1, 2) / 2; |
dw1 |= urb_entry_read_length << GEN7_SBE_URB_ENTRY_READ_LENGTH_SHIFT | |
urb_entry_read_offset << GEN7_SBE_URB_ENTRY_READ_OFFSET_SHIFT; |
for (; input_index < VARYING_SLOT_MAX; input_index++) |
attr_overrides[input_index] = 0; |
BEGIN_BATCH(14); |
OUT_BATCH(_3DSTATE_SBE << 16 | (14 - 2)); |
OUT_BATCH(dw1); |
/* Output dwords 2 through 9 */ |
for (i = 0; i < 8; i++) { |
OUT_BATCH(attr_overrides[i * 2] | attr_overrides[i * 2 + 1] << 16); |
} |
OUT_BATCH(dw10); /* point sprite texcoord bitmask */ |
OUT_BATCH(dw11); /* constant interp bitmask */ |
OUT_BATCH(0); /* wrapshortest enables 0-7 */ |
OUT_BATCH(0); /* wrapshortest enables 8-15 */ |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen7_sbe_state = { |
.dirty = { |
.mesa = (_NEW_BUFFERS | |
_NEW_LIGHT | |
_NEW_POINT | |
_NEW_PROGRAM), |
.brw = (BRW_NEW_CONTEXT | |
BRW_NEW_FRAGMENT_PROGRAM | |
BRW_NEW_VUE_MAP_GEOM_OUT) |
}, |
.emit = upload_sbe_state, |
}; |
static void |
upload_sf_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
uint32_t dw1, dw2, dw3; |
float point_size; |
/* _NEW_BUFFERS */ |
bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
bool multisampled_fbo = ctx->DrawBuffer->Visual.samples > 1; |
dw1 = GEN6_SF_STATISTICS_ENABLE | |
GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; |
/* _NEW_BUFFERS */ |
dw1 |= (brw_depthbuffer_format(brw) << GEN7_SF_DEPTH_BUFFER_SURFACE_FORMAT_SHIFT); |
/* _NEW_POLYGON */ |
if ((ctx->Polygon.FrontFace == GL_CCW) ^ render_to_fbo) |
dw1 |= GEN6_SF_WINDING_CCW; |
if (ctx->Polygon.OffsetFill) |
dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID; |
if (ctx->Polygon.OffsetLine) |
dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME; |
if (ctx->Polygon.OffsetPoint) |
dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT; |
switch (ctx->Polygon.FrontMode) { |
case GL_FILL: |
dw1 |= GEN6_SF_FRONT_SOLID; |
break; |
case GL_LINE: |
dw1 |= GEN6_SF_FRONT_WIREFRAME; |
break; |
case GL_POINT: |
dw1 |= GEN6_SF_FRONT_POINT; |
break; |
default: |
assert(0); |
break; |
} |
switch (ctx->Polygon.BackMode) { |
case GL_FILL: |
dw1 |= GEN6_SF_BACK_SOLID; |
break; |
case GL_LINE: |
dw1 |= GEN6_SF_BACK_WIREFRAME; |
break; |
case GL_POINT: |
dw1 |= GEN6_SF_BACK_POINT; |
break; |
default: |
assert(0); |
break; |
} |
dw2 = 0; |
if (ctx->Polygon.CullFlag) { |
switch (ctx->Polygon.CullFaceMode) { |
case GL_FRONT: |
dw2 |= GEN6_SF_CULL_FRONT; |
break; |
case GL_BACK: |
dw2 |= GEN6_SF_CULL_BACK; |
break; |
case GL_FRONT_AND_BACK: |
dw2 |= GEN6_SF_CULL_BOTH; |
break; |
default: |
assert(0); |
break; |
} |
} else { |
dw2 |= GEN6_SF_CULL_NONE; |
} |
/* _NEW_SCISSOR */ |
if (ctx->Scissor.Enabled) |
dw2 |= GEN6_SF_SCISSOR_ENABLE; |
/* _NEW_LINE */ |
{ |
uint32_t line_width_u3_7 = U_FIXED(CLAMP(ctx->Line.Width, 0.0, 7.99), 7); |
/* TODO: line width of 0 is not allowed when MSAA enabled */ |
if (line_width_u3_7 == 0) |
line_width_u3_7 = 1; |
dw2 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT; |
} |
if (ctx->Line.SmoothFlag) { |
dw2 |= GEN6_SF_LINE_AA_ENABLE; |
dw2 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; |
} |
if (ctx->Line.StippleFlag && brw->is_haswell) { |
dw2 |= HSW_SF_LINE_STIPPLE_ENABLE; |
} |
/* _NEW_MULTISAMPLE */ |
if (multisampled_fbo && ctx->Multisample.Enabled) |
dw2 |= GEN6_SF_MSRAST_ON_PATTERN; |
/* FINISHME: Last Pixel Enable? Vertex Sub Pixel Precision Select? |
*/ |
dw3 = GEN6_SF_LINE_AA_MODE_TRUE; |
/* _NEW_PROGRAM | _NEW_POINT */ |
if (!(ctx->VertexProgram.PointSizeEnabled || ctx->Point._Attenuated)) |
dw3 |= GEN6_SF_USE_STATE_POINT_WIDTH; |
/* Clamp to ARB_point_parameters user limits */ |
point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); |
/* Clamp to the hardware limits and convert to fixed point */ |
dw3 |= U_FIXED(CLAMP(point_size, 0.125, 255.875), 3); |
/* _NEW_LIGHT */ |
if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { |
dw3 |= |
(2 << GEN6_SF_TRI_PROVOKE_SHIFT) | |
(2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | |
(1 << GEN6_SF_LINE_PROVOKE_SHIFT); |
} else { |
dw3 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); |
} |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_SF << 16 | (7 - 2)); |
OUT_BATCH(dw1); |
OUT_BATCH(dw2); |
OUT_BATCH(dw3); |
OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */ |
OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */ |
OUT_BATCH_F(0.0); /* XXX: global depth offset clamp */ |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen7_sf_state = { |
.dirty = { |
.mesa = (_NEW_LIGHT | |
_NEW_PROGRAM | |
_NEW_POLYGON | |
_NEW_LINE | |
_NEW_SCISSOR | |
_NEW_BUFFERS | |
_NEW_POINT | |
_NEW_MULTISAMPLE), |
.brw = BRW_NEW_CONTEXT, |
.cache = CACHE_NEW_VS_PROG |
}, |
.emit = upload_sf_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_sol_state.c |
---|
0,0 → 1,275 |
/* |
* Copyright © 2011 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. |
*/ |
/** |
* @file gen7_sol_state.c |
* |
* Controls the stream output logic (SOL) stage of the gen7 hardware, which is |
* used to implement GL_EXT_transform_feedback. |
*/ |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "intel_batchbuffer.h" |
#include "intel_buffer_objects.h" |
#include "main/transformfeedback.h" |
static void |
upload_3dstate_so_buffers(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_VERTEX_PROGRAM */ |
const struct gl_shader_program *vs_prog = |
ctx->Shader.CurrentVertexProgram; |
const struct gl_transform_feedback_info *linked_xfb_info = |
&vs_prog->LinkedTransformFeedback; |
/* BRW_NEW_TRANSFORM_FEEDBACK */ |
struct gl_transform_feedback_object *xfb_obj = |
ctx->TransformFeedback.CurrentObject; |
int i; |
/* Set up the up to 4 output buffers. These are the ranges defined in the |
* gl_transform_feedback_object. |
*/ |
for (i = 0; i < 4; i++) { |
struct intel_buffer_object *bufferobj = |
intel_buffer_object(xfb_obj->Buffers[i]); |
drm_intel_bo *bo; |
uint32_t start, end; |
uint32_t stride; |
if (!xfb_obj->Buffers[i]) { |
/* The pitch of 0 in this command indicates that the buffer is |
* unbound and won't be written to. |
*/ |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_SO_BUFFER << 16 | (4 - 2)); |
OUT_BATCH((i << SO_BUFFER_INDEX_SHIFT)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
continue; |
} |
bo = intel_bufferobj_buffer(brw, bufferobj, INTEL_WRITE_PART); |
stride = linked_xfb_info->BufferStride[i] * 4; |
start = xfb_obj->Offset[i]; |
assert(start % 4 == 0); |
end = ALIGN(start + xfb_obj->Size[i], 4); |
assert(end <= bo->size); |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_SO_BUFFER << 16 | (4 - 2)); |
OUT_BATCH((i << SO_BUFFER_INDEX_SHIFT) | stride); |
OUT_RELOC(bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, start); |
OUT_RELOC(bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, end); |
ADVANCE_BATCH(); |
} |
} |
/** |
* Outputs the 3DSTATE_SO_DECL_LIST command. |
* |
* The data output is a series of 64-bit entries containing a SO_DECL per |
* stream. We only have one stream of rendering coming out of the GS unit, so |
* we only emit stream 0 (low 16 bits) SO_DECLs. |
*/ |
static void |
upload_3dstate_so_decl_list(struct brw_context *brw, |
const struct brw_vue_map *vue_map) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_VERTEX_PROGRAM */ |
const struct gl_shader_program *vs_prog = |
ctx->Shader.CurrentVertexProgram; |
/* BRW_NEW_TRANSFORM_FEEDBACK */ |
const struct gl_transform_feedback_info *linked_xfb_info = |
&vs_prog->LinkedTransformFeedback; |
int i; |
uint16_t so_decl[128]; |
int buffer_mask = 0; |
int next_offset[4] = {0, 0, 0, 0}; |
STATIC_ASSERT(ARRAY_SIZE(so_decl) >= MAX_PROGRAM_OUTPUTS); |
/* Construct the list of SO_DECLs to be emitted. The formatting of the |
* command is feels strange -- each dword pair contains a SO_DECL per stream. |
*/ |
for (i = 0; i < linked_xfb_info->NumOutputs; i++) { |
int buffer = linked_xfb_info->Outputs[i].OutputBuffer; |
uint16_t decl = 0; |
int varying = linked_xfb_info->Outputs[i].OutputRegister; |
unsigned component_mask = |
(1 << linked_xfb_info->Outputs[i].NumComponents) - 1; |
/* gl_PointSize is stored in VARYING_SLOT_PSIZ.w. */ |
if (varying == VARYING_SLOT_PSIZ) { |
assert(linked_xfb_info->Outputs[i].NumComponents == 1); |
component_mask <<= 3; |
} else { |
component_mask <<= linked_xfb_info->Outputs[i].ComponentOffset; |
} |
buffer_mask |= 1 << buffer; |
decl |= buffer << SO_DECL_OUTPUT_BUFFER_SLOT_SHIFT; |
decl |= vue_map->varying_to_slot[varying] << |
SO_DECL_REGISTER_INDEX_SHIFT; |
decl |= component_mask << SO_DECL_COMPONENT_MASK_SHIFT; |
/* This assert should be true until GL_ARB_transform_feedback_instanced |
* is added and we start using the hole flag. |
*/ |
assert(linked_xfb_info->Outputs[i].DstOffset == next_offset[buffer]); |
next_offset[buffer] += linked_xfb_info->Outputs[i].NumComponents; |
so_decl[i] = decl; |
} |
BEGIN_BATCH(linked_xfb_info->NumOutputs * 2 + 3); |
OUT_BATCH(_3DSTATE_SO_DECL_LIST << 16 | |
(linked_xfb_info->NumOutputs * 2 + 1)); |
OUT_BATCH((buffer_mask << SO_STREAM_TO_BUFFER_SELECTS_0_SHIFT) | |
(0 << SO_STREAM_TO_BUFFER_SELECTS_1_SHIFT) | |
(0 << SO_STREAM_TO_BUFFER_SELECTS_2_SHIFT) | |
(0 << SO_STREAM_TO_BUFFER_SELECTS_3_SHIFT)); |
OUT_BATCH((linked_xfb_info->NumOutputs << SO_NUM_ENTRIES_0_SHIFT) | |
(0 << SO_NUM_ENTRIES_1_SHIFT) | |
(0 << SO_NUM_ENTRIES_2_SHIFT) | |
(0 << SO_NUM_ENTRIES_3_SHIFT)); |
for (i = 0; i < linked_xfb_info->NumOutputs; i++) { |
OUT_BATCH(so_decl[i]); |
OUT_BATCH(0); |
} |
ADVANCE_BATCH(); |
} |
static void |
upload_3dstate_streamout(struct brw_context *brw, bool active, |
const struct brw_vue_map *vue_map) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_TRANSFORM_FEEDBACK */ |
struct gl_transform_feedback_object *xfb_obj = |
ctx->TransformFeedback.CurrentObject; |
uint32_t dw1 = 0, dw2 = 0; |
int i; |
if (active) { |
int urb_entry_read_offset = 0; |
int urb_entry_read_length = (vue_map->num_slots + 1) / 2 - |
urb_entry_read_offset; |
dw1 |= SO_FUNCTION_ENABLE; |
dw1 |= SO_STATISTICS_ENABLE; |
/* _NEW_LIGHT */ |
if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) |
dw1 |= SO_REORDER_TRAILING; |
for (i = 0; i < 4; i++) { |
if (xfb_obj->Buffers[i]) { |
dw1 |= SO_BUFFER_ENABLE(i); |
} |
} |
/* We always read the whole vertex. This could be reduced at some |
* point by reading less and offsetting the register index in the |
* SO_DECLs. |
*/ |
dw2 |= urb_entry_read_offset << SO_STREAM_0_VERTEX_READ_OFFSET_SHIFT; |
dw2 |= (urb_entry_read_length - 1) << |
SO_STREAM_0_VERTEX_READ_LENGTH_SHIFT; |
} |
BEGIN_BATCH(3); |
OUT_BATCH(_3DSTATE_STREAMOUT << 16 | (3 - 2)); |
OUT_BATCH(dw1); |
OUT_BATCH(dw2); |
ADVANCE_BATCH(); |
} |
static void |
upload_sol_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* BRW_NEW_TRANSFORM_FEEDBACK */ |
bool active = _mesa_is_xfb_active_and_unpaused(ctx); |
if (active) { |
upload_3dstate_so_buffers(brw); |
/* BRW_NEW_VUE_MAP_GEOM_OUT */ |
upload_3dstate_so_decl_list(brw, &brw->vue_map_geom_out); |
} |
/* Finally, set up the SOL stage. This command must always follow updates to |
* the nonpipelined SOL state (3DSTATE_SO_BUFFER, 3DSTATE_SO_DECL_LIST) or |
* MMIO register updates (current performed by the kernel at each batch |
* emit). |
*/ |
upload_3dstate_streamout(brw, active, &brw->vue_map_geom_out); |
} |
const struct brw_tracked_state gen7_sol_state = { |
.dirty = { |
.mesa = (_NEW_LIGHT), |
.brw = (BRW_NEW_BATCH | |
BRW_NEW_VERTEX_PROGRAM | |
BRW_NEW_VUE_MAP_GEOM_OUT | |
BRW_NEW_TRANSFORM_FEEDBACK) |
}, |
.emit = upload_sol_state, |
}; |
void |
gen7_begin_transform_feedback(struct gl_context *ctx, GLenum mode, |
struct gl_transform_feedback_object *obj) |
{ |
struct brw_context *brw = brw_context(ctx); |
intel_batchbuffer_flush(brw); |
brw->batch.needs_sol_reset = true; |
} |
void |
gen7_end_transform_feedback(struct gl_context *ctx, |
struct gl_transform_feedback_object *obj) |
{ |
/* Because we have to rely on the kernel to reset our SO write offsets, and |
* we only get to do it once per batchbuffer, flush the batch after feedback |
* so another transform feedback can get the write offset reset it needs. |
* |
* This also covers any cache flushing required. |
*/ |
struct brw_context *brw = brw_context(ctx); |
intel_batchbuffer_flush(brw); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_urb.c |
---|
0,0 → 1,134 |
/* |
* Copyright © 2011 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 "main/macros.h" |
#include "intel_batchbuffer.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
/** |
* The following diagram shows how we partition the URB: |
* |
* 8kB 8kB Rest of the URB space |
* ____-____ ____-____ _________________-_________________ |
* / \ / \ / \ |
* +-------------------------------------------------------------+ |
* | VS Push | FS Push | VS | |
* | Constants | Constants | Handles | |
* +-------------------------------------------------------------+ |
* |
* Notably, push constants must be stored at the beginning of the URB |
* space, while entries can be stored anywhere. Ivybridge and Haswell |
* GT1/GT2 have a maximum constant buffer size of 16kB, while Haswell GT3 |
* doubles this (32kB). |
* |
* Currently we split the constant buffer space evenly between VS and FS. |
* This is probably not ideal, but simple. |
* |
* Ivybridge GT1 and Haswell GT1 have 128kB of URB space. |
* Ivybridge GT2 and Haswell GT2 have 256kB of URB space. |
* Haswell GT3 has 512kB of URB space. |
* |
* See "Volume 2a: 3D Pipeline," section 1.8, "Volume 1b: Configurations", |
* and the documentation for 3DSTATE_PUSH_CONSTANT_ALLOC_xS. |
*/ |
void |
gen7_allocate_push_constants(struct brw_context *brw) |
{ |
unsigned size = 8; |
if (brw->is_haswell && brw->gt == 3) |
size = 16; |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PUSH_CONSTANT_ALLOC_VS << 16 | (2 - 2)); |
OUT_BATCH(size); |
OUT_BATCH(_3DSTATE_PUSH_CONSTANT_ALLOC_PS << 16 | (2 - 2)); |
OUT_BATCH(size | size << GEN7_PUSH_CONSTANT_BUFFER_OFFSET_SHIFT); |
ADVANCE_BATCH(); |
} |
static void |
gen7_upload_urb(struct brw_context *brw) |
{ |
const int push_size_kB = brw->is_haswell && brw->gt == 3 ? 32 : 16; |
/* Total space for entries is URB size - 16kB for push constants */ |
int handle_region_size = (brw->urb.size - push_size_kB) * 1024; /* bytes */ |
/* CACHE_NEW_VS_PROG */ |
unsigned vs_size = MAX2(brw->vs.prog_data->base.urb_entry_size, 1); |
int nr_vs_entries = handle_region_size / (vs_size * 64); |
if (nr_vs_entries > brw->urb.max_vs_entries) |
nr_vs_entries = brw->urb.max_vs_entries; |
/* According to volume 2a, nr_vs_entries must be a multiple of 8. */ |
brw->urb.nr_vs_entries = ROUND_DOWN_TO(nr_vs_entries, 8); |
/* URB Starting Addresses are specified in multiples of 8kB. */ |
brw->urb.vs_start = push_size_kB / 8; /* skip over push constants */ |
assert(brw->urb.nr_vs_entries % 8 == 0); |
assert(brw->urb.nr_gs_entries % 8 == 0); |
/* GS requirement */ |
assert(!brw->gs.prog_active); |
gen7_emit_vs_workaround_flush(brw); |
gen7_emit_urb_state(brw, brw->urb.nr_vs_entries, vs_size, brw->urb.vs_start); |
} |
void |
gen7_emit_urb_state(struct brw_context *brw, GLuint nr_vs_entries, |
GLuint vs_size, GLuint vs_start) |
{ |
BEGIN_BATCH(8); |
OUT_BATCH(_3DSTATE_URB_VS << 16 | (2 - 2)); |
OUT_BATCH(nr_vs_entries | |
((vs_size - 1) << GEN7_URB_ENTRY_SIZE_SHIFT) | |
(vs_start << GEN7_URB_STARTING_ADDRESS_SHIFT)); |
/* Allocate the GS, HS, and DS zero space - we don't use them. */ |
OUT_BATCH(_3DSTATE_URB_GS << 16 | (2 - 2)); |
OUT_BATCH((0 << GEN7_URB_ENTRY_SIZE_SHIFT) | |
(vs_start << GEN7_URB_STARTING_ADDRESS_SHIFT)); |
OUT_BATCH(_3DSTATE_URB_HS << 16 | (2 - 2)); |
OUT_BATCH((0 << GEN7_URB_ENTRY_SIZE_SHIFT) | |
(vs_start << GEN7_URB_STARTING_ADDRESS_SHIFT)); |
OUT_BATCH(_3DSTATE_URB_DS << 16 | (2 - 2)); |
OUT_BATCH((0 << GEN7_URB_ENTRY_SIZE_SHIFT) | |
(vs_start << GEN7_URB_STARTING_ADDRESS_SHIFT)); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen7_urb = { |
.dirty = { |
.mesa = 0, |
.brw = BRW_NEW_CONTEXT, |
.cache = (CACHE_NEW_VS_PROG | CACHE_NEW_GS_PROG), |
}, |
.emit = gen7_upload_urb, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_viewport_state.c |
---|
0,0 → 1,114 |
/* |
* Copyright © 2011 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 "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "intel_batchbuffer.h" |
#include "main/fbobject.h" |
static void |
gen7_upload_sf_clip_viewport(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
const GLfloat depth_scale = 1.0F / ctx->DrawBuffer->_DepthMaxF; |
GLfloat y_scale, y_bias; |
const bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
const GLfloat *v = ctx->Viewport._WindowMap.m; |
struct gen7_sf_clip_viewport *vp; |
vp = brw_state_batch(brw, AUB_TRACE_SF_VP_STATE, |
sizeof(*vp), 64, &brw->sf.vp_offset); |
/* Also assign to clip.vp_offset in case something uses it. */ |
brw->clip.vp_offset = brw->sf.vp_offset; |
/* According to the "Vertex X,Y Clamping and Quantization" section of the |
* Strips and Fans documentation, objects must not have a screen-space |
* extents of over 8192 pixels, or they may be mis-rasterized. The maximum |
* screen space coordinates of a small object may larger, but we have no |
* way to enforce the object size other than through clipping. |
* |
* If you're surprised that we set clip to -gbx to +gbx and it seems like |
* we'll end up with 16384 wide, note that for a 8192-wide render target, |
* we'll end up with a normal (-1, 1) clip volume that just covers the |
* drawable. |
*/ |
const float maximum_guardband_extent = 8192; |
float gbx = maximum_guardband_extent / (float) ctx->Viewport.Width; |
float gby = maximum_guardband_extent / (float) ctx->Viewport.Height; |
vp->guardband.xmin = -gbx; |
vp->guardband.xmax = gbx; |
vp->guardband.ymin = -gby; |
vp->guardband.ymax = gby; |
/* _NEW_BUFFERS */ |
if (render_to_fbo) { |
y_scale = 1.0; |
y_bias = 0; |
} else { |
y_scale = -1.0; |
y_bias = ctx->DrawBuffer->Height; |
} |
/* _NEW_VIEWPORT */ |
vp->viewport.m00 = v[MAT_SX]; |
vp->viewport.m11 = v[MAT_SY] * y_scale; |
vp->viewport.m22 = v[MAT_SZ] * depth_scale; |
vp->viewport.m30 = v[MAT_TX]; |
vp->viewport.m31 = v[MAT_TY] * y_scale + y_bias; |
vp->viewport.m32 = v[MAT_TZ] * depth_scale; |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CL << 16 | (2 - 2)); |
OUT_BATCH(brw->sf.vp_offset); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen7_sf_clip_viewport = { |
.dirty = { |
.mesa = _NEW_VIEWPORT | _NEW_BUFFERS, |
.brw = BRW_NEW_BATCH, |
.cache = 0, |
}, |
.emit = gen7_upload_sf_clip_viewport, |
}; |
/* ----------------------------------------------------- */ |
static void upload_cc_viewport_state_pointer(struct brw_context *brw) |
{ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_VIEWPORT_STATE_POINTERS_CC << 16 | (2 - 2)); |
OUT_BATCH(brw->cc.vp_offset); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen7_cc_viewport_state_pointer = { |
.dirty = { |
.mesa = 0, |
.brw = BRW_NEW_BATCH, |
.cache = CACHE_NEW_CC_VP |
}, |
.emit = upload_cc_viewport_state_pointer, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_vs_state.c |
---|
0,0 → 1,122 |
/* |
* Copyright © 2011 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 "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_util.h" |
#include "program/prog_parameter.h" |
#include "program/prog_statevars.h" |
#include "intel_batchbuffer.h" |
static void |
upload_vs_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
uint32_t floating_point_mode = 0; |
const int max_threads_shift = brw->is_haswell ? |
HSW_VS_MAX_THREADS_SHIFT : GEN6_VS_MAX_THREADS_SHIFT; |
gen7_emit_vs_workaround_flush(brw); |
/* BRW_NEW_VS_BINDING_TABLE */ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_VS << 16 | (2 - 2)); |
OUT_BATCH(brw->vs.bind_bo_offset); |
ADVANCE_BATCH(); |
/* CACHE_NEW_SAMPLER */ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_SAMPLER_STATE_POINTERS_VS << 16 | (2 - 2)); |
OUT_BATCH(brw->sampler.offset); |
ADVANCE_BATCH(); |
if (brw->vs.push_const_size == 0) { |
/* Disable the push constant buffers. */ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} else { |
uint8_t mocs = brw->is_haswell ? GEN7_MOCS_L3 : 0; |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 | (7 - 2)); |
OUT_BATCH(brw->vs.push_const_size); |
OUT_BATCH(0); |
/* Pointer to the VS constant buffer. Covered by the set of |
* state flags from gen6_prepare_wm_contants |
*/ |
OUT_BATCH(brw->vs.push_const_offset | mocs); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
/* Use ALT floating point mode for ARB vertex programs, because they |
* require 0^0 == 1. |
*/ |
if (ctx->Shader.CurrentVertexProgram == NULL) |
floating_point_mode = GEN6_VS_FLOATING_POINT_MODE_ALT; |
BEGIN_BATCH(6); |
OUT_BATCH(_3DSTATE_VS << 16 | (6 - 2)); |
OUT_BATCH(brw->vs.prog_offset); |
OUT_BATCH(floating_point_mode | |
((ALIGN(brw->sampler.count, 4)/4) << GEN6_VS_SAMPLER_COUNT_SHIFT)); |
if (brw->vs.prog_data->base.total_scratch) { |
OUT_RELOC(brw->vs.scratch_bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
ffs(brw->vs.prog_data->base.total_scratch) - 11); |
} else { |
OUT_BATCH(0); |
} |
OUT_BATCH((1 << GEN6_VS_DISPATCH_START_GRF_SHIFT) | |
(brw->vs.prog_data->base.urb_read_length << GEN6_VS_URB_READ_LENGTH_SHIFT) | |
(0 << GEN6_VS_URB_ENTRY_READ_OFFSET_SHIFT)); |
OUT_BATCH(((brw->max_vs_threads - 1) << max_threads_shift) | |
GEN6_VS_STATISTICS_ENABLE | |
GEN6_VS_ENABLE); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen7_vs_state = { |
.dirty = { |
.mesa = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS, |
.brw = (BRW_NEW_CONTEXT | |
BRW_NEW_VERTEX_PROGRAM | |
BRW_NEW_VS_BINDING_TABLE | |
BRW_NEW_BATCH), |
.cache = CACHE_NEW_VS_PROG | CACHE_NEW_SAMPLER |
}, |
.emit = upload_vs_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_wm_state.c |
---|
0,0 → 1,237 |
/* |
* Copyright © 2011 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 <stdbool.h> |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_util.h" |
#include "brw_wm.h" |
#include "program/prog_parameter.h" |
#include "program/prog_statevars.h" |
#include "intel_batchbuffer.h" |
static void |
upload_wm_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
const struct brw_fragment_program *fp = |
brw_fragment_program_const(brw->fragment_program); |
bool writes_depth = false; |
uint32_t dw1, dw2; |
/* _NEW_BUFFERS */ |
bool multisampled_fbo = ctx->DrawBuffer->Visual.samples > 1; |
dw1 = dw2 = 0; |
dw1 |= GEN7_WM_STATISTICS_ENABLE; |
dw1 |= GEN7_WM_LINE_AA_WIDTH_1_0; |
dw1 |= GEN7_WM_LINE_END_CAP_AA_WIDTH_0_5; |
/* _NEW_LINE */ |
if (ctx->Line.StippleFlag) |
dw1 |= GEN7_WM_LINE_STIPPLE_ENABLE; |
/* _NEW_POLYGON */ |
if (ctx->Polygon.StippleFlag) |
dw1 |= GEN7_WM_POLYGON_STIPPLE_ENABLE; |
/* BRW_NEW_FRAGMENT_PROGRAM */ |
if (fp->program.Base.InputsRead & VARYING_BIT_POS) |
dw1 |= GEN7_WM_USES_SOURCE_DEPTH | GEN7_WM_USES_SOURCE_W; |
if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { |
writes_depth = true; |
dw1 |= GEN7_WM_PSCDEPTH_ON; |
} |
/* CACHE_NEW_WM_PROG */ |
dw1 |= brw->wm.prog_data->barycentric_interp_modes << |
GEN7_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT; |
/* _NEW_COLOR, _NEW_MULTISAMPLE */ |
if (fp->program.UsesKill || ctx->Color.AlphaEnabled || |
ctx->Multisample.SampleAlphaToCoverage) |
dw1 |= GEN7_WM_KILL_ENABLE; |
/* _NEW_BUFFERS */ |
if (brw_color_buffer_write_enabled(brw) || writes_depth || |
dw1 & GEN7_WM_KILL_ENABLE) { |
dw1 |= GEN7_WM_DISPATCH_ENABLE; |
} |
if (multisampled_fbo) { |
/* _NEW_MULTISAMPLE */ |
if (ctx->Multisample.Enabled) |
dw1 |= GEN7_WM_MSRAST_ON_PATTERN; |
else |
dw1 |= GEN7_WM_MSRAST_OFF_PIXEL; |
dw2 |= GEN7_WM_MSDISPMODE_PERPIXEL; |
} else { |
dw1 |= GEN7_WM_MSRAST_OFF_PIXEL; |
dw2 |= GEN7_WM_MSDISPMODE_PERSAMPLE; |
} |
BEGIN_BATCH(3); |
OUT_BATCH(_3DSTATE_WM << 16 | (3 - 2)); |
OUT_BATCH(dw1); |
OUT_BATCH(dw2); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen7_wm_state = { |
.dirty = { |
.mesa = (_NEW_LINE | _NEW_POLYGON | |
_NEW_COLOR | _NEW_BUFFERS | |
_NEW_MULTISAMPLE), |
.brw = (BRW_NEW_FRAGMENT_PROGRAM | |
BRW_NEW_BATCH), |
.cache = CACHE_NEW_WM_PROG, |
}, |
.emit = upload_wm_state, |
}; |
static void |
upload_ps_state(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
uint32_t dw2, dw4, dw5; |
const int max_threads_shift = brw->is_haswell ? |
HSW_PS_MAX_THREADS_SHIFT : IVB_PS_MAX_THREADS_SHIFT; |
/* BRW_NEW_PS_BINDING_TABLE */ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_PS << 16 | (2 - 2)); |
OUT_BATCH(brw->wm.bind_bo_offset); |
ADVANCE_BATCH(); |
/* CACHE_NEW_SAMPLER */ |
BEGIN_BATCH(2); |
OUT_BATCH(_3DSTATE_SAMPLER_STATE_POINTERS_PS << 16 | (2 - 2)); |
OUT_BATCH(brw->sampler.offset); |
ADVANCE_BATCH(); |
/* CACHE_NEW_WM_PROG */ |
if (brw->wm.prog_data->nr_params == 0) { |
/* Disable the push constant buffers. */ |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_PS << 16 | (7 - 2)); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} else { |
uint8_t mocs = brw->is_haswell ? GEN7_MOCS_L3 : 0; |
BEGIN_BATCH(7); |
OUT_BATCH(_3DSTATE_CONSTANT_PS << 16 | (7 - 2)); |
OUT_BATCH(ALIGN(brw->wm.prog_data->nr_params, |
brw->wm.prog_data->dispatch_width) / 8); |
OUT_BATCH(0); |
/* Pointer to the WM constant buffer. Covered by the set of |
* state flags from gen6_upload_wm_push_constants. |
*/ |
OUT_BATCH(brw->wm.push_const_offset | mocs); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} |
dw2 = dw4 = dw5 = 0; |
/* CACHE_NEW_SAMPLER */ |
dw2 |= (ALIGN(brw->sampler.count, 4) / 4) << GEN7_PS_SAMPLER_COUNT_SHIFT; |
/* Use ALT floating point mode for ARB fragment programs, because they |
* require 0^0 == 1. Even though _CurrentFragmentProgram is used for |
* rendering, CurrentFragmentProgram is used for this check to |
* differentiate between the GLSL and non-GLSL cases. |
*/ |
if (ctx->Shader.CurrentFragmentProgram == NULL) |
dw2 |= GEN7_PS_FLOATING_POINT_MODE_ALT; |
if (brw->is_haswell) |
dw4 |= SET_FIELD(1, HSW_PS_SAMPLE_MASK); /* 1 sample for now */ |
dw4 |= (brw->max_wm_threads - 1) << max_threads_shift; |
/* CACHE_NEW_WM_PROG */ |
if (brw->wm.prog_data->nr_params > 0) |
dw4 |= GEN7_PS_PUSH_CONSTANT_ENABLE; |
/* CACHE_NEW_WM_PROG | _NEW_COLOR |
* |
* The hardware wedges if you have this bit set but don't turn on any dual |
* source blend factors. |
*/ |
if (brw->wm.prog_data->dual_src_blend && |
(ctx->Color.BlendEnabled & 1) && |
ctx->Color.Blend[0]._UsesDualSrc) { |
dw4 |= GEN7_PS_DUAL_SOURCE_BLEND_ENABLE; |
} |
/* BRW_NEW_FRAGMENT_PROGRAM */ |
if (brw->fragment_program->Base.InputsRead != 0) |
dw4 |= GEN7_PS_ATTRIBUTE_ENABLE; |
dw4 |= GEN7_PS_8_DISPATCH_ENABLE; |
if (brw->wm.prog_data->prog_offset_16) |
dw4 |= GEN7_PS_16_DISPATCH_ENABLE; |
dw5 |= (brw->wm.prog_data->first_curbe_grf << |
GEN7_PS_DISPATCH_START_GRF_SHIFT_0); |
dw5 |= (brw->wm.prog_data->first_curbe_grf_16 << |
GEN7_PS_DISPATCH_START_GRF_SHIFT_2); |
BEGIN_BATCH(8); |
OUT_BATCH(_3DSTATE_PS << 16 | (8 - 2)); |
OUT_BATCH(brw->wm.prog_offset); |
OUT_BATCH(dw2); |
if (brw->wm.prog_data->total_scratch) { |
OUT_RELOC(brw->wm.scratch_bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
ffs(brw->wm.prog_data->total_scratch) - 11); |
} else { |
OUT_BATCH(0); |
} |
OUT_BATCH(dw4); |
OUT_BATCH(dw5); |
OUT_BATCH(0); /* kernel 1 pointer */ |
OUT_BATCH(brw->wm.prog_offset + brw->wm.prog_data->prog_offset_16); |
ADVANCE_BATCH(); |
} |
const struct brw_tracked_state gen7_ps_state = { |
.dirty = { |
.mesa = (_NEW_PROGRAM_CONSTANTS | |
_NEW_COLOR), |
.brw = (BRW_NEW_FRAGMENT_PROGRAM | |
BRW_NEW_PS_BINDING_TABLE | |
BRW_NEW_BATCH), |
.cache = (CACHE_NEW_SAMPLER | |
CACHE_NEW_WM_PROG) |
}, |
.emit = upload_ps_state, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c |
---|
0,0 → 1,622 |
/* |
* Copyright © 2011 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 "main/mtypes.h" |
#include "main/blend.h" |
#include "main/samplerobj.h" |
#include "main/texformat.h" |
#include "program/prog_parameter.h" |
#include "intel_mipmap_tree.h" |
#include "intel_batchbuffer.h" |
#include "intel_tex.h" |
#include "intel_fbo.h" |
#include "intel_buffer_objects.h" |
#include "brw_context.h" |
#include "brw_state.h" |
#include "brw_defines.h" |
#include "brw_wm.h" |
/** |
* Convert an swizzle enumeration (i.e. SWIZZLE_X) to one of the Gen7.5+ |
* "Shader Channel Select" enumerations (i.e. HSW_SCS_RED) |
*/ |
static unsigned |
swizzle_to_scs(GLenum swizzle) |
{ |
switch (swizzle) { |
case SWIZZLE_X: |
return HSW_SCS_RED; |
case SWIZZLE_Y: |
return HSW_SCS_GREEN; |
case SWIZZLE_Z: |
return HSW_SCS_BLUE; |
case SWIZZLE_W: |
return HSW_SCS_ALPHA; |
case SWIZZLE_ZERO: |
return HSW_SCS_ZERO; |
case SWIZZLE_ONE: |
return HSW_SCS_ONE; |
} |
assert(!"Should not get here: invalid swizzle mode"); |
return HSW_SCS_ZERO; |
} |
uint32_t |
gen7_surface_tiling_mode(uint32_t tiling) |
{ |
switch (tiling) { |
case I915_TILING_X: |
return GEN7_SURFACE_TILING_X; |
case I915_TILING_Y: |
return GEN7_SURFACE_TILING_Y; |
default: |
return GEN7_SURFACE_TILING_NONE; |
} |
} |
uint32_t |
gen7_surface_msaa_bits(unsigned num_samples, enum intel_msaa_layout layout) |
{ |
uint32_t ss4 = 0; |
if (num_samples > 4) |
ss4 |= GEN7_SURFACE_MULTISAMPLECOUNT_8; |
else if (num_samples > 1) |
ss4 |= GEN7_SURFACE_MULTISAMPLECOUNT_4; |
else |
ss4 |= GEN7_SURFACE_MULTISAMPLECOUNT_1; |
if (layout == INTEL_MSAA_LAYOUT_IMS) |
ss4 |= GEN7_SURFACE_MSFMT_DEPTH_STENCIL; |
else |
ss4 |= GEN7_SURFACE_MSFMT_MSS; |
return ss4; |
} |
void |
gen7_set_surface_mcs_info(struct brw_context *brw, |
uint32_t *surf, |
uint32_t surf_offset, |
const struct intel_mipmap_tree *mcs_mt, |
bool is_render_target) |
{ |
/* From the Ivy Bridge PRM, Vol4 Part1 p76, "MCS Base Address": |
* |
* "The MCS surface must be stored as Tile Y." |
*/ |
assert(mcs_mt->region->tiling == I915_TILING_Y); |
/* Compute the pitch in units of tiles. To do this we need to divide the |
* pitch in bytes by 128, since a single Y-tile is 128 bytes wide. |
*/ |
unsigned pitch_tiles = mcs_mt->region->pitch / 128; |
/* The upper 20 bits of surface state DWORD 6 are the upper 20 bits of the |
* GPU address of the MCS buffer; the lower 12 bits contain other control |
* information. Since buffer addresses are always on 4k boundaries (and |
* thus have their lower 12 bits zero), we can use an ordinary reloc to do |
* the necessary address translation. |
*/ |
assert ((mcs_mt->region->bo->offset & 0xfff) == 0); |
surf[6] = GEN7_SURFACE_MCS_ENABLE | |
SET_FIELD(pitch_tiles - 1, GEN7_SURFACE_MCS_PITCH) | |
mcs_mt->region->bo->offset; |
drm_intel_bo_emit_reloc(brw->batch.bo, |
surf_offset + 6 * 4, |
mcs_mt->region->bo, |
surf[6] & 0xfff, |
is_render_target ? I915_GEM_DOMAIN_RENDER |
: I915_GEM_DOMAIN_SAMPLER, |
is_render_target ? I915_GEM_DOMAIN_RENDER : 0); |
} |
void |
gen7_check_surface_setup(uint32_t *surf, bool is_render_target) |
{ |
unsigned num_multisamples = surf[4] & INTEL_MASK(5, 3); |
unsigned multisampled_surface_storage_format = surf[4] & (1 << 6); |
unsigned surface_array_spacing = surf[0] & (1 << 10); |
bool is_multisampled = num_multisamples != GEN7_SURFACE_MULTISAMPLECOUNT_1; |
(void) surface_array_spacing; |
/* From the Ivybridge PRM, Volume 4 Part 1, page 66 (RENDER_SURFACE_STATE |
* dword 0 bit 10 "Surface Array Spacing" Programming Notes): |
* |
* If Multisampled Surface Storage Format is MSFMT_MSS and Number of |
* Multisamples is not MULTISAMPLECOUNT_1, this field must be set to |
* ARYSPC_LOD0. |
*/ |
if (multisampled_surface_storage_format == GEN7_SURFACE_MSFMT_MSS |
&& is_multisampled) |
assert(surface_array_spacing == GEN7_SURFACE_ARYSPC_LOD0); |
/* From the Ivybridge PRM, Volume 4 Part 1, page 72 (RENDER_SURFACE_STATE |
* dword 4 bit 6 "Multisampled Surface Storage" Programming Notes): |
* |
* All multisampled render target surfaces must have this field set to |
* MSFMT_MSS. |
* |
* But also: |
* |
* This field is ignored if Number of Multisamples is MULTISAMPLECOUNT_1. |
*/ |
if (is_render_target && is_multisampled) { |
assert(multisampled_surface_storage_format == GEN7_SURFACE_MSFMT_MSS); |
} |
/* From the Ivybridge PRM, Volume 4 Part 1, page 72 (RENDER_SURFACE_STATE |
* dword 4 bit 6 "Multisampled Surface Storage Format" Errata): |
* |
* If the surface’s Number of Multisamples is MULTISAMPLECOUNT_8, Width |
* is >= 8192 (meaning the actual surface width is >= 8193 pixels), this |
* field must be set to MSFMT_MSS. |
*/ |
uint32_t width = GET_FIELD(surf[2], GEN7_SURFACE_WIDTH) + 1; |
if (num_multisamples == GEN7_SURFACE_MULTISAMPLECOUNT_8 && width >= 8193) { |
assert(multisampled_surface_storage_format == GEN7_SURFACE_MSFMT_MSS); |
} |
/* From the Ivybridge PRM, Volume 4 Part 1, page 72 (RENDER_SURFACE_STATE |
* dword 4 bit 6 "Multisampled Surface Storage Format" Errata): |
* |
* If the surface’s Number of Multisamples is MULTISAMPLECOUNT_8, |
* ((Depth+1) * (Height+1)) is > 4,194,304, OR if the surface’s Number of |
* Multisamples is MULTISAMPLECOUNT_4, ((Depth+1) * (Height+1)) is > |
* 8,388,608, this field must be set to MSFMT_DEPTH_STENCIL.This field |
* must be set to MSFMT_DEPTH_STENCIL if Surface Format is one of the |
* following: I24X8_UNORM, L24X8_UNORM, A24X8_UNORM, or |
* R24_UNORM_X8_TYPELESS. |
* |
* But also (from the Programming Notes): |
* |
* This field is ignored if Number of Multisamples is MULTISAMPLECOUNT_1. |
*/ |
uint32_t depth = GET_FIELD(surf[3], BRW_SURFACE_DEPTH) + 1; |
uint32_t height = GET_FIELD(surf[2], GEN7_SURFACE_HEIGHT) + 1; |
if (num_multisamples == GEN7_SURFACE_MULTISAMPLECOUNT_8 && |
depth * height > 4194304) { |
assert(multisampled_surface_storage_format == |
GEN7_SURFACE_MSFMT_DEPTH_STENCIL); |
} |
if (num_multisamples == GEN7_SURFACE_MULTISAMPLECOUNT_4 && |
depth * height > 8388608) { |
assert(multisampled_surface_storage_format == |
GEN7_SURFACE_MSFMT_DEPTH_STENCIL); |
} |
if (is_multisampled) { |
switch (GET_FIELD(surf[0], BRW_SURFACE_FORMAT)) { |
case BRW_SURFACEFORMAT_I24X8_UNORM: |
case BRW_SURFACEFORMAT_L24X8_UNORM: |
case BRW_SURFACEFORMAT_A24X8_UNORM: |
case BRW_SURFACEFORMAT_R24_UNORM_X8_TYPELESS: |
assert(multisampled_surface_storage_format == |
GEN7_SURFACE_MSFMT_DEPTH_STENCIL); |
} |
} |
} |
static void |
gen7_update_buffer_texture_surface(struct gl_context *ctx, |
unsigned unit, |
uint32_t *binding_table, |
unsigned surf_index) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; |
struct intel_buffer_object *intel_obj = |
intel_buffer_object(tObj->BufferObject); |
drm_intel_bo *bo = intel_obj ? intel_obj->buffer : NULL; |
gl_format format = tObj->_BufferObjectFormat; |
uint32_t *surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, |
8 * 4, 32, &binding_table[surf_index]); |
memset(surf, 0, 8 * 4); |
uint32_t surface_format = brw_format_for_mesa_format(format); |
if (surface_format == 0 && format != MESA_FORMAT_RGBA_FLOAT32) { |
_mesa_problem(NULL, "bad format %s for texture buffer\n", |
_mesa_get_format_name(format)); |
} |
surf[0] = BRW_SURFACE_BUFFER << BRW_SURFACE_TYPE_SHIFT | |
surface_format << BRW_SURFACE_FORMAT_SHIFT | |
BRW_SURFACE_RC_READ_WRITE; |
if (bo) { |
surf[1] = bo->offset; /* reloc */ |
drm_intel_bo_emit_reloc(brw->batch.bo, |
binding_table[surf_index] + 4, |
bo, 0, |
I915_GEM_DOMAIN_SAMPLER, 0); |
int texel_size = _mesa_get_format_bytes(format); |
int w = intel_obj->Base.Size / texel_size; |
/* note that these differ from GEN6 */ |
surf[2] = SET_FIELD(w & 0x7f, GEN7_SURFACE_WIDTH) | /* bits 6:0 of size */ |
SET_FIELD((w >> 7) & 0x3fff, GEN7_SURFACE_HEIGHT); /* 20:7 */ |
surf[3] = SET_FIELD((w >> 21) & 0x3f, BRW_SURFACE_DEPTH) | /* bits 26:21 */ |
(texel_size - 1); |
} |
gen7_check_surface_setup(surf, false /* is_render_target */); |
} |
static void |
gen7_update_texture_surface(struct gl_context *ctx, |
unsigned unit, |
uint32_t *binding_table, |
unsigned surf_index) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; |
struct intel_texture_object *intelObj = intel_texture_object(tObj); |
struct intel_mipmap_tree *mt = intelObj->mt; |
struct gl_texture_image *firstImage = tObj->Image[0][tObj->BaseLevel]; |
struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); |
uint32_t tile_x, tile_y; |
uint8_t mocs = brw->is_haswell ? GEN7_MOCS_L3 : 0; |
if (tObj->Target == GL_TEXTURE_BUFFER) { |
gen7_update_buffer_texture_surface(ctx, unit, binding_table, surf_index); |
return; |
} |
uint32_t *surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, |
8 * 4, 32, &binding_table[surf_index]); |
memset(surf, 0, 8 * 4); |
uint32_t tex_format = translate_tex_format(brw, |
mt->format, |
tObj->DepthMode, |
sampler->sRGBDecode); |
surf[0] = translate_tex_target(tObj->Target) << BRW_SURFACE_TYPE_SHIFT | |
tex_format << BRW_SURFACE_FORMAT_SHIFT | |
gen7_surface_tiling_mode(mt->region->tiling) | |
BRW_SURFACE_CUBEFACE_ENABLES; |
if (mt->align_h == 4) |
surf[0] |= GEN7_SURFACE_VALIGN_4; |
if (mt->align_w == 8) |
surf[0] |= GEN7_SURFACE_HALIGN_8; |
if (mt->logical_depth0 > 1 && tObj->Target != GL_TEXTURE_3D) |
surf[0] |= GEN7_SURFACE_IS_ARRAY; |
if (mt->array_spacing_lod0) |
surf[0] |= GEN7_SURFACE_ARYSPC_LOD0; |
surf[1] = mt->region->bo->offset + mt->offset; /* reloc */ |
surf[1] += intel_miptree_get_tile_offsets(intelObj->mt, firstImage->Level, 0, |
&tile_x, &tile_y); |
surf[2] = SET_FIELD(mt->logical_width0 - 1, GEN7_SURFACE_WIDTH) | |
SET_FIELD(mt->logical_height0 - 1, GEN7_SURFACE_HEIGHT); |
surf[3] = SET_FIELD(mt->logical_depth0 - 1, BRW_SURFACE_DEPTH) | |
((intelObj->mt->region->pitch) - 1); |
surf[4] = gen7_surface_msaa_bits(mt->num_samples, mt->msaa_layout); |
assert(brw->has_surface_tile_offset || (tile_x == 0 && tile_y == 0)); |
/* Note that the low bits of these fields are missing, so |
* there's the possibility of getting in trouble. |
*/ |
surf[5] = ((tile_x / 4) << BRW_SURFACE_X_OFFSET_SHIFT | |
(tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT | |
SET_FIELD(mocs, GEN7_SURFACE_MOCS) | |
/* mip count */ |
(intelObj->_MaxLevel - tObj->BaseLevel)); |
if (brw->is_haswell) { |
/* Handling GL_ALPHA as a surface format override breaks 1.30+ style |
* texturing functions that return a float, as our code generation always |
* selects the .x channel (which would always be 0). |
*/ |
const bool alpha_depth = tObj->DepthMode == GL_ALPHA && |
(firstImage->_BaseFormat == GL_DEPTH_COMPONENT || |
firstImage->_BaseFormat == GL_DEPTH_STENCIL); |
const int swizzle = unlikely(alpha_depth) |
? SWIZZLE_XYZW : brw_get_texture_swizzle(ctx, tObj); |
surf[7] = |
SET_FIELD(swizzle_to_scs(GET_SWZ(swizzle, 0)), GEN7_SURFACE_SCS_R) | |
SET_FIELD(swizzle_to_scs(GET_SWZ(swizzle, 1)), GEN7_SURFACE_SCS_G) | |
SET_FIELD(swizzle_to_scs(GET_SWZ(swizzle, 2)), GEN7_SURFACE_SCS_B) | |
SET_FIELD(swizzle_to_scs(GET_SWZ(swizzle, 3)), GEN7_SURFACE_SCS_A); |
} |
/* Emit relocation to surface contents */ |
drm_intel_bo_emit_reloc(brw->batch.bo, |
binding_table[surf_index] + 4, |
intelObj->mt->region->bo, |
surf[1] - intelObj->mt->region->bo->offset, |
I915_GEM_DOMAIN_SAMPLER, 0); |
gen7_check_surface_setup(surf, false /* is_render_target */); |
} |
/** |
* Create the constant buffer surface. Vertex/fragment shader constants will |
* be read from this buffer with Data Port Read instructions/messages. |
*/ |
static void |
gen7_create_constant_surface(struct brw_context *brw, |
drm_intel_bo *bo, |
uint32_t offset, |
uint32_t size, |
uint32_t *out_offset, |
bool dword_pitch) |
{ |
uint32_t stride = dword_pitch ? 4 : 16; |
uint32_t elements = ALIGN(size, stride) / stride; |
const GLint w = elements - 1; |
uint32_t *surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, |
8 * 4, 32, out_offset); |
memset(surf, 0, 8 * 4); |
surf[0] = BRW_SURFACE_BUFFER << BRW_SURFACE_TYPE_SHIFT | |
BRW_SURFACEFORMAT_R32G32B32A32_FLOAT << BRW_SURFACE_FORMAT_SHIFT | |
BRW_SURFACE_RC_READ_WRITE; |
assert(bo); |
surf[1] = bo->offset + offset; /* reloc */ |
/* note that these differ from GEN6 */ |
surf[2] = SET_FIELD(w & 0x7f, GEN7_SURFACE_WIDTH) | |
SET_FIELD((w >> 7) & 0x3fff, GEN7_SURFACE_HEIGHT); |
surf[3] = SET_FIELD((w >> 21) & 0x3f, BRW_SURFACE_DEPTH) | |
(stride - 1); |
if (brw->is_haswell) { |
surf[7] = SET_FIELD(HSW_SCS_RED, GEN7_SURFACE_SCS_R) | |
SET_FIELD(HSW_SCS_GREEN, GEN7_SURFACE_SCS_G) | |
SET_FIELD(HSW_SCS_BLUE, GEN7_SURFACE_SCS_B) | |
SET_FIELD(HSW_SCS_ALPHA, GEN7_SURFACE_SCS_A); |
} |
drm_intel_bo_emit_reloc(brw->batch.bo, |
*out_offset + 4, |
bo, offset, |
I915_GEM_DOMAIN_SAMPLER, 0); |
gen7_check_surface_setup(surf, false /* is_render_target */); |
} |
/** |
* Create a surface for shader time. |
*/ |
void |
gen7_create_shader_time_surface(struct brw_context *brw, uint32_t *out_offset) |
{ |
const int w = brw->shader_time.bo->size - 1; |
uint32_t *surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, |
8 * 4, 32, out_offset); |
memset(surf, 0, 8 * 4); |
surf[0] = BRW_SURFACE_BUFFER << BRW_SURFACE_TYPE_SHIFT | |
BRW_SURFACEFORMAT_RAW << BRW_SURFACE_FORMAT_SHIFT | |
BRW_SURFACE_RC_READ_WRITE; |
surf[1] = brw->shader_time.bo->offset; /* reloc */ |
/* note that these differ from GEN6 */ |
surf[2] = SET_FIELD(w & 0x7f, GEN7_SURFACE_WIDTH) | |
SET_FIELD((w >> 7) & 0x3fff, GEN7_SURFACE_HEIGHT); |
surf[3] = SET_FIELD((w >> 21) & 0x3f, BRW_SURFACE_DEPTH); |
/* Unlike texture or renderbuffer surfaces, we only do untyped operations |
* on the shader_time surface, so there's no need to set HSW channel |
* overrides. |
*/ |
drm_intel_bo_emit_reloc(brw->batch.bo, |
*out_offset + 4, |
brw->shader_time.bo, 0, |
I915_GEM_DOMAIN_SAMPLER, 0); |
gen7_check_surface_setup(surf, false /* is_render_target */); |
} |
static void |
gen7_update_null_renderbuffer_surface(struct brw_context *brw, unsigned unit) |
{ |
/* From the Ivy bridge PRM, Vol4 Part1 p62 (Surface Type: Programming |
* Notes): |
* |
* A null surface is used in instances where an actual surface is not |
* bound. When a write message is generated to a null surface, no |
* actual surface is written to. When a read message (including any |
* sampling engine message) is generated to a null surface, the result |
* is all zeros. Note that a null surface type is allowed to be used |
* with all messages, even if it is not specificially indicated as |
* supported. All of the remaining fields in surface state are ignored |
* for null surfaces, with the following exceptions: Width, Height, |
* Depth, LOD, and Render Target View Extent fields must match the |
* depth buffer’s corresponding state for all render target surfaces, |
* including null. |
*/ |
struct gl_context *ctx = &brw->ctx; |
/* _NEW_BUFFERS */ |
const struct gl_framebuffer *fb = ctx->DrawBuffer; |
uint32_t *surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, |
8 * 4, 32, &brw->wm.surf_offset[unit]); |
memset(surf, 0, 8 * 4); |
/* From the Ivybridge PRM, Volume 4, Part 1, page 65, |
* Tiled Surface: Programming Notes: |
* "If Surface Type is SURFTYPE_NULL, this field must be TRUE." |
*/ |
surf[0] = BRW_SURFACE_NULL << BRW_SURFACE_TYPE_SHIFT | |
BRW_SURFACEFORMAT_B8G8R8A8_UNORM << BRW_SURFACE_FORMAT_SHIFT | |
GEN7_SURFACE_TILING_Y; |
surf[2] = SET_FIELD(fb->Width - 1, GEN7_SURFACE_WIDTH) | |
SET_FIELD(fb->Height - 1, GEN7_SURFACE_HEIGHT); |
gen7_check_surface_setup(surf, true /* is_render_target */); |
} |
/** |
* Sets up a surface state structure to point at the given region. |
* While it is only used for the front/back buffer currently, it should be |
* usable for further buffers when doing ARB_draw_buffer support. |
*/ |
static void |
gen7_update_renderbuffer_surface(struct brw_context *brw, |
struct gl_renderbuffer *rb, |
bool layered, |
unsigned int unit) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
struct intel_region *region = irb->mt->region; |
uint32_t format; |
/* _NEW_BUFFERS */ |
gl_format rb_format = _mesa_get_render_format(ctx, intel_rb_format(irb)); |
uint32_t surftype; |
bool is_array = false; |
int depth = MAX2(rb->Depth, 1); |
int min_array_element; |
uint8_t mocs = brw->is_haswell ? GEN7_MOCS_L3 : 0; |
GLenum gl_target = rb->TexImage ? |
rb->TexImage->TexObject->Target : GL_TEXTURE_2D; |
uint32_t *surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, |
8 * 4, 32, &brw->wm.surf_offset[unit]); |
memset(surf, 0, 8 * 4); |
intel_miptree_used_for_rendering(irb->mt); |
/* Render targets can't use IMS layout */ |
assert(irb->mt->msaa_layout != INTEL_MSAA_LAYOUT_IMS); |
assert(brw_render_target_supported(brw, rb)); |
format = brw->render_target_format[rb_format]; |
if (unlikely(!brw->format_supported_as_render_target[rb_format])) { |
_mesa_problem(ctx, "%s: renderbuffer format %s unsupported\n", |
__FUNCTION__, _mesa_get_format_name(rb_format)); |
} |
switch (gl_target) { |
case GL_TEXTURE_CUBE_MAP_ARRAY: |
case GL_TEXTURE_CUBE_MAP: |
surftype = BRW_SURFACE_2D; |
is_array = true; |
depth *= 6; |
break; |
default: |
surftype = translate_tex_target(gl_target); |
is_array = _mesa_tex_target_is_array(gl_target); |
break; |
} |
if (layered) { |
min_array_element = 0; |
} else if (irb->mt->num_samples > 1) { |
min_array_element = irb->mt_layer / irb->mt->num_samples; |
} else { |
min_array_element = irb->mt_layer; |
} |
surf[0] = surftype << BRW_SURFACE_TYPE_SHIFT | |
format << BRW_SURFACE_FORMAT_SHIFT | |
(irb->mt->array_spacing_lod0 ? GEN7_SURFACE_ARYSPC_LOD0 |
: GEN7_SURFACE_ARYSPC_FULL) | |
gen7_surface_tiling_mode(region->tiling); |
if (irb->mt->align_h == 4) |
surf[0] |= GEN7_SURFACE_VALIGN_4; |
if (irb->mt->align_w == 8) |
surf[0] |= GEN7_SURFACE_HALIGN_8; |
if (is_array) { |
surf[0] |= GEN7_SURFACE_IS_ARRAY; |
} |
surf[1] = region->bo->offset; |
assert(brw->has_surface_tile_offset); |
surf[5] = SET_FIELD(mocs, GEN7_SURFACE_MOCS) | |
(irb->mt_level - irb->mt->first_level); |
surf[2] = SET_FIELD(irb->mt->logical_width0 - 1, GEN7_SURFACE_WIDTH) | |
SET_FIELD(irb->mt->logical_height0 - 1, GEN7_SURFACE_HEIGHT); |
surf[3] = ((depth - 1) << BRW_SURFACE_DEPTH_SHIFT) | |
(region->pitch - 1); |
surf[4] = gen7_surface_msaa_bits(irb->mt->num_samples, irb->mt->msaa_layout) | |
min_array_element << GEN7_SURFACE_MIN_ARRAY_ELEMENT_SHIFT | |
(depth - 1) << GEN7_SURFACE_RENDER_TARGET_VIEW_EXTENT_SHIFT; |
if (irb->mt->mcs_mt) { |
gen7_set_surface_mcs_info(brw, surf, brw->wm.surf_offset[unit], |
irb->mt->mcs_mt, true /* is RT */); |
} |
surf[7] = irb->mt->fast_clear_color_value; |
if (brw->is_haswell) { |
surf[7] |= (SET_FIELD(HSW_SCS_RED, GEN7_SURFACE_SCS_R) | |
SET_FIELD(HSW_SCS_GREEN, GEN7_SURFACE_SCS_G) | |
SET_FIELD(HSW_SCS_BLUE, GEN7_SURFACE_SCS_B) | |
SET_FIELD(HSW_SCS_ALPHA, GEN7_SURFACE_SCS_A)); |
} |
drm_intel_bo_emit_reloc(brw->batch.bo, |
brw->wm.surf_offset[unit] + 4, |
region->bo, |
surf[1] - region->bo->offset, |
I915_GEM_DOMAIN_RENDER, |
I915_GEM_DOMAIN_RENDER); |
gen7_check_surface_setup(surf, true /* is_render_target */); |
} |
void |
gen7_init_vtable_surface_functions(struct brw_context *brw) |
{ |
brw->vtbl.update_texture_surface = gen7_update_texture_surface; |
brw->vtbl.update_renderbuffer_surface = gen7_update_renderbuffer_surface; |
brw->vtbl.update_null_renderbuffer_surface = |
gen7_update_null_renderbuffer_surface; |
brw->vtbl.create_constant_surface = gen7_create_constant_surface; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_batchbuffer.c |
---|
0,0 → 1,558 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#include "intel_batchbuffer.h" |
#include "intel_buffer_objects.h" |
#include "intel_reg.h" |
#include "intel_bufmgr.h" |
#include "intel_buffers.h" |
#include "brw_context.h" |
static void |
intel_batchbuffer_reset(struct brw_context *brw); |
struct cached_batch_item { |
struct cached_batch_item *next; |
uint16_t header; |
uint16_t size; |
}; |
static void |
clear_cache(struct brw_context *brw) |
{ |
struct cached_batch_item *item = brw->batch.cached_items; |
while (item) { |
struct cached_batch_item *next = item->next; |
free(item); |
item = next; |
} |
brw->batch.cached_items = NULL; |
} |
void |
intel_batchbuffer_init(struct brw_context *brw) |
{ |
intel_batchbuffer_reset(brw); |
if (brw->gen >= 6) { |
/* We can't just use brw_state_batch to get a chunk of space for |
* the gen6 workaround because it involves actually writing to |
* the buffer, and the kernel doesn't let us write to the batch. |
*/ |
brw->batch.workaround_bo = drm_intel_bo_alloc(brw->bufmgr, |
"pipe_control workaround", |
4096, 4096); |
} |
if (!brw->has_llc) { |
brw->batch.cpu_map = malloc(BATCH_SZ); |
brw->batch.map = brw->batch.cpu_map; |
} |
} |
static void |
intel_batchbuffer_reset(struct brw_context *brw) |
{ |
if (brw->batch.last_bo != NULL) { |
drm_intel_bo_unreference(brw->batch.last_bo); |
brw->batch.last_bo = NULL; |
} |
brw->batch.last_bo = brw->batch.bo; |
clear_cache(brw); |
brw->batch.bo = drm_intel_bo_alloc(brw->bufmgr, "batchbuffer", |
BATCH_SZ, 4096); |
if (brw->has_llc) { |
drm_intel_bo_map(brw->batch.bo, true); |
brw->batch.map = brw->batch.bo->virtual; |
} |
brw->batch.reserved_space = BATCH_RESERVED; |
brw->batch.state_batch_offset = brw->batch.bo->size; |
brw->batch.used = 0; |
brw->batch.needs_sol_reset = false; |
} |
void |
intel_batchbuffer_save_state(struct brw_context *brw) |
{ |
brw->batch.saved.used = brw->batch.used; |
brw->batch.saved.reloc_count = |
drm_intel_gem_bo_get_reloc_count(brw->batch.bo); |
} |
void |
intel_batchbuffer_reset_to_saved(struct brw_context *brw) |
{ |
drm_intel_gem_bo_clear_relocs(brw->batch.bo, brw->batch.saved.reloc_count); |
brw->batch.used = brw->batch.saved.used; |
/* Cached batch state is dead, since we just cleared some unknown part of the |
* batchbuffer. Assume that the caller resets any other state necessary. |
*/ |
clear_cache(brw); |
} |
void |
intel_batchbuffer_free(struct brw_context *brw) |
{ |
free(brw->batch.cpu_map); |
drm_intel_bo_unreference(brw->batch.last_bo); |
drm_intel_bo_unreference(brw->batch.bo); |
drm_intel_bo_unreference(brw->batch.workaround_bo); |
clear_cache(brw); |
} |
#if 0 |
static void |
do_batch_dump(struct brw_context *brw) |
{ |
struct drm_intel_decode *decode; |
struct intel_batchbuffer *batch = &brw->batch; |
int ret; |
decode = drm_intel_decode_context_alloc(brw->intelScreen->deviceID); |
if (!decode) |
return; |
ret = drm_intel_bo_map(batch->bo, false); |
if (ret == 0) { |
drm_intel_decode_set_batch_pointer(decode, |
batch->bo->virtual, |
batch->bo->offset, |
batch->used); |
} else { |
fprintf(stderr, |
"WARNING: failed to map batchbuffer (%s), " |
"dumping uploaded data instead.\n", strerror(ret)); |
drm_intel_decode_set_batch_pointer(decode, |
batch->map, |
batch->bo->offset, |
batch->used); |
} |
drm_intel_decode(decode); |
drm_intel_decode_context_free(decode); |
if (ret == 0) { |
drm_intel_bo_unmap(batch->bo); |
brw_debug_batch(brw); |
} |
} |
#endif |
/* TODO: Push this whole function into bufmgr. |
*/ |
static int |
do_flush_locked(struct brw_context *brw) |
{ |
struct intel_batchbuffer *batch = &brw->batch; |
int ret = 0; |
if (brw->has_llc) { |
drm_intel_bo_unmap(batch->bo); |
} else { |
ret = drm_intel_bo_subdata(batch->bo, 0, 4*batch->used, batch->map); |
if (ret == 0 && batch->state_batch_offset != batch->bo->size) { |
ret = drm_intel_bo_subdata(batch->bo, |
batch->state_batch_offset, |
batch->bo->size - batch->state_batch_offset, |
(char *)batch->map + batch->state_batch_offset); |
} |
} |
if (!brw->intelScreen->no_hw) { |
int flags; |
if (brw->gen < 6 || !batch->is_blit) { |
flags = I915_EXEC_RENDER; |
} else { |
flags = I915_EXEC_BLT; |
} |
if (batch->needs_sol_reset) |
flags |= I915_EXEC_GEN7_SOL_RESET; |
if (ret == 0) { |
if (unlikely(INTEL_DEBUG & DEBUG_AUB)) |
brw_annotate_aub(brw); |
if (brw->hw_ctx == NULL || batch->is_blit) { |
ret = drm_intel_bo_mrb_exec(batch->bo, 4 * batch->used, NULL, 0, 0, |
flags); |
} else { |
ret = drm_intel_gem_bo_context_exec(batch->bo, brw->hw_ctx, |
4 * batch->used, flags); |
} |
} |
} |
// if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) |
// do_batch_dump(brw); |
if (ret != 0) { |
fprintf(stderr, "intel_do_flush_locked failed: %s\n", strerror(-ret)); |
exit(1); |
} |
brw->vtbl.new_batch(brw); |
return ret; |
} |
int |
_intel_batchbuffer_flush(struct brw_context *brw, |
const char *file, int line) |
{ |
int ret; |
if (brw->batch.used == 0) |
return 0; |
if (brw->first_post_swapbuffers_batch == NULL) { |
brw->first_post_swapbuffers_batch = brw->batch.bo; |
drm_intel_bo_reference(brw->first_post_swapbuffers_batch); |
} |
if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) |
fprintf(stderr, "%s:%d: Batchbuffer flush with %db used\n", file, line, |
4*brw->batch.used); |
brw->batch.reserved_space = 0; |
if (brw->vtbl.finish_batch) |
brw->vtbl.finish_batch(brw); |
/* Mark the end of the buffer. */ |
intel_batchbuffer_emit_dword(brw, MI_BATCH_BUFFER_END); |
if (brw->batch.used & 1) { |
/* Round batchbuffer usage to 2 DWORDs. */ |
intel_batchbuffer_emit_dword(brw, MI_NOOP); |
} |
intel_upload_finish(brw); |
/* Check that we didn't just wrap our batchbuffer at a bad time. */ |
assert(!brw->no_batch_wrap); |
ret = do_flush_locked(brw); |
if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) { |
fprintf(stderr, "waiting for idle\n"); |
drm_intel_bo_wait_rendering(brw->batch.bo); |
} |
/* Reset the buffer: |
*/ |
intel_batchbuffer_reset(brw); |
return ret; |
} |
/* This is the only way buffers get added to the validate list. |
*/ |
bool |
intel_batchbuffer_emit_reloc(struct brw_context *brw, |
drm_intel_bo *buffer, |
uint32_t read_domains, uint32_t write_domain, |
uint32_t delta) |
{ |
int ret; |
ret = drm_intel_bo_emit_reloc(brw->batch.bo, 4*brw->batch.used, |
buffer, delta, |
read_domains, write_domain); |
assert(ret == 0); |
(void)ret; |
/* |
* Using the old buffer offset, write in what the right data would be, in case |
* the buffer doesn't move and we can short-circuit the relocation processing |
* in the kernel |
*/ |
intel_batchbuffer_emit_dword(brw, buffer->offset + delta); |
return true; |
} |
bool |
intel_batchbuffer_emit_reloc_fenced(struct brw_context *brw, |
drm_intel_bo *buffer, |
uint32_t read_domains, |
uint32_t write_domain, |
uint32_t delta) |
{ |
int ret; |
ret = drm_intel_bo_emit_reloc_fence(brw->batch.bo, 4*brw->batch.used, |
buffer, delta, |
read_domains, write_domain); |
assert(ret == 0); |
(void)ret; |
/* |
* Using the old buffer offset, write in what the right data would |
* be, in case the buffer doesn't move and we can short-circuit the |
* relocation processing in the kernel |
*/ |
intel_batchbuffer_emit_dword(brw, buffer->offset + delta); |
return true; |
} |
void |
intel_batchbuffer_data(struct brw_context *brw, |
const void *data, GLuint bytes, bool is_blit) |
{ |
assert((bytes & 3) == 0); |
intel_batchbuffer_require_space(brw, bytes, is_blit); |
__memcpy(brw->batch.map + brw->batch.used, data, bytes); |
brw->batch.used += bytes >> 2; |
} |
void |
intel_batchbuffer_cached_advance(struct brw_context *brw) |
{ |
struct cached_batch_item **prev = &brw->batch.cached_items, *item; |
uint32_t sz = (brw->batch.used - brw->batch.emit) * sizeof(uint32_t); |
uint32_t *start = brw->batch.map + brw->batch.emit; |
uint16_t op = *start >> 16; |
while (*prev) { |
uint32_t *old; |
item = *prev; |
old = brw->batch.map + item->header; |
if (op == *old >> 16) { |
if (item->size == sz && memcmp(old, start, sz) == 0) { |
if (prev != &brw->batch.cached_items) { |
*prev = item->next; |
item->next = brw->batch.cached_items; |
brw->batch.cached_items = item; |
} |
brw->batch.used = brw->batch.emit; |
return; |
} |
goto emit; |
} |
prev = &item->next; |
} |
item = malloc(sizeof(struct cached_batch_item)); |
if (item == NULL) |
return; |
item->next = brw->batch.cached_items; |
brw->batch.cached_items = item; |
emit: |
item->size = sz; |
item->header = brw->batch.emit; |
} |
/** |
* Restriction [DevSNB, DevIVB]: |
* |
* Prior to changing Depth/Stencil Buffer state (i.e. any combination of |
* 3DSTATE_DEPTH_BUFFER, 3DSTATE_CLEAR_PARAMS, 3DSTATE_STENCIL_BUFFER, |
* 3DSTATE_HIER_DEPTH_BUFFER) SW must first issue a pipelined depth stall |
* (PIPE_CONTROL with Depth Stall bit set), followed by a pipelined depth |
* cache flush (PIPE_CONTROL with Depth Flush Bit set), followed by |
* another pipelined depth stall (PIPE_CONTROL with Depth Stall bit set), |
* unless SW can otherwise guarantee that the pipeline from WM onwards is |
* already flushed (e.g., via a preceding MI_FLUSH). |
*/ |
void |
intel_emit_depth_stall_flushes(struct brw_context *brw) |
{ |
assert(brw->gen >= 6 && brw->gen <= 7); |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2)); |
OUT_BATCH(PIPE_CONTROL_DEPTH_STALL); |
OUT_BATCH(0); /* address */ |
OUT_BATCH(0); /* write data */ |
ADVANCE_BATCH() |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2)); |
OUT_BATCH(PIPE_CONTROL_DEPTH_CACHE_FLUSH); |
OUT_BATCH(0); /* address */ |
OUT_BATCH(0); /* write data */ |
ADVANCE_BATCH(); |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2)); |
OUT_BATCH(PIPE_CONTROL_DEPTH_STALL); |
OUT_BATCH(0); /* address */ |
OUT_BATCH(0); /* write data */ |
ADVANCE_BATCH(); |
} |
/** |
* From the Ivybridge PRM, Volume 2 Part 1, Section 3.2 (VS Stage Input): |
* "A PIPE_CONTROL with Post-Sync Operation set to 1h and a depth |
* stall needs to be sent just prior to any 3DSTATE_VS, 3DSTATE_URB_VS, |
* 3DSTATE_CONSTANT_VS, 3DSTATE_BINDING_TABLE_POINTER_VS, |
* 3DSTATE_SAMPLER_STATE_POINTER_VS command. Only one PIPE_CONTROL needs |
* to be sent before any combination of VS associated 3DSTATE." |
*/ |
void |
gen7_emit_vs_workaround_flush(struct brw_context *brw) |
{ |
assert(brw->gen == 7); |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2)); |
OUT_BATCH(PIPE_CONTROL_DEPTH_STALL | PIPE_CONTROL_WRITE_IMMEDIATE); |
OUT_RELOC(brw->batch.workaround_bo, |
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0); |
OUT_BATCH(0); /* write data */ |
ADVANCE_BATCH(); |
} |
/** |
* Emits a PIPE_CONTROL with a non-zero post-sync operation, for |
* implementing two workarounds on gen6. From section 1.4.7.1 |
* "PIPE_CONTROL" of the Sandy Bridge PRM volume 2 part 1: |
* |
* [DevSNB-C+{W/A}] Before any depth stall flush (including those |
* produced by non-pipelined state commands), software needs to first |
* send a PIPE_CONTROL with no bits set except Post-Sync Operation != |
* 0. |
* |
* [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache Flush Enable |
* =1, a PIPE_CONTROL with any non-zero post-sync-op is required. |
* |
* And the workaround for these two requires this workaround first: |
* |
* [Dev-SNB{W/A}]: Pipe-control with CS-stall bit set must be sent |
* BEFORE the pipe-control with a post-sync op and no write-cache |
* flushes. |
* |
* And this last workaround is tricky because of the requirements on |
* that bit. From section 1.4.7.2.3 "Stall" of the Sandy Bridge PRM |
* volume 2 part 1: |
* |
* "1 of the following must also be set: |
* - Render Target Cache Flush Enable ([12] of DW1) |
* - Depth Cache Flush Enable ([0] of DW1) |
* - Stall at Pixel Scoreboard ([1] of DW1) |
* - Depth Stall ([13] of DW1) |
* - Post-Sync Operation ([13] of DW1) |
* - Notify Enable ([8] of DW1)" |
* |
* The cache flushes require the workaround flush that triggered this |
* one, so we can't use it. Depth stall would trigger the same. |
* Post-sync nonzero is what triggered this second workaround, so we |
* can't use that one either. Notify enable is IRQs, which aren't |
* really our business. That leaves only stall at scoreboard. |
*/ |
void |
intel_emit_post_sync_nonzero_flush(struct brw_context *brw) |
{ |
if (!brw->batch.need_workaround_flush) |
return; |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2)); |
OUT_BATCH(PIPE_CONTROL_CS_STALL | |
PIPE_CONTROL_STALL_AT_SCOREBOARD); |
OUT_BATCH(0); /* address */ |
OUT_BATCH(0); /* write data */ |
ADVANCE_BATCH(); |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2)); |
OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE); |
OUT_RELOC(brw->batch.workaround_bo, |
I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0); |
OUT_BATCH(0); /* write data */ |
ADVANCE_BATCH(); |
brw->batch.need_workaround_flush = false; |
} |
/* Emit a pipelined flush to either flush render and texture cache for |
* reading from a FBO-drawn texture, or flush so that frontbuffer |
* render appears on the screen in DRI1. |
* |
* This is also used for the always_flush_cache driconf debug option. |
*/ |
void |
intel_batchbuffer_emit_mi_flush(struct brw_context *brw) |
{ |
if (brw->gen >= 6) { |
if (brw->batch.is_blit) { |
BEGIN_BATCH_BLT(4); |
OUT_BATCH(MI_FLUSH_DW); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
ADVANCE_BATCH(); |
} else { |
if (brw->gen == 6) { |
/* Hardware workaround: SNB B-Spec says: |
* |
* [Dev-SNB{W/A}]: Before a PIPE_CONTROL with Write Cache |
* Flush Enable =1, a PIPE_CONTROL with any non-zero |
* post-sync-op is required. |
*/ |
intel_emit_post_sync_nonzero_flush(brw); |
} |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2)); |
OUT_BATCH(PIPE_CONTROL_INSTRUCTION_FLUSH | |
PIPE_CONTROL_WRITE_FLUSH | |
PIPE_CONTROL_DEPTH_CACHE_FLUSH | |
PIPE_CONTROL_VF_CACHE_INVALIDATE | |
PIPE_CONTROL_TC_FLUSH | |
PIPE_CONTROL_NO_WRITE | |
PIPE_CONTROL_CS_STALL); |
OUT_BATCH(0); /* write address */ |
OUT_BATCH(0); /* write data */ |
ADVANCE_BATCH(); |
} |
} else { |
BEGIN_BATCH(4); |
OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2) | |
PIPE_CONTROL_WRITE_FLUSH | |
PIPE_CONTROL_NO_WRITE); |
OUT_BATCH(0); /* write address */ |
OUT_BATCH(0); /* write data */ |
OUT_BATCH(0); /* write data */ |
ADVANCE_BATCH(); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_batchbuffer.h |
---|
0,0 → 1,171 |
#ifndef INTEL_BATCHBUFFER_H |
#define INTEL_BATCHBUFFER_H |
#include "main/mtypes.h" |
#include "brw_context.h" |
#include "intel_bufmgr.h" |
#include "intel_reg.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
/** |
* Number of bytes to reserve for commands necessary to complete a batch. |
* |
* This includes: |
* - MI_BATCHBUFFER_END (4 bytes) |
* - Optional MI_NOOP for ensuring the batch length is qword aligned (4 bytes) |
* - Any state emitted by vtbl->finish_batch(): |
* - Gen4-5 record ending occlusion query values (4 * 4 = 16 bytes) |
*/ |
#define BATCH_RESERVED 24 |
struct intel_batchbuffer; |
void intel_batchbuffer_init(struct brw_context *brw); |
void intel_batchbuffer_free(struct brw_context *brw); |
void intel_batchbuffer_save_state(struct brw_context *brw); |
void intel_batchbuffer_reset_to_saved(struct brw_context *brw); |
int _intel_batchbuffer_flush(struct brw_context *brw, |
const char *file, int line); |
#define intel_batchbuffer_flush(intel) \ |
_intel_batchbuffer_flush(intel, __FILE__, __LINE__) |
/* Unlike bmBufferData, this currently requires the buffer be mapped. |
* Consider it a convenience function wrapping multple |
* intel_buffer_dword() calls. |
*/ |
void intel_batchbuffer_data(struct brw_context *brw, |
const void *data, GLuint bytes, bool is_blit); |
bool intel_batchbuffer_emit_reloc(struct brw_context *brw, |
drm_intel_bo *buffer, |
uint32_t read_domains, |
uint32_t write_domain, |
uint32_t offset); |
bool intel_batchbuffer_emit_reloc_fenced(struct brw_context *brw, |
drm_intel_bo *buffer, |
uint32_t read_domains, |
uint32_t write_domain, |
uint32_t offset); |
void intel_batchbuffer_emit_mi_flush(struct brw_context *brw); |
void intel_emit_post_sync_nonzero_flush(struct brw_context *brw); |
void intel_emit_depth_stall_flushes(struct brw_context *brw); |
void gen7_emit_vs_workaround_flush(struct brw_context *brw); |
static INLINE uint32_t float_as_int(float f) |
{ |
union { |
float f; |
uint32_t d; |
} fi; |
fi.f = f; |
return fi.d; |
} |
/* Inline functions - might actually be better off with these |
* non-inlined. Certainly better off switching all command packets to |
* be passed as structs rather than dwords, but that's a little bit of |
* work... |
*/ |
static INLINE unsigned |
intel_batchbuffer_space(struct brw_context *brw) |
{ |
return (brw->batch.state_batch_offset - brw->batch.reserved_space) |
- brw->batch.used*4; |
} |
static INLINE void |
intel_batchbuffer_emit_dword(struct brw_context *brw, GLuint dword) |
{ |
#ifdef DEBUG |
assert(intel_batchbuffer_space(brw) >= 4); |
#endif |
brw->batch.map[brw->batch.used++] = dword; |
} |
static INLINE void |
intel_batchbuffer_emit_float(struct brw_context *brw, float f) |
{ |
intel_batchbuffer_emit_dword(brw, float_as_int(f)); |
} |
static INLINE void |
intel_batchbuffer_require_space(struct brw_context *brw, GLuint sz, int is_blit) |
{ |
if (brw->gen >= 6 && |
brw->batch.is_blit != is_blit && brw->batch.used) { |
intel_batchbuffer_flush(brw); |
} |
brw->batch.is_blit = is_blit; |
#ifdef DEBUG |
assert(sz < BATCH_SZ - BATCH_RESERVED); |
#endif |
if (intel_batchbuffer_space(brw) < sz) |
intel_batchbuffer_flush(brw); |
} |
static INLINE void |
intel_batchbuffer_begin(struct brw_context *brw, int n, bool is_blit) |
{ |
intel_batchbuffer_require_space(brw, n * 4, is_blit); |
brw->batch.emit = brw->batch.used; |
#ifdef DEBUG |
brw->batch.total = n; |
#endif |
} |
static INLINE void |
intel_batchbuffer_advance(struct brw_context *brw) |
{ |
#ifdef DEBUG |
struct intel_batchbuffer *batch = &brw->batch; |
unsigned int _n = batch->used - batch->emit; |
assert(batch->total != 0); |
if (_n != batch->total) { |
fprintf(stderr, "ADVANCE_BATCH: %d of %d dwords emitted\n", |
_n, batch->total); |
abort(); |
} |
batch->total = 0; |
#endif |
} |
void intel_batchbuffer_cached_advance(struct brw_context *brw); |
/* Here are the crusty old macros, to be removed: |
*/ |
#define BATCH_LOCALS |
#define BEGIN_BATCH(n) intel_batchbuffer_begin(brw, n, false) |
#define BEGIN_BATCH_BLT(n) intel_batchbuffer_begin(brw, n, true) |
#define OUT_BATCH(d) intel_batchbuffer_emit_dword(brw, d) |
#define OUT_BATCH_F(f) intel_batchbuffer_emit_float(brw, f) |
#define OUT_RELOC(buf, read_domains, write_domain, delta) do { \ |
intel_batchbuffer_emit_reloc(brw, buf, \ |
read_domains, write_domain, delta); \ |
} while (0) |
#define OUT_RELOC_FENCED(buf, read_domains, write_domain, delta) do { \ |
intel_batchbuffer_emit_reloc_fenced(brw, buf, \ |
read_domains, write_domain, delta); \ |
} while (0) |
#define ADVANCE_BATCH() intel_batchbuffer_advance(brw); |
#define CACHED_BATCH() intel_batchbuffer_cached_advance(brw); |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_blit.c |
---|
0,0 → 1,581 |
/************************************************************************** |
* |
* 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 "main/mtypes.h" |
#include "main/context.h" |
#include "main/enums.h" |
#include "main/colormac.h" |
#include "main/fbobject.h" |
#include "brw_context.h" |
#include "intel_blit.h" |
#include "intel_buffers.h" |
#include "intel_fbo.h" |
#include "intel_reg.h" |
#include "intel_regions.h" |
#include "intel_batchbuffer.h" |
#include "intel_mipmap_tree.h" |
#define FILE_DEBUG_FLAG DEBUG_BLIT |
static void |
intel_miptree_set_alpha_to_one(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
int x, int y, int width, int height); |
static GLuint translate_raster_op(GLenum logicop) |
{ |
switch(logicop) { |
case GL_CLEAR: return 0x00; |
case GL_AND: return 0x88; |
case GL_AND_REVERSE: return 0x44; |
case GL_COPY: return 0xCC; |
case GL_AND_INVERTED: return 0x22; |
case GL_NOOP: return 0xAA; |
case GL_XOR: return 0x66; |
case GL_OR: return 0xEE; |
case GL_NOR: return 0x11; |
case GL_EQUIV: return 0x99; |
case GL_INVERT: return 0x55; |
case GL_OR_REVERSE: return 0xDD; |
case GL_COPY_INVERTED: return 0x33; |
case GL_OR_INVERTED: return 0xBB; |
case GL_NAND: return 0x77; |
case GL_SET: return 0xFF; |
default: return 0; |
} |
} |
static uint32_t |
br13_for_cpp(int cpp) |
{ |
switch (cpp) { |
case 4: |
return BR13_8888; |
break; |
case 2: |
return BR13_565; |
break; |
case 1: |
return BR13_8; |
break; |
default: |
assert(0); |
return 0; |
} |
} |
/** |
* Emits the packet for switching the blitter from X to Y tiled or back. |
* |
* This has to be called in a single BEGIN_BATCH_BLT_TILED() / |
* ADVANCE_BATCH_TILED(). This is because BCS_SWCTRL is saved and restored as |
* part of the power context, not a render context, and if the batchbuffer was |
* to get flushed between setting and blitting, or blitting and restoring, our |
* tiling state would leak into other unsuspecting applications (like the X |
* server). |
*/ |
static void |
set_blitter_tiling(struct brw_context *brw, |
bool dst_y_tiled, bool src_y_tiled) |
{ |
assert(brw->gen >= 6); |
/* Idle the blitter before we update how tiling is interpreted. */ |
OUT_BATCH(MI_FLUSH_DW); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(0); |
OUT_BATCH(MI_LOAD_REGISTER_IMM | (3 - 2)); |
OUT_BATCH(BCS_SWCTRL); |
OUT_BATCH((BCS_SWCTRL_DST_Y | BCS_SWCTRL_SRC_Y) << 16 | |
(dst_y_tiled ? BCS_SWCTRL_DST_Y : 0) | |
(src_y_tiled ? BCS_SWCTRL_SRC_Y : 0)); |
} |
#define BEGIN_BATCH_BLT_TILED(n, dst_y_tiled, src_y_tiled) do { \ |
BEGIN_BATCH_BLT(n + ((dst_y_tiled || src_y_tiled) ? 14 : 0)); \ |
if (dst_y_tiled || src_y_tiled) \ |
set_blitter_tiling(brw, dst_y_tiled, src_y_tiled); \ |
} while (0) |
#define ADVANCE_BATCH_TILED(dst_y_tiled, src_y_tiled) do { \ |
if (dst_y_tiled || src_y_tiled) \ |
set_blitter_tiling(brw, false, false); \ |
ADVANCE_BATCH(); \ |
} while (0) |
/** |
* Implements a rectangular block transfer (blit) of pixels between two |
* miptrees. |
* |
* Our blitter can operate on 1, 2, or 4-byte-per-pixel data, with generous, |
* but limited, pitches and sizes allowed. |
* |
* The src/dst coordinates are relative to the given level/slice of the |
* miptree. |
* |
* If @src_flip or @dst_flip is set, then the rectangle within that miptree |
* will be inverted (including scanline order) when copying. This is common |
* in GL when copying between window system and user-created |
* renderbuffers/textures. |
*/ |
bool |
intel_miptree_blit(struct brw_context *brw, |
struct intel_mipmap_tree *src_mt, |
int src_level, int src_slice, |
uint32_t src_x, uint32_t src_y, bool src_flip, |
struct intel_mipmap_tree *dst_mt, |
int dst_level, int dst_slice, |
uint32_t dst_x, uint32_t dst_y, bool dst_flip, |
uint32_t width, uint32_t height, |
GLenum logicop) |
{ |
/* No sRGB decode or encode is done by the hardware blitter, which is |
* consistent with what we want in the callers (glCopyTexSubImage(), |
* glBlitFramebuffer(), texture validation, etc.). |
*/ |
gl_format src_format = _mesa_get_srgb_format_linear(src_mt->format); |
gl_format dst_format = _mesa_get_srgb_format_linear(dst_mt->format); |
/* The blitter doesn't support doing any format conversions. We do also |
* support blitting ARGB8888 to XRGB8888 (trivial, the values dropped into |
* the X channel don't matter), and XRGB8888 to ARGB8888 by setting the A |
* channel to 1.0 at the end. |
*/ |
if (src_format != dst_format && |
((src_format != MESA_FORMAT_ARGB8888 && |
src_format != MESA_FORMAT_XRGB8888) || |
(dst_format != MESA_FORMAT_ARGB8888 && |
dst_format != MESA_FORMAT_XRGB8888))) { |
perf_debug("%s: Can't use hardware blitter from %s to %s, " |
"falling back.\n", __FUNCTION__, |
_mesa_get_format_name(src_format), |
_mesa_get_format_name(dst_format)); |
return false; |
} |
/* According to the Ivy Bridge PRM, Vol1 Part4, section 1.2.1.2 (Graphics |
* Data Size Limitations): |
* |
* The BLT engine is capable of transferring very large quantities of |
* graphics data. Any graphics data read from and written to the |
* destination is permitted to represent a number of pixels that |
* occupies up to 65,536 scan lines and up to 32,768 bytes per scan line |
* at the destination. The maximum number of pixels that may be |
* represented per scan line’s worth of graphics data depends on the |
* color depth. |
* |
* Furthermore, intelEmitCopyBlit (which is called below) uses a signed |
* 16-bit integer to represent buffer pitch, so it can only handle buffer |
* pitches < 32k. |
* |
* As a result of these two limitations, we can only use the blitter to do |
* this copy when the region's pitch is less than 32k. |
*/ |
if (src_mt->region->pitch > 32768 || |
dst_mt->region->pitch > 32768) { |
perf_debug("Falling back due to >32k pitch\n"); |
return false; |
} |
/* The blitter has no idea about HiZ or fast color clears, so we need to |
* resolve the miptrees before we do anything. |
*/ |
intel_miptree_slice_resolve_depth(brw, src_mt, src_level, src_slice); |
intel_miptree_slice_resolve_depth(brw, dst_mt, dst_level, dst_slice); |
intel_miptree_resolve_color(brw, src_mt); |
intel_miptree_resolve_color(brw, dst_mt); |
if (src_flip) |
src_y = src_mt->level[src_level].height - src_y - height; |
if (dst_flip) |
dst_y = dst_mt->level[dst_level].height - dst_y - height; |
int src_pitch = src_mt->region->pitch; |
if (src_flip != dst_flip) |
src_pitch = -src_pitch; |
uint32_t src_image_x, src_image_y; |
intel_miptree_get_image_offset(src_mt, src_level, src_slice, |
&src_image_x, &src_image_y); |
src_x += src_image_x; |
src_y += src_image_y; |
uint32_t dst_image_x, dst_image_y; |
intel_miptree_get_image_offset(dst_mt, dst_level, dst_slice, |
&dst_image_x, &dst_image_y); |
dst_x += dst_image_x; |
dst_y += dst_image_y; |
if (!intelEmitCopyBlit(brw, |
src_mt->cpp, |
src_pitch, |
src_mt->region->bo, src_mt->offset, |
src_mt->region->tiling, |
dst_mt->region->pitch, |
dst_mt->region->bo, dst_mt->offset, |
dst_mt->region->tiling, |
src_x, src_y, |
dst_x, dst_y, |
width, height, |
logicop)) { |
return false; |
} |
if (src_mt->format == MESA_FORMAT_XRGB8888 && |
dst_mt->format == MESA_FORMAT_ARGB8888) { |
intel_miptree_set_alpha_to_one(brw, dst_mt, |
dst_x, dst_y, |
width, height); |
} |
return true; |
} |
/* Copy BitBlt |
*/ |
bool |
intelEmitCopyBlit(struct brw_context *brw, |
GLuint cpp, |
GLshort src_pitch, |
drm_intel_bo *src_buffer, |
GLuint src_offset, |
uint32_t src_tiling, |
GLshort dst_pitch, |
drm_intel_bo *dst_buffer, |
GLuint dst_offset, |
uint32_t dst_tiling, |
GLshort src_x, GLshort src_y, |
GLshort dst_x, GLshort dst_y, |
GLshort w, GLshort h, |
GLenum logic_op) |
{ |
GLuint CMD, BR13, pass = 0; |
int dst_y2 = dst_y + h; |
int dst_x2 = dst_x + w; |
drm_intel_bo *aper_array[3]; |
bool dst_y_tiled = dst_tiling == I915_TILING_Y; |
bool src_y_tiled = src_tiling == I915_TILING_Y; |
BATCH_LOCALS; |
if (dst_tiling != I915_TILING_NONE) { |
if (dst_offset & 4095) |
return false; |
} |
if (src_tiling != I915_TILING_NONE) { |
if (src_offset & 4095) |
return false; |
} |
if ((dst_y_tiled || src_y_tiled) && brw->gen < 6) |
return false; |
/* do space check before going any further */ |
do { |
aper_array[0] = brw->batch.bo; |
aper_array[1] = dst_buffer; |
aper_array[2] = src_buffer; |
if (dri_bufmgr_check_aperture_space(aper_array, 3) != 0) { |
intel_batchbuffer_flush(brw); |
pass++; |
} else |
break; |
} while (pass < 2); |
if (pass >= 2) |
return false; |
intel_batchbuffer_require_space(brw, 8 * 4, true); |
DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", |
__FUNCTION__, |
src_buffer, src_pitch, src_offset, src_x, src_y, |
dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h); |
/* Blit pitch must be dword-aligned. Otherwise, the hardware appears to drop |
* the low bits. |
*/ |
if (src_pitch % 4 != 0 || dst_pitch % 4 != 0) |
return false; |
/* For big formats (such as floating point), do the copy using 16 or 32bpp |
* and multiply the coordinates. |
*/ |
if (cpp > 4) { |
if (cpp % 4 == 2) { |
dst_x *= cpp / 2; |
dst_x2 *= cpp / 2; |
src_x *= cpp / 2; |
cpp = 2; |
} else { |
assert(cpp % 4 == 0); |
dst_x *= cpp / 4; |
dst_x2 *= cpp / 4; |
src_x *= cpp / 4; |
cpp = 4; |
} |
} |
BR13 = br13_for_cpp(cpp) | translate_raster_op(logic_op) << 16; |
switch (cpp) { |
case 1: |
case 2: |
CMD = XY_SRC_COPY_BLT_CMD; |
break; |
case 4: |
CMD = XY_SRC_COPY_BLT_CMD | XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; |
break; |
default: |
return false; |
} |
if (dst_tiling != I915_TILING_NONE) { |
CMD |= XY_DST_TILED; |
dst_pitch /= 4; |
} |
if (src_tiling != I915_TILING_NONE) { |
CMD |= XY_SRC_TILED; |
src_pitch /= 4; |
} |
if (dst_y2 <= dst_y || dst_x2 <= dst_x) { |
return true; |
} |
assert(dst_x < dst_x2); |
assert(dst_y < dst_y2); |
BEGIN_BATCH_BLT_TILED(8, dst_y_tiled, src_y_tiled); |
OUT_BATCH(CMD | (8 - 2)); |
OUT_BATCH(BR13 | (uint16_t)dst_pitch); |
OUT_BATCH((dst_y << 16) | dst_x); |
OUT_BATCH((dst_y2 << 16) | dst_x2); |
OUT_RELOC_FENCED(dst_buffer, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
dst_offset); |
OUT_BATCH((src_y << 16) | src_x); |
OUT_BATCH((uint16_t)src_pitch); |
OUT_RELOC_FENCED(src_buffer, |
I915_GEM_DOMAIN_RENDER, 0, |
src_offset); |
ADVANCE_BATCH_TILED(dst_y_tiled, src_y_tiled); |
intel_batchbuffer_emit_mi_flush(brw); |
return true; |
} |
bool |
intelEmitImmediateColorExpandBlit(struct brw_context *brw, |
GLuint cpp, |
GLubyte *src_bits, GLuint src_size, |
GLuint fg_color, |
GLshort dst_pitch, |
drm_intel_bo *dst_buffer, |
GLuint dst_offset, |
uint32_t dst_tiling, |
GLshort x, GLshort y, |
GLshort w, GLshort h, |
GLenum logic_op) |
{ |
int dwords = ALIGN(src_size, 8) / 4; |
uint32_t opcode, br13, blit_cmd; |
if (dst_tiling != I915_TILING_NONE) { |
if (dst_offset & 4095) |
return false; |
if (dst_tiling == I915_TILING_Y) |
return false; |
} |
assert( logic_op - GL_CLEAR >= 0 ); |
assert( logic_op - GL_CLEAR < 0x10 ); |
assert(dst_pitch > 0); |
if (w < 0 || h < 0) |
return true; |
DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d, %d bytes %d dwords\n", |
__FUNCTION__, |
dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords); |
intel_batchbuffer_require_space(brw, (8 * 4) + (3 * 4) + dwords * 4, true); |
opcode = XY_SETUP_BLT_CMD; |
if (cpp == 4) |
opcode |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB; |
if (dst_tiling != I915_TILING_NONE) { |
opcode |= XY_DST_TILED; |
dst_pitch /= 4; |
} |
br13 = dst_pitch | (translate_raster_op(logic_op) << 16) | (1 << 29); |
br13 |= br13_for_cpp(cpp); |
blit_cmd = XY_TEXT_IMMEDIATE_BLIT_CMD | XY_TEXT_BYTE_PACKED; /* packing? */ |
if (dst_tiling != I915_TILING_NONE) |
blit_cmd |= XY_DST_TILED; |
BEGIN_BATCH_BLT(8 + 3); |
OUT_BATCH(opcode | (8 - 2)); |
OUT_BATCH(br13); |
OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */ |
OUT_BATCH((100 << 16) | 100); /* clip x2, y2 */ |
OUT_RELOC_FENCED(dst_buffer, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
dst_offset); |
OUT_BATCH(0); /* bg */ |
OUT_BATCH(fg_color); /* fg */ |
OUT_BATCH(0); /* pattern base addr */ |
OUT_BATCH(blit_cmd | ((3 - 2) + dwords)); |
OUT_BATCH((y << 16) | x); |
OUT_BATCH(((y + h) << 16) | (x + w)); |
ADVANCE_BATCH(); |
intel_batchbuffer_data(brw, src_bits, dwords * 4, true); |
intel_batchbuffer_emit_mi_flush(brw); |
return true; |
} |
/* We don't have a memmove-type blit like some other hardware, so we'll do a |
* rectangular blit covering a large space, then emit 1-scanline blit at the |
* end to cover the last if we need. |
*/ |
void |
intel_emit_linear_blit(struct brw_context *brw, |
drm_intel_bo *dst_bo, |
unsigned int dst_offset, |
drm_intel_bo *src_bo, |
unsigned int src_offset, |
unsigned int size) |
{ |
struct gl_context *ctx = &brw->ctx; |
GLuint pitch, height; |
bool ok; |
/* The pitch given to the GPU must be DWORD aligned, and |
* we want width to match pitch. Max width is (1 << 15 - 1), |
* rounding that down to the nearest DWORD is 1 << 15 - 4 |
*/ |
pitch = ROUND_DOWN_TO(MIN2(size, (1 << 15) - 1), 4); |
height = (pitch == 0) ? 1 : size / pitch; |
ok = intelEmitCopyBlit(brw, 1, |
pitch, src_bo, src_offset, I915_TILING_NONE, |
pitch, dst_bo, dst_offset, I915_TILING_NONE, |
0, 0, /* src x/y */ |
0, 0, /* dst x/y */ |
pitch, height, /* w, h */ |
GL_COPY); |
if (!ok) |
_mesa_problem(ctx, "Failed to linear blit %dx%d\n", pitch, height); |
src_offset += pitch * height; |
dst_offset += pitch * height; |
size -= pitch * height; |
assert (size < (1 << 15)); |
pitch = ALIGN(size, 4); |
if (size != 0) { |
ok = intelEmitCopyBlit(brw, 1, |
pitch, src_bo, src_offset, I915_TILING_NONE, |
pitch, dst_bo, dst_offset, I915_TILING_NONE, |
0, 0, /* src x/y */ |
0, 0, /* dst x/y */ |
size, 1, /* w, h */ |
GL_COPY); |
if (!ok) |
_mesa_problem(ctx, "Failed to linear blit %dx%d\n", size, 1); |
} |
} |
/** |
* Used to initialize the alpha value of an ARGB8888 miptree after copying |
* into it from an XRGB8888 source. |
* |
* This is very common with glCopyTexImage2D(). Note that the coordinates are |
* relative to the start of the miptree, not relative to a slice within the |
* miptree. |
*/ |
static void |
intel_miptree_set_alpha_to_one(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
int x, int y, int width, int height) |
{ |
struct intel_region *region = mt->region; |
uint32_t BR13, CMD; |
int pitch, cpp; |
drm_intel_bo *aper_array[2]; |
BATCH_LOCALS; |
pitch = region->pitch; |
cpp = region->cpp; |
DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n", |
__FUNCTION__, region->bo, pitch, x, y, width, height); |
BR13 = br13_for_cpp(cpp) | 0xf0 << 16; |
CMD = XY_COLOR_BLT_CMD; |
CMD |= XY_BLT_WRITE_ALPHA; |
if (region->tiling != I915_TILING_NONE) { |
CMD |= XY_DST_TILED; |
pitch /= 4; |
} |
BR13 |= pitch; |
/* do space check before going any further */ |
aper_array[0] = brw->batch.bo; |
aper_array[1] = region->bo; |
if (drm_intel_bufmgr_check_aperture_space(aper_array, |
ARRAY_SIZE(aper_array)) != 0) { |
intel_batchbuffer_flush(brw); |
} |
bool dst_y_tiled = region->tiling == I915_TILING_Y; |
BEGIN_BATCH_BLT_TILED(6, dst_y_tiled, false); |
OUT_BATCH(CMD | (6 - 2)); |
OUT_BATCH(BR13); |
OUT_BATCH((y << 16) | x); |
OUT_BATCH(((y + height) << 16) | (x + width)); |
OUT_RELOC_FENCED(region->bo, |
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, |
0); |
OUT_BATCH(0xffffffff); /* white, but only alpha gets written */ |
ADVANCE_BATCH_TILED(dst_y_tiled, false); |
intel_batchbuffer_emit_mi_flush(brw); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_blit.h |
---|
0,0 → 1,78 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_BLIT_H |
#define INTEL_BLIT_H |
#include "brw_context.h" |
bool |
intelEmitCopyBlit(struct brw_context *brw, |
GLuint cpp, |
GLshort src_pitch, |
drm_intel_bo *src_buffer, |
GLuint src_offset, |
uint32_t src_tiling, |
GLshort dst_pitch, |
drm_intel_bo *dst_buffer, |
GLuint dst_offset, |
uint32_t dst_tiling, |
GLshort srcx, GLshort srcy, |
GLshort dstx, GLshort dsty, |
GLshort w, GLshort h, |
GLenum logicop ); |
bool intel_miptree_blit(struct brw_context *brw, |
struct intel_mipmap_tree *src_mt, |
int src_level, int src_slice, |
uint32_t src_x, uint32_t src_y, bool src_flip, |
struct intel_mipmap_tree *dst_mt, |
int dst_level, int dst_slice, |
uint32_t dst_x, uint32_t dst_y, bool dst_flip, |
uint32_t width, uint32_t height, |
GLenum logicop); |
bool |
intelEmitImmediateColorExpandBlit(struct brw_context *brw, |
GLuint cpp, |
GLubyte *src_bits, GLuint src_size, |
GLuint fg_color, |
GLshort dst_pitch, |
drm_intel_bo *dst_buffer, |
GLuint dst_offset, |
uint32_t dst_tiling, |
GLshort x, GLshort y, |
GLshort w, GLshort h, |
GLenum logic_op); |
void intel_emit_linear_blit(struct brw_context *brw, |
drm_intel_bo *dst_bo, |
unsigned int dst_offset, |
drm_intel_bo *src_bo, |
unsigned int src_offset, |
unsigned int size); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_buffer_objects.c |
---|
0,0 → 1,736 |
/************************************************************************** |
* |
* 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 "main/imports.h" |
#include "main/mtypes.h" |
#include "main/macros.h" |
#include "main/bufferobj.h" |
#include "brw_context.h" |
#include "intel_blit.h" |
#include "intel_buffer_objects.h" |
#include "intel_batchbuffer.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "brw_context.h" |
static GLboolean |
intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj); |
/** Allocates a new drm_intel_bo to store the data for the buffer object. */ |
static void |
intel_bufferobj_alloc_buffer(struct brw_context *brw, |
struct intel_buffer_object *intel_obj) |
{ |
intel_obj->buffer = drm_intel_bo_alloc(brw->bufmgr, "bufferobj", |
intel_obj->Base.Size, 64); |
/* the buffer might be bound as a uniform buffer, need to update it |
*/ |
brw->state.dirty.brw |= BRW_NEW_UNIFORM_BUFFER; |
} |
static void |
release_buffer(struct intel_buffer_object *intel_obj) |
{ |
drm_intel_bo_unreference(intel_obj->buffer); |
intel_obj->buffer = NULL; |
intel_obj->offset = 0; |
} |
/** |
* There is some duplication between mesa's bufferobjects and our |
* bufmgr buffers. Both have an integer handle and a hashtable to |
* lookup an opaque structure. It would be nice if the handles and |
* internal structure where somehow shared. |
*/ |
static struct gl_buffer_object * |
intel_bufferobj_alloc(struct gl_context * ctx, GLuint name, GLenum target) |
{ |
struct intel_buffer_object *obj = CALLOC_STRUCT(intel_buffer_object); |
_mesa_initialize_buffer_object(ctx, &obj->Base, name, target); |
obj->buffer = NULL; |
return &obj->Base; |
} |
/** |
* Deallocate/free a vertex/pixel buffer object. |
* Called via glDeleteBuffersARB(). |
*/ |
static void |
intel_bufferobj_free(struct gl_context * ctx, struct gl_buffer_object *obj) |
{ |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
assert(intel_obj); |
/* Buffer objects are automatically unmapped when deleting according |
* to the spec, but Mesa doesn't do UnmapBuffer for us at context destroy |
* (though it does if you call glDeleteBuffers) |
*/ |
if (obj->Pointer) |
intel_bufferobj_unmap(ctx, obj); |
drm_intel_bo_unreference(intel_obj->buffer); |
free(intel_obj); |
} |
/** |
* Allocate space for and store data in a buffer object. Any data that was |
* previously stored in the buffer object is lost. If data is NULL, |
* memory will be allocated, but no copy will occur. |
* Called via ctx->Driver.BufferData(). |
* \return true for success, false if out of memory |
*/ |
static GLboolean |
intel_bufferobj_data(struct gl_context * ctx, |
GLenum target, |
GLsizeiptrARB size, |
const GLvoid * data, |
GLenum usage, struct gl_buffer_object *obj) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
/* Part of the ABI, but this function doesn't use it. |
*/ |
(void) target; |
intel_obj->Base.Size = size; |
intel_obj->Base.Usage = usage; |
assert(!obj->Pointer); /* Mesa should have unmapped it */ |
if (intel_obj->buffer != NULL) |
release_buffer(intel_obj); |
if (size != 0) { |
intel_bufferobj_alloc_buffer(brw, intel_obj); |
if (!intel_obj->buffer) |
return false; |
if (data != NULL) |
drm_intel_bo_subdata(intel_obj->buffer, 0, size, data); |
} |
return true; |
} |
/** |
* Replace data in a subrange of buffer object. If the data range |
* specified by size + offset extends beyond the end of the buffer or |
* if data is NULL, no copy is performed. |
* Called via glBufferSubDataARB(). |
*/ |
static void |
intel_bufferobj_subdata(struct gl_context * ctx, |
GLintptrARB offset, |
GLsizeiptrARB size, |
const GLvoid * data, struct gl_buffer_object *obj) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
bool busy; |
if (size == 0) |
return; |
assert(intel_obj); |
busy = |
drm_intel_bo_busy(intel_obj->buffer) || |
drm_intel_bo_references(brw->batch.bo, intel_obj->buffer); |
if (busy) { |
if (size == intel_obj->Base.Size) { |
/* Replace the current busy bo with fresh data. */ |
drm_intel_bo_unreference(intel_obj->buffer); |
intel_bufferobj_alloc_buffer(brw, intel_obj); |
drm_intel_bo_subdata(intel_obj->buffer, 0, size, data); |
} else { |
perf_debug("Using a blit copy to avoid stalling on %ldb " |
"glBufferSubData() to a busy buffer object.\n", |
(long)size); |
drm_intel_bo *temp_bo = |
drm_intel_bo_alloc(brw->bufmgr, "subdata temp", size, 64); |
drm_intel_bo_subdata(temp_bo, 0, size, data); |
intel_emit_linear_blit(brw, |
intel_obj->buffer, offset, |
temp_bo, 0, |
size); |
drm_intel_bo_unreference(temp_bo); |
} |
} else { |
drm_intel_bo_subdata(intel_obj->buffer, offset, size, data); |
} |
} |
/** |
* Called via glGetBufferSubDataARB(). |
*/ |
static void |
intel_bufferobj_get_subdata(struct gl_context * ctx, |
GLintptrARB offset, |
GLsizeiptrARB size, |
GLvoid * data, struct gl_buffer_object *obj) |
{ |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
struct brw_context *brw = brw_context(ctx); |
assert(intel_obj); |
if (drm_intel_bo_references(brw->batch.bo, intel_obj->buffer)) { |
intel_batchbuffer_flush(brw); |
} |
drm_intel_bo_get_subdata(intel_obj->buffer, offset, size, data); |
} |
/** |
* Called via glMapBufferRange and glMapBuffer |
* |
* The goal of this extension is to allow apps to accumulate their rendering |
* at the same time as they accumulate their buffer object. Without it, |
* you'd end up blocking on execution of rendering every time you mapped |
* the buffer to put new data in. |
* |
* We support it in 3 ways: If unsynchronized, then don't bother |
* flushing the batchbuffer before mapping the buffer, which can save blocking |
* in many cases. If we would still block, and they allow the whole buffer |
* to be invalidated, then just allocate a new buffer to replace the old one. |
* If not, and we'd block, and they allow the subrange of the buffer to be |
* invalidated, then we can make a new little BO, let them write into that, |
* and blit it into the real BO at unmap time. |
*/ |
static void * |
intel_bufferobj_map_range(struct gl_context * ctx, |
GLintptr offset, GLsizeiptr length, |
GLbitfield access, struct gl_buffer_object *obj) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
assert(intel_obj); |
/* _mesa_MapBufferRange (GL entrypoint) sets these, but the vbo module also |
* internally uses our functions directly. |
*/ |
obj->Offset = offset; |
obj->Length = length; |
obj->AccessFlags = access; |
if (intel_obj->buffer == NULL) { |
obj->Pointer = NULL; |
return NULL; |
} |
/* If the access is synchronized (like a normal buffer mapping), then get |
* things flushed out so the later mapping syncs appropriately through GEM. |
* If the user doesn't care about existing buffer contents and mapping would |
* cause us to block, then throw out the old buffer. |
* |
* If they set INVALIDATE_BUFFER, we can pitch the current contents to |
* achieve the required synchronization. |
*/ |
if (!(access & GL_MAP_UNSYNCHRONIZED_BIT)) { |
if (drm_intel_bo_references(brw->batch.bo, intel_obj->buffer)) { |
if (access & GL_MAP_INVALIDATE_BUFFER_BIT) { |
drm_intel_bo_unreference(intel_obj->buffer); |
intel_bufferobj_alloc_buffer(brw, intel_obj); |
} else { |
perf_debug("Stalling on the GPU for mapping a busy buffer " |
"object\n"); |
intel_flush(ctx); |
} |
} else if (drm_intel_bo_busy(intel_obj->buffer) && |
(access & GL_MAP_INVALIDATE_BUFFER_BIT)) { |
drm_intel_bo_unreference(intel_obj->buffer); |
intel_bufferobj_alloc_buffer(brw, intel_obj); |
} |
} |
/* If the user is mapping a range of an active buffer object but |
* doesn't require the current contents of that range, make a new |
* BO, and we'll copy what they put in there out at unmap or |
* FlushRange time. |
*/ |
if ((access & GL_MAP_INVALIDATE_RANGE_BIT) && |
drm_intel_bo_busy(intel_obj->buffer)) { |
if (access & GL_MAP_FLUSH_EXPLICIT_BIT) { |
intel_obj->range_map_buffer = malloc(length); |
obj->Pointer = intel_obj->range_map_buffer; |
} else { |
intel_obj->range_map_bo = drm_intel_bo_alloc(brw->bufmgr, |
"range map", |
length, 64); |
if (!(access & GL_MAP_READ_BIT)) { |
drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo); |
} else { |
drm_intel_bo_map(intel_obj->range_map_bo, |
(access & GL_MAP_WRITE_BIT) != 0); |
} |
obj->Pointer = intel_obj->range_map_bo->virtual; |
} |
return obj->Pointer; |
} |
if (access & GL_MAP_UNSYNCHRONIZED_BIT) |
drm_intel_gem_bo_map_unsynchronized(intel_obj->buffer); |
else if (!(access & GL_MAP_READ_BIT)) { |
drm_intel_gem_bo_map_gtt(intel_obj->buffer); |
} else { |
drm_intel_bo_map(intel_obj->buffer, (access & GL_MAP_WRITE_BIT) != 0); |
} |
obj->Pointer = intel_obj->buffer->virtual + offset; |
return obj->Pointer; |
} |
/* Ideally we'd use a BO to avoid taking up cache space for the temporary |
* data, but FlushMappedBufferRange may be followed by further writes to |
* the pointer, so we would have to re-map after emitting our blit, which |
* would defeat the point. |
*/ |
static void |
intel_bufferobj_flush_mapped_range(struct gl_context *ctx, |
GLintptr offset, GLsizeiptr length, |
struct gl_buffer_object *obj) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
drm_intel_bo *temp_bo; |
/* Unless we're in the range map using a temporary system buffer, |
* there's no work to do. |
*/ |
if (intel_obj->range_map_buffer == NULL) |
return; |
if (length == 0) |
return; |
temp_bo = drm_intel_bo_alloc(brw->bufmgr, "range map flush", length, 64); |
drm_intel_bo_subdata(temp_bo, 0, length, intel_obj->range_map_buffer); |
intel_emit_linear_blit(brw, |
intel_obj->buffer, obj->Offset + offset, |
temp_bo, 0, |
length); |
drm_intel_bo_unreference(temp_bo); |
} |
/** |
* Called via glUnmapBuffer(). |
*/ |
static GLboolean |
intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_buffer_object *intel_obj = intel_buffer_object(obj); |
assert(intel_obj); |
assert(obj->Pointer); |
if (intel_obj->range_map_buffer != NULL) { |
/* Since we've emitted some blits to buffers that will (likely) be used |
* in rendering operations in other cache domains in this batch, emit a |
* flush. Once again, we wish for a domain tracker in libdrm to cover |
* usage inside of a batchbuffer. |
*/ |
intel_batchbuffer_emit_mi_flush(brw); |
free(intel_obj->range_map_buffer); |
intel_obj->range_map_buffer = NULL; |
} else if (intel_obj->range_map_bo != NULL) { |
drm_intel_bo_unmap(intel_obj->range_map_bo); |
intel_emit_linear_blit(brw, |
intel_obj->buffer, obj->Offset, |
intel_obj->range_map_bo, 0, |
obj->Length); |
/* Since we've emitted some blits to buffers that will (likely) be used |
* in rendering operations in other cache domains in this batch, emit a |
* flush. Once again, we wish for a domain tracker in libdrm to cover |
* usage inside of a batchbuffer. |
*/ |
intel_batchbuffer_emit_mi_flush(brw); |
drm_intel_bo_unreference(intel_obj->range_map_bo); |
intel_obj->range_map_bo = NULL; |
} else if (intel_obj->buffer != NULL) { |
drm_intel_bo_unmap(intel_obj->buffer); |
} |
obj->Pointer = NULL; |
obj->Offset = 0; |
obj->Length = 0; |
return true; |
} |
drm_intel_bo * |
intel_bufferobj_buffer(struct brw_context *brw, |
struct intel_buffer_object *intel_obj, |
GLuint flag) |
{ |
if (intel_obj->buffer == NULL) |
intel_bufferobj_alloc_buffer(brw, intel_obj); |
return intel_obj->buffer; |
} |
#define INTEL_UPLOAD_SIZE (64*1024) |
void |
intel_upload_finish(struct brw_context *brw) |
{ |
if (!brw->upload.bo) |
return; |
if (brw->upload.buffer_len) { |
drm_intel_bo_subdata(brw->upload.bo, |
brw->upload.buffer_offset, |
brw->upload.buffer_len, |
brw->upload.buffer); |
brw->upload.buffer_len = 0; |
} |
drm_intel_bo_unreference(brw->upload.bo); |
brw->upload.bo = NULL; |
} |
static void wrap_buffers(struct brw_context *brw, GLuint size) |
{ |
intel_upload_finish(brw); |
if (size < INTEL_UPLOAD_SIZE) |
size = INTEL_UPLOAD_SIZE; |
brw->upload.bo = drm_intel_bo_alloc(brw->bufmgr, "upload", size, 0); |
brw->upload.offset = 0; |
} |
void intel_upload_data(struct brw_context *brw, |
const void *ptr, GLuint size, GLuint align, |
drm_intel_bo **return_bo, |
GLuint *return_offset) |
{ |
GLuint base, delta; |
base = (brw->upload.offset + align - 1) / align * align; |
if (brw->upload.bo == NULL || base + size > brw->upload.bo->size) { |
wrap_buffers(brw, size); |
base = 0; |
} |
drm_intel_bo_reference(brw->upload.bo); |
*return_bo = brw->upload.bo; |
*return_offset = base; |
delta = base - brw->upload.offset; |
if (brw->upload.buffer_len && |
brw->upload.buffer_len + delta + size > sizeof(brw->upload.buffer)) |
{ |
drm_intel_bo_subdata(brw->upload.bo, |
brw->upload.buffer_offset, |
brw->upload.buffer_len, |
brw->upload.buffer); |
brw->upload.buffer_len = 0; |
} |
if (size < sizeof(brw->upload.buffer)) |
{ |
if (brw->upload.buffer_len == 0) |
brw->upload.buffer_offset = base; |
else |
brw->upload.buffer_len += delta; |
memcpy(brw->upload.buffer + brw->upload.buffer_len, ptr, size); |
brw->upload.buffer_len += size; |
} |
else |
{ |
drm_intel_bo_subdata(brw->upload.bo, base, size, ptr); |
} |
brw->upload.offset = base + size; |
} |
void *intel_upload_map(struct brw_context *brw, GLuint size, GLuint align) |
{ |
GLuint base, delta; |
char *ptr; |
base = (brw->upload.offset + align - 1) / align * align; |
if (brw->upload.bo == NULL || base + size > brw->upload.bo->size) { |
wrap_buffers(brw, size); |
base = 0; |
} |
delta = base - brw->upload.offset; |
if (brw->upload.buffer_len && |
brw->upload.buffer_len + delta + size > sizeof(brw->upload.buffer)) |
{ |
drm_intel_bo_subdata(brw->upload.bo, |
brw->upload.buffer_offset, |
brw->upload.buffer_len, |
brw->upload.buffer); |
brw->upload.buffer_len = 0; |
} |
if (size <= sizeof(brw->upload.buffer)) { |
if (brw->upload.buffer_len == 0) |
brw->upload.buffer_offset = base; |
else |
brw->upload.buffer_len += delta; |
ptr = brw->upload.buffer + brw->upload.buffer_len; |
brw->upload.buffer_len += size; |
} else |
ptr = malloc(size); |
return ptr; |
} |
void intel_upload_unmap(struct brw_context *brw, |
const void *ptr, GLuint size, GLuint align, |
drm_intel_bo **return_bo, |
GLuint *return_offset) |
{ |
GLuint base; |
base = (brw->upload.offset + align - 1) / align * align; |
if (size > sizeof(brw->upload.buffer)) { |
drm_intel_bo_subdata(brw->upload.bo, base, size, ptr); |
free((void*)ptr); |
} |
drm_intel_bo_reference(brw->upload.bo); |
*return_bo = brw->upload.bo; |
*return_offset = base; |
brw->upload.offset = base + size; |
} |
drm_intel_bo * |
intel_bufferobj_source(struct brw_context *brw, |
struct intel_buffer_object *intel_obj, |
GLuint align, GLuint *offset) |
{ |
*offset = intel_obj->offset; |
return intel_obj->buffer; |
} |
static void |
intel_bufferobj_copy_subdata(struct gl_context *ctx, |
struct gl_buffer_object *src, |
struct gl_buffer_object *dst, |
GLintptr read_offset, GLintptr write_offset, |
GLsizeiptr size) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_buffer_object *intel_src = intel_buffer_object(src); |
struct intel_buffer_object *intel_dst = intel_buffer_object(dst); |
drm_intel_bo *src_bo, *dst_bo; |
GLuint src_offset; |
if (size == 0) |
return; |
dst_bo = intel_bufferobj_buffer(brw, intel_dst, INTEL_WRITE_PART); |
src_bo = intel_bufferobj_source(brw, intel_src, 64, &src_offset); |
intel_emit_linear_blit(brw, |
dst_bo, write_offset, |
src_bo, read_offset + src_offset, size); |
/* Since we've emitted some blits to buffers that will (likely) be used |
* in rendering operations in other cache domains in this batch, emit a |
* flush. Once again, we wish for a domain tracker in libdrm to cover |
* usage inside of a batchbuffer. |
*/ |
intel_batchbuffer_emit_mi_flush(brw); |
} |
static GLenum |
intel_buffer_purgeable(drm_intel_bo *buffer) |
{ |
int retained = 0; |
if (buffer != NULL) |
retained = drm_intel_bo_madvise (buffer, I915_MADV_DONTNEED); |
return retained ? GL_VOLATILE_APPLE : GL_RELEASED_APPLE; |
} |
static GLenum |
intel_buffer_object_purgeable(struct gl_context * ctx, |
struct gl_buffer_object *obj, |
GLenum option) |
{ |
struct intel_buffer_object *intel_obj = intel_buffer_object (obj); |
if (intel_obj->buffer != NULL) |
return intel_buffer_purgeable(intel_obj->buffer); |
if (option == GL_RELEASED_APPLE) { |
return GL_RELEASED_APPLE; |
} else { |
/* XXX Create the buffer and madvise(MADV_DONTNEED)? */ |
struct brw_context *brw = brw_context(ctx); |
drm_intel_bo *bo = intel_bufferobj_buffer(brw, intel_obj, INTEL_READ); |
return intel_buffer_purgeable(bo); |
} |
} |
static GLenum |
intel_texture_object_purgeable(struct gl_context * ctx, |
struct gl_texture_object *obj, |
GLenum option) |
{ |
struct intel_texture_object *intel; |
(void) ctx; |
(void) option; |
intel = intel_texture_object(obj); |
if (intel->mt == NULL || intel->mt->region == NULL) |
return GL_RELEASED_APPLE; |
return intel_buffer_purgeable(intel->mt->region->bo); |
} |
static GLenum |
intel_render_object_purgeable(struct gl_context * ctx, |
struct gl_renderbuffer *obj, |
GLenum option) |
{ |
struct intel_renderbuffer *intel; |
(void) ctx; |
(void) option; |
intel = intel_renderbuffer(obj); |
if (intel->mt == NULL) |
return GL_RELEASED_APPLE; |
return intel_buffer_purgeable(intel->mt->region->bo); |
} |
static GLenum |
intel_buffer_unpurgeable(drm_intel_bo *buffer) |
{ |
int retained; |
retained = 0; |
if (buffer != NULL) |
retained = drm_intel_bo_madvise (buffer, I915_MADV_WILLNEED); |
return retained ? GL_RETAINED_APPLE : GL_UNDEFINED_APPLE; |
} |
static GLenum |
intel_buffer_object_unpurgeable(struct gl_context * ctx, |
struct gl_buffer_object *obj, |
GLenum option) |
{ |
(void) ctx; |
(void) option; |
return intel_buffer_unpurgeable(intel_buffer_object (obj)->buffer); |
} |
static GLenum |
intel_texture_object_unpurgeable(struct gl_context * ctx, |
struct gl_texture_object *obj, |
GLenum option) |
{ |
struct intel_texture_object *intel; |
(void) ctx; |
(void) option; |
intel = intel_texture_object(obj); |
if (intel->mt == NULL || intel->mt->region == NULL) |
return GL_UNDEFINED_APPLE; |
return intel_buffer_unpurgeable(intel->mt->region->bo); |
} |
static GLenum |
intel_render_object_unpurgeable(struct gl_context * ctx, |
struct gl_renderbuffer *obj, |
GLenum option) |
{ |
struct intel_renderbuffer *intel; |
(void) ctx; |
(void) option; |
intel = intel_renderbuffer(obj); |
if (intel->mt == NULL) |
return GL_UNDEFINED_APPLE; |
return intel_buffer_unpurgeable(intel->mt->region->bo); |
} |
void |
intelInitBufferObjectFuncs(struct dd_function_table *functions) |
{ |
functions->NewBufferObject = intel_bufferobj_alloc; |
functions->DeleteBuffer = intel_bufferobj_free; |
functions->BufferData = intel_bufferobj_data; |
functions->BufferSubData = intel_bufferobj_subdata; |
functions->GetBufferSubData = intel_bufferobj_get_subdata; |
functions->MapBufferRange = intel_bufferobj_map_range; |
functions->FlushMappedBufferRange = intel_bufferobj_flush_mapped_range; |
functions->UnmapBuffer = intel_bufferobj_unmap; |
functions->CopyBufferSubData = intel_bufferobj_copy_subdata; |
functions->BufferObjectPurgeable = intel_buffer_object_purgeable; |
functions->TextureObjectPurgeable = intel_texture_object_purgeable; |
functions->RenderObjectPurgeable = intel_render_object_purgeable; |
functions->BufferObjectUnpurgeable = intel_buffer_object_unpurgeable; |
functions->TextureObjectUnpurgeable = intel_texture_object_unpurgeable; |
functions->RenderObjectUnpurgeable = intel_render_object_unpurgeable; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_buffer_objects.h |
---|
0,0 → 1,86 |
/************************************************************************** |
* |
* Copyright 2005 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 INTEL_BUFFEROBJ_H |
#define INTEL_BUFFEROBJ_H |
#include "main/mtypes.h" |
struct brw_context; |
struct gl_buffer_object; |
/** |
* Intel vertex/pixel buffer object, derived from Mesa's gl_buffer_object. |
*/ |
struct intel_buffer_object |
{ |
struct gl_buffer_object Base; |
drm_intel_bo *buffer; /* the low-level buffer manager's buffer handle */ |
GLuint offset; /* any offset into that buffer */ |
drm_intel_bo *range_map_bo; |
void *range_map_buffer; |
unsigned int range_map_offset; |
}; |
/* Get the bm buffer associated with a GL bufferobject: |
*/ |
drm_intel_bo *intel_bufferobj_buffer(struct brw_context *brw, |
struct intel_buffer_object *obj, |
GLuint flag); |
drm_intel_bo *intel_bufferobj_source(struct brw_context *brw, |
struct intel_buffer_object *obj, |
GLuint align, |
GLuint *offset); |
void intel_upload_data(struct brw_context *brw, |
const void *ptr, GLuint size, GLuint align, |
drm_intel_bo **return_bo, |
GLuint *return_offset); |
void *intel_upload_map(struct brw_context *brw, |
GLuint size, GLuint align); |
void intel_upload_unmap(struct brw_context *brw, |
const void *ptr, GLuint size, GLuint align, |
drm_intel_bo **return_bo, |
GLuint *return_offset); |
void intel_upload_finish(struct brw_context *brw); |
/* Hook the bufferobject implementation into mesa: |
*/ |
void intelInitBufferObjectFuncs(struct dd_function_table *functions); |
static inline struct intel_buffer_object * |
intel_buffer_object(struct gl_buffer_object *obj) |
{ |
return (struct intel_buffer_object *) obj; |
} |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_buffers.c |
---|
0,0 → 1,100 |
/************************************************************************** |
* |
* 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 "brw_context.h" |
#include "intel_buffers.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "main/fbobject.h" |
#include "main/framebuffer.h" |
#include "main/renderbuffer.h" |
/** |
* Check if we're about to draw into the front color buffer. |
* If so, set the brw->front_buffer_dirty field to true. |
*/ |
void |
intel_check_front_buffer_rendering(struct brw_context *brw) |
{ |
struct gl_context *ctx = &brw->ctx; |
const struct gl_framebuffer *fb = ctx->DrawBuffer; |
if (_mesa_is_winsys_fbo(fb)) { |
/* drawing to window system buffer */ |
if (fb->_NumColorDrawBuffers > 0) { |
if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { |
brw->front_buffer_dirty = true; |
} |
} |
} |
} |
static void |
intelDrawBuffer(struct gl_context * ctx, GLenum mode) |
{ |
if (ctx->DrawBuffer && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
struct brw_context *const brw = brw_context(ctx); |
const bool was_front_buffer_rendering = brw->is_front_buffer_rendering; |
brw->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) |
|| (mode == GL_FRONT) || (mode == GL_FRONT_AND_BACK); |
/* If we weren't front-buffer rendering before but we are now, |
* invalidate our DRI drawable so we'll ask for new buffers |
* (including the fake front) before we start rendering again. |
*/ |
if (!was_front_buffer_rendering && brw->is_front_buffer_rendering) |
dri2InvalidateDrawable(brw->driContext->driDrawablePriv); |
} |
} |
static void |
intelReadBuffer(struct gl_context * ctx, GLenum mode) |
{ |
if (ctx->DrawBuffer && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
struct brw_context *const brw = brw_context(ctx); |
const bool was_front_buffer_reading = brw->is_front_buffer_reading; |
brw->is_front_buffer_reading = mode == GL_FRONT_LEFT || mode == GL_FRONT; |
/* If we weren't front-buffer reading before but we are now, |
* invalidate our DRI drawable so we'll ask for new buffers |
* (including the fake front) before we start reading again. |
*/ |
if (!was_front_buffer_reading && brw->is_front_buffer_reading) |
dri2InvalidateDrawable(brw->driContext->driReadablePriv); |
} |
} |
void |
intelInitBufferFuncs(struct dd_function_table *functions) |
{ |
functions->DrawBuffer = intelDrawBuffer; |
functions->ReadBuffer = intelReadBuffer; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_buffers.h |
---|
0,0 → 1,42 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_BUFFERS_H |
#define INTEL_BUFFERS_H |
#include "dri_util.h" |
#include "drm.h" |
#include "brw_context.h" |
struct intel_framebuffer; |
extern void intel_check_front_buffer_rendering(struct brw_context *brw); |
extern void intelInitBufferFuncs(struct dd_function_table *functions); |
#endif /* INTEL_BUFFERS_H */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_chipset.h |
---|
0,0 → 1,243 |
/* |
* Copyright © 2007 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
#define PCI_CHIP_IGD_GM 0xA011 |
#define PCI_CHIP_IGD_G 0xA001 |
#define IS_IGDGM(devid) (devid == PCI_CHIP_IGD_GM) |
#define IS_IGDG(devid) (devid == PCI_CHIP_IGD_G) |
#define IS_IGD(devid) (IS_IGDG(devid) || IS_IGDGM(devid)) |
#define PCI_CHIP_I965_G 0x29A2 |
#define PCI_CHIP_I965_Q 0x2992 |
#define PCI_CHIP_I965_G_1 0x2982 |
#define PCI_CHIP_I946_GZ 0x2972 |
#define PCI_CHIP_I965_GM 0x2A02 |
#define PCI_CHIP_I965_GME 0x2A12 |
#define PCI_CHIP_GM45_GM 0x2A42 |
#define PCI_CHIP_IGD_E_G 0x2E02 |
#define PCI_CHIP_Q45_G 0x2E12 |
#define PCI_CHIP_G45_G 0x2E22 |
#define PCI_CHIP_G41_G 0x2E32 |
#define PCI_CHIP_B43_G 0x2E42 |
#define PCI_CHIP_B43_G1 0x2E92 |
#define PCI_CHIP_ILD_G 0x0042 |
#define PCI_CHIP_ILM_G 0x0046 |
#define PCI_CHIP_SANDYBRIDGE_GT1 0x0102 /* Desktop */ |
#define PCI_CHIP_SANDYBRIDGE_GT2 0x0112 |
#define PCI_CHIP_SANDYBRIDGE_GT2_PLUS 0x0122 |
#define PCI_CHIP_SANDYBRIDGE_M_GT1 0x0106 /* Mobile */ |
#define PCI_CHIP_SANDYBRIDGE_M_GT2 0x0116 |
#define PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS 0x0126 |
#define PCI_CHIP_SANDYBRIDGE_S 0x010A /* Server */ |
#define PCI_CHIP_IVYBRIDGE_GT1 0x0152 /* Desktop */ |
#define PCI_CHIP_IVYBRIDGE_GT2 0x0162 |
#define PCI_CHIP_IVYBRIDGE_M_GT1 0x0156 /* Mobile */ |
#define PCI_CHIP_IVYBRIDGE_M_GT2 0x0166 |
#define PCI_CHIP_IVYBRIDGE_S_GT1 0x015a /* Server */ |
#define PCI_CHIP_IVYBRIDGE_S_GT2 0x016a |
#define PCI_CHIP_BAYTRAIL_M_1 0x0F31 |
#define PCI_CHIP_BAYTRAIL_M_2 0x0F32 |
#define PCI_CHIP_BAYTRAIL_M_3 0x0F33 |
#define PCI_CHIP_BAYTRAIL_M_4 0x0157 |
#define PCI_CHIP_BAYTRAIL_D 0x0155 |
#define PCI_CHIP_HASWELL_GT1 0x0402 /* Desktop */ |
#define PCI_CHIP_HASWELL_GT2 0x0412 |
#define PCI_CHIP_HASWELL_GT3 0x0422 |
#define PCI_CHIP_HASWELL_M_GT1 0x0406 /* Mobile */ |
#define PCI_CHIP_HASWELL_M_GT2 0x0416 |
#define PCI_CHIP_HASWELL_M_GT3 0x0426 |
#define PCI_CHIP_HASWELL_S_GT1 0x040A /* Server */ |
#define PCI_CHIP_HASWELL_S_GT2 0x041A |
#define PCI_CHIP_HASWELL_S_GT3 0x042A |
#define PCI_CHIP_HASWELL_B_GT1 0x040B /* Reserved */ |
#define PCI_CHIP_HASWELL_B_GT2 0x041B |
#define PCI_CHIP_HASWELL_B_GT3 0x042B |
#define PCI_CHIP_HASWELL_E_GT1 0x040E /* Reserved */ |
#define PCI_CHIP_HASWELL_E_GT2 0x041E |
#define PCI_CHIP_HASWELL_E_GT3 0x042E |
#define PCI_CHIP_HASWELL_SDV_GT1 0x0C02 /* Desktop */ |
#define PCI_CHIP_HASWELL_SDV_GT2 0x0C12 |
#define PCI_CHIP_HASWELL_SDV_GT3 0x0C22 |
#define PCI_CHIP_HASWELL_SDV_M_GT1 0x0C06 /* Mobile */ |
#define PCI_CHIP_HASWELL_SDV_M_GT2 0x0C16 |
#define PCI_CHIP_HASWELL_SDV_M_GT3 0x0C26 |
#define PCI_CHIP_HASWELL_SDV_S_GT1 0x0C0A /* Server */ |
#define PCI_CHIP_HASWELL_SDV_S_GT2 0x0C1A |
#define PCI_CHIP_HASWELL_SDV_S_GT3 0x0C2A |
#define PCI_CHIP_HASWELL_SDV_B_GT1 0x0C0B /* Reserved */ |
#define PCI_CHIP_HASWELL_SDV_B_GT2 0x0C1B |
#define PCI_CHIP_HASWELL_SDV_B_GT3 0x0C2B |
#define PCI_CHIP_HASWELL_SDV_E_GT1 0x0C0E /* Reserved */ |
#define PCI_CHIP_HASWELL_SDV_E_GT2 0x0C1E |
#define PCI_CHIP_HASWELL_SDV_E_GT3 0x0C2E |
#define PCI_CHIP_HASWELL_ULT_GT1 0x0A02 /* Desktop */ |
#define PCI_CHIP_HASWELL_ULT_GT2 0x0A12 |
#define PCI_CHIP_HASWELL_ULT_GT3 0x0A22 |
#define PCI_CHIP_HASWELL_ULT_M_GT1 0x0A06 /* Mobile */ |
#define PCI_CHIP_HASWELL_ULT_M_GT2 0x0A16 |
#define PCI_CHIP_HASWELL_ULT_M_GT3 0x0A26 |
#define PCI_CHIP_HASWELL_ULT_S_GT1 0x0A0A /* Server */ |
#define PCI_CHIP_HASWELL_ULT_S_GT2 0x0A1A |
#define PCI_CHIP_HASWELL_ULT_S_GT3 0x0A2A |
#define PCI_CHIP_HASWELL_ULT_B_GT1 0x0A0B /* Reserved */ |
#define PCI_CHIP_HASWELL_ULT_B_GT2 0x0A1B |
#define PCI_CHIP_HASWELL_ULT_B_GT3 0x0A2B |
#define PCI_CHIP_HASWELL_ULT_E_GT1 0x0A0E /* Reserved */ |
#define PCI_CHIP_HASWELL_ULT_E_GT2 0x0A1E |
#define PCI_CHIP_HASWELL_ULT_E_GT3 0x0A2E |
#define PCI_CHIP_HASWELL_CRW_GT1 0x0D02 /* Desktop */ |
#define PCI_CHIP_HASWELL_CRW_GT2 0x0D12 |
#define PCI_CHIP_HASWELL_CRW_GT3 0x0D22 |
#define PCI_CHIP_HASWELL_CRW_M_GT1 0x0D06 /* Mobile */ |
#define PCI_CHIP_HASWELL_CRW_M_GT2 0x0D16 |
#define PCI_CHIP_HASWELL_CRW_M_GT3 0x0D26 |
#define PCI_CHIP_HASWELL_CRW_S_GT1 0x0D0A /* Server */ |
#define PCI_CHIP_HASWELL_CRW_S_GT2 0x0D1A |
#define PCI_CHIP_HASWELL_CRW_S_GT3 0x0D2A |
#define PCI_CHIP_HASWELL_CRW_B_GT1 0x0D0B /* Reserved */ |
#define PCI_CHIP_HASWELL_CRW_B_GT2 0x0D1B |
#define PCI_CHIP_HASWELL_CRW_B_GT3 0x0D2B |
#define PCI_CHIP_HASWELL_CRW_E_GT1 0x0D0E /* Reserved */ |
#define PCI_CHIP_HASWELL_CRW_E_GT2 0x0D1E |
#define PCI_CHIP_HASWELL_CRW_E_GT3 0x0D2E |
#define IS_G45(devid) (devid == PCI_CHIP_IGD_E_G || \ |
devid == PCI_CHIP_Q45_G || \ |
devid == PCI_CHIP_G45_G || \ |
devid == PCI_CHIP_G41_G || \ |
devid == PCI_CHIP_B43_G || \ |
devid == PCI_CHIP_B43_G1) |
#define IS_GM45(devid) (devid == PCI_CHIP_GM45_GM) |
#define IS_G4X(devid) (IS_G45(devid) || IS_GM45(devid)) |
#define IS_ILD(devid) (devid == PCI_CHIP_ILD_G) |
#define IS_ILM(devid) (devid == PCI_CHIP_ILM_G) |
#define IS_GEN5(devid) (IS_ILD(devid) || IS_ILM(devid)) |
#define IS_SNB_GT1(devid) (devid == PCI_CHIP_SANDYBRIDGE_GT1 || \ |
devid == PCI_CHIP_SANDYBRIDGE_M_GT1 || \ |
devid == PCI_CHIP_SANDYBRIDGE_S) |
#define IS_SNB_GT2(devid) (devid == PCI_CHIP_SANDYBRIDGE_GT2 || \ |
devid == PCI_CHIP_SANDYBRIDGE_GT2_PLUS || \ |
devid == PCI_CHIP_SANDYBRIDGE_M_GT2 || \ |
devid == PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS) |
#define IS_GEN6(devid) (IS_SNB_GT1(devid) || IS_SNB_GT2(devid)) |
#define IS_IVB_GT1(devid) (devid == PCI_CHIP_IVYBRIDGE_GT1 || \ |
devid == PCI_CHIP_IVYBRIDGE_M_GT1 || \ |
devid == PCI_CHIP_IVYBRIDGE_S_GT1) |
#define IS_IVB_GT2(devid) (devid == PCI_CHIP_IVYBRIDGE_GT2 || \ |
devid == PCI_CHIP_IVYBRIDGE_M_GT2 || \ |
devid == PCI_CHIP_IVYBRIDGE_S_GT2) |
#define IS_IVYBRIDGE(devid) (IS_IVB_GT1(devid) || IS_IVB_GT2(devid)) |
#define IS_BAYTRAIL(devid) (devid == PCI_CHIP_BAYTRAIL_M_1 || \ |
devid == PCI_CHIP_BAYTRAIL_M_2 || \ |
devid == PCI_CHIP_BAYTRAIL_M_3 || \ |
devid == PCI_CHIP_BAYTRAIL_M_4 || \ |
devid == PCI_CHIP_BAYTRAIL_D) |
#define IS_GEN7(devid) (IS_IVYBRIDGE(devid) || \ |
IS_BAYTRAIL(devid) || \ |
IS_HASWELL(devid)) |
#define IS_HSW_GT1(devid) (devid == PCI_CHIP_HASWELL_GT1 || \ |
devid == PCI_CHIP_HASWELL_M_GT1 || \ |
devid == PCI_CHIP_HASWELL_S_GT1 || \ |
devid == PCI_CHIP_HASWELL_B_GT1 || \ |
devid == PCI_CHIP_HASWELL_E_GT1 || \ |
devid == PCI_CHIP_HASWELL_SDV_GT1 || \ |
devid == PCI_CHIP_HASWELL_SDV_M_GT1 || \ |
devid == PCI_CHIP_HASWELL_SDV_S_GT1 || \ |
devid == PCI_CHIP_HASWELL_SDV_B_GT1 || \ |
devid == PCI_CHIP_HASWELL_SDV_E_GT1 || \ |
devid == PCI_CHIP_HASWELL_ULT_GT1 || \ |
devid == PCI_CHIP_HASWELL_ULT_M_GT1 || \ |
devid == PCI_CHIP_HASWELL_ULT_S_GT1 || \ |
devid == PCI_CHIP_HASWELL_ULT_B_GT1 || \ |
devid == PCI_CHIP_HASWELL_ULT_E_GT1 || \ |
devid == PCI_CHIP_HASWELL_CRW_GT1 || \ |
devid == PCI_CHIP_HASWELL_CRW_M_GT1 || \ |
devid == PCI_CHIP_HASWELL_CRW_S_GT1 || \ |
devid == PCI_CHIP_HASWELL_CRW_B_GT1 || \ |
devid == PCI_CHIP_HASWELL_CRW_E_GT1) |
#define IS_HSW_GT2(devid) (devid == PCI_CHIP_HASWELL_GT2 || \ |
devid == PCI_CHIP_HASWELL_M_GT2 || \ |
devid == PCI_CHIP_HASWELL_S_GT2 || \ |
devid == PCI_CHIP_HASWELL_B_GT2 || \ |
devid == PCI_CHIP_HASWELL_E_GT2 || \ |
devid == PCI_CHIP_HASWELL_SDV_GT2 || \ |
devid == PCI_CHIP_HASWELL_SDV_M_GT2 || \ |
devid == PCI_CHIP_HASWELL_SDV_S_GT2 || \ |
devid == PCI_CHIP_HASWELL_SDV_B_GT2 || \ |
devid == PCI_CHIP_HASWELL_SDV_E_GT2 || \ |
devid == PCI_CHIP_HASWELL_ULT_GT2 || \ |
devid == PCI_CHIP_HASWELL_ULT_M_GT2 || \ |
devid == PCI_CHIP_HASWELL_ULT_S_GT2 || \ |
devid == PCI_CHIP_HASWELL_ULT_B_GT2 || \ |
devid == PCI_CHIP_HASWELL_ULT_E_GT2 || \ |
devid == PCI_CHIP_HASWELL_CRW_GT2 || \ |
devid == PCI_CHIP_HASWELL_CRW_M_GT2 || \ |
devid == PCI_CHIP_HASWELL_CRW_S_GT2 || \ |
devid == PCI_CHIP_HASWELL_CRW_B_GT2 || \ |
devid == PCI_CHIP_HASWELL_CRW_E_GT2) |
#define IS_HSW_GT3(devid) (devid == PCI_CHIP_HASWELL_GT3 || \ |
devid == PCI_CHIP_HASWELL_M_GT3 || \ |
devid == PCI_CHIP_HASWELL_S_GT3 || \ |
devid == PCI_CHIP_HASWELL_B_GT3 || \ |
devid == PCI_CHIP_HASWELL_E_GT3 || \ |
devid == PCI_CHIP_HASWELL_SDV_GT3 || \ |
devid == PCI_CHIP_HASWELL_SDV_M_GT3 || \ |
devid == PCI_CHIP_HASWELL_SDV_S_GT3 || \ |
devid == PCI_CHIP_HASWELL_SDV_B_GT3 || \ |
devid == PCI_CHIP_HASWELL_SDV_E_GT3 || \ |
devid == PCI_CHIP_HASWELL_ULT_GT3 || \ |
devid == PCI_CHIP_HASWELL_ULT_M_GT3 || \ |
devid == PCI_CHIP_HASWELL_ULT_S_GT3 || \ |
devid == PCI_CHIP_HASWELL_ULT_B_GT3 || \ |
devid == PCI_CHIP_HASWELL_ULT_E_GT3 || \ |
devid == PCI_CHIP_HASWELL_CRW_GT3 || \ |
devid == PCI_CHIP_HASWELL_CRW_M_GT3 || \ |
devid == PCI_CHIP_HASWELL_CRW_S_GT3 || \ |
devid == PCI_CHIP_HASWELL_CRW_B_GT3 || \ |
devid == PCI_CHIP_HASWELL_CRW_E_GT3) |
#define IS_HASWELL(devid) (IS_HSW_GT1(devid) || \ |
IS_HSW_GT2(devid) || \ |
IS_HSW_GT3(devid)) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_context.c |
---|
0,0 → 1,919 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/context.h" |
#include "main/extensions.h" |
#include "main/fbobject.h" |
#include "main/framebuffer.h" |
#include "main/imports.h" |
#include "main/renderbuffer.h" |
#include "swrast/swrast.h" |
#include "swrast_setup/swrast_setup.h" |
#include "tnl/tnl.h" |
#include "drivers/common/driverfuncs.h" |
#include "drivers/common/meta.h" |
#include "intel_chipset.h" |
#include "intel_buffers.h" |
#include "intel_tex.h" |
#include "intel_batchbuffer.h" |
#include "intel_pixel.h" |
#include "intel_regions.h" |
#include "intel_buffer_objects.h" |
#include "intel_fbo.h" |
#include "intel_bufmgr.h" |
#include "intel_screen.h" |
#include "intel_mipmap_tree.h" |
#include "utils.h" |
#include "../glsl/ralloc.h" |
#ifndef INTEL_DEBUG |
int INTEL_DEBUG = (0); |
#endif |
static const GLubyte * |
intelGetString(struct gl_context * ctx, GLenum name) |
{ |
const struct brw_context *const brw = brw_context(ctx); |
const char *chipset; |
static char buffer[128]; |
switch (name) { |
case GL_VENDOR: |
return (GLubyte *) "Intel Open Source Technology Center"; |
break; |
case GL_RENDERER: |
switch (brw->intelScreen->deviceID) { |
#undef CHIPSET |
#define CHIPSET(id, symbol, str) case id: chipset = str; break; |
#include "pci_ids/i965_pci_ids.h" |
default: |
chipset = "Unknown Intel Chipset"; |
break; |
} |
(void) driGetRendererString(buffer, chipset, 0); |
return (GLubyte *) buffer; |
default: |
return NULL; |
} |
} |
void |
intel_resolve_for_dri2_flush(struct brw_context *brw, |
__DRIdrawable *drawable) |
{ |
if (brw->gen < 6) { |
/* MSAA and fast color clear are not supported, so don't waste time |
* checking whether a resolve is needed. |
*/ |
return; |
} |
struct gl_framebuffer *fb = drawable->driverPrivate; |
struct intel_renderbuffer *rb; |
/* Usually, only the back buffer will need to be downsampled. However, |
* the front buffer will also need it if the user has rendered into it. |
*/ |
static const gl_buffer_index buffers[2] = { |
BUFFER_BACK_LEFT, |
BUFFER_FRONT_LEFT, |
}; |
for (int i = 0; i < 2; ++i) { |
rb = intel_get_renderbuffer(fb, buffers[i]); |
if (rb == NULL || rb->mt == NULL) |
continue; |
if (rb->mt->num_samples <= 1) |
intel_miptree_resolve_color(brw, rb->mt); |
else |
intel_miptree_downsample(brw, rb->mt); |
} |
} |
static void |
intel_flush_front(struct gl_context *ctx) |
{ |
struct brw_context *brw = brw_context(ctx); |
__DRIcontext *driContext = brw->driContext; |
__DRIdrawable *driDrawable = driContext->driDrawablePriv; |
__DRIscreen *const screen = brw->intelScreen->driScrnPriv; |
if (brw->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
if (screen->dri2.loader->flushFrontBuffer != NULL && |
driDrawable && |
driDrawable->loaderPrivate) { |
/* Resolve before flushing FAKE_FRONT_LEFT to FRONT_LEFT. |
* |
* This potentially resolves both front and back buffer. It |
* is unnecessary to resolve the back, but harms nothing except |
* performance. And no one cares about front-buffer render |
* performance. |
*/ |
intel_resolve_for_dri2_flush(brw, driDrawable); |
screen->dri2.loader->flushFrontBuffer(driDrawable, |
driDrawable->loaderPrivate); |
/* We set the dirty bit in intel_prepare_render() if we're |
* front buffer rendering once we get there. |
*/ |
brw->front_buffer_dirty = false; |
} |
} |
} |
static unsigned |
intel_bits_per_pixel(const struct intel_renderbuffer *rb) |
{ |
return _mesa_get_format_bytes(intel_rb_format(rb)) * 8; |
} |
static void |
intel_query_dri2_buffers(struct brw_context *brw, |
__DRIdrawable *drawable, |
__DRIbuffer **buffers, |
int *count); |
static void |
intel_process_dri2_buffer(struct brw_context *brw, |
__DRIdrawable *drawable, |
__DRIbuffer *buffer, |
struct intel_renderbuffer *rb, |
const char *buffer_name); |
void |
intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) |
{ |
struct gl_framebuffer *fb = drawable->driverPrivate; |
struct intel_renderbuffer *rb; |
struct brw_context *brw = context->driverPrivate; |
__DRIbuffer *buffers = NULL; |
int i, count; |
const char *region_name; |
/* Set this up front, so that in case our buffers get invalidated |
* while we're getting new buffers, we don't clobber the stamp and |
* thus ignore the invalidate. */ |
drawable->lastStamp = drawable->dri2.stamp; |
if (unlikely(INTEL_DEBUG & DEBUG_DRI)) |
fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); |
intel_query_dri2_buffers(brw, drawable, &buffers, &count); |
if (buffers == NULL) |
return; |
for (i = 0; i < count; i++) { |
switch (buffers[i].attachment) { |
case __DRI_BUFFER_FRONT_LEFT: |
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
region_name = "dri2 front buffer"; |
break; |
case __DRI_BUFFER_FAKE_FRONT_LEFT: |
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
region_name = "dri2 fake front buffer"; |
break; |
case __DRI_BUFFER_BACK_LEFT: |
rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); |
region_name = "dri2 back buffer"; |
break; |
case __DRI_BUFFER_DEPTH: |
case __DRI_BUFFER_HIZ: |
case __DRI_BUFFER_DEPTH_STENCIL: |
case __DRI_BUFFER_STENCIL: |
case __DRI_BUFFER_ACCUM: |
default: |
fprintf(stderr, |
"unhandled buffer attach event, attachment type %d\n", |
buffers[i].attachment); |
return; |
} |
intel_process_dri2_buffer(brw, drawable, &buffers[i], rb, region_name); |
} |
driUpdateFramebufferSize(&brw->ctx, drawable); |
} |
/** |
* intel_prepare_render should be called anywhere that curent read/drawbuffer |
* state is required. |
*/ |
void |
intel_prepare_render(struct brw_context *brw) |
{ |
__DRIcontext *driContext = brw->driContext; |
__DRIdrawable *drawable; |
drawable = driContext->driDrawablePriv; |
if (drawable && drawable->dri2.stamp != driContext->dri2.draw_stamp) { |
if (drawable->lastStamp != drawable->dri2.stamp) |
intel_update_renderbuffers(driContext, drawable); |
driContext->dri2.draw_stamp = drawable->dri2.stamp; |
} |
drawable = driContext->driReadablePriv; |
if (drawable && drawable->dri2.stamp != driContext->dri2.read_stamp) { |
if (drawable->lastStamp != drawable->dri2.stamp) |
intel_update_renderbuffers(driContext, drawable); |
driContext->dri2.read_stamp = drawable->dri2.stamp; |
} |
/* If we're currently rendering to the front buffer, the rendering |
* that will happen next will probably dirty the front buffer. So |
* mark it as dirty here. |
*/ |
if (brw->is_front_buffer_rendering) |
brw->front_buffer_dirty = true; |
/* Wait for the swapbuffers before the one we just emitted, so we |
* don't get too many swaps outstanding for apps that are GPU-heavy |
* but not CPU-heavy. |
* |
* We're using intelDRI2Flush (called from the loader before |
* swapbuffer) and glFlush (for front buffer rendering) as the |
* indicator that a frame is done and then throttle when we get |
* here as we prepare to render the next frame. At this point for |
* round trips for swap/copy and getting new buffers are done and |
* we'll spend less time waiting on the GPU. |
* |
* Unfortunately, we don't have a handle to the batch containing |
* the swap, and getting our hands on that doesn't seem worth it, |
* so we just us the first batch we emitted after the last swap. |
*/ |
if (brw->need_throttle && brw->first_post_swapbuffers_batch) { |
if (!brw->disable_throttling) |
drm_intel_bo_wait_rendering(brw->first_post_swapbuffers_batch); |
drm_intel_bo_unreference(brw->first_post_swapbuffers_batch); |
brw->first_post_swapbuffers_batch = NULL; |
brw->need_throttle = false; |
} |
} |
static void |
intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
{ |
struct brw_context *brw = brw_context(ctx); |
__DRIcontext *driContext = brw->driContext; |
if (brw->saved_viewport) |
brw->saved_viewport(ctx, x, y, w, h); |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
dri2InvalidateDrawable(driContext->driDrawablePriv); |
dri2InvalidateDrawable(driContext->driReadablePriv); |
} |
} |
static const struct dri_debug_control debug_control[] = { |
{ "tex", DEBUG_TEXTURE}, |
{ "state", DEBUG_STATE}, |
{ "ioctl", DEBUG_IOCTL}, |
{ "blit", DEBUG_BLIT}, |
{ "mip", DEBUG_MIPTREE}, |
{ "fall", DEBUG_PERF}, |
{ "perf", DEBUG_PERF}, |
{ "bat", DEBUG_BATCH}, |
{ "pix", DEBUG_PIXEL}, |
{ "buf", DEBUG_BUFMGR}, |
{ "reg", DEBUG_REGION}, |
{ "fbo", DEBUG_FBO}, |
{ "fs", DEBUG_WM }, |
{ "gs", DEBUG_GS}, |
{ "sync", DEBUG_SYNC}, |
{ "prim", DEBUG_PRIMS }, |
{ "vert", DEBUG_VERTS }, |
{ "dri", DEBUG_DRI }, |
{ "sf", DEBUG_SF }, |
{ "stats", DEBUG_STATS }, |
{ "wm", DEBUG_WM }, |
{ "urb", DEBUG_URB }, |
{ "vs", DEBUG_VS }, |
{ "clip", DEBUG_CLIP }, |
{ "aub", DEBUG_AUB }, |
{ "shader_time", DEBUG_SHADER_TIME }, |
{ "no16", DEBUG_NO16 }, |
{ "blorp", DEBUG_BLORP }, |
{ NULL, 0 } |
}; |
static void |
intelInvalidateState(struct gl_context * ctx, GLuint new_state) |
{ |
struct brw_context *brw = brw_context(ctx); |
if (ctx->swrast_context) |
_swrast_InvalidateState(ctx, new_state); |
_vbo_InvalidateState(ctx, new_state); |
brw->NewGLState |= new_state; |
} |
void |
_intel_flush(struct gl_context *ctx, const char *file, int line) |
{ |
struct brw_context *brw = brw_context(ctx); |
if (brw->batch.used) |
_intel_batchbuffer_flush(brw, file, line); |
} |
static void |
intel_glFlush(struct gl_context *ctx) |
{ |
struct brw_context *brw = brw_context(ctx); |
intel_flush(ctx); |
intel_flush_front(ctx); |
if (brw->is_front_buffer_rendering) |
brw->need_throttle = true; |
} |
void |
intelFinish(struct gl_context * ctx) |
{ |
struct brw_context *brw = brw_context(ctx); |
intel_flush(ctx); |
intel_flush_front(ctx); |
if (brw->batch.last_bo) |
drm_intel_bo_wait_rendering(brw->batch.last_bo); |
} |
void |
intelInitDriverFunctions(struct dd_function_table *functions) |
{ |
_mesa_init_driver_functions(functions); |
functions->Flush = intel_glFlush; |
functions->Finish = intelFinish; |
functions->GetString = intelGetString; |
functions->UpdateState = intelInvalidateState; |
intelInitTextureFuncs(functions); |
intelInitTextureImageFuncs(functions); |
intelInitTextureSubImageFuncs(functions); |
intelInitTextureCopyImageFuncs(functions); |
intelInitClearFuncs(functions); |
intelInitBufferFuncs(functions); |
intelInitPixelFuncs(functions); |
intelInitBufferObjectFuncs(functions); |
intel_init_syncobj_functions(functions); |
} |
static bool |
validate_context_version(struct intel_screen *screen, |
int mesa_api, |
unsigned major_version, |
unsigned minor_version, |
unsigned *dri_ctx_error) |
{ |
unsigned req_version = 10 * major_version + minor_version; |
unsigned max_version = 0; |
switch (mesa_api) { |
case API_OPENGL_COMPAT: |
max_version = screen->max_gl_compat_version; |
break; |
case API_OPENGL_CORE: |
max_version = screen->max_gl_core_version; |
break; |
case API_OPENGLES: |
max_version = screen->max_gl_es1_version; |
break; |
case API_OPENGLES2: |
max_version = screen->max_gl_es2_version; |
break; |
default: |
max_version = 0; |
break; |
} |
if (max_version == 0) { |
*dri_ctx_error = __DRI_CTX_ERROR_BAD_API; |
return false; |
} else if (req_version > max_version) { |
*dri_ctx_error = __DRI_CTX_ERROR_BAD_VERSION; |
return false; |
} |
return true; |
} |
bool |
intelInitContext(struct brw_context *brw, |
int api, |
unsigned major_version, |
unsigned minor_version, |
const struct gl_config * mesaVis, |
__DRIcontext * driContextPriv, |
void *sharedContextPrivate, |
struct dd_function_table *functions, |
unsigned *dri_ctx_error) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gl_context *shareCtx = (struct gl_context *) sharedContextPrivate; |
__DRIscreen *sPriv = driContextPriv->driScreenPriv; |
struct intel_screen *intelScreen = sPriv->driverPrivate; |
int bo_reuse_mode; |
struct gl_config visual; |
/* we can't do anything without a connection to the device */ |
if (intelScreen->bufmgr == NULL) { |
*dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY; |
return false; |
} |
if (!validate_context_version(intelScreen, |
api, major_version, minor_version, |
dri_ctx_error)) |
return false; |
/* Can't rely on invalidate events, fall back to glViewport hack */ |
if (!driContextPriv->driScreenPriv->dri2.useInvalidate) { |
brw->saved_viewport = functions->Viewport; |
functions->Viewport = intel_viewport; |
} |
if (mesaVis == NULL) { |
memset(&visual, 0, sizeof visual); |
mesaVis = &visual; |
} |
brw->intelScreen = intelScreen; |
if (!_mesa_initialize_context(&brw->ctx, api, mesaVis, shareCtx, |
functions)) { |
*dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY; |
printf("%s: failed to init mesa context\n", __FUNCTION__); |
return false; |
} |
driContextPriv->driverPrivate = brw; |
brw->driContext = driContextPriv; |
brw->gen = intelScreen->gen; |
const int devID = intelScreen->deviceID; |
if (IS_SNB_GT1(devID) || IS_IVB_GT1(devID) || IS_HSW_GT1(devID)) |
brw->gt = 1; |
else if (IS_SNB_GT2(devID) || IS_IVB_GT2(devID) || IS_HSW_GT2(devID)) |
brw->gt = 2; |
else if (IS_HSW_GT3(devID)) |
brw->gt = 3; |
else |
brw->gt = 0; |
if (IS_HASWELL(devID)) { |
brw->is_haswell = true; |
} else if (IS_BAYTRAIL(devID)) { |
brw->is_baytrail = true; |
brw->gt = 1; |
} else if (IS_G4X(devID)) { |
brw->is_g4x = true; |
} |
brw->has_separate_stencil = brw->intelScreen->hw_has_separate_stencil; |
brw->must_use_separate_stencil = brw->intelScreen->hw_must_use_separate_stencil; |
brw->has_hiz = brw->gen >= 6; |
brw->has_llc = brw->intelScreen->hw_has_llc; |
brw->has_swizzling = brw->intelScreen->hw_has_swizzling; |
memset(&ctx->TextureFormatSupported, |
0, sizeof(ctx->TextureFormatSupported)); |
driParseConfigFiles(&brw->optionCache, &intelScreen->optionCache, |
sPriv->myNum, "i965"); |
/* Estimate the size of the mappable aperture into the GTT. There's an |
* ioctl to get the whole GTT size, but not one to get the mappable subset. |
* It turns out it's basically always 256MB, though some ancient hardware |
* was smaller. |
*/ |
uint32_t gtt_size = 256 * 1024 * 1024; |
/* We don't want to map two objects such that a memcpy between them would |
* just fault one mapping in and then the other over and over forever. So |
* we would need to divide the GTT size by 2. Additionally, some GTT is |
* taken up by things like the framebuffer and the ringbuffer and such, so |
* be more conservative. |
*/ |
brw->max_gtt_map_object_size = gtt_size / 4; |
brw->bufmgr = intelScreen->bufmgr; |
bo_reuse_mode = driQueryOptioni(&brw->optionCache, "bo_reuse"); |
switch (bo_reuse_mode) { |
case DRI_CONF_BO_REUSE_DISABLED: |
break; |
case DRI_CONF_BO_REUSE_ALL: |
intel_bufmgr_gem_enable_reuse(brw->bufmgr); |
break; |
} |
/* Initialize the software rasterizer and helper modules. |
* |
* As of GL 3.1 core, the gen4+ driver doesn't need the swrast context for |
* software fallbacks (which we have to support on legacy GL to do weird |
* glDrawPixels(), glBitmap(), and other functions). |
*/ |
if (api != API_OPENGL_CORE) { |
_swrast_CreateContext(ctx); |
} |
_vbo_CreateContext(ctx); |
if (ctx->swrast_context) { |
_tnl_CreateContext(ctx); |
_swsetup_CreateContext(ctx); |
/* Configure swrast to match hardware characteristics: */ |
_swrast_allow_pixel_fog(ctx, false); |
_swrast_allow_vertex_fog(ctx, true); |
} |
_mesa_meta_init(ctx); |
intelInitExtensions(ctx); |
INTEL_DEBUG = driParseDebugString(getenv("INTEL_DEBUG"), debug_control); |
if (INTEL_DEBUG & DEBUG_BUFMGR) |
dri_bufmgr_set_debug(brw->bufmgr, true); |
if ((INTEL_DEBUG & DEBUG_SHADER_TIME) && brw->gen < 7) { |
fprintf(stderr, |
"shader_time debugging requires gen7 (Ivybridge) or better.\n"); |
INTEL_DEBUG &= ~DEBUG_SHADER_TIME; |
} |
if (INTEL_DEBUG & DEBUG_PERF) |
brw->perf_debug = true; |
if (INTEL_DEBUG & DEBUG_AUB) |
drm_intel_bufmgr_gem_set_aub_dump(brw->bufmgr, true); |
intel_batchbuffer_init(brw); |
intel_fbo_init(brw); |
if (!driQueryOptionb(&brw->optionCache, "hiz")) { |
brw->has_hiz = false; |
/* On gen6, you can only do separate stencil with HIZ. */ |
if (brw->gen == 6) |
brw->has_separate_stencil = false; |
} |
if (driQueryOptionb(&brw->optionCache, "always_flush_batch")) { |
fprintf(stderr, "flushing batchbuffer before/after each draw call\n"); |
brw->always_flush_batch = 1; |
} |
if (driQueryOptionb(&brw->optionCache, "always_flush_cache")) { |
fprintf(stderr, "flushing GPU caches before/after each draw call\n"); |
brw->always_flush_cache = 1; |
} |
if (driQueryOptionb(&brw->optionCache, "disable_throttling")) { |
fprintf(stderr, "disabling flush throttling\n"); |
brw->disable_throttling = 1; |
} |
return true; |
} |
void |
intelDestroyContext(__DRIcontext * driContextPriv) |
{ |
struct brw_context *brw = |
(struct brw_context *) driContextPriv->driverPrivate; |
struct gl_context *ctx = &brw->ctx; |
assert(brw); /* should never be null */ |
if (brw) { |
/* Dump a final BMP in case the application doesn't call SwapBuffers */ |
if (INTEL_DEBUG & DEBUG_AUB) { |
intel_batchbuffer_flush(brw); |
aub_dump_bmp(&brw->ctx); |
} |
_mesa_meta_free(&brw->ctx); |
brw->vtbl.destroy(brw); |
if (ctx->swrast_context) { |
_swsetup_DestroyContext(&brw->ctx); |
_tnl_DestroyContext(&brw->ctx); |
} |
_vbo_DestroyContext(&brw->ctx); |
if (ctx->swrast_context) |
_swrast_DestroyContext(&brw->ctx); |
intel_batchbuffer_free(brw); |
drm_intel_bo_unreference(brw->first_post_swapbuffers_batch); |
brw->first_post_swapbuffers_batch = NULL; |
driDestroyOptionCache(&brw->optionCache); |
/* free the Mesa context */ |
_mesa_free_context_data(&brw->ctx); |
ralloc_free(brw); |
driContextPriv->driverPrivate = NULL; |
} |
} |
GLboolean |
intelUnbindContext(__DRIcontext * driContextPriv) |
{ |
/* Unset current context and dispath table */ |
_mesa_make_current(NULL, NULL, NULL); |
return true; |
} |
/** |
* Fixes up the context for GLES23 with our default-to-sRGB-capable behavior |
* on window system framebuffers. |
* |
* Desktop GL is fairly reasonable in its handling of sRGB: You can ask if |
* your renderbuffer can do sRGB encode, and you can flip a switch that does |
* sRGB encode if the renderbuffer can handle it. You can ask specifically |
* for a visual where you're guaranteed to be capable, but it turns out that |
* everyone just makes all their ARGB8888 visuals capable and doesn't offer |
* incapable ones, becuase there's no difference between the two in resources |
* used. Applications thus get built that accidentally rely on the default |
* visual choice being sRGB, so we make ours sRGB capable. Everything sounds |
* great... |
* |
* But for GLES2/3, they decided that it was silly to not turn on sRGB encode |
* for sRGB renderbuffers you made with the GL_EXT_texture_sRGB equivalent. |
* So they removed the enable knob and made it "if the renderbuffer is sRGB |
* capable, do sRGB encode". Then, for your window system renderbuffers, you |
* can ask for sRGB visuals and get sRGB encode, or not ask for sRGB visuals |
* and get no sRGB encode (assuming that both kinds of visual are available). |
* Thus our choice to support sRGB by default on our visuals for desktop would |
* result in broken rendering of GLES apps that aren't expecting sRGB encode. |
* |
* Unfortunately, renderbuffer setup happens before a context is created. So |
* in intel_screen.c we always set up sRGB, and here, if you're a GLES2/3 |
* context (without an sRGB visual, though we don't have sRGB visuals exposed |
* yet), we go turn that back off before anyone finds out. |
*/ |
static void |
intel_gles3_srgb_workaround(struct brw_context *brw, |
struct gl_framebuffer *fb) |
{ |
struct gl_context *ctx = &brw->ctx; |
if (_mesa_is_desktop_gl(ctx) || !fb->Visual.sRGBCapable) |
return; |
/* Some day when we support the sRGB capable bit on visuals available for |
* GLES, we'll need to respect that and not disable things here. |
*/ |
fb->Visual.sRGBCapable = false; |
for (int i = 0; i < BUFFER_COUNT; i++) { |
if (fb->Attachment[i].Renderbuffer && |
fb->Attachment[i].Renderbuffer->Format == MESA_FORMAT_SARGB8) { |
fb->Attachment[i].Renderbuffer->Format = MESA_FORMAT_ARGB8888; |
} |
} |
} |
GLboolean |
intelMakeCurrent(__DRIcontext * driContextPriv, |
__DRIdrawable * driDrawPriv, |
__DRIdrawable * driReadPriv) |
{ |
struct brw_context *brw; |
GET_CURRENT_CONTEXT(curCtx); |
if (driContextPriv) |
brw = (struct brw_context *) driContextPriv->driverPrivate; |
else |
brw = NULL; |
/* According to the glXMakeCurrent() man page: "Pending commands to |
* the previous context, if any, are flushed before it is released." |
* But only flush if we're actually changing contexts. |
*/ |
if (brw_context(curCtx) && brw_context(curCtx) != brw) { |
_mesa_flush(curCtx); |
} |
if (driContextPriv) { |
struct gl_context *ctx = &brw->ctx; |
struct gl_framebuffer *fb, *readFb; |
if (driDrawPriv == NULL && driReadPriv == NULL) { |
fb = _mesa_get_incomplete_framebuffer(); |
readFb = _mesa_get_incomplete_framebuffer(); |
} else { |
fb = driDrawPriv->driverPrivate; |
readFb = driReadPriv->driverPrivate; |
driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; |
driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; |
} |
/* The sRGB workaround changes the renderbuffer's format. We must change |
* the format before the renderbuffer's miptree get's allocated, otherwise |
* the formats of the renderbuffer and its miptree will differ. |
*/ |
intel_gles3_srgb_workaround(brw, fb); |
intel_gles3_srgb_workaround(brw, readFb); |
intel_prepare_render(brw); |
_mesa_make_current(ctx, fb, readFb); |
} |
else { |
_mesa_make_current(NULL, NULL, NULL); |
} |
return true; |
} |
/** |
* \brief Query DRI2 to obtain a DRIdrawable's buffers. |
* |
* To determine which DRI buffers to request, examine the renderbuffers |
* attached to the drawable's framebuffer. Then request the buffers with |
* DRI2GetBuffers() or DRI2GetBuffersWithFormat(). |
* |
* This is called from intel_update_renderbuffers(). |
* |
* \param drawable Drawable whose buffers are queried. |
* \param buffers [out] List of buffers returned by DRI2 query. |
* \param buffer_count [out] Number of buffers returned. |
* |
* \see intel_update_renderbuffers() |
* \see DRI2GetBuffers() |
* \see DRI2GetBuffersWithFormat() |
*/ |
static void |
intel_query_dri2_buffers(struct brw_context *brw, |
__DRIdrawable *drawable, |
__DRIbuffer **buffers, |
int *buffer_count) |
{ |
__DRIscreen *screen = brw->intelScreen->driScrnPriv; |
struct gl_framebuffer *fb = drawable->driverPrivate; |
int i = 0; |
unsigned attachments[8]; |
struct intel_renderbuffer *front_rb; |
struct intel_renderbuffer *back_rb; |
front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); |
memset(attachments, 0, sizeof(attachments)); |
if ((brw->is_front_buffer_rendering || |
brw->is_front_buffer_reading || |
!back_rb) && front_rb) { |
/* If a fake front buffer is in use, then querying for |
* __DRI_BUFFER_FRONT_LEFT will cause the server to copy the image from |
* the real front buffer to the fake front buffer. So before doing the |
* query, we need to make sure all the pending drawing has landed in the |
* real front buffer. |
*/ |
intel_flush(&brw->ctx); |
intel_flush_front(&brw->ctx); |
attachments[i++] = __DRI_BUFFER_FRONT_LEFT; |
attachments[i++] = intel_bits_per_pixel(front_rb); |
} else if (front_rb && brw->front_buffer_dirty) { |
/* We have pending front buffer rendering, but we aren't querying for a |
* front buffer. If the front buffer we have is a fake front buffer, |
* the X server is going to throw it away when it processes the query. |
* So before doing the query, make sure all the pending drawing has |
* landed in the real front buffer. |
*/ |
intel_flush(&brw->ctx); |
intel_flush_front(&brw->ctx); |
} |
if (back_rb) { |
attachments[i++] = __DRI_BUFFER_BACK_LEFT; |
attachments[i++] = intel_bits_per_pixel(back_rb); |
} |
assert(i <= ARRAY_SIZE(attachments)); |
*buffers = screen->dri2.loader->getBuffersWithFormat(drawable, |
&drawable->w, |
&drawable->h, |
attachments, i / 2, |
buffer_count, |
drawable->loaderPrivate); |
} |
/** |
* \brief Assign a DRI buffer's DRM region to a renderbuffer. |
* |
* This is called from intel_update_renderbuffers(). |
* |
* \par Note: |
* DRI buffers whose attachment point is DRI2BufferStencil or |
* DRI2BufferDepthStencil are handled as special cases. |
* |
* \param buffer_name is a human readable name, such as "dri2 front buffer", |
* that is passed to intel_region_alloc_for_handle(). |
* |
* \see intel_update_renderbuffers() |
* \see intel_region_alloc_for_handle() |
*/ |
static void |
intel_process_dri2_buffer(struct brw_context *brw, |
__DRIdrawable *drawable, |
__DRIbuffer *buffer, |
struct intel_renderbuffer *rb, |
const char *buffer_name) |
{ |
struct intel_region *region = NULL; |
if (!rb) |
return; |
unsigned num_samples = rb->Base.Base.NumSamples; |
/* We try to avoid closing and reopening the same BO name, because the first |
* use of a mapping of the buffer involves a bunch of page faulting which is |
* moderately expensive. |
*/ |
if (num_samples == 0) { |
if (rb->mt && |
rb->mt->region && |
rb->mt->region->name == buffer->name) |
return; |
} else { |
if (rb->mt && |
rb->mt->singlesample_mt && |
rb->mt->singlesample_mt->region && |
rb->mt->singlesample_mt->region->name == buffer->name) |
return; |
} |
if (unlikely(INTEL_DEBUG & DEBUG_DRI)) { |
fprintf(stderr, |
"attaching buffer %d, at %d, cpp %d, pitch %d\n", |
buffer->name, buffer->attachment, |
buffer->cpp, buffer->pitch); |
} |
intel_miptree_release(&rb->mt); |
region = intel_region_alloc_for_handle(brw->intelScreen, |
buffer->cpp, |
drawable->w, |
drawable->h, |
buffer->pitch, |
buffer->name, |
buffer_name); |
if (!region) |
return; |
rb->mt = intel_miptree_create_for_dri2_buffer(brw, |
buffer->attachment, |
intel_rb_format(rb), |
num_samples, |
region); |
intel_region_release(®ion); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_context.c.bak |
---|
0,0 → 1,920 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/context.h" |
#include "main/extensions.h" |
#include "main/fbobject.h" |
#include "main/framebuffer.h" |
#include "main/imports.h" |
#include "main/renderbuffer.h" |
#include "swrast/swrast.h" |
#include "swrast_setup/swrast_setup.h" |
#include "tnl/tnl.h" |
#include "drivers/common/driverfuncs.h" |
#include "drivers/common/meta.h" |
#include "intel_chipset.h" |
#include "intel_buffers.h" |
#include "intel_tex.h" |
#include "intel_batchbuffer.h" |
#include "intel_pixel.h" |
#include "intel_regions.h" |
#include "intel_buffer_objects.h" |
#include "intel_fbo.h" |
#include "intel_bufmgr.h" |
#include "intel_screen.h" |
#include "intel_mipmap_tree.h" |
#include "utils.h" |
#include "../glsl/ralloc.h" |
#ifndef INTEL_DEBUG |
int INTEL_DEBUG = (0); |
#endif |
static const GLubyte * |
intelGetString(struct gl_context * ctx, GLenum name) |
{ |
const struct brw_context *const brw = brw_context(ctx); |
const char *chipset; |
static char buffer[128]; |
switch (name) { |
case GL_VENDOR: |
return (GLubyte *) "Intel Open Source Technology Center"; |
break; |
case GL_RENDERER: |
switch (brw->intelScreen->deviceID) { |
#undef CHIPSET |
#define CHIPSET(id, symbol, str) case id: chipset = str; break; |
#include "pci_ids/i965_pci_ids.h" |
default: |
chipset = "Unknown Intel Chipset"; |
break; |
} |
(void) driGetRendererString(buffer, chipset, 0); |
return (GLubyte *) buffer; |
default: |
return NULL; |
} |
} |
void |
intel_resolve_for_dri2_flush(struct brw_context *brw, |
__DRIdrawable *drawable) |
{ |
if (brw->gen < 6) { |
/* MSAA and fast color clear are not supported, so don't waste time |
* checking whether a resolve is needed. |
*/ |
return; |
} |
struct gl_framebuffer *fb = drawable->driverPrivate; |
struct intel_renderbuffer *rb; |
/* Usually, only the back buffer will need to be downsampled. However, |
* the front buffer will also need it if the user has rendered into it. |
*/ |
static const gl_buffer_index buffers[2] = { |
BUFFER_BACK_LEFT, |
BUFFER_FRONT_LEFT, |
}; |
for (int i = 0; i < 2; ++i) { |
rb = intel_get_renderbuffer(fb, buffers[i]); |
if (rb == NULL || rb->mt == NULL) |
continue; |
if (rb->mt->num_samples <= 1) |
intel_miptree_resolve_color(brw, rb->mt); |
else |
intel_miptree_downsample(brw, rb->mt); |
} |
} |
static void |
intel_flush_front(struct gl_context *ctx) |
{ |
struct brw_context *brw = brw_context(ctx); |
__DRIcontext *driContext = brw->driContext; |
__DRIdrawable *driDrawable = driContext->driDrawablePriv; |
__DRIscreen *const screen = brw->intelScreen->driScrnPriv; |
if (brw->front_buffer_dirty && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
if (screen->dri2.loader->flushFrontBuffer != NULL && |
driDrawable && |
driDrawable->loaderPrivate) { |
/* Resolve before flushing FAKE_FRONT_LEFT to FRONT_LEFT. |
* |
* This potentially resolves both front and back buffer. It |
* is unnecessary to resolve the back, but harms nothing except |
* performance. And no one cares about front-buffer render |
* performance. |
*/ |
intel_resolve_for_dri2_flush(brw, driDrawable); |
screen->dri2.loader->flushFrontBuffer(driDrawable, |
driDrawable->loaderPrivate); |
/* We set the dirty bit in intel_prepare_render() if we're |
* front buffer rendering once we get there. |
*/ |
brw->front_buffer_dirty = false; |
} |
} |
} |
static unsigned |
intel_bits_per_pixel(const struct intel_renderbuffer *rb) |
{ |
return _mesa_get_format_bytes(intel_rb_format(rb)) * 8; |
} |
static void |
intel_query_dri2_buffers(struct brw_context *brw, |
__DRIdrawable *drawable, |
__DRIbuffer **buffers, |
int *count); |
static void |
intel_process_dri2_buffer(struct brw_context *brw, |
__DRIdrawable *drawable, |
__DRIbuffer *buffer, |
struct intel_renderbuffer *rb, |
const char *buffer_name); |
void |
intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable) |
{ |
struct gl_framebuffer *fb = drawable->driverPrivate; |
struct intel_renderbuffer *rb; |
struct brw_context *brw = context->driverPrivate; |
__DRIbuffer *buffers = NULL; |
int i, count; |
const char *region_name; |
/* Set this up front, so that in case our buffers get invalidated |
* while we're getting new buffers, we don't clobber the stamp and |
* thus ignore the invalidate. */ |
drawable->lastStamp = drawable->dri2.stamp; |
if (unlikely(INTEL_DEBUG & DEBUG_DRI)) |
fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); |
intel_query_dri2_buffers(brw, drawable, &buffers, &count); |
if (buffers == NULL) |
return; |
for (i = 0; i < count; i++) { |
switch (buffers[i].attachment) { |
case __DRI_BUFFER_FRONT_LEFT: |
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
region_name = "dri2 front buffer"; |
break; |
case __DRI_BUFFER_FAKE_FRONT_LEFT: |
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
region_name = "dri2 fake front buffer"; |
break; |
case __DRI_BUFFER_BACK_LEFT: |
rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); |
region_name = "dri2 back buffer"; |
break; |
case __DRI_BUFFER_DEPTH: |
case __DRI_BUFFER_HIZ: |
case __DRI_BUFFER_DEPTH_STENCIL: |
case __DRI_BUFFER_STENCIL: |
case __DRI_BUFFER_ACCUM: |
default: |
fprintf(stderr, |
"unhandled buffer attach event, attachment type %d\n", |
buffers[i].attachment); |
return; |
} |
intel_process_dri2_buffer(brw, drawable, &buffers[i], rb, region_name); |
} |
driUpdateFramebufferSize(&brw->ctx, drawable); |
} |
/** |
* intel_prepare_render should be called anywhere that curent read/drawbuffer |
* state is required. |
*/ |
void |
intel_prepare_render(struct brw_context *brw) |
{ |
__DRIcontext *driContext = brw->driContext; |
__DRIdrawable *drawable; |
drawable = driContext->driDrawablePriv; |
if (drawable && drawable->dri2.stamp != driContext->dri2.draw_stamp) { |
if (drawable->lastStamp != drawable->dri2.stamp) |
intel_update_renderbuffers(driContext, drawable); |
driContext->dri2.draw_stamp = drawable->dri2.stamp; |
} |
drawable = driContext->driReadablePriv; |
if (drawable && drawable->dri2.stamp != driContext->dri2.read_stamp) { |
if (drawable->lastStamp != drawable->dri2.stamp) |
intel_update_renderbuffers(driContext, drawable); |
driContext->dri2.read_stamp = drawable->dri2.stamp; |
} |
/* If we're currently rendering to the front buffer, the rendering |
* that will happen next will probably dirty the front buffer. So |
* mark it as dirty here. |
*/ |
if (brw->is_front_buffer_rendering) |
brw->front_buffer_dirty = true; |
/* Wait for the swapbuffers before the one we just emitted, so we |
* don't get too many swaps outstanding for apps that are GPU-heavy |
* but not CPU-heavy. |
* |
* We're using intelDRI2Flush (called from the loader before |
* swapbuffer) and glFlush (for front buffer rendering) as the |
* indicator that a frame is done and then throttle when we get |
* here as we prepare to render the next frame. At this point for |
* round trips for swap/copy and getting new buffers are done and |
* we'll spend less time waiting on the GPU. |
* |
* Unfortunately, we don't have a handle to the batch containing |
* the swap, and getting our hands on that doesn't seem worth it, |
* so we just us the first batch we emitted after the last swap. |
*/ |
if (brw->need_throttle && brw->first_post_swapbuffers_batch) { |
if (!brw->disable_throttling) |
drm_intel_bo_wait_rendering(brw->first_post_swapbuffers_batch); |
drm_intel_bo_unreference(brw->first_post_swapbuffers_batch); |
brw->first_post_swapbuffers_batch = NULL; |
brw->need_throttle = false; |
} |
} |
static void |
intel_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
{ |
struct brw_context *brw = brw_context(ctx); |
__DRIcontext *driContext = brw->driContext; |
if (brw->saved_viewport) |
brw->saved_viewport(ctx, x, y, w, h); |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
dri2InvalidateDrawable(driContext->driDrawablePriv); |
dri2InvalidateDrawable(driContext->driReadablePriv); |
} |
} |
static const struct dri_debug_control debug_control[] = { |
{ "tex", DEBUG_TEXTURE}, |
{ "state", DEBUG_STATE}, |
{ "ioctl", DEBUG_IOCTL}, |
{ "blit", DEBUG_BLIT}, |
{ "mip", DEBUG_MIPTREE}, |
{ "fall", DEBUG_PERF}, |
{ "perf", DEBUG_PERF}, |
{ "bat", DEBUG_BATCH}, |
{ "pix", DEBUG_PIXEL}, |
{ "buf", DEBUG_BUFMGR}, |
{ "reg", DEBUG_REGION}, |
{ "fbo", DEBUG_FBO}, |
{ "fs", DEBUG_WM }, |
{ "gs", DEBUG_GS}, |
{ "sync", DEBUG_SYNC}, |
{ "prim", DEBUG_PRIMS }, |
{ "vert", DEBUG_VERTS }, |
{ "dri", DEBUG_DRI }, |
{ "sf", DEBUG_SF }, |
{ "stats", DEBUG_STATS }, |
{ "wm", DEBUG_WM }, |
{ "urb", DEBUG_URB }, |
{ "vs", DEBUG_VS }, |
{ "clip", DEBUG_CLIP }, |
{ "aub", DEBUG_AUB }, |
{ "shader_time", DEBUG_SHADER_TIME }, |
{ "no16", DEBUG_NO16 }, |
{ "blorp", DEBUG_BLORP }, |
{ NULL, 0 } |
}; |
static void |
intelInvalidateState(struct gl_context * ctx, GLuint new_state) |
{ |
struct brw_context *brw = brw_context(ctx); |
if (ctx->swrast_context) |
_swrast_InvalidateState(ctx, new_state); |
_vbo_InvalidateState(ctx, new_state); |
brw->NewGLState |= new_state; |
} |
void |
_intel_flush(struct gl_context *ctx, const char *file, int line) |
{ |
struct brw_context *brw = brw_context(ctx); |
if (brw->batch.used) |
_intel_batchbuffer_flush(brw, file, line); |
} |
static void |
intel_glFlush(struct gl_context *ctx) |
{ |
struct brw_context *brw = brw_context(ctx); |
intel_flush(ctx); |
intel_flush_front(ctx); |
if (brw->is_front_buffer_rendering) |
brw->need_throttle = true; |
} |
void |
intelFinish(struct gl_context * ctx) |
{ |
struct brw_context *brw = brw_context(ctx); |
intel_flush(ctx); |
intel_flush_front(ctx); |
if (brw->batch.last_bo) |
drm_intel_bo_wait_rendering(brw->batch.last_bo); |
} |
void |
intelInitDriverFunctions(struct dd_function_table *functions) |
{ |
_mesa_init_driver_functions(functions); |
functions->Flush = intel_glFlush; |
functions->Finish = intelFinish; |
functions->GetString = intelGetString; |
functions->UpdateState = intelInvalidateState; |
intelInitTextureFuncs(functions); |
intelInitTextureImageFuncs(functions); |
intelInitTextureSubImageFuncs(functions); |
intelInitTextureCopyImageFuncs(functions); |
intelInitClearFuncs(functions); |
intelInitBufferFuncs(functions); |
intelInitPixelFuncs(functions); |
intelInitBufferObjectFuncs(functions); |
intel_init_syncobj_functions(functions); |
} |
static bool |
validate_context_version(struct intel_screen *screen, |
int mesa_api, |
unsigned major_version, |
unsigned minor_version, |
unsigned *dri_ctx_error) |
{ |
unsigned req_version = 10 * major_version + minor_version; |
unsigned max_version = 0; |
switch (mesa_api) { |
case API_OPENGL_COMPAT: |
max_version = screen->max_gl_compat_version; |
break; |
case API_OPENGL_CORE: |
max_version = screen->max_gl_core_version; |
break; |
case API_OPENGLES: |
max_version = screen->max_gl_es1_version; |
break; |
case API_OPENGLES2: |
max_version = screen->max_gl_es2_version; |
break; |
default: |
max_version = 0; |
break; |
} |
if (max_version == 0) { |
*dri_ctx_error = __DRI_CTX_ERROR_BAD_API; |
return false; |
} else if (req_version > max_version) { |
*dri_ctx_error = __DRI_CTX_ERROR_BAD_VERSION; |
return false; |
} |
return true; |
} |
bool |
intelInitContext(struct brw_context *brw, |
int api, |
unsigned major_version, |
unsigned minor_version, |
const struct gl_config * mesaVis, |
__DRIcontext * driContextPriv, |
void *sharedContextPrivate, |
struct dd_function_table *functions, |
unsigned *dri_ctx_error) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gl_context *shareCtx = (struct gl_context *) sharedContextPrivate; |
__DRIscreen *sPriv = driContextPriv->driScreenPriv; |
struct intel_screen *intelScreen = sPriv->driverPrivate; |
int bo_reuse_mode; |
struct gl_config visual; |
/* we can't do anything without a connection to the device */ |
if (intelScreen->bufmgr == NULL) { |
*dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY; |
return false; |
} |
if (!validate_context_version(intelScreen, |
api, major_version, minor_version, |
dri_ctx_error)) |
return false; |
/* Can't rely on invalidate events, fall back to glViewport hack */ |
if (!driContextPriv->driScreenPriv->dri2.useInvalidate) { |
brw->saved_viewport = functions->Viewport; |
functions->Viewport = intel_viewport; |
} |
if (mesaVis == NULL) { |
memset(&visual, 0, sizeof visual); |
mesaVis = &visual; |
} |
brw->intelScreen = intelScreen; |
if (!_mesa_initialize_context(&brw->ctx, api, mesaVis, shareCtx, |
functions)) { |
*dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY; |
printf("%s: failed to init mesa context\n", __FUNCTION__); |
return false; |
} |
driContextPriv->driverPrivate = brw; |
brw->driContext = driContextPriv; |
brw->gen = intelScreen->gen; |
const int devID = intelScreen->deviceID; |
if (IS_SNB_GT1(devID) || IS_IVB_GT1(devID) || IS_HSW_GT1(devID)) |
brw->gt = 1; |
else if (IS_SNB_GT2(devID) || IS_IVB_GT2(devID) || IS_HSW_GT2(devID)) |
brw->gt = 2; |
else if (IS_HSW_GT3(devID)) |
brw->gt = 3; |
else |
brw->gt = 0; |
if (IS_HASWELL(devID)) { |
brw->is_haswell = true; |
} else if (IS_BAYTRAIL(devID)) { |
brw->is_baytrail = true; |
brw->gt = 1; |
} else if (IS_G4X(devID)) { |
brw->is_g4x = true; |
} |
brw->has_separate_stencil = brw->intelScreen->hw_has_separate_stencil; |
brw->must_use_separate_stencil = brw->intelScreen->hw_must_use_separate_stencil; |
brw->has_hiz = brw->gen >= 6; |
brw->has_llc = brw->intelScreen->hw_has_llc; |
brw->has_swizzling = brw->intelScreen->hw_has_swizzling; |
memset(&ctx->TextureFormatSupported, |
0, sizeof(ctx->TextureFormatSupported)); |
driParseConfigFiles(&brw->optionCache, &intelScreen->optionCache, |
sPriv->myNum, "i965"); |
/* Estimate the size of the mappable aperture into the GTT. There's an |
* ioctl to get the whole GTT size, but not one to get the mappable subset. |
* It turns out it's basically always 256MB, though some ancient hardware |
* was smaller. |
*/ |
uint32_t gtt_size = 256 * 1024 * 1024; |
/* We don't want to map two objects such that a memcpy between them would |
* just fault one mapping in and then the other over and over forever. So |
* we would need to divide the GTT size by 2. Additionally, some GTT is |
* taken up by things like the framebuffer and the ringbuffer and such, so |
* be more conservative. |
*/ |
brw->max_gtt_map_object_size = gtt_size / 4; |
brw->bufmgr = intelScreen->bufmgr; |
bo_reuse_mode = driQueryOptioni(&brw->optionCache, "bo_reuse"); |
switch (bo_reuse_mode) { |
case DRI_CONF_BO_REUSE_DISABLED: |
break; |
case DRI_CONF_BO_REUSE_ALL: |
intel_bufmgr_gem_enable_reuse(brw->bufmgr); |
break; |
} |
/* Initialize the software rasterizer and helper modules. |
* |
* As of GL 3.1 core, the gen4+ driver doesn't need the swrast context for |
* software fallbacks (which we have to support on legacy GL to do weird |
* glDrawPixels(), glBitmap(), and other functions). |
*/ |
if (api != API_OPENGL_CORE) { |
_swrast_CreateContext(ctx); |
} |
_vbo_CreateContext(ctx); |
if (ctx->swrast_context) { |
_tnl_CreateContext(ctx); |
_swsetup_CreateContext(ctx); |
/* Configure swrast to match hardware characteristics: */ |
_swrast_allow_pixel_fog(ctx, false); |
_swrast_allow_vertex_fog(ctx, true); |
} |
_mesa_meta_init(ctx); |
intelInitExtensions(ctx); |
INTEL_DEBUG = driParseDebugString(getenv("INTEL_DEBUG"), debug_control); |
if (INTEL_DEBUG & DEBUG_BUFMGR) |
dri_bufmgr_set_debug(brw->bufmgr, true); |
if ((INTEL_DEBUG & DEBUG_SHADER_TIME) && brw->gen < 7) { |
fprintf(stderr, |
"shader_time debugging requires gen7 (Ivybridge) or better.\n"); |
INTEL_DEBUG &= ~DEBUG_SHADER_TIME; |
} |
if (INTEL_DEBUG & DEBUG_PERF) |
brw->perf_debug = true; |
if (INTEL_DEBUG & DEBUG_AUB) |
drm_intel_bufmgr_gem_set_aub_dump(brw->bufmgr, true); |
intel_batchbuffer_init(brw); |
intel_fbo_init(brw); |
if (!driQueryOptionb(&brw->optionCache, "hiz")) { |
brw->has_hiz = false; |
/* On gen6, you can only do separate stencil with HIZ. */ |
if (brw->gen == 6) |
brw->has_separate_stencil = false; |
} |
if (driQueryOptionb(&brw->optionCache, "always_flush_batch")) { |
fprintf(stderr, "flushing batchbuffer before/after each draw call\n"); |
brw->always_flush_batch = 1; |
} |
if (driQueryOptionb(&brw->optionCache, "always_flush_cache")) { |
fprintf(stderr, "flushing GPU caches before/after each draw call\n"); |
brw->always_flush_cache = 1; |
} |
if (driQueryOptionb(&brw->optionCache, "disable_throttling")) { |
fprintf(stderr, "disabling flush throttling\n"); |
brw->disable_throttling = 1; |
} |
return true; |
} |
void |
intelDestroyContext(__DRIcontext * driContextPriv) |
{ |
struct brw_context *brw = |
(struct brw_context *) driContextPriv->driverPrivate; |
struct gl_context *ctx = &brw->ctx; |
assert(brw); /* should never be null */ |
if (brw) { |
/* Dump a final BMP in case the application doesn't call SwapBuffers */ |
if (INTEL_DEBUG & DEBUG_AUB) { |
intel_batchbuffer_flush(brw); |
aub_dump_bmp(&brw->ctx); |
} |
_mesa_meta_free(&brw->ctx); |
brw->vtbl.destroy(brw); |
if (ctx->swrast_context) { |
_swsetup_DestroyContext(&brw->ctx); |
_tnl_DestroyContext(&brw->ctx); |
} |
_vbo_DestroyContext(&brw->ctx); |
if (ctx->swrast_context) |
_swrast_DestroyContext(&brw->ctx); |
intel_batchbuffer_free(brw); |
drm_intel_bo_unreference(brw->first_post_swapbuffers_batch); |
brw->first_post_swapbuffers_batch = NULL; |
driDestroyOptionCache(&brw->optionCache); |
/* free the Mesa context */ |
_mesa_free_context_data(&brw->ctx); |
ralloc_free(brw); |
driContextPriv->driverPrivate = NULL; |
} |
} |
GLboolean |
intelUnbindContext(__DRIcontext * driContextPriv) |
{ |
/* Unset current context and dispath table */ |
_mesa_make_current(NULL, NULL, NULL); |
return true; |
} |
/** |
* Fixes up the context for GLES23 with our default-to-sRGB-capable behavior |
* on window system framebuffers. |
* |
* Desktop GL is fairly reasonable in its handling of sRGB: You can ask if |
* your renderbuffer can do sRGB encode, and you can flip a switch that does |
* sRGB encode if the renderbuffer can handle it. You can ask specifically |
* for a visual where you're guaranteed to be capable, but it turns out that |
* everyone just makes all their ARGB8888 visuals capable and doesn't offer |
* incapable ones, becuase there's no difference between the two in resources |
* used. Applications thus get built that accidentally rely on the default |
* visual choice being sRGB, so we make ours sRGB capable. Everything sounds |
* great... |
* |
* But for GLES2/3, they decided that it was silly to not turn on sRGB encode |
* for sRGB renderbuffers you made with the GL_EXT_texture_sRGB equivalent. |
* So they removed the enable knob and made it "if the renderbuffer is sRGB |
* capable, do sRGB encode". Then, for your window system renderbuffers, you |
* can ask for sRGB visuals and get sRGB encode, or not ask for sRGB visuals |
* and get no sRGB encode (assuming that both kinds of visual are available). |
* Thus our choice to support sRGB by default on our visuals for desktop would |
* result in broken rendering of GLES apps that aren't expecting sRGB encode. |
* |
* Unfortunately, renderbuffer setup happens before a context is created. So |
* in intel_screen.c we always set up sRGB, and here, if you're a GLES2/3 |
* context (without an sRGB visual, though we don't have sRGB visuals exposed |
* yet), we go turn that back off before anyone finds out. |
*/ |
static void |
intel_gles3_srgb_workaround(struct brw_context *brw, |
struct gl_framebuffer *fb) |
{ |
struct gl_context *ctx = &brw->ctx; |
if (_mesa_is_desktop_gl(ctx) || !fb->Visual.sRGBCapable) |
return; |
/* Some day when we support the sRGB capable bit on visuals available for |
* GLES, we'll need to respect that and not disable things here. |
*/ |
fb->Visual.sRGBCapable = false; |
for (int i = 0; i < BUFFER_COUNT; i++) { |
if (fb->Attachment[i].Renderbuffer && |
fb->Attachment[i].Renderbuffer->Format == MESA_FORMAT_SARGB8) { |
fb->Attachment[i].Renderbuffer->Format = MESA_FORMAT_ARGB8888; |
} |
} |
} |
GLboolean |
intelMakeCurrent(__DRIcontext * driContextPriv, |
__DRIdrawable * driDrawPriv, |
__DRIdrawable * driReadPriv) |
{ |
struct brw_context *brw; |
GET_CURRENT_CONTEXT(curCtx); |
if (driContextPriv) |
brw = (struct brw_context *) driContextPriv->driverPrivate; |
else |
brw = NULL; |
/* According to the glXMakeCurrent() man page: "Pending commands to |
* the previous context, if any, are flushed before it is released." |
* But only flush if we're actually changing contexts. |
*/ |
if (brw_context(curCtx) && brw_context(curCtx) != brw) { |
_mesa_flush(curCtx); |
} |
if (driContextPriv) { |
struct gl_context *ctx = &brw->ctx; |
struct gl_framebuffer *fb, *readFb; |
if (driDrawPriv == NULL && driReadPriv == NULL) { |
fb = _mesa_get_incomplete_framebuffer(); |
readFb = _mesa_get_incomplete_framebuffer(); |
} else { |
fb = driDrawPriv->driverPrivate; |
readFb = driReadPriv->driverPrivate; |
driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1; |
driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1; |
} |
/* The sRGB workaround changes the renderbuffer's format. We must change |
* the format before the renderbuffer's miptree get's allocated, otherwise |
* the formats of the renderbuffer and its miptree will differ. |
*/ |
intel_gles3_srgb_workaround(brw, fb); |
intel_gles3_srgb_workaround(brw, readFb); |
intel_prepare_render(brw); |
_mesa_make_current(ctx, fb, readFb); |
} |
else { |
_mesa_make_current(NULL, NULL, NULL); |
} |
return true; |
} |
/** |
* \brief Query DRI2 to obtain a DRIdrawable's buffers. |
* |
* To determine which DRI buffers to request, examine the renderbuffers |
* attached to the drawable's framebuffer. Then request the buffers with |
* DRI2GetBuffers() or DRI2GetBuffersWithFormat(). |
* |
* This is called from intel_update_renderbuffers(). |
* |
* \param drawable Drawable whose buffers are queried. |
* \param buffers [out] List of buffers returned by DRI2 query. |
* \param buffer_count [out] Number of buffers returned. |
* |
* \see intel_update_renderbuffers() |
* \see DRI2GetBuffers() |
* \see DRI2GetBuffersWithFormat() |
*/ |
static void |
intel_query_dri2_buffers(struct brw_context *brw, |
__DRIdrawable *drawable, |
__DRIbuffer **buffers, |
int *buffer_count) |
{ |
__DRIscreen *screen = brw->intelScreen->driScrnPriv; |
struct gl_framebuffer *fb = drawable->driverPrivate; |
int i = 0; |
unsigned attachments[8]; |
struct intel_renderbuffer *front_rb; |
struct intel_renderbuffer *back_rb; |
front_rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
back_rb = intel_get_renderbuffer(fb, BUFFER_BACK_LEFT); |
memset(attachments, 0, sizeof(attachments)); |
if ((brw->is_front_buffer_rendering || |
brw->is_front_buffer_reading || |
!back_rb) && front_rb) { |
/* If a fake front buffer is in use, then querying for |
* __DRI_BUFFER_FRONT_LEFT will cause the server to copy the image from |
* the real front buffer to the fake front buffer. So before doing the |
* query, we need to make sure all the pending drawing has landed in the |
* real front buffer. |
*/ |
intel_flush(&brw->ctx); |
intel_flush_front(&brw->ctx); |
attachments[i++] = __DRI_BUFFER_FRONT_LEFT; |
attachments[i++] = intel_bits_per_pixel(front_rb); |
} else if (front_rb && brw->front_buffer_dirty) { |
/* We have pending front buffer rendering, but we aren't querying for a |
* front buffer. If the front buffer we have is a fake front buffer, |
* the X server is going to throw it away when it processes the query. |
* So before doing the query, make sure all the pending drawing has |
* landed in the real front buffer. |
*/ |
intel_flush(&brw->ctx); |
intel_flush_front(&brw->ctx); |
} |
if (back_rb) { |
attachments[i++] = __DRI_BUFFER_BACK_LEFT; |
attachments[i++] = intel_bits_per_pixel(back_rb); |
} |
assert(i <= ARRAY_SIZE(attachments)); |
*buffers = screen->dri2.loader->getBuffersWithFormat(drawable, |
&drawable->w, |
&drawable->h, |
attachments, i / 2, |
buffer_count, |
drawable->loaderPrivate); |
LEAVE(); |
} |
/** |
* \brief Assign a DRI buffer's DRM region to a renderbuffer. |
* |
* This is called from intel_update_renderbuffers(). |
* |
* \par Note: |
* DRI buffers whose attachment point is DRI2BufferStencil or |
* DRI2BufferDepthStencil are handled as special cases. |
* |
* \param buffer_name is a human readable name, such as "dri2 front buffer", |
* that is passed to intel_region_alloc_for_handle(). |
* |
* \see intel_update_renderbuffers() |
* \see intel_region_alloc_for_handle() |
*/ |
static void |
intel_process_dri2_buffer(struct brw_context *brw, |
__DRIdrawable *drawable, |
__DRIbuffer *buffer, |
struct intel_renderbuffer *rb, |
const char *buffer_name) |
{ |
struct intel_region *region = NULL; |
if (!rb) |
return; |
unsigned num_samples = rb->Base.Base.NumSamples; |
/* We try to avoid closing and reopening the same BO name, because the first |
* use of a mapping of the buffer involves a bunch of page faulting which is |
* moderately expensive. |
*/ |
if (num_samples == 0) { |
if (rb->mt && |
rb->mt->region && |
rb->mt->region->name == buffer->name) |
return; |
} else { |
if (rb->mt && |
rb->mt->singlesample_mt && |
rb->mt->singlesample_mt->region && |
rb->mt->singlesample_mt->region->name == buffer->name) |
return; |
} |
if (unlikely(INTEL_DEBUG & DEBUG_DRI)) { |
fprintf(stderr, |
"attaching buffer %d, at %d, cpp %d, pitch %d\n", |
buffer->name, buffer->attachment, |
buffer->cpp, buffer->pitch); |
} |
intel_miptree_release(&rb->mt); |
region = intel_region_alloc_for_handle(brw->intelScreen, |
buffer->cpp, |
drawable->w, |
drawable->h, |
buffer->pitch, |
buffer->name, |
buffer_name); |
if (!region) |
return; |
rb->mt = intel_miptree_create_for_dri2_buffer(brw, |
buffer->attachment, |
intel_rb_format(rb), |
num_samples, |
region); |
intel_region_release(®ion); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_context.h |
---|
0,0 → 1,293 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTELCONTEXT_INC |
#define INTELCONTEXT_INC |
#include <stdbool.h> |
#include <string.h> |
#include "main/mtypes.h" |
#include "main/mm.h" |
#ifdef __cplusplus |
extern "C" { |
/* Evil hack for using libdrm in a c++ compiler. */ |
#define virtual virt |
#endif |
#include "drm.h" |
#include "intel_bufmgr.h" |
#include "intel_screen.h" |
#include "intel_tex_obj.h" |
#include "i915_drm.h" |
#ifdef __cplusplus |
#undef virtual |
#endif |
#include "tnl/t_vertex.h" |
struct intel_region; |
#define INTEL_WRITE_PART 0x1 |
#define INTEL_WRITE_FULL 0x2 |
#define INTEL_READ 0x4 |
#ifndef likely |
#ifdef __GNUC__ |
#define likely(expr) (__builtin_expect(expr, 1)) |
#define unlikely(expr) (__builtin_expect(expr, 0)) |
#else |
#define likely(expr) (expr) |
#define unlikely(expr) (expr) |
#endif |
#endif |
struct intel_sync_object { |
struct gl_sync_object Base; |
/** Batch associated with this sync object */ |
drm_intel_bo *bo; |
}; |
struct brw_context; |
struct intel_batchbuffer { |
/** Current batchbuffer being queued up. */ |
drm_intel_bo *bo; |
/** Last BO submitted to the hardware. Used for glFinish(). */ |
drm_intel_bo *last_bo; |
/** BO for post-sync nonzero writes for gen6 workaround. */ |
drm_intel_bo *workaround_bo; |
bool need_workaround_flush; |
struct cached_batch_item *cached_items; |
uint16_t emit, total; |
uint16_t used, reserved_space; |
uint32_t *map; |
uint32_t *cpu_map; |
#define BATCH_SZ (8192*sizeof(uint32_t)) |
uint32_t state_batch_offset; |
bool is_blit; |
bool needs_sol_reset; |
struct { |
uint16_t used; |
int reloc_count; |
} saved; |
}; |
/** |
* Align a value down to an alignment value |
* |
* If \c value is not already aligned to the requested alignment value, it |
* will be rounded down. |
* |
* \param value Value to be rounded |
* \param alignment Alignment value to be used. This must be a power of two. |
* |
* \sa ALIGN() |
*/ |
#define ROUND_DOWN_TO(value, alignment) ((value) & ~(alignment - 1)) |
static INLINE uint32_t |
U_FIXED(float value, uint32_t frac_bits) |
{ |
value *= (1 << frac_bits); |
return value < 0 ? 0 : value; |
} |
static INLINE uint32_t |
S_FIXED(float value, uint32_t frac_bits) |
{ |
return value * (1 << frac_bits); |
} |
/* ================================================================ |
* From linux kernel i386 header files, copes with odd sizes better |
* than COPY_DWORDS would: |
* XXX Put this in src/mesa/main/imports.h ??? |
*/ |
#if defined(i386) || defined(__i386__) |
static INLINE void * __memcpy(void * to, const void * from, size_t n) |
{ |
int d0, d1, d2; |
__asm__ __volatile__( |
"rep ; movsl\n\t" |
"testb $2,%b4\n\t" |
"je 1f\n\t" |
"movsw\n" |
"1:\ttestb $1,%b4\n\t" |
"je 2f\n\t" |
"movsb\n" |
"2:" |
: "=&c" (d0), "=&D" (d1), "=&S" (d2) |
:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) |
: "memory"); |
return (to); |
} |
#else |
#define __memcpy(a,b,c) memcpy(a,b,c) |
#endif |
/* ================================================================ |
* Debugging: |
*/ |
extern int INTEL_DEBUG; |
#define DEBUG_TEXTURE 0x1 |
#define DEBUG_STATE 0x2 |
#define DEBUG_IOCTL 0x4 |
#define DEBUG_BLIT 0x8 |
#define DEBUG_MIPTREE 0x10 |
#define DEBUG_PERF 0x20 |
#define DEBUG_BATCH 0x80 |
#define DEBUG_PIXEL 0x100 |
#define DEBUG_BUFMGR 0x200 |
#define DEBUG_REGION 0x400 |
#define DEBUG_FBO 0x800 |
#define DEBUG_GS 0x1000 |
#define DEBUG_SYNC 0x2000 |
#define DEBUG_PRIMS 0x4000 |
#define DEBUG_VERTS 0x8000 |
#define DEBUG_DRI 0x10000 |
#define DEBUG_SF 0x20000 |
#define DEBUG_STATS 0x100000 |
#define DEBUG_WM 0x400000 |
#define DEBUG_URB 0x800000 |
#define DEBUG_VS 0x1000000 |
#define DEBUG_CLIP 0x2000000 |
#define DEBUG_AUB 0x4000000 |
#define DEBUG_SHADER_TIME 0x8000000 |
#define DEBUG_BLORP 0x10000000 |
#define DEBUG_NO16 0x20000000 |
#ifdef HAVE_ANDROID_PLATFORM |
#define LOG_TAG "INTEL-MESA" |
#include <cutils/log.h> |
#ifndef ALOGW |
#define ALOGW LOGW |
#endif |
#define dbg_printf(...) ALOGW(__VA_ARGS__) |
#else |
#define dbg_printf(...) printf(__VA_ARGS__) |
#endif /* HAVE_ANDROID_PLATFORM */ |
#define DBG(...) do { \ |
if (unlikely(INTEL_DEBUG & FILE_DEBUG_FLAG)) \ |
dbg_printf(__VA_ARGS__); \ |
} while(0) |
#define perf_debug(...) do { \ |
static GLuint msg_id = 0; \ |
if (unlikely(INTEL_DEBUG & DEBUG_PERF)) \ |
dbg_printf(__VA_ARGS__); \ |
if (brw->perf_debug) \ |
_mesa_gl_debug(&brw->ctx, &msg_id, \ |
MESA_DEBUG_TYPE_PERFORMANCE, \ |
MESA_DEBUG_SEVERITY_MEDIUM, \ |
__VA_ARGS__); \ |
} while(0) |
#define WARN_ONCE(cond, fmt...) do { \ |
if (unlikely(cond)) { \ |
static bool _warned = false; \ |
static GLuint msg_id = 0; \ |
if (!_warned) { \ |
fprintf(stderr, "WARNING: "); \ |
fprintf(stderr, fmt); \ |
_warned = true; \ |
\ |
_mesa_gl_debug(ctx, &msg_id, \ |
MESA_DEBUG_TYPE_OTHER, \ |
MESA_DEBUG_SEVERITY_HIGH, fmt); \ |
} \ |
} \ |
} while (0) |
/* ================================================================ |
* intel_context.c: |
*/ |
extern bool intelInitContext(struct brw_context *brw, |
int api, |
unsigned major_version, |
unsigned minor_version, |
const struct gl_config * mesaVis, |
__DRIcontext * driContextPriv, |
void *sharedContextPrivate, |
struct dd_function_table *functions, |
unsigned *dri_ctx_error); |
extern void intelFinish(struct gl_context * ctx); |
extern void _intel_flush(struct gl_context * ctx, const char *file, int line); |
#define intel_flush(ctx) _intel_flush(ctx, __FILE__, __LINE__) |
extern void intelInitDriverFunctions(struct dd_function_table *functions); |
void intel_init_syncobj_functions(struct dd_function_table *functions); |
enum { |
DRI_CONF_BO_REUSE_DISABLED, |
DRI_CONF_BO_REUSE_ALL |
}; |
extern int intel_translate_shadow_compare_func(GLenum func); |
extern int intel_translate_compare_func(GLenum func); |
extern int intel_translate_stencil_op(GLenum op); |
extern int intel_translate_logic_op(GLenum opcode); |
void intel_update_renderbuffers(__DRIcontext *context, |
__DRIdrawable *drawable); |
void intel_prepare_render(struct brw_context *brw); |
void |
intel_resolve_for_dri2_flush(struct brw_context *brw, |
__DRIdrawable *drawable); |
extern void |
intelInitExtensions(struct gl_context *ctx); |
extern void |
intelInitClearFuncs(struct dd_function_table *functions); |
static INLINE bool |
is_power_of_two(uint32_t value) |
{ |
return (value & (value - 1)) == 0; |
} |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_extensions.c |
---|
0,0 → 1,169 |
/************************************************************************** |
* |
* 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 "main/version.h" |
#include "brw_context.h" |
#include "intel_chipset.h" |
#include "intel_reg.h" |
#include "utils.h" |
/** |
* Initializes potential list of extensions if ctx == NULL, or actually enables |
* extensions for a context. |
*/ |
void |
intelInitExtensions(struct gl_context *ctx) |
{ |
struct brw_context *brw = brw_context(ctx); |
assert(brw->gen >= 4); |
ctx->Extensions.ARB_depth_buffer_float = true; |
ctx->Extensions.ARB_depth_clamp = true; |
ctx->Extensions.ARB_depth_texture = true; |
ctx->Extensions.ARB_draw_elements_base_vertex = true; |
ctx->Extensions.ARB_draw_instanced = true; |
ctx->Extensions.ARB_ES2_compatibility = true; |
ctx->Extensions.ARB_explicit_attrib_location = true; |
ctx->Extensions.ARB_fragment_coord_conventions = true; |
ctx->Extensions.ARB_fragment_program = true; |
ctx->Extensions.ARB_fragment_program_shadow = true; |
ctx->Extensions.ARB_fragment_shader = true; |
ctx->Extensions.ARB_framebuffer_object = true; |
ctx->Extensions.ARB_half_float_pixel = true; |
ctx->Extensions.ARB_half_float_vertex = true; |
ctx->Extensions.ARB_instanced_arrays = true; |
ctx->Extensions.ARB_internalformat_query = true; |
ctx->Extensions.ARB_map_buffer_range = true; |
ctx->Extensions.ARB_occlusion_query = true; |
ctx->Extensions.ARB_occlusion_query2 = true; |
ctx->Extensions.ARB_point_sprite = true; |
ctx->Extensions.ARB_seamless_cube_map = true; |
ctx->Extensions.ARB_shader_bit_encoding = true; |
ctx->Extensions.ARB_shader_texture_lod = true; |
ctx->Extensions.ARB_shadow = true; |
ctx->Extensions.ARB_sync = true; |
ctx->Extensions.ARB_texture_border_clamp = true; |
ctx->Extensions.ARB_texture_compression_rgtc = true; |
ctx->Extensions.ARB_texture_cube_map = true; |
ctx->Extensions.ARB_texture_env_combine = true; |
ctx->Extensions.ARB_texture_env_crossbar = true; |
ctx->Extensions.ARB_texture_env_dot3 = true; |
ctx->Extensions.ARB_texture_float = true; |
ctx->Extensions.ARB_texture_non_power_of_two = true; |
ctx->Extensions.ARB_texture_rg = true; |
ctx->Extensions.ARB_texture_rgb10_a2ui = true; |
ctx->Extensions.ARB_vertex_program = true; |
ctx->Extensions.ARB_vertex_shader = true; |
ctx->Extensions.ARB_vertex_type_2_10_10_10_rev = true; |
ctx->Extensions.EXT_blend_color = true; |
ctx->Extensions.EXT_blend_equation_separate = true; |
ctx->Extensions.EXT_blend_func_separate = true; |
ctx->Extensions.EXT_blend_minmax = true; |
ctx->Extensions.EXT_draw_buffers2 = true; |
ctx->Extensions.EXT_framebuffer_blit = true; |
ctx->Extensions.EXT_framebuffer_sRGB = true; |
ctx->Extensions.EXT_gpu_program_parameters = true; |
ctx->Extensions.EXT_packed_depth_stencil = true; |
ctx->Extensions.EXT_packed_float = true; |
ctx->Extensions.EXT_pixel_buffer_object = true; |
ctx->Extensions.EXT_point_parameters = true; |
ctx->Extensions.EXT_provoking_vertex = true; |
ctx->Extensions.EXT_separate_shader_objects = true; |
ctx->Extensions.EXT_texture_array = true; |
ctx->Extensions.EXT_texture_env_dot3 = true; |
ctx->Extensions.EXT_texture_filter_anisotropic = true; |
ctx->Extensions.EXT_texture_integer = true; |
ctx->Extensions.EXT_texture_shared_exponent = true; |
ctx->Extensions.EXT_texture_snorm = true; |
ctx->Extensions.EXT_texture_sRGB = true; |
ctx->Extensions.EXT_texture_sRGB_decode = true; |
ctx->Extensions.EXT_texture_swizzle = true; |
ctx->Extensions.EXT_stencil_two_side = true; |
ctx->Extensions.EXT_vertex_array_bgra = true; |
ctx->Extensions.APPLE_object_purgeable = true; |
ctx->Extensions.ATI_envmap_bumpmap = true; |
ctx->Extensions.ATI_separate_stencil = true; |
ctx->Extensions.ATI_texture_env_combine3 = true; |
ctx->Extensions.MESA_pack_invert = true; |
ctx->Extensions.MESA_texture_array = true; |
ctx->Extensions.MESA_ycbcr_texture = true; |
ctx->Extensions.NV_conditional_render = true; |
ctx->Extensions.NV_primitive_restart = true; |
ctx->Extensions.NV_texture_env_combine4 = true; |
ctx->Extensions.NV_texture_rectangle = true; |
ctx->Extensions.TDFX_texture_compression_FXT1 = true; |
ctx->Extensions.OES_compressed_ETC1_RGB8_texture = true; |
ctx->Extensions.OES_EGL_image = true; |
ctx->Extensions.OES_draw_texture = true; |
ctx->Extensions.OES_standard_derivatives = true; |
if (brw->gen >= 6) |
ctx->Const.GLSLVersion = 140; |
else |
ctx->Const.GLSLVersion = 120; |
_mesa_override_glsl_version(ctx); |
if (brw->gen >= 6) { |
uint64_t dummy; |
ctx->Extensions.EXT_framebuffer_multisample = true; |
ctx->Extensions.EXT_transform_feedback = true; |
ctx->Extensions.EXT_framebuffer_multisample_blit_scaled = true; |
ctx->Extensions.ARB_blend_func_extended = !driQueryOptionb(&brw->optionCache, "disable_blend_func_extended"); |
ctx->Extensions.ARB_draw_buffers_blend = true; |
ctx->Extensions.ARB_ES3_compatibility = true; |
ctx->Extensions.ARB_uniform_buffer_object = true; |
ctx->Extensions.ARB_shading_language_420pack = true; |
ctx->Extensions.ARB_texture_buffer_object = true; |
ctx->Extensions.ARB_texture_buffer_object_rgb32 = true; |
ctx->Extensions.ARB_texture_cube_map_array = true; |
ctx->Extensions.OES_depth_texture_cube_map = true; |
ctx->Extensions.ARB_shading_language_packing = true; |
ctx->Extensions.ARB_texture_multisample = true; |
/* Test if the kernel has the ioctl. */ |
if (drm_intel_reg_read(brw->bufmgr, TIMESTAMP, &dummy) == 0) |
ctx->Extensions.ARB_timer_query = true; |
} |
if (brw->gen >= 5) { |
ctx->Extensions.ARB_texture_query_lod = true; |
ctx->Extensions.EXT_timer_query = true; |
} |
if (ctx->API == API_OPENGL_CORE) |
ctx->Extensions.ARB_base_instance = true; |
if (ctx->API != API_OPENGL_CORE) |
ctx->Extensions.ARB_color_buffer_float = true; |
if (ctx->Mesa_DXTn || driQueryOptionb(&brw->optionCache, "force_s3tc_enable")) |
ctx->Extensions.EXT_texture_compression_s3tc = true; |
ctx->Extensions.ANGLE_texture_compression_dxt = true; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_fbo.c |
---|
0,0 → 1,895 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#include "main/enums.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/fbobject.h" |
#include "main/framebuffer.h" |
#include "main/renderbuffer.h" |
#include "main/context.h" |
#include "main/teximage.h" |
#include "main/image.h" |
#include "swrast/swrast.h" |
#include "drivers/common/meta.h" |
#include "intel_batchbuffer.h" |
#include "intel_buffers.h" |
#include "intel_blit.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_tex.h" |
#include "brw_context.h" |
#define FILE_DEBUG_FLAG DEBUG_FBO |
/** |
* Create a new framebuffer object. |
*/ |
static struct gl_framebuffer * |
intel_new_framebuffer(struct gl_context * ctx, GLuint name) |
{ |
/* Only drawable state in intel_framebuffer at this time, just use Mesa's |
* class |
*/ |
return _mesa_new_framebuffer(ctx, name); |
} |
/** Called by gl_renderbuffer::Delete() */ |
static void |
intel_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) |
{ |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
ASSERT(irb); |
intel_miptree_release(&irb->mt); |
_mesa_delete_renderbuffer(ctx, rb); |
} |
/** |
* \see dd_function_table::MapRenderbuffer |
*/ |
static void |
intel_map_renderbuffer(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **out_map, |
GLint *out_stride) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
void *map; |
int stride; |
if (srb->Buffer) { |
/* this is a malloc'd renderbuffer (accum buffer), not an irb */ |
GLint bpp = _mesa_get_format_bytes(rb->Format); |
GLint rowStride = srb->RowStride; |
*out_map = (GLubyte *) srb->Buffer + y * rowStride + x * bpp; |
*out_stride = rowStride; |
return; |
} |
intel_prepare_render(brw); |
/* For a window-system renderbuffer, we need to flip the mapping we receive |
* upside-down. So we need to ask for a rectangle on flipped vertically, and |
* we then return a pointer to the bottom of it with a negative stride. |
*/ |
if (rb->Name == 0) { |
y = rb->Height - y - h; |
} |
intel_miptree_map(brw, irb->mt, irb->mt_level, irb->mt_layer, |
x, y, w, h, mode, &map, &stride); |
if (rb->Name == 0) { |
map += (h - 1) * stride; |
stride = -stride; |
} |
DBG("%s: rb %d (%s) mt mapped: (%d, %d) (%dx%d) -> %p/%d\n", |
__FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format), |
x, y, w, h, map, stride); |
*out_map = map; |
*out_stride = stride; |
} |
/** |
* \see dd_function_table::UnmapRenderbuffer |
*/ |
static void |
intel_unmap_renderbuffer(struct gl_context *ctx, |
struct gl_renderbuffer *rb) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
DBG("%s: rb %d (%s)\n", __FUNCTION__, |
rb->Name, _mesa_get_format_name(rb->Format)); |
if (srb->Buffer) { |
/* this is a malloc'd renderbuffer (accum buffer) */ |
/* nothing to do */ |
return; |
} |
intel_miptree_unmap(brw, irb->mt, irb->mt_level, irb->mt_layer); |
} |
/** |
* Round up the requested multisample count to the next supported sample size. |
*/ |
unsigned |
intel_quantize_num_samples(struct intel_screen *intel, unsigned num_samples) |
{ |
switch (intel->gen) { |
case 6: |
/* Gen6 supports only 4x multisampling. */ |
if (num_samples > 0) |
return 4; |
else |
return 0; |
case 7: |
/* Gen7 supports 4x and 8x multisampling. */ |
if (num_samples > 4) |
return 8; |
else if (num_samples > 0) |
return 4; |
else |
return 0; |
return 0; |
default: |
/* MSAA unsupported. */ |
return 0; |
} |
} |
/** |
* Called via glRenderbufferStorageEXT() to set the format and allocate |
* storage for a user-created renderbuffer. |
*/ |
static GLboolean |
intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, |
GLuint width, GLuint height) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_screen *screen = brw->intelScreen; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
rb->NumSamples = intel_quantize_num_samples(screen, rb->NumSamples); |
switch (internalFormat) { |
default: |
/* Use the same format-choice logic as for textures. |
* Renderbuffers aren't any different from textures for us, |
* except they're less useful because you can't texture with |
* them. |
*/ |
rb->Format = ctx->Driver.ChooseTextureFormat(ctx, GL_TEXTURE_2D, |
internalFormat, |
GL_NONE, GL_NONE); |
break; |
case GL_STENCIL_INDEX: |
case GL_STENCIL_INDEX1_EXT: |
case GL_STENCIL_INDEX4_EXT: |
case GL_STENCIL_INDEX8_EXT: |
case GL_STENCIL_INDEX16_EXT: |
/* These aren't actual texture formats, so force them here. */ |
if (brw->has_separate_stencil) { |
rb->Format = MESA_FORMAT_S8; |
} else { |
assert(!brw->must_use_separate_stencil); |
rb->Format = MESA_FORMAT_S8_Z24; |
} |
break; |
} |
rb->Width = width; |
rb->Height = height; |
rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); |
intel_miptree_release(&irb->mt); |
DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(internalFormat), |
_mesa_get_format_name(rb->Format), width, height); |
if (width == 0 || height == 0) |
return true; |
irb->mt = intel_miptree_create_for_renderbuffer(brw, rb->Format, |
width, height, |
rb->NumSamples); |
if (!irb->mt) |
return false; |
return true; |
} |
static void |
intel_image_target_renderbuffer_storage(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
void *image_handle) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_renderbuffer *irb; |
__DRIscreen *screen; |
__DRIimage *image; |
screen = brw->intelScreen->driScrnPriv; |
image = screen->dri2.image->lookupEGLImage(screen, image_handle, |
screen->loaderPrivate); |
if (image == NULL) |
return; |
/* __DRIimage is opaque to the core so it has to be checked here */ |
switch (image->format) { |
case MESA_FORMAT_RGBA8888_REV: |
_mesa_error(ctx, GL_INVALID_OPERATION, |
"glEGLImageTargetRenderbufferStorage(unsupported image format"); |
return; |
break; |
default: |
break; |
} |
irb = intel_renderbuffer(rb); |
intel_miptree_release(&irb->mt); |
irb->mt = intel_miptree_create_for_bo(brw, |
image->region->bo, |
image->format, |
image->offset, |
image->region->width, |
image->region->height, |
image->region->pitch, |
image->region->tiling); |
if (!irb->mt) |
return; |
rb->InternalFormat = image->internal_format; |
rb->Width = image->region->width; |
rb->Height = image->region->height; |
rb->Format = image->format; |
rb->_BaseFormat = _mesa_base_fbo_format(ctx, image->internal_format); |
rb->NeedsFinishRenderTexture = true; |
} |
/** |
* Called by _mesa_resize_framebuffer() for each hardware renderbuffer when a |
* window system framebuffer is resized. |
* |
* Any actual buffer reallocations for hardware renderbuffers (which would |
* have triggered _mesa_resize_framebuffer()) were done by |
* intel_process_dri2_buffer(). |
*/ |
static GLboolean |
intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, GLuint width, GLuint height) |
{ |
ASSERT(rb->Name == 0); |
rb->Width = width; |
rb->Height = height; |
rb->InternalFormat = internalFormat; |
return true; |
} |
/** Dummy function for gl_renderbuffer::AllocStorage() */ |
static GLboolean |
intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, GLuint width, GLuint height) |
{ |
_mesa_problem(ctx, "intel_op_alloc_storage should never be called."); |
return false; |
} |
/** |
* Create a new intel_renderbuffer which corresponds to an on-screen window, |
* not a user-created renderbuffer. |
* |
* \param num_samples must be quantized. |
*/ |
struct intel_renderbuffer * |
intel_create_renderbuffer(gl_format format, unsigned num_samples) |
{ |
struct intel_renderbuffer *irb; |
struct gl_renderbuffer *rb; |
GET_CURRENT_CONTEXT(ctx); |
irb = CALLOC_STRUCT(intel_renderbuffer); |
if (!irb) { |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); |
return NULL; |
} |
rb = &irb->Base.Base; |
_mesa_init_renderbuffer(rb, 0); |
rb->ClassID = INTEL_RB_CLASS; |
rb->_BaseFormat = _mesa_get_format_base_format(format); |
rb->Format = format; |
rb->InternalFormat = rb->_BaseFormat; |
rb->NumSamples = num_samples; |
/* intel-specific methods */ |
rb->Delete = intel_delete_renderbuffer; |
rb->AllocStorage = intel_alloc_window_storage; |
return irb; |
} |
/** |
* Private window-system buffers (as opposed to ones shared with the display |
* server created with intel_create_renderbuffer()) are most similar in their |
* handling to user-created renderbuffers, but they have a resize handler that |
* may be called at intel_update_renderbuffers() time. |
* |
* \param num_samples must be quantized. |
*/ |
struct intel_renderbuffer * |
intel_create_private_renderbuffer(gl_format format, unsigned num_samples) |
{ |
struct intel_renderbuffer *irb; |
irb = intel_create_renderbuffer(format, num_samples); |
irb->Base.Base.AllocStorage = intel_alloc_renderbuffer_storage; |
return irb; |
} |
/** |
* Create a new renderbuffer object. |
* Typically called via glBindRenderbufferEXT(). |
*/ |
static struct gl_renderbuffer * |
intel_new_renderbuffer(struct gl_context * ctx, GLuint name) |
{ |
struct intel_renderbuffer *irb; |
struct gl_renderbuffer *rb; |
irb = CALLOC_STRUCT(intel_renderbuffer); |
if (!irb) { |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); |
return NULL; |
} |
rb = &irb->Base.Base; |
_mesa_init_renderbuffer(rb, name); |
rb->ClassID = INTEL_RB_CLASS; |
/* intel-specific methods */ |
rb->Delete = intel_delete_renderbuffer; |
rb->AllocStorage = intel_alloc_renderbuffer_storage; |
/* span routines set in alloc_storage function */ |
return rb; |
} |
static bool |
intel_renderbuffer_update_wrapper(struct brw_context *brw, |
struct intel_renderbuffer *irb, |
struct gl_texture_image *image, |
uint32_t layer) |
{ |
struct gl_renderbuffer *rb = &irb->Base.Base; |
struct intel_texture_image *intel_image = intel_texture_image(image); |
struct intel_mipmap_tree *mt = intel_image->mt; |
int level = image->Level; |
rb->Depth = image->Depth; |
rb->AllocStorage = intel_nop_alloc_storage; |
intel_miptree_check_level_layer(mt, level, layer); |
irb->mt_level = level; |
switch (mt->msaa_layout) { |
case INTEL_MSAA_LAYOUT_UMS: |
case INTEL_MSAA_LAYOUT_CMS: |
irb->mt_layer = layer * mt->num_samples; |
break; |
default: |
irb->mt_layer = layer; |
} |
intel_miptree_reference(&irb->mt, mt); |
intel_renderbuffer_set_draw_offset(irb); |
if (mt->hiz_mt == NULL && brw_is_hiz_depth_format(brw, rb->Format)) { |
intel_miptree_alloc_hiz(brw, mt); |
if (!mt->hiz_mt) |
return false; |
} |
return true; |
} |
void |
intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb) |
{ |
unsigned int dst_x, dst_y; |
/* compute offset of the particular 2D image within the texture region */ |
intel_miptree_get_image_offset(irb->mt, |
irb->mt_level, |
irb->mt_layer, |
&dst_x, &dst_y); |
irb->draw_x = dst_x; |
irb->draw_y = dst_y; |
} |
/** |
* Called by glFramebufferTexture[123]DEXT() (and other places) to |
* prepare for rendering into texture memory. This might be called |
* many times to choose different texture levels, cube faces, etc |
* before intel_finish_render_texture() is ever called. |
*/ |
static void |
intel_render_texture(struct gl_context * ctx, |
struct gl_framebuffer *fb, |
struct gl_renderbuffer_attachment *att) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct gl_renderbuffer *rb = att->Renderbuffer; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
struct gl_texture_image *image = rb->TexImage; |
struct intel_texture_image *intel_image = intel_texture_image(image); |
struct intel_mipmap_tree *mt = intel_image->mt; |
int layer; |
(void) fb; |
if (att->CubeMapFace > 0) { |
assert(att->Zoffset == 0); |
layer = att->CubeMapFace; |
} else { |
layer = att->Zoffset; |
} |
if (!intel_image->mt) { |
/* Fallback on drawing to a texture that doesn't have a miptree |
* (has a border, width/height 0, etc.) |
*/ |
_swrast_render_texture(ctx, fb, att); |
return; |
} |
intel_miptree_check_level_layer(mt, att->TextureLevel, layer); |
if (!intel_renderbuffer_update_wrapper(brw, irb, image, layer)) { |
_swrast_render_texture(ctx, fb, att); |
return; |
} |
DBG("Begin render %s texture tex=%u w=%d h=%d d=%d refcount=%d\n", |
_mesa_get_format_name(image->TexFormat), |
att->Texture->Name, image->Width, image->Height, image->Depth, |
rb->RefCount); |
} |
/** |
* Called by Mesa when rendering to a texture is done. |
*/ |
static void |
intel_finish_render_texture(struct gl_context * ctx, struct gl_renderbuffer *rb) |
{ |
struct brw_context *brw = brw_context(ctx); |
DBG("Finish render %s texture\n", _mesa_get_format_name(rb->Format)); |
/* Since we've (probably) rendered to the texture and will (likely) use |
* it in the texture domain later on in this batchbuffer, flush the |
* batch. Once again, we wish for a domain tracker in libdrm to cover |
* usage inside of a batchbuffer like GEM does in the kernel. |
*/ |
intel_batchbuffer_emit_mi_flush(brw); |
} |
#define fbo_incomplete(fb, ...) do { \ |
static GLuint msg_id = 0; \ |
if (unlikely(ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT)) { \ |
_mesa_gl_debug(ctx, &msg_id, \ |
MESA_DEBUG_TYPE_OTHER, \ |
MESA_DEBUG_SEVERITY_MEDIUM, \ |
__VA_ARGS__); \ |
} \ |
DBG(__VA_ARGS__); \ |
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; \ |
} while (0) |
/** |
* Do additional "completeness" testing of a framebuffer object. |
*/ |
static void |
intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_renderbuffer *depthRb = |
intel_get_renderbuffer(fb, BUFFER_DEPTH); |
struct intel_renderbuffer *stencilRb = |
intel_get_renderbuffer(fb, BUFFER_STENCIL); |
struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL; |
int i; |
DBG("%s() on fb %p (%s)\n", __FUNCTION__, |
fb, (fb == ctx->DrawBuffer ? "drawbuffer" : |
(fb == ctx->ReadBuffer ? "readbuffer" : "other buffer"))); |
if (depthRb) |
depth_mt = depthRb->mt; |
if (stencilRb) { |
stencil_mt = stencilRb->mt; |
if (stencil_mt->stencil_mt) |
stencil_mt = stencil_mt->stencil_mt; |
} |
if (depth_mt && stencil_mt) { |
if (depth_mt == stencil_mt) { |
/* For true packed depth/stencil (not faked on prefers-separate-stencil |
* hardware) we need to be sure they're the same level/layer, since |
* we'll be emitting a single packet describing the packed setup. |
*/ |
if (depthRb->mt_level != stencilRb->mt_level || |
depthRb->mt_layer != stencilRb->mt_layer) { |
fbo_incomplete(fb, |
"FBO incomplete: depth image level/layer %d/%d != " |
"stencil image %d/%d\n", |
depthRb->mt_level, |
depthRb->mt_layer, |
stencilRb->mt_level, |
stencilRb->mt_layer); |
} |
} else { |
if (!brw->has_separate_stencil) { |
fbo_incomplete(fb, "FBO incomplete: separate stencil " |
"unsupported\n"); |
} |
if (stencil_mt->format != MESA_FORMAT_S8) { |
fbo_incomplete(fb, "FBO incomplete: separate stencil is %s " |
"instead of S8\n", |
_mesa_get_format_name(stencil_mt->format)); |
} |
if (brw->gen < 7 && !intel_renderbuffer_has_hiz(depthRb)) { |
/* Before Gen7, separate depth and stencil buffers can be used |
* only if HiZ is enabled. From the Sandybridge PRM, Volume 2, |
* Part 1, Bit 3DSTATE_DEPTH_BUFFER.SeparateStencilBufferEnable: |
* [DevSNB]: This field must be set to the same value (enabled |
* or disabled) as Hierarchical Depth Buffer Enable. |
*/ |
fbo_incomplete(fb, "FBO incomplete: separate stencil " |
"without HiZ\n"); |
} |
} |
} |
for (i = 0; i < Elements(fb->Attachment); i++) { |
struct gl_renderbuffer *rb; |
struct intel_renderbuffer *irb; |
if (fb->Attachment[i].Type == GL_NONE) |
continue; |
/* A supported attachment will have a Renderbuffer set either |
* from being a Renderbuffer or being a texture that got the |
* intel_wrap_texture() treatment. |
*/ |
rb = fb->Attachment[i].Renderbuffer; |
if (rb == NULL) { |
fbo_incomplete(fb, "FBO incomplete: attachment without " |
"renderbuffer\n"); |
continue; |
} |
if (fb->Attachment[i].Type == GL_TEXTURE) { |
if (rb->TexImage->Border) { |
fbo_incomplete(fb, "FBO incomplete: texture with border\n"); |
continue; |
} |
} |
irb = intel_renderbuffer(rb); |
if (irb == NULL) { |
fbo_incomplete(fb, "FBO incomplete: software rendering " |
"renderbuffer\n"); |
continue; |
} |
if (!brw_render_target_supported(brw, rb)) { |
fbo_incomplete(fb, "FBO incomplete: Unsupported HW " |
"texture/renderbuffer format attached: %s\n", |
_mesa_get_format_name(intel_rb_format(irb))); |
} |
} |
} |
/** |
* Try to do a glBlitFramebuffer using glCopyTexSubImage2D |
* We can do this when the dst renderbuffer is actually a texture and |
* there is no scaling, mirroring or scissoring. |
* |
* \return new buffer mask indicating the buffers left to blit using the |
* normal path. |
*/ |
static GLbitfield |
intel_blit_framebuffer_with_blitter(struct gl_context *ctx, |
GLint srcX0, GLint srcY0, |
GLint srcX1, GLint srcY1, |
GLint dstX0, GLint dstY0, |
GLint dstX1, GLint dstY1, |
GLbitfield mask, GLenum filter) |
{ |
struct brw_context *brw = brw_context(ctx); |
/* Sync up the state of window system buffers. We need to do this before |
* we go looking for the buffers. |
*/ |
intel_prepare_render(brw); |
if (mask & GL_COLOR_BUFFER_BIT) { |
GLint i; |
const struct gl_framebuffer *drawFb = ctx->DrawBuffer; |
const struct gl_framebuffer *readFb = ctx->ReadBuffer; |
struct gl_renderbuffer *src_rb = readFb->_ColorReadBuffer; |
struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb); |
if (!src_irb) { |
perf_debug("glBlitFramebuffer(): missing src renderbuffer. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
/* If the source and destination are the same size with no mirroring, |
* the rectangles are within the size of the texture and there is no |
* scissor, then we can probably use the blit engine. |
*/ |
if (!(srcX0 - srcX1 == dstX0 - dstX1 && |
srcY0 - srcY1 == dstY0 - dstY1 && |
srcX1 >= srcX0 && |
srcY1 >= srcY0 && |
srcX0 >= 0 && srcX1 <= readFb->Width && |
srcY0 >= 0 && srcY1 <= readFb->Height && |
dstX0 >= 0 && dstX1 <= drawFb->Width && |
dstY0 >= 0 && dstY1 <= drawFb->Height && |
!ctx->Scissor.Enabled)) { |
perf_debug("glBlitFramebuffer(): non-1:1 blit. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
/* Blit to all active draw buffers. We don't do any pre-checking, |
* because we assume that copying to MRTs is rare, and failure midway |
* through copying is even more rare. Even if it was to occur, it's |
* safe to let meta start the copy over from scratch, because |
* glBlitFramebuffer completely overwrites the destination pixels, and |
* results are undefined if any destination pixels have a dependency on |
* source pixels. |
*/ |
for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { |
struct gl_renderbuffer *dst_rb = ctx->DrawBuffer->_ColorDrawBuffers[i]; |
struct intel_renderbuffer *dst_irb = intel_renderbuffer(dst_rb); |
if (!dst_irb) { |
perf_debug("glBlitFramebuffer(): missing dst renderbuffer. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
gl_format src_format = _mesa_get_srgb_format_linear(src_rb->Format); |
gl_format dst_format = _mesa_get_srgb_format_linear(dst_rb->Format); |
if (src_format != dst_format) { |
perf_debug("glBlitFramebuffer(): unsupported blit from %s to %s. " |
"Falling back to software rendering.\n", |
_mesa_get_format_name(src_format), |
_mesa_get_format_name(dst_format)); |
return mask; |
} |
if (!intel_miptree_blit(brw, |
src_irb->mt, |
src_irb->mt_level, src_irb->mt_layer, |
srcX0, srcY0, src_rb->Name == 0, |
dst_irb->mt, |
dst_irb->mt_level, dst_irb->mt_layer, |
dstX0, dstY0, dst_rb->Name == 0, |
dstX1 - dstX0, dstY1 - dstY0, GL_COPY)) { |
perf_debug("glBlitFramebuffer(): unknown blit failure. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
} |
mask &= ~GL_COLOR_BUFFER_BIT; |
} |
return mask; |
} |
static void |
intel_blit_framebuffer(struct gl_context *ctx, |
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, |
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, |
GLbitfield mask, GLenum filter) |
{ |
mask = brw_blorp_framebuffer(brw_context(ctx), |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
mask, filter); |
if (mask == 0x0) |
return; |
/* Try using the BLT engine. */ |
mask = intel_blit_framebuffer_with_blitter(ctx, |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
mask, filter); |
if (mask == 0x0) |
return; |
_mesa_meta_BlitFramebuffer(ctx, |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
mask, filter); |
} |
/** |
* This is a no-op except on multisample buffers shared with DRI2. |
*/ |
void |
intel_renderbuffer_set_needs_downsample(struct intel_renderbuffer *irb) |
{ |
if (irb->mt && irb->mt->singlesample_mt) |
irb->mt->need_downsample = true; |
} |
/** |
* Does the renderbuffer have hiz enabled? |
*/ |
bool |
intel_renderbuffer_has_hiz(struct intel_renderbuffer *irb) |
{ |
return intel_miptree_slice_has_hiz(irb->mt, irb->mt_level, irb->mt_layer); |
} |
void |
intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb) |
{ |
if (irb->mt) { |
intel_miptree_slice_set_needs_hiz_resolve(irb->mt, |
irb->mt_level, |
irb->mt_layer); |
} |
} |
void |
intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb) |
{ |
if (irb->mt) { |
intel_miptree_slice_set_needs_depth_resolve(irb->mt, |
irb->mt_level, |
irb->mt_layer); |
} |
} |
bool |
intel_renderbuffer_resolve_hiz(struct brw_context *brw, |
struct intel_renderbuffer *irb) |
{ |
if (irb->mt) |
return intel_miptree_slice_resolve_hiz(brw, |
irb->mt, |
irb->mt_level, |
irb->mt_layer); |
return false; |
} |
bool |
intel_renderbuffer_resolve_depth(struct brw_context *brw, |
struct intel_renderbuffer *irb) |
{ |
if (irb->mt) |
return intel_miptree_slice_resolve_depth(brw, |
irb->mt, |
irb->mt_level, |
irb->mt_layer); |
return false; |
} |
void |
intel_renderbuffer_move_to_temp(struct brw_context *brw, |
struct intel_renderbuffer *irb, |
bool invalidate) |
{ |
struct gl_renderbuffer *rb =&irb->Base.Base; |
struct intel_texture_image *intel_image = intel_texture_image(rb->TexImage); |
struct intel_mipmap_tree *new_mt; |
int width, height, depth; |
intel_miptree_get_dimensions_for_image(rb->TexImage, &width, &height, &depth); |
new_mt = intel_miptree_create(brw, rb->TexImage->TexObject->Target, |
intel_image->base.Base.TexFormat, |
intel_image->base.Base.Level, |
intel_image->base.Base.Level, |
width, height, depth, |
true, |
irb->mt->num_samples, |
INTEL_MIPTREE_TILING_ANY); |
if (brw_is_hiz_depth_format(brw, new_mt->format)) { |
intel_miptree_alloc_hiz(brw, new_mt); |
} |
intel_miptree_copy_teximage(brw, intel_image, new_mt, invalidate); |
intel_miptree_reference(&irb->mt, intel_image->mt); |
intel_renderbuffer_set_draw_offset(irb); |
intel_miptree_release(&new_mt); |
} |
/** |
* Do one-time context initializations related to GL_EXT_framebuffer_object. |
* Hook in device driver functions. |
*/ |
void |
intel_fbo_init(struct brw_context *brw) |
{ |
struct dd_function_table *dd = &brw->ctx.Driver; |
dd->NewFramebuffer = intel_new_framebuffer; |
dd->NewRenderbuffer = intel_new_renderbuffer; |
dd->MapRenderbuffer = intel_map_renderbuffer; |
dd->UnmapRenderbuffer = intel_unmap_renderbuffer; |
dd->RenderTexture = intel_render_texture; |
dd->FinishRenderTexture = intel_finish_render_texture; |
dd->ValidateFramebuffer = intel_validate_framebuffer; |
dd->BlitFramebuffer = intel_blit_framebuffer; |
dd->EGLImageTargetRenderbufferStorage = |
intel_image_target_renderbuffer_storage; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_fbo.c.bak |
---|
0,0 → 1,899 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#include "main/enums.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/fbobject.h" |
#include "main/framebuffer.h" |
#include "main/renderbuffer.h" |
#include "main/context.h" |
#include "main/teximage.h" |
#include "main/image.h" |
#include "swrast/swrast.h" |
#include "drivers/common/meta.h" |
#include "intel_batchbuffer.h" |
#include "intel_buffers.h" |
#include "intel_blit.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_tex.h" |
#include "brw_context.h" |
#define FILE_DEBUG_FLAG DEBUG_FBO |
/** |
* Create a new framebuffer object. |
*/ |
static struct gl_framebuffer * |
intel_new_framebuffer(struct gl_context * ctx, GLuint name) |
{ |
/* Only drawable state in intel_framebuffer at this time, just use Mesa's |
* class |
*/ |
return _mesa_new_framebuffer(ctx, name); |
} |
/** Called by gl_renderbuffer::Delete() */ |
static void |
intel_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) |
{ |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
ASSERT(irb); |
intel_miptree_release(&irb->mt); |
_mesa_delete_renderbuffer(ctx, rb); |
} |
/** |
* \see dd_function_table::MapRenderbuffer |
*/ |
static void |
intel_map_renderbuffer(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **out_map, |
GLint *out_stride) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
void *map; |
int stride; |
if (srb->Buffer) { |
/* this is a malloc'd renderbuffer (accum buffer), not an irb */ |
GLint bpp = _mesa_get_format_bytes(rb->Format); |
GLint rowStride = srb->RowStride; |
*out_map = (GLubyte *) srb->Buffer + y * rowStride + x * bpp; |
*out_stride = rowStride; |
return; |
} |
intel_prepare_render(brw); |
/* For a window-system renderbuffer, we need to flip the mapping we receive |
* upside-down. So we need to ask for a rectangle on flipped vertically, and |
* we then return a pointer to the bottom of it with a negative stride. |
*/ |
if (rb->Name == 0) { |
y = rb->Height - y - h; |
} |
intel_miptree_map(brw, irb->mt, irb->mt_level, irb->mt_layer, |
x, y, w, h, mode, &map, &stride); |
if (rb->Name == 0) { |
map += (h - 1) * stride; |
stride = -stride; |
} |
DBG("%s: rb %d (%s) mt mapped: (%d, %d) (%dx%d) -> %p/%d\n", |
__FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format), |
x, y, w, h, map, stride); |
*out_map = map; |
*out_stride = stride; |
} |
/** |
* \see dd_function_table::UnmapRenderbuffer |
*/ |
static void |
intel_unmap_renderbuffer(struct gl_context *ctx, |
struct gl_renderbuffer *rb) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
DBG("%s: rb %d (%s)\n", __FUNCTION__, |
rb->Name, _mesa_get_format_name(rb->Format)); |
if (srb->Buffer) { |
/* this is a malloc'd renderbuffer (accum buffer) */ |
/* nothing to do */ |
return; |
} |
intel_miptree_unmap(brw, irb->mt, irb->mt_level, irb->mt_layer); |
} |
/** |
* Round up the requested multisample count to the next supported sample size. |
*/ |
unsigned |
intel_quantize_num_samples(struct intel_screen *intel, unsigned num_samples) |
{ |
switch (intel->gen) { |
case 6: |
/* Gen6 supports only 4x multisampling. */ |
if (num_samples > 0) |
return 4; |
else |
return 0; |
case 7: |
/* Gen7 supports 4x and 8x multisampling. */ |
if (num_samples > 4) |
return 8; |
else if (num_samples > 0) |
return 4; |
else |
return 0; |
return 0; |
default: |
/* MSAA unsupported. */ |
return 0; |
} |
} |
/** |
* Called via glRenderbufferStorageEXT() to set the format and allocate |
* storage for a user-created renderbuffer. |
*/ |
static GLboolean |
intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, |
GLuint width, GLuint height) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_screen *screen = brw->intelScreen; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
rb->NumSamples = intel_quantize_num_samples(screen, rb->NumSamples); |
switch (internalFormat) { |
default: |
/* Use the same format-choice logic as for textures. |
* Renderbuffers aren't any different from textures for us, |
* except they're less useful because you can't texture with |
* them. |
*/ |
rb->Format = ctx->Driver.ChooseTextureFormat(ctx, GL_TEXTURE_2D, |
internalFormat, |
GL_NONE, GL_NONE); |
break; |
case GL_STENCIL_INDEX: |
case GL_STENCIL_INDEX1_EXT: |
case GL_STENCIL_INDEX4_EXT: |
case GL_STENCIL_INDEX8_EXT: |
case GL_STENCIL_INDEX16_EXT: |
/* These aren't actual texture formats, so force them here. */ |
if (brw->has_separate_stencil) { |
rb->Format = MESA_FORMAT_S8; |
} else { |
assert(!brw->must_use_separate_stencil); |
rb->Format = MESA_FORMAT_S8_Z24; |
} |
break; |
} |
rb->Width = width; |
rb->Height = height; |
rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); |
intel_miptree_release(&irb->mt); |
DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(internalFormat), |
_mesa_get_format_name(rb->Format), width, height); |
if (width == 0 || height == 0) |
return true; |
irb->mt = intel_miptree_create_for_renderbuffer(brw, rb->Format, |
width, height, |
rb->NumSamples); |
if (!irb->mt) |
return false; |
return true; |
} |
static void |
intel_image_target_renderbuffer_storage(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
void *image_handle) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_renderbuffer *irb; |
__DRIscreen *screen; |
__DRIimage *image; |
screen = brw->intelScreen->driScrnPriv; |
image = screen->dri2.image->lookupEGLImage(screen, image_handle, |
screen->loaderPrivate); |
if (image == NULL) |
return; |
/* __DRIimage is opaque to the core so it has to be checked here */ |
switch (image->format) { |
case MESA_FORMAT_RGBA8888_REV: |
_mesa_error(ctx, GL_INVALID_OPERATION, |
"glEGLImageTargetRenderbufferStorage(unsupported image format"); |
return; |
break; |
default: |
break; |
} |
irb = intel_renderbuffer(rb); |
intel_miptree_release(&irb->mt); |
irb->mt = intel_miptree_create_for_bo(brw, |
image->region->bo, |
image->format, |
image->offset, |
image->region->width, |
image->region->height, |
image->region->pitch, |
image->region->tiling); |
if (!irb->mt) |
return; |
rb->InternalFormat = image->internal_format; |
rb->Width = image->region->width; |
rb->Height = image->region->height; |
rb->Format = image->format; |
rb->_BaseFormat = _mesa_base_fbo_format(ctx, image->internal_format); |
rb->NeedsFinishRenderTexture = true; |
} |
/** |
* Called by _mesa_resize_framebuffer() for each hardware renderbuffer when a |
* window system framebuffer is resized. |
* |
* Any actual buffer reallocations for hardware renderbuffers (which would |
* have triggered _mesa_resize_framebuffer()) were done by |
* intel_process_dri2_buffer(). |
*/ |
static GLboolean |
intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, GLuint width, GLuint height) |
{ |
ASSERT(rb->Name == 0); |
rb->Width = width; |
rb->Height = height; |
rb->InternalFormat = internalFormat; |
return true; |
} |
/** Dummy function for gl_renderbuffer::AllocStorage() */ |
static GLboolean |
intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, GLuint width, GLuint height) |
{ |
_mesa_problem(ctx, "intel_op_alloc_storage should never be called."); |
return false; |
} |
/** |
* Create a new intel_renderbuffer which corresponds to an on-screen window, |
* not a user-created renderbuffer. |
* |
* \param num_samples must be quantized. |
*/ |
struct intel_renderbuffer * |
intel_create_renderbuffer(gl_format format, unsigned num_samples) |
{ |
struct intel_renderbuffer *irb; |
struct gl_renderbuffer *rb; |
ENTER(); |
GET_CURRENT_CONTEXT(ctx); |
irb = CALLOC_STRUCT(intel_renderbuffer); |
if (!irb) { |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); |
return NULL; |
} |
rb = &irb->Base.Base; |
_mesa_init_renderbuffer(rb, 0); |
rb->ClassID = INTEL_RB_CLASS; |
rb->_BaseFormat = _mesa_get_format_base_format(format); |
rb->Format = format; |
rb->InternalFormat = rb->_BaseFormat; |
rb->NumSamples = num_samples; |
/* intel-specific methods */ |
rb->Delete = intel_delete_renderbuffer; |
rb->AllocStorage = intel_alloc_window_storage; |
LEAVE(); |
return irb; |
} |
/** |
* Private window-system buffers (as opposed to ones shared with the display |
* server created with intel_create_renderbuffer()) are most similar in their |
* handling to user-created renderbuffers, but they have a resize handler that |
* may be called at intel_update_renderbuffers() time. |
* |
* \param num_samples must be quantized. |
*/ |
struct intel_renderbuffer * |
intel_create_private_renderbuffer(gl_format format, unsigned num_samples) |
{ |
struct intel_renderbuffer *irb; |
irb = intel_create_renderbuffer(format, num_samples); |
irb->Base.Base.AllocStorage = intel_alloc_renderbuffer_storage; |
return irb; |
} |
/** |
* Create a new renderbuffer object. |
* Typically called via glBindRenderbufferEXT(). |
*/ |
static struct gl_renderbuffer * |
intel_new_renderbuffer(struct gl_context * ctx, GLuint name) |
{ |
struct intel_renderbuffer *irb; |
struct gl_renderbuffer *rb; |
irb = CALLOC_STRUCT(intel_renderbuffer); |
if (!irb) { |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); |
return NULL; |
} |
rb = &irb->Base.Base; |
_mesa_init_renderbuffer(rb, name); |
rb->ClassID = INTEL_RB_CLASS; |
/* intel-specific methods */ |
rb->Delete = intel_delete_renderbuffer; |
rb->AllocStorage = intel_alloc_renderbuffer_storage; |
/* span routines set in alloc_storage function */ |
return rb; |
} |
static bool |
intel_renderbuffer_update_wrapper(struct brw_context *brw, |
struct intel_renderbuffer *irb, |
struct gl_texture_image *image, |
uint32_t layer) |
{ |
struct gl_renderbuffer *rb = &irb->Base.Base; |
struct intel_texture_image *intel_image = intel_texture_image(image); |
struct intel_mipmap_tree *mt = intel_image->mt; |
int level = image->Level; |
rb->Depth = image->Depth; |
rb->AllocStorage = intel_nop_alloc_storage; |
intel_miptree_check_level_layer(mt, level, layer); |
irb->mt_level = level; |
switch (mt->msaa_layout) { |
case INTEL_MSAA_LAYOUT_UMS: |
case INTEL_MSAA_LAYOUT_CMS: |
irb->mt_layer = layer * mt->num_samples; |
break; |
default: |
irb->mt_layer = layer; |
} |
intel_miptree_reference(&irb->mt, mt); |
intel_renderbuffer_set_draw_offset(irb); |
if (mt->hiz_mt == NULL && brw_is_hiz_depth_format(brw, rb->Format)) { |
intel_miptree_alloc_hiz(brw, mt); |
if (!mt->hiz_mt) |
return false; |
} |
return true; |
} |
void |
intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb) |
{ |
unsigned int dst_x, dst_y; |
/* compute offset of the particular 2D image within the texture region */ |
intel_miptree_get_image_offset(irb->mt, |
irb->mt_level, |
irb->mt_layer, |
&dst_x, &dst_y); |
irb->draw_x = dst_x; |
irb->draw_y = dst_y; |
} |
/** |
* Called by glFramebufferTexture[123]DEXT() (and other places) to |
* prepare for rendering into texture memory. This might be called |
* many times to choose different texture levels, cube faces, etc |
* before intel_finish_render_texture() is ever called. |
*/ |
static void |
intel_render_texture(struct gl_context * ctx, |
struct gl_framebuffer *fb, |
struct gl_renderbuffer_attachment *att) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct gl_renderbuffer *rb = att->Renderbuffer; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
struct gl_texture_image *image = rb->TexImage; |
struct intel_texture_image *intel_image = intel_texture_image(image); |
struct intel_mipmap_tree *mt = intel_image->mt; |
int layer; |
(void) fb; |
if (att->CubeMapFace > 0) { |
assert(att->Zoffset == 0); |
layer = att->CubeMapFace; |
} else { |
layer = att->Zoffset; |
} |
if (!intel_image->mt) { |
/* Fallback on drawing to a texture that doesn't have a miptree |
* (has a border, width/height 0, etc.) |
*/ |
_swrast_render_texture(ctx, fb, att); |
return; |
} |
intel_miptree_check_level_layer(mt, att->TextureLevel, layer); |
if (!intel_renderbuffer_update_wrapper(brw, irb, image, layer)) { |
_swrast_render_texture(ctx, fb, att); |
return; |
} |
DBG("Begin render %s texture tex=%u w=%d h=%d d=%d refcount=%d\n", |
_mesa_get_format_name(image->TexFormat), |
att->Texture->Name, image->Width, image->Height, image->Depth, |
rb->RefCount); |
} |
/** |
* Called by Mesa when rendering to a texture is done. |
*/ |
static void |
intel_finish_render_texture(struct gl_context * ctx, struct gl_renderbuffer *rb) |
{ |
struct brw_context *brw = brw_context(ctx); |
DBG("Finish render %s texture\n", _mesa_get_format_name(rb->Format)); |
/* Since we've (probably) rendered to the texture and will (likely) use |
* it in the texture domain later on in this batchbuffer, flush the |
* batch. Once again, we wish for a domain tracker in libdrm to cover |
* usage inside of a batchbuffer like GEM does in the kernel. |
*/ |
intel_batchbuffer_emit_mi_flush(brw); |
} |
#define fbo_incomplete(fb, ...) do { \ |
static GLuint msg_id = 0; \ |
if (unlikely(ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT)) { \ |
_mesa_gl_debug(ctx, &msg_id, \ |
MESA_DEBUG_TYPE_OTHER, \ |
MESA_DEBUG_SEVERITY_MEDIUM, \ |
__VA_ARGS__); \ |
} \ |
DBG(__VA_ARGS__); \ |
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; \ |
} while (0) |
/** |
* Do additional "completeness" testing of a framebuffer object. |
*/ |
static void |
intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_renderbuffer *depthRb = |
intel_get_renderbuffer(fb, BUFFER_DEPTH); |
struct intel_renderbuffer *stencilRb = |
intel_get_renderbuffer(fb, BUFFER_STENCIL); |
struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL; |
int i; |
DBG("%s() on fb %p (%s)\n", __FUNCTION__, |
fb, (fb == ctx->DrawBuffer ? "drawbuffer" : |
(fb == ctx->ReadBuffer ? "readbuffer" : "other buffer"))); |
if (depthRb) |
depth_mt = depthRb->mt; |
if (stencilRb) { |
stencil_mt = stencilRb->mt; |
if (stencil_mt->stencil_mt) |
stencil_mt = stencil_mt->stencil_mt; |
} |
if (depth_mt && stencil_mt) { |
if (depth_mt == stencil_mt) { |
/* For true packed depth/stencil (not faked on prefers-separate-stencil |
* hardware) we need to be sure they're the same level/layer, since |
* we'll be emitting a single packet describing the packed setup. |
*/ |
if (depthRb->mt_level != stencilRb->mt_level || |
depthRb->mt_layer != stencilRb->mt_layer) { |
fbo_incomplete(fb, |
"FBO incomplete: depth image level/layer %d/%d != " |
"stencil image %d/%d\n", |
depthRb->mt_level, |
depthRb->mt_layer, |
stencilRb->mt_level, |
stencilRb->mt_layer); |
} |
} else { |
if (!brw->has_separate_stencil) { |
fbo_incomplete(fb, "FBO incomplete: separate stencil " |
"unsupported\n"); |
} |
if (stencil_mt->format != MESA_FORMAT_S8) { |
fbo_incomplete(fb, "FBO incomplete: separate stencil is %s " |
"instead of S8\n", |
_mesa_get_format_name(stencil_mt->format)); |
} |
if (brw->gen < 7 && !intel_renderbuffer_has_hiz(depthRb)) { |
/* Before Gen7, separate depth and stencil buffers can be used |
* only if HiZ is enabled. From the Sandybridge PRM, Volume 2, |
* Part 1, Bit 3DSTATE_DEPTH_BUFFER.SeparateStencilBufferEnable: |
* [DevSNB]: This field must be set to the same value (enabled |
* or disabled) as Hierarchical Depth Buffer Enable. |
*/ |
fbo_incomplete(fb, "FBO incomplete: separate stencil " |
"without HiZ\n"); |
} |
} |
} |
for (i = 0; i < Elements(fb->Attachment); i++) { |
struct gl_renderbuffer *rb; |
struct intel_renderbuffer *irb; |
if (fb->Attachment[i].Type == GL_NONE) |
continue; |
/* A supported attachment will have a Renderbuffer set either |
* from being a Renderbuffer or being a texture that got the |
* intel_wrap_texture() treatment. |
*/ |
rb = fb->Attachment[i].Renderbuffer; |
if (rb == NULL) { |
fbo_incomplete(fb, "FBO incomplete: attachment without " |
"renderbuffer\n"); |
continue; |
} |
if (fb->Attachment[i].Type == GL_TEXTURE) { |
if (rb->TexImage->Border) { |
fbo_incomplete(fb, "FBO incomplete: texture with border\n"); |
continue; |
} |
} |
irb = intel_renderbuffer(rb); |
if (irb == NULL) { |
fbo_incomplete(fb, "FBO incomplete: software rendering " |
"renderbuffer\n"); |
continue; |
} |
if (!brw_render_target_supported(brw, rb)) { |
fbo_incomplete(fb, "FBO incomplete: Unsupported HW " |
"texture/renderbuffer format attached: %s\n", |
_mesa_get_format_name(intel_rb_format(irb))); |
} |
} |
} |
/** |
* Try to do a glBlitFramebuffer using glCopyTexSubImage2D |
* We can do this when the dst renderbuffer is actually a texture and |
* there is no scaling, mirroring or scissoring. |
* |
* \return new buffer mask indicating the buffers left to blit using the |
* normal path. |
*/ |
static GLbitfield |
intel_blit_framebuffer_with_blitter(struct gl_context *ctx, |
GLint srcX0, GLint srcY0, |
GLint srcX1, GLint srcY1, |
GLint dstX0, GLint dstY0, |
GLint dstX1, GLint dstY1, |
GLbitfield mask, GLenum filter) |
{ |
struct brw_context *brw = brw_context(ctx); |
/* Sync up the state of window system buffers. We need to do this before |
* we go looking for the buffers. |
*/ |
intel_prepare_render(brw); |
if (mask & GL_COLOR_BUFFER_BIT) { |
GLint i; |
const struct gl_framebuffer *drawFb = ctx->DrawBuffer; |
const struct gl_framebuffer *readFb = ctx->ReadBuffer; |
struct gl_renderbuffer *src_rb = readFb->_ColorReadBuffer; |
struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb); |
if (!src_irb) { |
perf_debug("glBlitFramebuffer(): missing src renderbuffer. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
/* If the source and destination are the same size with no mirroring, |
* the rectangles are within the size of the texture and there is no |
* scissor, then we can probably use the blit engine. |
*/ |
if (!(srcX0 - srcX1 == dstX0 - dstX1 && |
srcY0 - srcY1 == dstY0 - dstY1 && |
srcX1 >= srcX0 && |
srcY1 >= srcY0 && |
srcX0 >= 0 && srcX1 <= readFb->Width && |
srcY0 >= 0 && srcY1 <= readFb->Height && |
dstX0 >= 0 && dstX1 <= drawFb->Width && |
dstY0 >= 0 && dstY1 <= drawFb->Height && |
!ctx->Scissor.Enabled)) { |
perf_debug("glBlitFramebuffer(): non-1:1 blit. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
/* Blit to all active draw buffers. We don't do any pre-checking, |
* because we assume that copying to MRTs is rare, and failure midway |
* through copying is even more rare. Even if it was to occur, it's |
* safe to let meta start the copy over from scratch, because |
* glBlitFramebuffer completely overwrites the destination pixels, and |
* results are undefined if any destination pixels have a dependency on |
* source pixels. |
*/ |
for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { |
struct gl_renderbuffer *dst_rb = ctx->DrawBuffer->_ColorDrawBuffers[i]; |
struct intel_renderbuffer *dst_irb = intel_renderbuffer(dst_rb); |
if (!dst_irb) { |
perf_debug("glBlitFramebuffer(): missing dst renderbuffer. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
gl_format src_format = _mesa_get_srgb_format_linear(src_rb->Format); |
gl_format dst_format = _mesa_get_srgb_format_linear(dst_rb->Format); |
if (src_format != dst_format) { |
perf_debug("glBlitFramebuffer(): unsupported blit from %s to %s. " |
"Falling back to software rendering.\n", |
_mesa_get_format_name(src_format), |
_mesa_get_format_name(dst_format)); |
return mask; |
} |
if (!intel_miptree_blit(brw, |
src_irb->mt, |
src_irb->mt_level, src_irb->mt_layer, |
srcX0, srcY0, src_rb->Name == 0, |
dst_irb->mt, |
dst_irb->mt_level, dst_irb->mt_layer, |
dstX0, dstY0, dst_rb->Name == 0, |
dstX1 - dstX0, dstY1 - dstY0, GL_COPY)) { |
perf_debug("glBlitFramebuffer(): unknown blit failure. " |
"Falling back to software rendering.\n"); |
return mask; |
} |
} |
mask &= ~GL_COLOR_BUFFER_BIT; |
} |
return mask; |
} |
static void |
intel_blit_framebuffer(struct gl_context *ctx, |
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, |
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, |
GLbitfield mask, GLenum filter) |
{ |
mask = brw_blorp_framebuffer(brw_context(ctx), |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
mask, filter); |
if (mask == 0x0) |
return; |
/* Try using the BLT engine. */ |
mask = intel_blit_framebuffer_with_blitter(ctx, |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
mask, filter); |
if (mask == 0x0) |
return; |
_mesa_meta_BlitFramebuffer(ctx, |
srcX0, srcY0, srcX1, srcY1, |
dstX0, dstY0, dstX1, dstY1, |
mask, filter); |
} |
/** |
* This is a no-op except on multisample buffers shared with DRI2. |
*/ |
void |
intel_renderbuffer_set_needs_downsample(struct intel_renderbuffer *irb) |
{ |
if (irb->mt && irb->mt->singlesample_mt) |
irb->mt->need_downsample = true; |
} |
/** |
* Does the renderbuffer have hiz enabled? |
*/ |
bool |
intel_renderbuffer_has_hiz(struct intel_renderbuffer *irb) |
{ |
return intel_miptree_slice_has_hiz(irb->mt, irb->mt_level, irb->mt_layer); |
} |
void |
intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb) |
{ |
if (irb->mt) { |
intel_miptree_slice_set_needs_hiz_resolve(irb->mt, |
irb->mt_level, |
irb->mt_layer); |
} |
} |
void |
intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb) |
{ |
if (irb->mt) { |
intel_miptree_slice_set_needs_depth_resolve(irb->mt, |
irb->mt_level, |
irb->mt_layer); |
} |
} |
bool |
intel_renderbuffer_resolve_hiz(struct brw_context *brw, |
struct intel_renderbuffer *irb) |
{ |
if (irb->mt) |
return intel_miptree_slice_resolve_hiz(brw, |
irb->mt, |
irb->mt_level, |
irb->mt_layer); |
return false; |
} |
bool |
intel_renderbuffer_resolve_depth(struct brw_context *brw, |
struct intel_renderbuffer *irb) |
{ |
if (irb->mt) |
return intel_miptree_slice_resolve_depth(brw, |
irb->mt, |
irb->mt_level, |
irb->mt_layer); |
return false; |
} |
void |
intel_renderbuffer_move_to_temp(struct brw_context *brw, |
struct intel_renderbuffer *irb, |
bool invalidate) |
{ |
struct gl_renderbuffer *rb =&irb->Base.Base; |
struct intel_texture_image *intel_image = intel_texture_image(rb->TexImage); |
struct intel_mipmap_tree *new_mt; |
int width, height, depth; |
intel_miptree_get_dimensions_for_image(rb->TexImage, &width, &height, &depth); |
new_mt = intel_miptree_create(brw, rb->TexImage->TexObject->Target, |
intel_image->base.Base.TexFormat, |
intel_image->base.Base.Level, |
intel_image->base.Base.Level, |
width, height, depth, |
true, |
irb->mt->num_samples, |
INTEL_MIPTREE_TILING_ANY); |
if (brw_is_hiz_depth_format(brw, new_mt->format)) { |
intel_miptree_alloc_hiz(brw, new_mt); |
} |
intel_miptree_copy_teximage(brw, intel_image, new_mt, invalidate); |
intel_miptree_reference(&irb->mt, intel_image->mt); |
intel_renderbuffer_set_draw_offset(irb); |
intel_miptree_release(&new_mt); |
} |
/** |
* Do one-time context initializations related to GL_EXT_framebuffer_object. |
* Hook in device driver functions. |
*/ |
void |
intel_fbo_init(struct brw_context *brw) |
{ |
struct dd_function_table *dd = &brw->ctx.Driver; |
dd->NewFramebuffer = intel_new_framebuffer; |
dd->NewRenderbuffer = intel_new_renderbuffer; |
dd->MapRenderbuffer = intel_map_renderbuffer; |
dd->UnmapRenderbuffer = intel_unmap_renderbuffer; |
dd->RenderTexture = intel_render_texture; |
dd->FinishRenderTexture = intel_finish_render_texture; |
dd->ValidateFramebuffer = intel_validate_framebuffer; |
dd->BlitFramebuffer = intel_blit_framebuffer; |
dd->EGLImageTargetRenderbufferStorage = |
intel_image_target_renderbuffer_storage; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_fbo.h |
---|
0,0 → 1,203 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_FBO_H |
#define INTEL_FBO_H |
#include <stdbool.h> |
#include <assert.h> |
#include "main/formats.h" |
#include "main/macros.h" |
#include "brw_context.h" |
#include "intel_mipmap_tree.h" |
#include "intel_screen.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
struct intel_mipmap_tree; |
struct intel_texture_image; |
/** |
* Intel renderbuffer, derived from gl_renderbuffer. |
*/ |
struct intel_renderbuffer |
{ |
struct swrast_renderbuffer Base; |
struct intel_mipmap_tree *mt; /**< The renderbuffer storage. */ |
/** |
* \name Miptree view |
* \{ |
* |
* Multiple renderbuffers may simultaneously wrap a single texture and each |
* provide a different view into that texture. The fields below indicate |
* which miptree slice is wrapped by this renderbuffer. The fields' values |
* are consistent with the 'level' and 'layer' parameters of |
* glFramebufferTextureLayer(). |
* |
* For renderbuffers not created with glFramebufferTexture*(), mt_level and |
* mt_layer are 0. |
*/ |
unsigned int mt_level; |
unsigned int mt_layer; |
/** \} */ |
GLuint draw_x, draw_y; /**< Offset of drawing within the region */ |
}; |
/** |
* gl_renderbuffer is a base class which we subclass. The Class field |
* is used for simple run-time type checking. |
*/ |
#define INTEL_RB_CLASS 0x12345678 |
/** |
* Return a gl_renderbuffer ptr casted to intel_renderbuffer. |
* NULL will be returned if the rb isn't really an intel_renderbuffer. |
* This is determined by checking the ClassID. |
*/ |
static INLINE struct intel_renderbuffer * |
intel_renderbuffer(struct gl_renderbuffer *rb) |
{ |
struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb; |
if (irb && irb->Base.Base.ClassID == INTEL_RB_CLASS) { |
/*_mesa_warning(NULL, "Returning non-intel Rb\n");*/ |
return irb; |
} |
else |
return NULL; |
} |
/** |
* \brief Return the framebuffer attachment specified by attIndex. |
* |
* If the framebuffer lacks the specified attachment, then return null. |
* |
* If the attached renderbuffer is a wrapper, then return wrapped |
* renderbuffer. |
*/ |
static INLINE struct intel_renderbuffer * |
intel_get_renderbuffer(struct gl_framebuffer *fb, gl_buffer_index attIndex) |
{ |
struct gl_renderbuffer *rb; |
assert((unsigned)attIndex < ARRAY_SIZE(fb->Attachment)); |
rb = fb->Attachment[attIndex].Renderbuffer; |
if (!rb) |
return NULL; |
return intel_renderbuffer(rb); |
} |
static INLINE gl_format |
intel_rb_format(const struct intel_renderbuffer *rb) |
{ |
return rb->Base.Base.Format; |
} |
extern struct intel_renderbuffer * |
intel_create_renderbuffer(gl_format format, unsigned num_samples); |
struct intel_renderbuffer * |
intel_create_private_renderbuffer(gl_format format, unsigned num_samples); |
struct gl_renderbuffer* |
intel_create_wrapped_renderbuffer(struct gl_context * ctx, |
int width, int height, |
gl_format format); |
extern void |
intel_fbo_init(struct brw_context *brw); |
void |
intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb); |
static inline uint32_t |
intel_renderbuffer_get_tile_offsets(struct intel_renderbuffer *irb, |
uint32_t *tile_x, |
uint32_t *tile_y) |
{ |
return intel_miptree_get_tile_offsets(irb->mt, irb->mt_level, irb->mt_layer, |
tile_x, tile_y); |
} |
void |
intel_renderbuffer_set_needs_downsample(struct intel_renderbuffer *irb); |
bool |
intel_renderbuffer_has_hiz(struct intel_renderbuffer *irb); |
void |
intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb); |
void |
intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb); |
/** |
* \brief Perform a HiZ resolve on the renderbuffer. |
* |
* It is safe to call this function on a renderbuffer without HiZ. In that |
* case, the function is a no-op. |
* |
* \return false if no resolve was needed |
*/ |
bool |
intel_renderbuffer_resolve_hiz(struct brw_context *brw, |
struct intel_renderbuffer *irb); |
/** |
* \brief Perform a depth resolve on the renderbuffer. |
* |
* It is safe to call this function on a renderbuffer without HiZ. In that |
* case, the function is a no-op. |
* |
* \return false if no resolve was needed |
*/ |
bool |
intel_renderbuffer_resolve_depth(struct brw_context *brw, |
struct intel_renderbuffer *irb); |
void intel_renderbuffer_move_to_temp(struct brw_context *brw, |
struct intel_renderbuffer *irb, |
bool invalidate); |
unsigned |
intel_quantize_num_samples(struct intel_screen *intel, unsigned num_samples); |
#ifdef __cplusplus |
} |
#endif |
#endif /* INTEL_FBO_H */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_mipmap_tree.c |
---|
0,0 → 1,2309 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#include <GL/gl.h> |
#include <GL/internal/dri_interface.h> |
#include "intel_batchbuffer.h" |
#include "intel_chipset.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_resolve_map.h" |
#include "intel_tex.h" |
#include "intel_blit.h" |
#include "brw_blorp.h" |
#include "brw_context.h" |
#include "main/enums.h" |
#include "main/formats.h" |
#include "main/glformats.h" |
#include "main/texcompress_etc.h" |
#include "main/teximage.h" |
#define FILE_DEBUG_FLAG DEBUG_MIPTREE |
static GLenum |
target_to_target(GLenum target) |
{ |
switch (target) { |
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: |
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: |
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: |
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: |
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: |
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: |
return GL_TEXTURE_CUBE_MAP_ARB; |
default: |
return target; |
} |
} |
/** |
* Determine which MSAA layout should be used by the MSAA surface being |
* created, based on the chip generation and the surface type. |
*/ |
static enum intel_msaa_layout |
compute_msaa_layout(struct brw_context *brw, gl_format format, GLenum target) |
{ |
/* Prior to Gen7, all MSAA surfaces used IMS layout. */ |
if (brw->gen < 7) |
return INTEL_MSAA_LAYOUT_IMS; |
/* In Gen7, IMS layout is only used for depth and stencil buffers. */ |
switch (_mesa_get_format_base_format(format)) { |
case GL_DEPTH_COMPONENT: |
case GL_STENCIL_INDEX: |
case GL_DEPTH_STENCIL: |
return INTEL_MSAA_LAYOUT_IMS; |
default: |
/* From the Ivy Bridge PRM, Vol4 Part1 p77 ("MCS Enable"): |
* |
* This field must be set to 0 for all SINT MSRTs when all RT channels |
* are not written |
* |
* In practice this means that we have to disable MCS for all signed |
* integer MSAA buffers. The alternative, to disable MCS only when one |
* of the render target channels is disabled, is impractical because it |
* would require converting between CMS and UMS MSAA layouts on the fly, |
* which is expensive. |
*/ |
if (_mesa_get_format_datatype(format) == GL_INT) { |
/* TODO: is this workaround needed for future chipsets? */ |
assert(brw->gen == 7); |
return INTEL_MSAA_LAYOUT_UMS; |
} else { |
/* For now, if we're going to be texturing from this surface, |
* force UMS, so that the shader doesn't have to do different things |
* based on whether there's a multisample control surface needing sampled first. |
* We can't just blindly read the MCS surface in all cases because: |
* |
* From the Ivy Bridge PRM, Vol4 Part1 p77 ("MCS Enable"): |
* |
* If this field is disabled and the sampling engine <ld_mcs> message |
* is issued on this surface, the MCS surface may be accessed. Software |
* must ensure that the surface is defined to avoid GTT errors. |
*/ |
if (target == GL_TEXTURE_2D_MULTISAMPLE || |
target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { |
return INTEL_MSAA_LAYOUT_UMS; |
} else { |
return INTEL_MSAA_LAYOUT_CMS; |
} |
} |
} |
} |
/** |
* For single-sampled render targets ("non-MSRT"), the MCS buffer is a |
* scaled-down bitfield representation of the color buffer which is capable of |
* recording when blocks of the color buffer are equal to the clear value. |
* This function returns the block size that will be used by the MCS buffer |
* corresponding to a certain color miptree. |
* |
* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render Target(s)", |
* beneath the "Fast Color Clear" bullet (p327): |
* |
* The following table describes the RT alignment |
* |
* Pixels Lines |
* TiledY RT CL |
* bpp |
* 32 8 4 |
* 64 4 4 |
* 128 2 4 |
* TiledX RT CL |
* bpp |
* 32 16 2 |
* 64 8 2 |
* 128 4 2 |
* |
* This alignment has the following uses: |
* |
* - For figuring out the size of the MCS buffer. Each 4k tile in the MCS |
* buffer contains 128 blocks horizontally and 256 blocks vertically. |
* |
* - For figuring out alignment restrictions for a fast clear operation. Fast |
* clear operations must always clear aligned multiples of 16 blocks |
* horizontally and 32 blocks vertically. |
* |
* - For scaling down the coordinates sent through the render pipeline during |
* a fast clear. X coordinates must be scaled down by 8 times the block |
* width, and Y coordinates by 16 times the block height. |
* |
* - For scaling down the coordinates sent through the render pipeline during |
* a "Render Target Resolve" operation. X coordinates must be scaled down |
* by half the block width, and Y coordinates by half the block height. |
*/ |
void |
intel_get_non_msrt_mcs_alignment(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned *width_px, unsigned *height) |
{ |
switch (mt->region->tiling) { |
default: |
assert(!"Non-MSRT MCS requires X or Y tiling"); |
/* In release builds, fall through */ |
case I915_TILING_Y: |
*width_px = 32 / mt->cpp; |
*height = 4; |
break; |
case I915_TILING_X: |
*width_px = 64 / mt->cpp; |
*height = 2; |
} |
} |
/** |
* For a single-sampled render target ("non-MSRT"), determine if an MCS buffer |
* can be used. |
* |
* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render Target(s)", |
* beneath the "Fast Color Clear" bullet (p326): |
* |
* - Support is limited to tiled render targets. |
* - Support is for non-mip-mapped and non-array surface types only. |
* |
* And then later, on p327: |
* |
* - MCS buffer for non-MSRT is supported only for RT formats 32bpp, |
* 64bpp, and 128bpp. |
*/ |
bool |
intel_is_non_msrt_mcs_buffer_supported(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
/* MCS support does not exist prior to Gen7 */ |
if (brw->gen < 7) |
return false; |
/* MCS is only supported for color buffers */ |
switch (_mesa_get_format_base_format(mt->format)) { |
case GL_DEPTH_COMPONENT: |
case GL_DEPTH_STENCIL: |
case GL_STENCIL_INDEX: |
return false; |
} |
if (mt->region->tiling != I915_TILING_X && |
mt->region->tiling != I915_TILING_Y) |
return false; |
if (mt->cpp != 4 && mt->cpp != 8 && mt->cpp != 16) |
return false; |
if (mt->first_level != 0 || mt->last_level != 0) |
return false; |
if (mt->physical_depth0 != 1) |
return false; |
/* There's no point in using an MCS buffer if the surface isn't in a |
* renderable format. |
*/ |
if (!brw->format_supported_as_render_target[mt->format]) |
return false; |
return true; |
} |
/** |
* @param for_bo Indicates that the caller is |
* intel_miptree_create_for_bo(). If true, then do not create |
* \c stencil_mt. |
*/ |
struct intel_mipmap_tree * |
intel_miptree_create_layout(struct brw_context *brw, |
GLenum target, |
gl_format format, |
GLuint first_level, |
GLuint last_level, |
GLuint width0, |
GLuint height0, |
GLuint depth0, |
bool for_bo, |
GLuint num_samples) |
{ |
struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1); |
if (!mt) |
return NULL; |
DBG("%s target %s format %s level %d..%d <-- %p\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(target), |
_mesa_get_format_name(format), |
first_level, last_level, mt); |
mt->target = target_to_target(target); |
mt->format = format; |
mt->first_level = first_level; |
mt->last_level = last_level; |
mt->logical_width0 = width0; |
mt->logical_height0 = height0; |
mt->logical_depth0 = depth0; |
mt->mcs_state = INTEL_MCS_STATE_NONE; |
/* The cpp is bytes per (1, blockheight)-sized block for compressed |
* textures. This is why you'll see divides by blockheight all over |
*/ |
unsigned bw, bh; |
_mesa_get_format_block_size(format, &bw, &bh); |
assert(_mesa_get_format_bytes(mt->format) % bw == 0); |
mt->cpp = _mesa_get_format_bytes(mt->format) / bw; |
mt->num_samples = num_samples; |
mt->compressed = _mesa_is_format_compressed(format); |
mt->msaa_layout = INTEL_MSAA_LAYOUT_NONE; |
mt->refcount = 1; |
if (num_samples > 1) { |
/* Adjust width/height/depth for MSAA */ |
mt->msaa_layout = compute_msaa_layout(brw, format, mt->target); |
if (mt->msaa_layout == INTEL_MSAA_LAYOUT_IMS) { |
/* In the Sandy Bridge PRM, volume 4, part 1, page 31, it says: |
* |
* "Any of the other messages (sample*, LOD, load4) used with a |
* (4x) multisampled surface will in-effect sample a surface with |
* double the height and width as that indicated in the surface |
* state. Each pixel position on the original-sized surface is |
* replaced with a 2x2 of samples with the following arrangement: |
* |
* sample 0 sample 2 |
* sample 1 sample 3" |
* |
* Thus, when sampling from a multisampled texture, it behaves as |
* though the layout in memory for (x,y,sample) is: |
* |
* (0,0,0) (0,0,2) (1,0,0) (1,0,2) |
* (0,0,1) (0,0,3) (1,0,1) (1,0,3) |
* |
* (0,1,0) (0,1,2) (1,1,0) (1,1,2) |
* (0,1,1) (0,1,3) (1,1,1) (1,1,3) |
* |
* However, the actual layout of multisampled data in memory is: |
* |
* (0,0,0) (1,0,0) (0,0,1) (1,0,1) |
* (0,1,0) (1,1,0) (0,1,1) (1,1,1) |
* |
* (0,0,2) (1,0,2) (0,0,3) (1,0,3) |
* (0,1,2) (1,1,2) (0,1,3) (1,1,3) |
* |
* This pattern repeats for each 2x2 pixel block. |
* |
* As a result, when calculating the size of our 4-sample buffer for |
* an odd width or height, we have to align before scaling up because |
* sample 3 is in that bottom right 2x2 block. |
*/ |
switch (num_samples) { |
case 4: |
width0 = ALIGN(width0, 2) * 2; |
height0 = ALIGN(height0, 2) * 2; |
break; |
case 8: |
width0 = ALIGN(width0, 2) * 4; |
height0 = ALIGN(height0, 2) * 2; |
break; |
default: |
/* num_samples should already have been quantized to 0, 1, 4, or |
* 8. |
*/ |
assert(false); |
} |
} else { |
/* Non-interleaved */ |
depth0 *= num_samples; |
} |
} |
/* array_spacing_lod0 is only used for non-IMS MSAA surfaces. TODO: can we |
* use it elsewhere? |
*/ |
switch (mt->msaa_layout) { |
case INTEL_MSAA_LAYOUT_NONE: |
case INTEL_MSAA_LAYOUT_IMS: |
mt->array_spacing_lod0 = false; |
break; |
case INTEL_MSAA_LAYOUT_UMS: |
case INTEL_MSAA_LAYOUT_CMS: |
mt->array_spacing_lod0 = true; |
break; |
} |
if (target == GL_TEXTURE_CUBE_MAP) { |
assert(depth0 == 1); |
depth0 = 6; |
} |
mt->physical_width0 = width0; |
mt->physical_height0 = height0; |
mt->physical_depth0 = depth0; |
if (!for_bo && |
_mesa_get_format_base_format(format) == GL_DEPTH_STENCIL && |
(brw->must_use_separate_stencil || |
(brw->has_separate_stencil && brw_is_hiz_depth_format(brw, format)))) { |
mt->stencil_mt = intel_miptree_create(brw, |
mt->target, |
MESA_FORMAT_S8, |
mt->first_level, |
mt->last_level, |
mt->logical_width0, |
mt->logical_height0, |
mt->logical_depth0, |
true, |
num_samples, |
INTEL_MIPTREE_TILING_ANY); |
if (!mt->stencil_mt) { |
intel_miptree_release(&mt); |
return NULL; |
} |
/* Fix up the Z miptree format for how we're splitting out separate |
* stencil. Gen7 expects there to be no stencil bits in its depth buffer. |
*/ |
if (mt->format == MESA_FORMAT_S8_Z24) { |
mt->format = MESA_FORMAT_X8_Z24; |
} else if (mt->format == MESA_FORMAT_Z32_FLOAT_X24S8) { |
mt->format = MESA_FORMAT_Z32_FLOAT; |
mt->cpp = 4; |
} else { |
_mesa_problem(NULL, "Unknown format %s in separate stencil mt\n", |
_mesa_get_format_name(mt->format)); |
} |
} |
brw_miptree_layout(brw, mt); |
return mt; |
} |
/** |
* \brief Helper function for intel_miptree_create(). |
*/ |
static uint32_t |
intel_miptree_choose_tiling(struct brw_context *brw, |
gl_format format, |
uint32_t width0, |
uint32_t num_samples, |
enum intel_miptree_tiling_mode requested, |
struct intel_mipmap_tree *mt) |
{ |
if (format == MESA_FORMAT_S8) { |
/* The stencil buffer is W tiled. However, we request from the kernel a |
* non-tiled buffer because the GTT is incapable of W fencing. |
*/ |
return I915_TILING_NONE; |
} |
/* Some usages may want only one type of tiling, like depth miptrees (Y |
* tiled), or temporary BOs for uploading data once (linear). |
*/ |
switch (requested) { |
case INTEL_MIPTREE_TILING_ANY: |
break; |
case INTEL_MIPTREE_TILING_Y: |
return I915_TILING_Y; |
case INTEL_MIPTREE_TILING_NONE: |
return I915_TILING_NONE; |
} |
if (num_samples > 1) { |
/* From p82 of the Sandy Bridge PRM, dw3[1] of SURFACE_STATE ("Tiled |
* Surface"): |
* |
* [DevSNB+]: For multi-sample render targets, this field must be |
* 1. MSRTs can only be tiled. |
* |
* Our usual reason for preferring X tiling (fast blits using the |
* blitting engine) doesn't apply to MSAA, since we'll generally be |
* downsampling or upsampling when blitting between the MSAA buffer |
* and another buffer, and the blitting engine doesn't support that. |
* So use Y tiling, since it makes better use of the cache. |
*/ |
return I915_TILING_Y; |
} |
GLenum base_format = _mesa_get_format_base_format(format); |
if (base_format == GL_DEPTH_COMPONENT || |
base_format == GL_DEPTH_STENCIL_EXT) |
return I915_TILING_Y; |
int minimum_pitch = mt->total_width * mt->cpp; |
/* If the width is much smaller than a tile, don't bother tiling. */ |
if (minimum_pitch < 64) |
return I915_TILING_NONE; |
if (ALIGN(minimum_pitch, 512) >= 32768) { |
perf_debug("%dx%d miptree too large to blit, falling back to untiled", |
mt->total_width, mt->total_height); |
return I915_TILING_NONE; |
} |
/* Pre-gen6 doesn't have BLORP to handle Y-tiling, so use X-tiling. */ |
if (brw->gen < 6) |
return I915_TILING_X; |
/* From the Sandybridge PRM, Volume 1, Part 2, page 32: |
* "NOTE: 128BPE Format Color Buffer ( render target ) MUST be either TileX |
* or Linear." |
* 128 bits per pixel translates to 16 bytes per pixel. This is necessary |
* all the way back to 965, but is explicitly permitted on Gen7. |
*/ |
if (brw->gen != 7 && mt->cpp >= 16) |
return I915_TILING_X; |
return I915_TILING_Y | I915_TILING_X; |
} |
struct intel_mipmap_tree * |
intel_miptree_create(struct brw_context *brw, |
GLenum target, |
gl_format format, |
GLuint first_level, |
GLuint last_level, |
GLuint width0, |
GLuint height0, |
GLuint depth0, |
bool expect_accelerated_upload, |
GLuint num_samples, |
enum intel_miptree_tiling_mode requested_tiling) |
{ |
struct intel_mipmap_tree *mt; |
gl_format tex_format = format; |
gl_format etc_format = MESA_FORMAT_NONE; |
GLuint total_width, total_height; |
if (!brw->is_baytrail) { |
switch (format) { |
case MESA_FORMAT_ETC1_RGB8: |
format = MESA_FORMAT_RGBX8888_REV; |
break; |
case MESA_FORMAT_ETC2_RGB8: |
format = MESA_FORMAT_RGBX8888_REV; |
break; |
case MESA_FORMAT_ETC2_SRGB8: |
case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: |
case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: |
format = MESA_FORMAT_SARGB8; |
break; |
case MESA_FORMAT_ETC2_RGBA8_EAC: |
case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: |
format = MESA_FORMAT_RGBA8888_REV; |
break; |
case MESA_FORMAT_ETC2_R11_EAC: |
format = MESA_FORMAT_R16; |
break; |
case MESA_FORMAT_ETC2_SIGNED_R11_EAC: |
format = MESA_FORMAT_SIGNED_R16; |
break; |
case MESA_FORMAT_ETC2_RG11_EAC: |
format = MESA_FORMAT_GR1616; |
break; |
case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: |
format = MESA_FORMAT_SIGNED_GR1616; |
break; |
default: |
/* Non ETC1 / ETC2 format */ |
break; |
} |
} |
etc_format = (format != tex_format) ? tex_format : MESA_FORMAT_NONE; |
mt = intel_miptree_create_layout(brw, target, format, |
first_level, last_level, width0, |
height0, depth0, |
false, num_samples); |
/* |
* pitch == 0 || height == 0 indicates the null texture |
*/ |
if (!mt || !mt->total_width || !mt->total_height) { |
intel_miptree_release(&mt); |
return NULL; |
} |
total_width = mt->total_width; |
total_height = mt->total_height; |
if (format == MESA_FORMAT_S8) { |
/* Align to size of W tile, 64x64. */ |
total_width = ALIGN(total_width, 64); |
total_height = ALIGN(total_height, 64); |
} |
uint32_t tiling = intel_miptree_choose_tiling(brw, format, width0, |
num_samples, requested_tiling, |
mt); |
bool y_or_x = tiling == (I915_TILING_Y | I915_TILING_X); |
mt->etc_format = etc_format; |
mt->region = intel_region_alloc(brw->intelScreen, |
y_or_x ? I915_TILING_Y : tiling, |
mt->cpp, |
total_width, |
total_height, |
expect_accelerated_upload); |
/* If the region is too large to fit in the aperture, we need to use the |
* BLT engine to support it. The BLT paths can't currently handle Y-tiling, |
* so we need to fall back to X. |
*/ |
if (y_or_x && mt->region->bo->size >= brw->max_gtt_map_object_size) { |
perf_debug("%dx%d miptree larger than aperture; falling back to X-tiled\n", |
mt->total_width, mt->total_height); |
intel_region_release(&mt->region); |
mt->region = intel_region_alloc(brw->intelScreen, |
I915_TILING_X, |
mt->cpp, |
total_width, |
total_height, |
expect_accelerated_upload); |
} |
mt->offset = 0; |
if (!mt->region) { |
intel_miptree_release(&mt); |
return NULL; |
} |
/* If this miptree is capable of supporting fast color clears, set |
* mcs_state appropriately to ensure that fast clears will occur. |
* Allocation of the MCS miptree will be deferred until the first fast |
* clear actually occurs. |
*/ |
if (intel_is_non_msrt_mcs_buffer_supported(brw, mt)) |
mt->mcs_state = INTEL_MCS_STATE_RESOLVED; |
return mt; |
} |
struct intel_mipmap_tree * |
intel_miptree_create_for_bo(struct brw_context *brw, |
drm_intel_bo *bo, |
gl_format format, |
uint32_t offset, |
uint32_t width, |
uint32_t height, |
int pitch, |
uint32_t tiling) |
{ |
struct intel_mipmap_tree *mt; |
struct intel_region *region = calloc(1, sizeof(*region)); |
if (!region) |
return NULL; |
/* Nothing will be able to use this miptree with the BO if the offset isn't |
* aligned. |
*/ |
if (tiling != I915_TILING_NONE) |
assert(offset % 4096 == 0); |
/* miptrees can't handle negative pitch. If you need flipping of images, |
* that's outside of the scope of the mt. |
*/ |
assert(pitch >= 0); |
mt = intel_miptree_create_layout(brw, GL_TEXTURE_2D, format, |
0, 0, |
width, height, 1, |
true, 0 /* num_samples */); |
if (!mt) |
return mt; |
region->cpp = mt->cpp; |
region->width = width; |
region->height = height; |
region->pitch = pitch; |
region->refcount = 1; |
drm_intel_bo_reference(bo); |
region->bo = bo; |
region->tiling = tiling; |
mt->region = region; |
mt->offset = offset; |
return mt; |
} |
/** |
* For a singlesample DRI2 buffer, this simply wraps the given region with a miptree. |
* |
* For a multisample DRI2 buffer, this wraps the given region with |
* a singlesample miptree, then creates a multisample miptree into which the |
* singlesample miptree is embedded as a child. |
*/ |
struct intel_mipmap_tree* |
intel_miptree_create_for_dri2_buffer(struct brw_context *brw, |
unsigned dri_attachment, |
gl_format format, |
uint32_t num_samples, |
struct intel_region *region) |
{ |
struct intel_mipmap_tree *singlesample_mt = NULL; |
struct intel_mipmap_tree *multisample_mt = NULL; |
/* Only the front and back buffers, which are color buffers, are shared |
* through DRI2. |
*/ |
assert(dri_attachment == __DRI_BUFFER_BACK_LEFT || |
dri_attachment == __DRI_BUFFER_FRONT_LEFT || |
dri_attachment == __DRI_BUFFER_FAKE_FRONT_LEFT); |
assert(_mesa_get_format_base_format(format) == GL_RGB || |
_mesa_get_format_base_format(format) == GL_RGBA); |
singlesample_mt = intel_miptree_create_for_bo(brw, |
region->bo, |
format, |
0, |
region->width, |
region->height, |
region->pitch, |
region->tiling); |
if (!singlesample_mt) |
return NULL; |
singlesample_mt->region->name = region->name; |
/* If this miptree is capable of supporting fast color clears, set |
* mcs_state appropriately to ensure that fast clears will occur. |
* Allocation of the MCS miptree will be deferred until the first fast |
* clear actually occurs. |
*/ |
if (intel_is_non_msrt_mcs_buffer_supported(brw, singlesample_mt)) |
singlesample_mt->mcs_state = INTEL_MCS_STATE_RESOLVED; |
if (num_samples == 0) |
return singlesample_mt; |
multisample_mt = intel_miptree_create_for_renderbuffer(brw, |
format, |
region->width, |
region->height, |
num_samples); |
if (!multisample_mt) { |
intel_miptree_release(&singlesample_mt); |
return NULL; |
} |
multisample_mt->singlesample_mt = singlesample_mt; |
multisample_mt->need_downsample = false; |
if (brw->is_front_buffer_rendering && |
(dri_attachment == __DRI_BUFFER_FRONT_LEFT || |
dri_attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)) { |
intel_miptree_upsample(brw, multisample_mt); |
} |
return multisample_mt; |
} |
struct intel_mipmap_tree* |
intel_miptree_create_for_renderbuffer(struct brw_context *brw, |
gl_format format, |
uint32_t width, |
uint32_t height, |
uint32_t num_samples) |
{ |
struct intel_mipmap_tree *mt; |
uint32_t depth = 1; |
bool ok; |
mt = intel_miptree_create(brw, GL_TEXTURE_2D, format, 0, 0, |
width, height, depth, true, num_samples, |
INTEL_MIPTREE_TILING_ANY); |
if (!mt) |
goto fail; |
if (brw_is_hiz_depth_format(brw, format)) { |
ok = intel_miptree_alloc_hiz(brw, mt); |
if (!ok) |
goto fail; |
} |
if (mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) { |
ok = intel_miptree_alloc_mcs(brw, mt, num_samples); |
if (!ok) |
goto fail; |
} |
return mt; |
fail: |
intel_miptree_release(&mt); |
return NULL; |
} |
void |
intel_miptree_reference(struct intel_mipmap_tree **dst, |
struct intel_mipmap_tree *src) |
{ |
if (*dst == src) |
return; |
intel_miptree_release(dst); |
if (src) { |
src->refcount++; |
DBG("%s %p refcount now %d\n", __FUNCTION__, src, src->refcount); |
} |
*dst = src; |
} |
void |
intel_miptree_release(struct intel_mipmap_tree **mt) |
{ |
if (!*mt) |
return; |
DBG("%s %p refcount will be %d\n", __FUNCTION__, *mt, (*mt)->refcount - 1); |
if (--(*mt)->refcount <= 0) { |
GLuint i; |
DBG("%s deleting %p\n", __FUNCTION__, *mt); |
intel_region_release(&((*mt)->region)); |
intel_miptree_release(&(*mt)->stencil_mt); |
intel_miptree_release(&(*mt)->hiz_mt); |
intel_miptree_release(&(*mt)->mcs_mt); |
intel_miptree_release(&(*mt)->singlesample_mt); |
intel_resolve_map_clear(&(*mt)->hiz_map); |
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { |
free((*mt)->level[i].slice); |
} |
free(*mt); |
} |
*mt = NULL; |
} |
void |
intel_miptree_get_dimensions_for_image(struct gl_texture_image *image, |
int *width, int *height, int *depth) |
{ |
switch (image->TexObject->Target) { |
case GL_TEXTURE_1D_ARRAY: |
*width = image->Width; |
*height = 1; |
*depth = image->Height; |
break; |
default: |
*width = image->Width; |
*height = image->Height; |
*depth = image->Depth; |
break; |
} |
} |
/** |
* Can the image be pulled into a unified mipmap tree? This mirrors |
* the completeness test in a lot of ways. |
* |
* Not sure whether I want to pass gl_texture_image here. |
*/ |
bool |
intel_miptree_match_image(struct intel_mipmap_tree *mt, |
struct gl_texture_image *image) |
{ |
struct intel_texture_image *intelImage = intel_texture_image(image); |
GLuint level = intelImage->base.Base.Level; |
int width, height, depth; |
/* glTexImage* choose the texture object based on the target passed in, and |
* objects can't change targets over their lifetimes, so this should be |
* true. |
*/ |
assert(target_to_target(image->TexObject->Target) == mt->target); |
gl_format mt_format = mt->format; |
if (mt->format == MESA_FORMAT_X8_Z24 && mt->stencil_mt) |
mt_format = MESA_FORMAT_S8_Z24; |
if (mt->format == MESA_FORMAT_Z32_FLOAT && mt->stencil_mt) |
mt_format = MESA_FORMAT_Z32_FLOAT_X24S8; |
if (mt->etc_format != MESA_FORMAT_NONE) |
mt_format = mt->etc_format; |
if (image->TexFormat != mt_format) |
return false; |
intel_miptree_get_dimensions_for_image(image, &width, &height, &depth); |
if (mt->target == GL_TEXTURE_CUBE_MAP) |
depth = 6; |
/* Test image dimensions against the base level image adjusted for |
* minification. This will also catch images not present in the |
* tree, changed targets, etc. |
*/ |
if (mt->target == GL_TEXTURE_2D_MULTISAMPLE || |
mt->target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { |
/* nonzero level here is always bogus */ |
assert(level == 0); |
if (width != mt->logical_width0 || |
height != mt->logical_height0 || |
depth != mt->logical_depth0) { |
return false; |
} |
} |
else { |
/* all normal textures, renderbuffers, etc */ |
if (width != mt->level[level].width || |
height != mt->level[level].height || |
depth != mt->level[level].depth) { |
return false; |
} |
} |
if (image->NumSamples != mt->num_samples) |
return false; |
return true; |
} |
void |
intel_miptree_set_level_info(struct intel_mipmap_tree *mt, |
GLuint level, |
GLuint x, GLuint y, |
GLuint w, GLuint h, GLuint d) |
{ |
mt->level[level].width = w; |
mt->level[level].height = h; |
mt->level[level].depth = d; |
mt->level[level].level_x = x; |
mt->level[level].level_y = y; |
DBG("%s level %d size: %d,%d,%d offset %d,%d\n", __FUNCTION__, |
level, w, h, d, x, y); |
assert(mt->level[level].slice == NULL); |
mt->level[level].slice = calloc(d, sizeof(*mt->level[0].slice)); |
mt->level[level].slice[0].x_offset = mt->level[level].level_x; |
mt->level[level].slice[0].y_offset = mt->level[level].level_y; |
} |
void |
intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, |
GLuint level, GLuint img, |
GLuint x, GLuint y) |
{ |
if (img == 0 && level == 0) |
assert(x == 0 && y == 0); |
assert(img < mt->level[level].depth); |
mt->level[level].slice[img].x_offset = mt->level[level].level_x + x; |
mt->level[level].slice[img].y_offset = mt->level[level].level_y + y; |
DBG("%s level %d img %d pos %d,%d\n", |
__FUNCTION__, level, img, |
mt->level[level].slice[img].x_offset, |
mt->level[level].slice[img].y_offset); |
} |
void |
intel_miptree_get_image_offset(struct intel_mipmap_tree *mt, |
GLuint level, GLuint slice, |
GLuint *x, GLuint *y) |
{ |
assert(slice < mt->level[level].depth); |
*x = mt->level[level].slice[slice].x_offset; |
*y = mt->level[level].slice[slice].y_offset; |
} |
/** |
* Rendering with tiled buffers requires that the base address of the buffer |
* be aligned to a page boundary. For renderbuffers, and sometimes with |
* textures, we may want the surface to point at a texture image level that |
* isn't at a page boundary. |
* |
* This function returns an appropriately-aligned base offset |
* according to the tiling restrictions, plus any required x/y offset |
* from there. |
*/ |
uint32_t |
intel_miptree_get_tile_offsets(struct intel_mipmap_tree *mt, |
GLuint level, GLuint slice, |
uint32_t *tile_x, |
uint32_t *tile_y) |
{ |
struct intel_region *region = mt->region; |
uint32_t x, y; |
uint32_t mask_x, mask_y; |
intel_region_get_tile_masks(region, &mask_x, &mask_y, false); |
intel_miptree_get_image_offset(mt, level, slice, &x, &y); |
*tile_x = x & mask_x; |
*tile_y = y & mask_y; |
return intel_region_get_aligned_offset(region, x & ~mask_x, y & ~mask_y, |
false); |
} |
static void |
intel_miptree_copy_slice_sw(struct brw_context *brw, |
struct intel_mipmap_tree *dst_mt, |
struct intel_mipmap_tree *src_mt, |
int level, |
int slice, |
int width, |
int height) |
{ |
void *src, *dst; |
int src_stride, dst_stride; |
int cpp = dst_mt->cpp; |
intel_miptree_map(brw, src_mt, |
level, slice, |
0, 0, |
width, height, |
GL_MAP_READ_BIT | BRW_MAP_DIRECT_BIT, |
&src, &src_stride); |
intel_miptree_map(brw, dst_mt, |
level, slice, |
0, 0, |
width, height, |
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | |
BRW_MAP_DIRECT_BIT, |
&dst, &dst_stride); |
DBG("sw blit %s mt %p %p/%d -> %s mt %p %p/%d (%dx%d)\n", |
_mesa_get_format_name(src_mt->format), |
src_mt, src, src_stride, |
_mesa_get_format_name(dst_mt->format), |
dst_mt, dst, dst_stride, |
width, height); |
int row_size = cpp * width; |
if (src_stride == row_size && |
dst_stride == row_size) { |
memcpy(dst, src, row_size * height); |
} else { |
for (int i = 0; i < height; i++) { |
memcpy(dst, src, row_size); |
dst += dst_stride; |
src += src_stride; |
} |
} |
intel_miptree_unmap(brw, dst_mt, level, slice); |
intel_miptree_unmap(brw, src_mt, level, slice); |
/* Don't forget to copy the stencil data over, too. We could have skipped |
* passing BRW_MAP_DIRECT_BIT, but that would have meant intel_miptree_map |
* shuffling the two data sources in/out of temporary storage instead of |
* the direct mapping we get this way. |
*/ |
if (dst_mt->stencil_mt) { |
assert(src_mt->stencil_mt); |
intel_miptree_copy_slice_sw(brw, dst_mt->stencil_mt, src_mt->stencil_mt, |
level, slice, width, height); |
} |
} |
static void |
intel_miptree_copy_slice(struct brw_context *brw, |
struct intel_mipmap_tree *dst_mt, |
struct intel_mipmap_tree *src_mt, |
int level, |
int face, |
int depth) |
{ |
gl_format format = src_mt->format; |
uint32_t width = src_mt->level[level].width; |
uint32_t height = src_mt->level[level].height; |
int slice; |
if (face > 0) |
slice = face; |
else |
slice = depth; |
assert(depth < src_mt->level[level].depth); |
assert(src_mt->format == dst_mt->format); |
if (dst_mt->compressed) { |
height = ALIGN(height, dst_mt->align_h) / dst_mt->align_h; |
width = ALIGN(width, dst_mt->align_w); |
} |
/* If it's a packed depth/stencil buffer with separate stencil, the blit |
* below won't apply since we can't do the depth's Y tiling or the |
* stencil's W tiling in the blitter. |
*/ |
if (src_mt->stencil_mt) { |
intel_miptree_copy_slice_sw(brw, |
dst_mt, src_mt, |
level, slice, |
width, height); |
return; |
} |
uint32_t dst_x, dst_y, src_x, src_y; |
intel_miptree_get_image_offset(dst_mt, level, slice, &dst_x, &dst_y); |
intel_miptree_get_image_offset(src_mt, level, slice, &src_x, &src_y); |
DBG("validate blit mt %s %p %d,%d/%d -> mt %s %p %d,%d/%d (%dx%d)\n", |
_mesa_get_format_name(src_mt->format), |
src_mt, src_x, src_y, src_mt->region->pitch, |
_mesa_get_format_name(dst_mt->format), |
dst_mt, dst_x, dst_y, dst_mt->region->pitch, |
width, height); |
if (!intel_miptree_blit(brw, |
src_mt, level, slice, 0, 0, false, |
dst_mt, level, slice, 0, 0, false, |
width, height, GL_COPY)) { |
perf_debug("miptree validate blit for %s failed\n", |
_mesa_get_format_name(format)); |
intel_miptree_copy_slice_sw(brw, dst_mt, src_mt, level, slice, |
width, height); |
} |
} |
/** |
* Copies the image's current data to the given miptree, and associates that |
* miptree with the image. |
* |
* If \c invalidate is true, then the actual image data does not need to be |
* copied, but the image still needs to be associated to the new miptree (this |
* is set to true if we're about to clear the image). |
*/ |
void |
intel_miptree_copy_teximage(struct brw_context *brw, |
struct intel_texture_image *intelImage, |
struct intel_mipmap_tree *dst_mt, |
bool invalidate) |
{ |
struct intel_mipmap_tree *src_mt = intelImage->mt; |
struct intel_texture_object *intel_obj = |
intel_texture_object(intelImage->base.Base.TexObject); |
int level = intelImage->base.Base.Level; |
int face = intelImage->base.Base.Face; |
GLuint depth = intelImage->base.Base.Depth; |
if (!invalidate) { |
for (int slice = 0; slice < depth; slice++) { |
intel_miptree_copy_slice(brw, dst_mt, src_mt, level, face, slice); |
} |
} |
intel_miptree_reference(&intelImage->mt, dst_mt); |
intel_obj->needs_validate = true; |
} |
bool |
intel_miptree_alloc_mcs(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
GLuint num_samples) |
{ |
assert(brw->gen >= 7); /* MCS only used on Gen7+ */ |
assert(mt->mcs_mt == NULL); |
/* Choose the correct format for the MCS buffer. All that really matters |
* is that we allocate the right buffer size, since we'll always be |
* accessing this miptree using MCS-specific hardware mechanisms, which |
* infer the correct format based on num_samples. |
*/ |
gl_format format; |
switch (num_samples) { |
case 4: |
/* 8 bits/pixel are required for MCS data when using 4x MSAA (2 bits for |
* each sample). |
*/ |
format = MESA_FORMAT_R8; |
break; |
case 8: |
/* 32 bits/pixel are required for MCS data when using 8x MSAA (3 bits |
* for each sample, plus 8 padding bits). |
*/ |
format = MESA_FORMAT_R_UINT32; |
break; |
default: |
assert(!"Unrecognized sample count in intel_miptree_alloc_mcs"); |
return false; |
}; |
/* From the Ivy Bridge PRM, Vol4 Part1 p76, "MCS Base Address": |
* |
* "The MCS surface must be stored as Tile Y." |
*/ |
mt->mcs_state = INTEL_MCS_STATE_MSAA; |
mt->mcs_mt = intel_miptree_create(brw, |
mt->target, |
format, |
mt->first_level, |
mt->last_level, |
mt->logical_width0, |
mt->logical_height0, |
mt->logical_depth0, |
true, |
0 /* num_samples */, |
INTEL_MIPTREE_TILING_Y); |
/* From the Ivy Bridge PRM, Vol 2 Part 1 p326: |
* |
* When MCS buffer is enabled and bound to MSRT, it is required that it |
* is cleared prior to any rendering. |
* |
* Since we don't use the MCS buffer for any purpose other than rendering, |
* it makes sense to just clear it immediately upon allocation. |
* |
* Note: the clear value for MCS buffers is all 1's, so we memset to 0xff. |
*/ |
void *data = intel_miptree_map_raw(brw, mt->mcs_mt); |
memset(data, 0xff, mt->mcs_mt->region->bo->size); |
intel_miptree_unmap_raw(brw, mt->mcs_mt); |
return mt->mcs_mt; |
} |
bool |
intel_miptree_alloc_non_msrt_mcs(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
assert(mt->mcs_mt == NULL); |
/* The format of the MCS buffer is opaque to the driver; all that matters |
* is that we get its size and pitch right. We'll pretend that the format |
* is R32. Since an MCS tile covers 128 blocks horizontally, and a Y-tiled |
* R32 buffer is 32 pixels across, we'll need to scale the width down by |
* the block width and then a further factor of 4. Since an MCS tile |
* covers 256 blocks vertically, and a Y-tiled R32 buffer is 32 rows high, |
* we'll need to scale the height down by the block height and then a |
* further factor of 8. |
*/ |
const gl_format format = MESA_FORMAT_R_UINT32; |
unsigned block_width_px; |
unsigned block_height; |
intel_get_non_msrt_mcs_alignment(brw, mt, &block_width_px, &block_height); |
unsigned width_divisor = block_width_px * 4; |
unsigned height_divisor = block_height * 8; |
unsigned mcs_width = |
ALIGN(mt->logical_width0, width_divisor) / width_divisor; |
unsigned mcs_height = |
ALIGN(mt->logical_height0, height_divisor) / height_divisor; |
assert(mt->logical_depth0 == 1); |
mt->mcs_mt = intel_miptree_create(brw, |
mt->target, |
format, |
mt->first_level, |
mt->last_level, |
mcs_width, |
mcs_height, |
mt->logical_depth0, |
true, |
0 /* num_samples */, |
INTEL_MIPTREE_TILING_Y); |
return mt->mcs_mt; |
} |
/** |
* Helper for intel_miptree_alloc_hiz() that sets |
* \c mt->level[level].slice[layer].has_hiz. Return true if and only if |
* \c has_hiz was set. |
*/ |
static bool |
intel_miptree_slice_enable_hiz(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t layer) |
{ |
assert(mt->hiz_mt); |
if (brw->is_haswell) { |
/* Disable HiZ for some slices to work around a hardware bug. |
* |
* Haswell hardware fails to respect |
* 3DSTATE_DEPTH_BUFFER.Depth_Coordinate_Offset_X/Y when during HiZ |
* ambiguate operations. The failure is inconsistent and affected by |
* other GPU contexts. Running a heavy GPU workload in a separate |
* process causes the failure rate to drop to nearly 0. |
* |
* To workaround the bug, we enable HiZ only when we can guarantee that |
* the Depth Coordinate Offset fields will be set to 0. The function |
* brw_get_depthstencil_tile_masks() is used to calculate the fields, |
* and the function is sometimes called in such a way that the presence |
* of an attached stencil buffer changes the fuction's return value. |
* |
* The largest tile size considered by brw_get_depthstencil_tile_masks() |
* is that of the stencil buffer. Therefore, if this hiz slice's |
* corresponding depth slice has an offset that is aligned to the |
* stencil buffer tile size, 64x64 pixels, then |
* 3DSTATE_DEPTH_BUFFER.Depth_Coordinate_Offset_X/Y is set to 0. |
*/ |
uint32_t depth_x_offset = mt->level[level].slice[layer].x_offset; |
uint32_t depth_y_offset = mt->level[level].slice[layer].y_offset; |
if ((depth_x_offset & 63) || (depth_y_offset & 63)) { |
return false; |
} |
} |
mt->level[level].slice[layer].has_hiz = true; |
return true; |
} |
bool |
intel_miptree_alloc_hiz(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
assert(mt->hiz_mt == NULL); |
mt->hiz_mt = intel_miptree_create(brw, |
mt->target, |
mt->format, |
mt->first_level, |
mt->last_level, |
mt->logical_width0, |
mt->logical_height0, |
mt->logical_depth0, |
true, |
mt->num_samples, |
INTEL_MIPTREE_TILING_ANY); |
if (!mt->hiz_mt) |
return false; |
/* Mark that all slices need a HiZ resolve. */ |
struct intel_resolve_map *head = &mt->hiz_map; |
for (int level = mt->first_level; level <= mt->last_level; ++level) { |
for (int layer = 0; layer < mt->level[level].depth; ++layer) { |
if (!intel_miptree_slice_enable_hiz(brw, mt, level, layer)) |
continue; |
head->next = malloc(sizeof(*head->next)); |
head->next->prev = head; |
head->next->next = NULL; |
head = head->next; |
head->level = level; |
head->layer = layer; |
head->need = GEN6_HIZ_OP_HIZ_RESOLVE; |
} |
} |
return true; |
} |
/** |
* Does the miptree slice have hiz enabled? |
*/ |
bool |
intel_miptree_slice_has_hiz(struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t layer) |
{ |
intel_miptree_check_level_layer(mt, level, layer); |
return mt->level[level].slice[layer].has_hiz; |
} |
void |
intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t layer) |
{ |
if (!intel_miptree_slice_has_hiz(mt, level, layer)) |
return; |
intel_resolve_map_set(&mt->hiz_map, |
level, layer, GEN6_HIZ_OP_HIZ_RESOLVE); |
} |
void |
intel_miptree_slice_set_needs_depth_resolve(struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t layer) |
{ |
if (!intel_miptree_slice_has_hiz(mt, level, layer)) |
return; |
intel_resolve_map_set(&mt->hiz_map, |
level, layer, GEN6_HIZ_OP_DEPTH_RESOLVE); |
} |
static bool |
intel_miptree_slice_resolve(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t layer, |
enum gen6_hiz_op need) |
{ |
intel_miptree_check_level_layer(mt, level, layer); |
struct intel_resolve_map *item = |
intel_resolve_map_get(&mt->hiz_map, level, layer); |
if (!item || item->need != need) |
return false; |
intel_hiz_exec(brw, mt, level, layer, need); |
intel_resolve_map_remove(item); |
return true; |
} |
bool |
intel_miptree_slice_resolve_hiz(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t layer) |
{ |
return intel_miptree_slice_resolve(brw, mt, level, layer, |
GEN6_HIZ_OP_HIZ_RESOLVE); |
} |
bool |
intel_miptree_slice_resolve_depth(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t layer) |
{ |
return intel_miptree_slice_resolve(brw, mt, level, layer, |
GEN6_HIZ_OP_DEPTH_RESOLVE); |
} |
static bool |
intel_miptree_all_slices_resolve(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
enum gen6_hiz_op need) |
{ |
bool did_resolve = false; |
struct intel_resolve_map *i, *next; |
for (i = mt->hiz_map.next; i; i = next) { |
next = i->next; |
if (i->need != need) |
continue; |
intel_hiz_exec(brw, mt, i->level, i->layer, need); |
intel_resolve_map_remove(i); |
did_resolve = true; |
} |
return did_resolve; |
} |
bool |
intel_miptree_all_slices_resolve_hiz(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
return intel_miptree_all_slices_resolve(brw, mt, |
GEN6_HIZ_OP_HIZ_RESOLVE); |
} |
bool |
intel_miptree_all_slices_resolve_depth(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
return intel_miptree_all_slices_resolve(brw, mt, |
GEN6_HIZ_OP_DEPTH_RESOLVE); |
} |
void |
intel_miptree_resolve_color(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
switch (mt->mcs_state) { |
case INTEL_MCS_STATE_NONE: |
case INTEL_MCS_STATE_MSAA: |
case INTEL_MCS_STATE_RESOLVED: |
/* No resolve needed */ |
break; |
case INTEL_MCS_STATE_UNRESOLVED: |
case INTEL_MCS_STATE_CLEAR: |
brw_blorp_resolve_color(brw, mt); |
break; |
} |
} |
/** |
* Make it possible to share the region backing the given miptree with another |
* process or another miptree. |
* |
* Fast color clears are unsafe with shared buffers, so we need to resolve and |
* then discard the MCS buffer, if present. We also set the mcs_state to |
* INTEL_MCS_STATE_NONE to ensure that no MCS buffer gets allocated in the |
* future. |
*/ |
void |
intel_miptree_make_shareable(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
/* MCS buffers are also used for multisample buffers, but we can't resolve |
* away a multisample MCS buffer because it's an integral part of how the |
* pixel data is stored. Fortunately this code path should never be |
* reached for multisample buffers. |
*/ |
assert(mt->msaa_layout == INTEL_MSAA_LAYOUT_NONE); |
if (mt->mcs_mt) { |
intel_miptree_resolve_color(brw, mt); |
intel_miptree_release(&mt->mcs_mt); |
mt->mcs_state = INTEL_MCS_STATE_NONE; |
} |
} |
/** |
* \brief Get pointer offset into stencil buffer. |
* |
* The stencil buffer is W tiled. Since the GTT is incapable of W fencing, we |
* must decode the tile's layout in software. |
* |
* See |
* - PRM, 2011 Sandy Bridge, Volume 1, Part 2, Section 4.5.2.1 W-Major Tile |
* Format. |
* - PRM, 2011 Sandy Bridge, Volume 1, Part 2, Section 4.5.3 Tiling Algorithm |
* |
* Even though the returned offset is always positive, the return type is |
* signed due to |
* commit e8b1c6d6f55f5be3bef25084fdd8b6127517e137 |
* mesa: Fix return type of _mesa_get_format_bytes() (#37351) |
*/ |
static intptr_t |
intel_offset_S8(uint32_t stride, uint32_t x, uint32_t y, bool swizzled) |
{ |
uint32_t tile_size = 4096; |
uint32_t tile_width = 64; |
uint32_t tile_height = 64; |
uint32_t row_size = 64 * stride; |
uint32_t tile_x = x / tile_width; |
uint32_t tile_y = y / tile_height; |
/* The byte's address relative to the tile's base addres. */ |
uint32_t byte_x = x % tile_width; |
uint32_t byte_y = y % tile_height; |
uintptr_t u = tile_y * row_size |
+ tile_x * tile_size |
+ 512 * (byte_x / 8) |
+ 64 * (byte_y / 8) |
+ 32 * ((byte_y / 4) % 2) |
+ 16 * ((byte_x / 4) % 2) |
+ 8 * ((byte_y / 2) % 2) |
+ 4 * ((byte_x / 2) % 2) |
+ 2 * (byte_y % 2) |
+ 1 * (byte_x % 2); |
if (swizzled) { |
/* adjust for bit6 swizzling */ |
if (((byte_x / 8) % 2) == 1) { |
if (((byte_y / 8) % 2) == 0) { |
u += 64; |
} else { |
u -= 64; |
} |
} |
} |
return u; |
} |
static void |
intel_miptree_updownsample(struct brw_context *brw, |
struct intel_mipmap_tree *src, |
struct intel_mipmap_tree *dst, |
unsigned width, |
unsigned height) |
{ |
int src_x0 = 0; |
int src_y0 = 0; |
int dst_x0 = 0; |
int dst_y0 = 0; |
brw_blorp_blit_miptrees(brw, |
src, 0 /* level */, 0 /* layer */, |
dst, 0 /* level */, 0 /* layer */, |
src_x0, src_y0, |
width, height, |
dst_x0, dst_y0, |
width, height, |
false, false /*mirror x, y*/); |
if (src->stencil_mt) { |
brw_blorp_blit_miptrees(brw, |
src->stencil_mt, 0 /* level */, 0 /* layer */, |
dst->stencil_mt, 0 /* level */, 0 /* layer */, |
src_x0, src_y0, |
width, height, |
dst_x0, dst_y0, |
width, height, |
false, false /*mirror x, y*/); |
} |
} |
static void |
assert_is_flat(struct intel_mipmap_tree *mt) |
{ |
assert(mt->target == GL_TEXTURE_2D); |
assert(mt->first_level == 0); |
assert(mt->last_level == 0); |
} |
/** |
* \brief Downsample from mt to mt->singlesample_mt. |
* |
* If the miptree needs no downsample, then skip. |
*/ |
void |
intel_miptree_downsample(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
/* Only flat, renderbuffer-like miptrees are supported. */ |
assert_is_flat(mt); |
if (!mt->need_downsample) |
return; |
intel_miptree_updownsample(brw, |
mt, mt->singlesample_mt, |
mt->logical_width0, |
mt->logical_height0); |
mt->need_downsample = false; |
} |
/** |
* \brief Upsample from mt->singlesample_mt to mt. |
* |
* The upsample is done unconditionally. |
*/ |
void |
intel_miptree_upsample(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
/* Only flat, renderbuffer-like miptrees are supported. */ |
assert_is_flat(mt); |
assert(!mt->need_downsample); |
intel_miptree_updownsample(brw, |
mt->singlesample_mt, mt, |
mt->logical_width0, |
mt->logical_height0); |
} |
void * |
intel_miptree_map_raw(struct brw_context *brw, struct intel_mipmap_tree *mt) |
{ |
struct gl_context *ctx = &brw->ctx; |
/* CPU accesses to color buffers don't understand fast color clears, so |
* resolve any pending fast color clears before we map. |
*/ |
intel_miptree_resolve_color(brw, mt); |
drm_intel_bo *bo = mt->region->bo; |
if (unlikely(INTEL_DEBUG & DEBUG_PERF)) { |
if (drm_intel_bo_busy(bo)) { |
perf_debug("Mapping a busy BO, causing a stall on the GPU.\n"); |
} |
} |
intel_flush(ctx); |
if (mt->region->tiling != I915_TILING_NONE) |
drm_intel_gem_bo_map_gtt(bo); |
else |
drm_intel_bo_map(bo, true); |
return bo->virtual; |
} |
void |
intel_miptree_unmap_raw(struct brw_context *brw, |
struct intel_mipmap_tree *mt) |
{ |
drm_intel_bo_unmap(mt->region->bo); |
} |
static void |
intel_miptree_map_gtt(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, unsigned int slice) |
{ |
unsigned int bw, bh; |
void *base; |
unsigned int image_x, image_y; |
int x = map->x; |
int y = map->y; |
/* For compressed formats, the stride is the number of bytes per |
* row of blocks. intel_miptree_get_image_offset() already does |
* the divide. |
*/ |
_mesa_get_format_block_size(mt->format, &bw, &bh); |
assert(y % bh == 0); |
y /= bh; |
base = intel_miptree_map_raw(brw, mt) + mt->offset; |
if (base == NULL) |
map->ptr = NULL; |
else { |
/* Note that in the case of cube maps, the caller must have passed the |
* slice number referencing the face. |
*/ |
intel_miptree_get_image_offset(mt, level, slice, &image_x, &image_y); |
x += image_x; |
y += image_y; |
map->stride = mt->region->pitch; |
map->ptr = base + y * map->stride + x * mt->cpp; |
} |
DBG("%s: %d,%d %dx%d from mt %p (%s) %d,%d = %p/%d\n", __FUNCTION__, |
map->x, map->y, map->w, map->h, |
mt, _mesa_get_format_name(mt->format), |
x, y, map->ptr, map->stride); |
} |
static void |
intel_miptree_unmap_gtt(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, |
unsigned int slice) |
{ |
intel_miptree_unmap_raw(brw, mt); |
} |
static void |
intel_miptree_map_blit(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, unsigned int slice) |
{ |
map->mt = intel_miptree_create(brw, GL_TEXTURE_2D, mt->format, |
0, 0, |
map->w, map->h, 1, |
false, 0, |
INTEL_MIPTREE_TILING_NONE); |
if (!map->mt) { |
fprintf(stderr, "Failed to allocate blit temporary\n"); |
goto fail; |
} |
map->stride = map->mt->region->pitch; |
if (!intel_miptree_blit(brw, |
mt, level, slice, |
map->x, map->y, false, |
map->mt, 0, 0, |
0, 0, false, |
map->w, map->h, GL_COPY)) { |
fprintf(stderr, "Failed to blit\n"); |
goto fail; |
} |
intel_batchbuffer_flush(brw); |
map->ptr = intel_miptree_map_raw(brw, map->mt); |
DBG("%s: %d,%d %dx%d from mt %p (%s) %d,%d = %p/%d\n", __FUNCTION__, |
map->x, map->y, map->w, map->h, |
mt, _mesa_get_format_name(mt->format), |
level, slice, map->ptr, map->stride); |
return; |
fail: |
intel_miptree_release(&map->mt); |
map->ptr = NULL; |
map->stride = 0; |
} |
static void |
intel_miptree_unmap_blit(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, |
unsigned int slice) |
{ |
struct gl_context *ctx = &brw->ctx; |
intel_miptree_unmap_raw(brw, map->mt); |
if (map->mode & GL_MAP_WRITE_BIT) { |
bool ok = intel_miptree_blit(brw, |
map->mt, 0, 0, |
0, 0, false, |
mt, level, slice, |
map->x, map->y, false, |
map->w, map->h, GL_COPY); |
WARN_ONCE(!ok, "Failed to blit from linear temporary mapping"); |
} |
intel_miptree_release(&map->mt); |
} |
static void |
intel_miptree_map_s8(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, unsigned int slice) |
{ |
map->stride = map->w; |
map->buffer = map->ptr = malloc(map->stride * map->h); |
if (!map->buffer) |
return; |
/* One of either READ_BIT or WRITE_BIT or both is set. READ_BIT implies no |
* INVALIDATE_RANGE_BIT. WRITE_BIT needs the original values read in unless |
* invalidate is set, since we'll be writing the whole rectangle from our |
* temporary buffer back out. |
*/ |
if (!(map->mode & GL_MAP_INVALIDATE_RANGE_BIT)) { |
uint8_t *untiled_s8_map = map->ptr; |
uint8_t *tiled_s8_map = intel_miptree_map_raw(brw, mt); |
unsigned int image_x, image_y; |
intel_miptree_get_image_offset(mt, level, slice, &image_x, &image_y); |
for (uint32_t y = 0; y < map->h; y++) { |
for (uint32_t x = 0; x < map->w; x++) { |
ptrdiff_t offset = intel_offset_S8(mt->region->pitch, |
x + image_x + map->x, |
y + image_y + map->y, |
brw->has_swizzling); |
untiled_s8_map[y * map->w + x] = tiled_s8_map[offset]; |
} |
} |
intel_miptree_unmap_raw(brw, mt); |
DBG("%s: %d,%d %dx%d from mt %p %d,%d = %p/%d\n", __FUNCTION__, |
map->x, map->y, map->w, map->h, |
mt, map->x + image_x, map->y + image_y, map->ptr, map->stride); |
} else { |
DBG("%s: %d,%d %dx%d from mt %p = %p/%d\n", __FUNCTION__, |
map->x, map->y, map->w, map->h, |
mt, map->ptr, map->stride); |
} |
} |
static void |
intel_miptree_unmap_s8(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, |
unsigned int slice) |
{ |
if (map->mode & GL_MAP_WRITE_BIT) { |
unsigned int image_x, image_y; |
uint8_t *untiled_s8_map = map->ptr; |
uint8_t *tiled_s8_map = intel_miptree_map_raw(brw, mt); |
intel_miptree_get_image_offset(mt, level, slice, &image_x, &image_y); |
for (uint32_t y = 0; y < map->h; y++) { |
for (uint32_t x = 0; x < map->w; x++) { |
ptrdiff_t offset = intel_offset_S8(mt->region->pitch, |
x + map->x, |
y + map->y, |
brw->has_swizzling); |
tiled_s8_map[offset] = untiled_s8_map[y * map->w + x]; |
} |
} |
intel_miptree_unmap_raw(brw, mt); |
} |
free(map->buffer); |
} |
static void |
intel_miptree_map_etc(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, |
unsigned int slice) |
{ |
assert(mt->etc_format != MESA_FORMAT_NONE); |
if (mt->etc_format == MESA_FORMAT_ETC1_RGB8) { |
assert(mt->format == MESA_FORMAT_RGBX8888_REV); |
} |
assert(map->mode & GL_MAP_WRITE_BIT); |
assert(map->mode & GL_MAP_INVALIDATE_RANGE_BIT); |
map->stride = _mesa_format_row_stride(mt->etc_format, map->w); |
map->buffer = malloc(_mesa_format_image_size(mt->etc_format, |
map->w, map->h, 1)); |
map->ptr = map->buffer; |
} |
static void |
intel_miptree_unmap_etc(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, |
unsigned int slice) |
{ |
uint32_t image_x; |
uint32_t image_y; |
intel_miptree_get_image_offset(mt, level, slice, &image_x, &image_y); |
image_x += map->x; |
image_y += map->y; |
uint8_t *dst = intel_miptree_map_raw(brw, mt) |
+ image_y * mt->region->pitch |
+ image_x * mt->region->cpp; |
if (mt->etc_format == MESA_FORMAT_ETC1_RGB8) |
_mesa_etc1_unpack_rgba8888(dst, mt->region->pitch, |
map->ptr, map->stride, |
map->w, map->h); |
else |
_mesa_unpack_etc2_format(dst, mt->region->pitch, |
map->ptr, map->stride, |
map->w, map->h, mt->etc_format); |
intel_miptree_unmap_raw(brw, mt); |
free(map->buffer); |
} |
/** |
* Mapping function for packed depth/stencil miptrees backed by real separate |
* miptrees for depth and stencil. |
* |
* On gen7, and to support HiZ pre-gen7, we have to have the stencil buffer |
* separate from the depth buffer. Yet at the GL API level, we have to expose |
* packed depth/stencil textures and FBO attachments, and Mesa core expects to |
* be able to map that memory for texture storage and glReadPixels-type |
* operations. We give Mesa core that access by mallocing a temporary and |
* copying the data between the actual backing store and the temporary. |
*/ |
static void |
intel_miptree_map_depthstencil(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, unsigned int slice) |
{ |
struct intel_mipmap_tree *z_mt = mt; |
struct intel_mipmap_tree *s_mt = mt->stencil_mt; |
bool map_z32f_x24s8 = mt->format == MESA_FORMAT_Z32_FLOAT; |
int packed_bpp = map_z32f_x24s8 ? 8 : 4; |
map->stride = map->w * packed_bpp; |
map->buffer = map->ptr = malloc(map->stride * map->h); |
if (!map->buffer) |
return; |
/* One of either READ_BIT or WRITE_BIT or both is set. READ_BIT implies no |
* INVALIDATE_RANGE_BIT. WRITE_BIT needs the original values read in unless |
* invalidate is set, since we'll be writing the whole rectangle from our |
* temporary buffer back out. |
*/ |
if (!(map->mode & GL_MAP_INVALIDATE_RANGE_BIT)) { |
uint32_t *packed_map = map->ptr; |
uint8_t *s_map = intel_miptree_map_raw(brw, s_mt); |
uint32_t *z_map = intel_miptree_map_raw(brw, z_mt); |
unsigned int s_image_x, s_image_y; |
unsigned int z_image_x, z_image_y; |
intel_miptree_get_image_offset(s_mt, level, slice, |
&s_image_x, &s_image_y); |
intel_miptree_get_image_offset(z_mt, level, slice, |
&z_image_x, &z_image_y); |
for (uint32_t y = 0; y < map->h; y++) { |
for (uint32_t x = 0; x < map->w; x++) { |
int map_x = map->x + x, map_y = map->y + y; |
ptrdiff_t s_offset = intel_offset_S8(s_mt->region->pitch, |
map_x + s_image_x, |
map_y + s_image_y, |
brw->has_swizzling); |
ptrdiff_t z_offset = ((map_y + z_image_y) * |
(z_mt->region->pitch / 4) + |
(map_x + z_image_x)); |
uint8_t s = s_map[s_offset]; |
uint32_t z = z_map[z_offset]; |
if (map_z32f_x24s8) { |
packed_map[(y * map->w + x) * 2 + 0] = z; |
packed_map[(y * map->w + x) * 2 + 1] = s; |
} else { |
packed_map[y * map->w + x] = (s << 24) | (z & 0x00ffffff); |
} |
} |
} |
intel_miptree_unmap_raw(brw, s_mt); |
intel_miptree_unmap_raw(brw, z_mt); |
DBG("%s: %d,%d %dx%d from z mt %p %d,%d, s mt %p %d,%d = %p/%d\n", |
__FUNCTION__, |
map->x, map->y, map->w, map->h, |
z_mt, map->x + z_image_x, map->y + z_image_y, |
s_mt, map->x + s_image_x, map->y + s_image_y, |
map->ptr, map->stride); |
} else { |
DBG("%s: %d,%d %dx%d from mt %p = %p/%d\n", __FUNCTION__, |
map->x, map->y, map->w, map->h, |
mt, map->ptr, map->stride); |
} |
} |
static void |
intel_miptree_unmap_depthstencil(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
struct intel_miptree_map *map, |
unsigned int level, |
unsigned int slice) |
{ |
struct intel_mipmap_tree *z_mt = mt; |
struct intel_mipmap_tree *s_mt = mt->stencil_mt; |
bool map_z32f_x24s8 = mt->format == MESA_FORMAT_Z32_FLOAT; |
if (map->mode & GL_MAP_WRITE_BIT) { |
uint32_t *packed_map = map->ptr; |
uint8_t *s_map = intel_miptree_map_raw(brw, s_mt); |
uint32_t *z_map = intel_miptree_map_raw(brw, z_mt); |
unsigned int s_image_x, s_image_y; |
unsigned int z_image_x, z_image_y; |
intel_miptree_get_image_offset(s_mt, level, slice, |
&s_image_x, &s_image_y); |
intel_miptree_get_image_offset(z_mt, level, slice, |
&z_image_x, &z_image_y); |
for (uint32_t y = 0; y < map->h; y++) { |
for (uint32_t x = 0; x < map->w; x++) { |
ptrdiff_t s_offset = intel_offset_S8(s_mt->region->pitch, |
x + s_image_x + map->x, |
y + s_image_y + map->y, |
brw->has_swizzling); |
ptrdiff_t z_offset = ((y + z_image_y) * |
(z_mt->region->pitch / 4) + |
(x + z_image_x)); |
if (map_z32f_x24s8) { |
z_map[z_offset] = packed_map[(y * map->w + x) * 2 + 0]; |
s_map[s_offset] = packed_map[(y * map->w + x) * 2 + 1]; |
} else { |
uint32_t packed = packed_map[y * map->w + x]; |
s_map[s_offset] = packed >> 24; |
z_map[z_offset] = packed; |
} |
} |
} |
intel_miptree_unmap_raw(brw, s_mt); |
intel_miptree_unmap_raw(brw, z_mt); |
DBG("%s: %d,%d %dx%d from z mt %p (%s) %d,%d, s mt %p %d,%d = %p/%d\n", |
__FUNCTION__, |
map->x, map->y, map->w, map->h, |
z_mt, _mesa_get_format_name(z_mt->format), |
map->x + z_image_x, map->y + z_image_y, |
s_mt, map->x + s_image_x, map->y + s_image_y, |
map->ptr, map->stride); |
} |
free(map->buffer); |
} |
/** |
* Create and attach a map to the miptree at (level, slice). Return the |
* attached map. |
*/ |
static struct intel_miptree_map* |
intel_miptree_attach_map(struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice, |
unsigned int x, |
unsigned int y, |
unsigned int w, |
unsigned int h, |
GLbitfield mode) |
{ |
struct intel_miptree_map *map = calloc(1, sizeof(*map)); |
if (!map) |
return NULL; |
assert(mt->level[level].slice[slice].map == NULL); |
mt->level[level].slice[slice].map = map; |
map->mode = mode; |
map->x = x; |
map->y = y; |
map->w = w; |
map->h = h; |
return map; |
} |
/** |
* Release the map at (level, slice). |
*/ |
static void |
intel_miptree_release_map(struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice) |
{ |
struct intel_miptree_map **map; |
map = &mt->level[level].slice[slice].map; |
free(*map); |
*map = NULL; |
} |
static void |
intel_miptree_map_singlesample(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice, |
unsigned int x, |
unsigned int y, |
unsigned int w, |
unsigned int h, |
GLbitfield mode, |
void **out_ptr, |
int *out_stride) |
{ |
struct intel_miptree_map *map; |
assert(mt->num_samples <= 1); |
map = intel_miptree_attach_map(mt, level, slice, x, y, w, h, mode); |
if (!map){ |
*out_ptr = NULL; |
*out_stride = 0; |
return; |
} |
intel_miptree_slice_resolve_depth(brw, mt, level, slice); |
if (map->mode & GL_MAP_WRITE_BIT) { |
intel_miptree_slice_set_needs_hiz_resolve(mt, level, slice); |
} |
if (mt->format == MESA_FORMAT_S8) { |
intel_miptree_map_s8(brw, mt, map, level, slice); |
} else if (mt->etc_format != MESA_FORMAT_NONE && |
!(mode & BRW_MAP_DIRECT_BIT)) { |
intel_miptree_map_etc(brw, mt, map, level, slice); |
} else if (mt->stencil_mt && !(mode & BRW_MAP_DIRECT_BIT)) { |
intel_miptree_map_depthstencil(brw, mt, map, level, slice); |
} |
/* See intel_miptree_blit() for details on the 32k pitch limit. */ |
else if (brw->has_llc && |
!(mode & GL_MAP_WRITE_BIT) && |
!mt->compressed && |
(mt->region->tiling == I915_TILING_X || |
(brw->gen >= 6 && mt->region->tiling == I915_TILING_Y)) && |
mt->region->pitch < 32768) { |
intel_miptree_map_blit(brw, mt, map, level, slice); |
} else if (mt->region->tiling != I915_TILING_NONE && |
mt->region->bo->size >= brw->max_gtt_map_object_size) { |
assert(mt->region->pitch < 32768); |
intel_miptree_map_blit(brw, mt, map, level, slice); |
} else { |
intel_miptree_map_gtt(brw, mt, map, level, slice); |
} |
*out_ptr = map->ptr; |
*out_stride = map->stride; |
if (map->ptr == NULL) |
intel_miptree_release_map(mt, level, slice); |
} |
static void |
intel_miptree_unmap_singlesample(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice) |
{ |
struct intel_miptree_map *map = mt->level[level].slice[slice].map; |
assert(mt->num_samples <= 1); |
if (!map) |
return; |
DBG("%s: mt %p (%s) level %d slice %d\n", __FUNCTION__, |
mt, _mesa_get_format_name(mt->format), level, slice); |
if (mt->format == MESA_FORMAT_S8) { |
intel_miptree_unmap_s8(brw, mt, map, level, slice); |
} else if (mt->etc_format != MESA_FORMAT_NONE && |
!(map->mode & BRW_MAP_DIRECT_BIT)) { |
intel_miptree_unmap_etc(brw, mt, map, level, slice); |
} else if (mt->stencil_mt && !(map->mode & BRW_MAP_DIRECT_BIT)) { |
intel_miptree_unmap_depthstencil(brw, mt, map, level, slice); |
} else if (map->mt) { |
intel_miptree_unmap_blit(brw, mt, map, level, slice); |
} else { |
intel_miptree_unmap_gtt(brw, mt, map, level, slice); |
} |
intel_miptree_release_map(mt, level, slice); |
} |
static void |
intel_miptree_map_multisample(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice, |
unsigned int x, |
unsigned int y, |
unsigned int w, |
unsigned int h, |
GLbitfield mode, |
void **out_ptr, |
int *out_stride) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct intel_miptree_map *map; |
assert(mt->num_samples > 1); |
/* Only flat, renderbuffer-like miptrees are supported. */ |
if (mt->target != GL_TEXTURE_2D || |
mt->first_level != 0 || |
mt->last_level != 0) { |
_mesa_problem(ctx, "attempt to map a multisample miptree for " |
"which (target, first_level, last_level != " |
"(GL_TEXTURE_2D, 0, 0)"); |
goto fail; |
} |
map = intel_miptree_attach_map(mt, level, slice, x, y, w, h, mode); |
if (!map) |
goto fail; |
if (!mt->singlesample_mt) { |
mt->singlesample_mt = |
intel_miptree_create_for_renderbuffer(brw, |
mt->format, |
mt->logical_width0, |
mt->logical_height0, |
0 /*num_samples*/); |
if (!mt->singlesample_mt) |
goto fail; |
map->singlesample_mt_is_tmp = true; |
mt->need_downsample = true; |
} |
intel_miptree_downsample(brw, mt); |
intel_miptree_map_singlesample(brw, mt->singlesample_mt, |
level, slice, |
x, y, w, h, |
mode, |
out_ptr, out_stride); |
return; |
fail: |
intel_miptree_release_map(mt, level, slice); |
*out_ptr = NULL; |
*out_stride = 0; |
} |
static void |
intel_miptree_unmap_multisample(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice) |
{ |
struct intel_miptree_map *map = mt->level[level].slice[slice].map; |
assert(mt->num_samples > 1); |
if (!map) |
return; |
intel_miptree_unmap_singlesample(brw, mt->singlesample_mt, level, slice); |
mt->need_downsample = false; |
if (map->mode & GL_MAP_WRITE_BIT) |
intel_miptree_upsample(brw, mt); |
if (map->singlesample_mt_is_tmp) |
intel_miptree_release(&mt->singlesample_mt); |
intel_miptree_release_map(mt, level, slice); |
} |
void |
intel_miptree_map(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice, |
unsigned int x, |
unsigned int y, |
unsigned int w, |
unsigned int h, |
GLbitfield mode, |
void **out_ptr, |
int *out_stride) |
{ |
if (mt->num_samples <= 1) |
intel_miptree_map_singlesample(brw, mt, |
level, slice, |
x, y, w, h, |
mode, |
out_ptr, out_stride); |
else |
intel_miptree_map_multisample(brw, mt, |
level, slice, |
x, y, w, h, |
mode, |
out_ptr, out_stride); |
} |
void |
intel_miptree_unmap(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice) |
{ |
if (mt->num_samples <= 1) |
intel_miptree_unmap_singlesample(brw, mt, level, slice); |
else |
intel_miptree_unmap_multisample(brw, mt, level, slice); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_mipmap_tree.h |
---|
0,0 → 1,733 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_MIPMAP_TREE_H |
#define INTEL_MIPMAP_TREE_H |
#include <assert.h> |
#include "intel_regions.h" |
#include "intel_resolve_map.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
/* A layer on top of the intel_regions code which adds: |
* |
* - Code to size and layout a region to hold a set of mipmaps. |
* - Query to determine if a new image fits in an existing tree. |
* - More refcounting |
* - maybe able to remove refcounting from intel_region? |
* - ? |
* |
* The fixed mipmap layout of intel hardware where one offset |
* specifies the position of all images in a mipmap hierachy |
* complicates the implementation of GL texture image commands, |
* compared to hardware where each image is specified with an |
* independent offset. |
* |
* In an ideal world, each texture object would be associated with a |
* single bufmgr buffer or 2d intel_region, and all the images within |
* the texture object would slot into the tree as they arrive. The |
* reality can be a little messier, as images can arrive from the user |
* with sizes that don't fit in the existing tree, or in an order |
* where the tree layout cannot be guessed immediately. |
* |
* This structure encodes an idealized mipmap tree. The GL image |
* commands build these where possible, otherwise store the images in |
* temporary system buffers. |
*/ |
struct intel_resolve_map; |
struct intel_texture_image; |
/** |
* When calling intel_miptree_map() on an ETC-transcoded-to-RGB miptree or a |
* depthstencil-split-to-separate-stencil miptree, we'll normally make a |
* tmeporary and recreate the kind of data requested by Mesa core, since we're |
* satisfying some glGetTexImage() request or something. |
* |
* However, occasionally you want to actually map the miptree's current data |
* without transcoding back. This flag to intel_miptree_map() gets you that. |
*/ |
#define BRW_MAP_DIRECT_BIT 0x80000000 |
struct intel_miptree_map { |
/** Bitfield of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, GL_MAP_INVALIDATE_BIT */ |
GLbitfield mode; |
/** Region of interest for the map. */ |
int x, y, w, h; |
/** Possibly malloced temporary buffer for the mapping. */ |
void *buffer; |
/** Possible pointer to a temporary linear miptree for the mapping. */ |
struct intel_mipmap_tree *mt; |
/** Pointer to the start of (map_x, map_y) returned by the mapping. */ |
void *ptr; |
/** Stride of the mapping. */ |
int stride; |
/** |
* intel_mipmap_tree::singlesample_mt is temporary storage that persists |
* only for the duration of the map. |
*/ |
bool singlesample_mt_is_tmp; |
}; |
/** |
* Describes the location of each texture image within a texture region. |
*/ |
struct intel_mipmap_level |
{ |
/** Offset to this miptree level, used in computing x_offset. */ |
GLuint level_x; |
/** Offset to this miptree level, used in computing y_offset. */ |
GLuint level_y; |
GLuint width; |
GLuint height; |
/** |
* \brief Number of 2D slices in this miplevel. |
* |
* The exact semantics of depth varies according to the texture target: |
* - For GL_TEXTURE_CUBE_MAP, depth is 6. |
* - For GL_TEXTURE_2D_ARRAY, depth is the number of array slices. It is |
* identical for all miplevels in the texture. |
* - For GL_TEXTURE_3D, it is the texture's depth at this miplevel. Its |
* value, like width and height, varies with miplevel. |
* - For other texture types, depth is 1. |
*/ |
GLuint depth; |
/** |
* \brief List of 2D images in this mipmap level. |
* |
* This may be a list of cube faces, array slices in 2D array texture, or |
* layers in a 3D texture. The list's length is \c depth. |
*/ |
struct intel_mipmap_slice { |
/** |
* \name Offset to slice |
* \{ |
* |
* Hardware formats are so diverse that that there is no unified way to |
* compute the slice offsets, so we store them in this table. |
* |
* The (x, y) offset to slice \c s at level \c l relative the miptrees |
* base address is |
* \code |
* x = mt->level[l].slice[s].x_offset |
* y = mt->level[l].slice[s].y_offset |
*/ |
GLuint x_offset; |
GLuint y_offset; |
/** \} */ |
/** |
* Mapping information. Persistent for the duration of |
* intel_miptree_map/unmap on this slice. |
*/ |
struct intel_miptree_map *map; |
/** |
* \brief Is HiZ enabled for this slice? |
* |
* If \c mt->level[l].slice[s].has_hiz is set, then (1) \c mt->hiz_mt |
* has been allocated and (2) the HiZ memory corresponding to this slice |
* resides at \c mt->hiz_mt->level[l].slice[s]. |
*/ |
bool has_hiz; |
} *slice; |
}; |
/** |
* Enum for keeping track of the different MSAA layouts supported by Gen7. |
*/ |
enum intel_msaa_layout |
{ |
/** |
* Ordinary surface with no MSAA. |
*/ |
INTEL_MSAA_LAYOUT_NONE, |
/** |
* Interleaved Multisample Surface. The additional samples are |
* accommodated by scaling up the width and the height of the surface so |
* that all the samples corresponding to a pixel are located at nearby |
* memory locations. |
*/ |
INTEL_MSAA_LAYOUT_IMS, |
/** |
* Uncompressed Multisample Surface. The surface is stored as a 2D array, |
* with array slice n containing all pixel data for sample n. |
*/ |
INTEL_MSAA_LAYOUT_UMS, |
/** |
* Compressed Multisample Surface. The surface is stored as in |
* INTEL_MSAA_LAYOUT_UMS, but there is an additional buffer called the MCS |
* (Multisample Control Surface) buffer. Each pixel in the MCS buffer |
* indicates the mapping from sample number to array slice. This allows |
* the common case (where all samples constituting a pixel have the same |
* color value) to be stored efficiently by just using a single array |
* slice. |
*/ |
INTEL_MSAA_LAYOUT_CMS, |
}; |
/** |
* Enum for keeping track of the state of an MCS buffer associated with a |
* miptree. This determines when fast clear related operations are needed. |
* |
* Fast clear works by deferring the memory writes that would be used to clear |
* the buffer, so that instead of performing them at the time of the clear |
* operation, the hardware automatically performs them at the time that the |
* buffer is later accessed for rendering. The MCS buffer keeps track of |
* which regions of the buffer still have pending clear writes. |
* |
* This enum keeps track of the driver's knowledge of the state of the MCS |
* buffer. |
* |
* MCS buffers only exist on Gen7+. |
*/ |
enum intel_mcs_state |
{ |
/** |
* There is no MCS buffer for this miptree, and one should never be |
* allocated. |
*/ |
INTEL_MCS_STATE_NONE, |
/** |
* An MCS buffer exists for this miptree, and it is used for MSAA purposes. |
*/ |
INTEL_MCS_STATE_MSAA, |
/** |
* No deferred clears are pending for this miptree, and the contents of the |
* color buffer are entirely correct. An MCS buffer may or may not exist |
* for this miptree. If it does exist, it is entirely in the "no deferred |
* clears pending" state. If it does not exist, it will be created the |
* first time a fast color clear is executed. |
* |
* In this state, the color buffer can be used for purposes other than |
* rendering without needing a render target resolve. |
*/ |
INTEL_MCS_STATE_RESOLVED, |
/** |
* An MCS buffer exists for this miptree, and deferred clears are pending |
* for some regions of the color buffer, as indicated by the MCS buffer. |
* The contents of the color buffer are only correct for the regions where |
* the MCS buffer doesn't indicate a deferred clear. |
* |
* In this state, a render target resolve must be performed before the |
* color buffer can be used for purposes other than rendering. |
*/ |
INTEL_MCS_STATE_UNRESOLVED, |
/** |
* An MCS buffer exists for this miptree, and deferred clears are pending |
* for the entire color buffer, and the contents of the MCS buffer reflect |
* this. The contents of the color buffer are undefined. |
* |
* In this state, a render target resolve must be performed before the |
* color buffer can be used for purposes other than rendering. |
* |
* If the client attempts to clear a buffer which is already in this state, |
* the clear can be safely skipped, since the buffer is already clear. |
*/ |
INTEL_MCS_STATE_CLEAR, |
}; |
struct intel_mipmap_tree |
{ |
/* Effectively the key: |
*/ |
GLenum target; |
/** |
* Generally, this is just the same as the gl_texture_image->TexFormat or |
* gl_renderbuffer->Format. |
* |
* However, for textures and renderbuffers with packed depth/stencil formats |
* on hardware where we want or need to use separate stencil, there will be |
* two miptrees for storing the data. If the depthstencil texture or rb is |
* MESA_FORMAT_Z32_FLOAT_X24S8, then mt->format will be |
* MESA_FORMAT_Z32_FLOAT, otherwise for MESA_FORMAT_S8_Z24 objects it will be |
* MESA_FORMAT_X8_Z24. |
* |
* For ETC1/ETC2 textures, this is one of the uncompressed mesa texture |
* formats if the hardware lacks support for ETC1/ETC2. See @ref wraps_etc. |
*/ |
gl_format format; |
/** This variable stores the value of ETC compressed texture format */ |
gl_format etc_format; |
/** |
* The X offset of each image in the miptree must be aligned to this. |
* See the comments in brw_tex_layout.c. |
*/ |
unsigned int align_w; |
unsigned int align_h; /**< \see align_w */ |
GLuint first_level; |
GLuint last_level; |
/** |
* Level zero image dimensions. These dimensions correspond to the |
* physical layout of data in memory. Accordingly, they account for the |
* extra width, height, and or depth that must be allocated in order to |
* accommodate multisample formats, and they account for the extra factor |
* of 6 in depth that must be allocated in order to accommodate cubemap |
* textures. |
*/ |
GLuint physical_width0, physical_height0, physical_depth0; |
GLuint cpp; |
GLuint num_samples; |
bool compressed; |
/** |
* Level zero image dimensions. These dimensions correspond to the |
* logical width, height, and depth of the region as seen by client code. |
* Accordingly, they do not account for the extra width, height, and/or |
* depth that must be allocated in order to accommodate multisample |
* formats, nor do they account for the extra factor of 6 in depth that |
* must be allocated in order to accommodate cubemap textures. |
*/ |
uint32_t logical_width0, logical_height0, logical_depth0; |
/** |
* For 1D array, 2D array, cube, and 2D multisampled surfaces on Gen7: true |
* if the surface only contains LOD 0, and hence no space is for LOD's |
* other than 0 in between array slices. |
* |
* Corresponds to the surface_array_spacing bit in gen7_surface_state. |
*/ |
bool array_spacing_lod0; |
/** |
* MSAA layout used by this buffer. |
*/ |
enum intel_msaa_layout msaa_layout; |
/* Derived from the above: |
*/ |
GLuint total_width; |
GLuint total_height; |
/* The 3DSTATE_CLEAR_PARAMS value associated with the last depth clear to |
* this depth mipmap tree, if any. |
*/ |
uint32_t depth_clear_value; |
/* Includes image offset tables: |
*/ |
struct intel_mipmap_level level[MAX_TEXTURE_LEVELS]; |
/* The data is held here: |
*/ |
struct intel_region *region; |
/* Offset into region bo where miptree starts: |
*/ |
uint32_t offset; |
/** |
* \brief Singlesample miptree. |
* |
* This is used under two cases. |
* |
* --- Case 1: As persistent singlesample storage for multisample window |
* system front and back buffers --- |
* |
* Suppose that the window system FBO was created with a multisample |
* config. Let `back_irb` be the `intel_renderbuffer` for the FBO's back |
* buffer. Then `back_irb` contains two miptrees: a parent multisample |
* miptree (back_irb->mt) and a child singlesample miptree |
* (back_irb->mt->singlesample_mt). The DRM buffer shared with DRI2 |
* belongs to `back_irb->mt->singlesample_mt` and contains singlesample |
* data. The singlesample miptree is created at the same time as and |
* persists for the lifetime of its parent multisample miptree. |
* |
* When access to the singlesample data is needed, such as at |
* eglSwapBuffers and glReadPixels, an automatic downsample occurs from |
* `back_rb->mt` to `back_rb->mt->singlesample_mt` when necessary. |
* |
* This description of the back buffer applies analogously to the front |
* buffer. |
* |
* |
* --- Case 2: As temporary singlesample storage for mapping multisample |
* miptrees --- |
* |
* Suppose the intel_miptree_map is called on a multisample miptree, `mt`, |
* for which case 1 does not apply (that is, `mt` does not belong to |
* a front or back buffer). Then `mt->singlesample_mt` is null at the |
* start of the call. intel_miptree_map will create a temporary |
* singlesample miptree, store it at `mt->singlesample_mt`, downsample from |
* `mt` to `mt->singlesample_mt` if necessary, then map |
* `mt->singlesample_mt`. The temporary miptree is later deleted during |
* intel_miptree_unmap. |
*/ |
struct intel_mipmap_tree *singlesample_mt; |
/** |
* \brief A downsample is needed from this miptree to singlesample_mt. |
*/ |
bool need_downsample; |
/** |
* \brief HiZ miptree |
* |
* The hiz miptree contains the miptree's hiz buffer. To allocate the hiz |
* miptree, use intel_miptree_alloc_hiz(). |
* |
* To determine if hiz is enabled, do not check this pointer. Instead, use |
* intel_miptree_slice_has_hiz(). |
*/ |
struct intel_mipmap_tree *hiz_mt; |
/** |
* \brief Map of miptree slices to needed resolves. |
* |
* This is used only when the miptree has a child HiZ miptree. |
* |
* Let \c mt be a depth miptree with HiZ enabled. Then the resolve map is |
* \c mt->hiz_map. The resolve map of the child HiZ miptree, \c |
* mt->hiz_mt->hiz_map, is unused. |
*/ |
struct intel_resolve_map hiz_map; |
/** |
* \brief Stencil miptree for depthstencil textures. |
* |
* This miptree is used for depthstencil textures and renderbuffers that |
* require separate stencil. It always has the true copy of the stencil |
* bits, regardless of mt->format. |
* |
* \see intel_miptree_map_depthstencil() |
* \see intel_miptree_unmap_depthstencil() |
*/ |
struct intel_mipmap_tree *stencil_mt; |
/** |
* \brief MCS miptree. |
* |
* This miptree contains the "multisample control surface", which stores |
* the necessary information to implement compressed MSAA |
* (INTEL_MSAA_FORMAT_CMS) and "fast color clear" behaviour on Gen7+. |
* |
* NULL if no MCS miptree is in use for this surface. |
*/ |
struct intel_mipmap_tree *mcs_mt; |
/** |
* MCS state for this buffer. |
*/ |
enum intel_mcs_state mcs_state; |
/** |
* The SURFACE_STATE bits associated with the last fast color clear to this |
* color mipmap tree, if any. |
* |
* This value will only ever contain ones in bits 28-31, so it is safe to |
* OR into dword 7 of SURFACE_STATE. |
*/ |
uint32_t fast_clear_color_value; |
/* These are also refcounted: |
*/ |
GLuint refcount; |
}; |
enum intel_miptree_tiling_mode { |
INTEL_MIPTREE_TILING_ANY, |
INTEL_MIPTREE_TILING_Y, |
INTEL_MIPTREE_TILING_NONE, |
}; |
bool |
intel_is_non_msrt_mcs_buffer_supported(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
void |
intel_get_non_msrt_mcs_alignment(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned *width_px, unsigned *height); |
bool |
intel_miptree_alloc_non_msrt_mcs(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
struct intel_mipmap_tree *intel_miptree_create(struct brw_context *brw, |
GLenum target, |
gl_format format, |
GLuint first_level, |
GLuint last_level, |
GLuint width0, |
GLuint height0, |
GLuint depth0, |
bool expect_accelerated_upload, |
GLuint num_samples, |
enum intel_miptree_tiling_mode); |
struct intel_mipmap_tree * |
intel_miptree_create_layout(struct brw_context *brw, |
GLenum target, |
gl_format format, |
GLuint first_level, |
GLuint last_level, |
GLuint width0, |
GLuint height0, |
GLuint depth0, |
bool for_bo, |
GLuint num_samples); |
struct intel_mipmap_tree * |
intel_miptree_create_for_bo(struct brw_context *brw, |
drm_intel_bo *bo, |
gl_format format, |
uint32_t offset, |
uint32_t width, |
uint32_t height, |
int pitch, |
uint32_t tiling); |
struct intel_mipmap_tree* |
intel_miptree_create_for_dri2_buffer(struct brw_context *brw, |
unsigned dri_attachment, |
gl_format format, |
uint32_t num_samples, |
struct intel_region *region); |
/** |
* Create a miptree appropriate as the storage for a non-texture renderbuffer. |
* The miptree has the following properties: |
* - The target is GL_TEXTURE_2D. |
* - There are no levels other than the base level 0. |
* - Depth is 1. |
*/ |
struct intel_mipmap_tree* |
intel_miptree_create_for_renderbuffer(struct brw_context *brw, |
gl_format format, |
uint32_t width, |
uint32_t height, |
uint32_t num_samples); |
/** \brief Assert that the level and layer are valid for the miptree. */ |
static inline void |
intel_miptree_check_level_layer(struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t layer) |
{ |
assert(level >= mt->first_level); |
assert(level <= mt->last_level); |
assert(layer < mt->level[level].depth); |
} |
void intel_miptree_reference(struct intel_mipmap_tree **dst, |
struct intel_mipmap_tree *src); |
void intel_miptree_release(struct intel_mipmap_tree **mt); |
/* Check if an image fits an existing mipmap tree layout |
*/ |
bool intel_miptree_match_image(struct intel_mipmap_tree *mt, |
struct gl_texture_image *image); |
void |
intel_miptree_get_image_offset(struct intel_mipmap_tree *mt, |
GLuint level, GLuint slice, |
GLuint *x, GLuint *y); |
void |
intel_miptree_get_dimensions_for_image(struct gl_texture_image *image, |
int *width, int *height, int *depth); |
uint32_t |
intel_miptree_get_tile_offsets(struct intel_mipmap_tree *mt, |
GLuint level, GLuint slice, |
uint32_t *tile_x, |
uint32_t *tile_y); |
void intel_miptree_set_level_info(struct intel_mipmap_tree *mt, |
GLuint level, |
GLuint x, GLuint y, |
GLuint w, GLuint h, GLuint d); |
void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, |
GLuint level, |
GLuint img, GLuint x, GLuint y); |
void |
intel_miptree_copy_teximage(struct brw_context *brw, |
struct intel_texture_image *intelImage, |
struct intel_mipmap_tree *dst_mt, bool invalidate); |
bool |
intel_miptree_alloc_mcs(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
GLuint num_samples); |
/** |
* \name Miptree HiZ functions |
* \{ |
* |
* It is safe to call the "slice_set_need_resolve" and "slice_resolve" |
* functions on a miptree without HiZ. In that case, each function is a no-op. |
*/ |
/** |
* \brief Allocate the miptree's embedded HiZ miptree. |
* \see intel_mipmap_tree:hiz_mt |
* \return false if allocation failed |
*/ |
bool |
intel_miptree_alloc_hiz(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
bool |
intel_miptree_slice_has_hiz(struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t layer); |
void |
intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t depth); |
void |
intel_miptree_slice_set_needs_depth_resolve(struct intel_mipmap_tree *mt, |
uint32_t level, |
uint32_t depth); |
/** |
* \return false if no resolve was needed |
*/ |
bool |
intel_miptree_slice_resolve_hiz(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int depth); |
/** |
* \return false if no resolve was needed |
*/ |
bool |
intel_miptree_slice_resolve_depth(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int depth); |
/** |
* \return false if no resolve was needed |
*/ |
bool |
intel_miptree_all_slices_resolve_hiz(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
/** |
* \return false if no resolve was needed |
*/ |
bool |
intel_miptree_all_slices_resolve_depth(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
/**\}*/ |
/** |
* Update the fast clear state for a miptree to indicate that it has been used |
* for rendering. |
*/ |
static inline void |
intel_miptree_used_for_rendering(struct intel_mipmap_tree *mt) |
{ |
/* If the buffer was previously in fast clear state, change it to |
* unresolved state, since it won't be guaranteed to be clear after |
* rendering occurs. |
*/ |
if (mt->mcs_state == INTEL_MCS_STATE_CLEAR) |
mt->mcs_state = INTEL_MCS_STATE_UNRESOLVED; |
} |
void |
intel_miptree_resolve_color(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
void |
intel_miptree_make_shareable(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
void |
intel_miptree_downsample(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
void |
intel_miptree_upsample(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
void brw_miptree_layout(struct brw_context *brw, struct intel_mipmap_tree *mt); |
void *intel_miptree_map_raw(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
void intel_miptree_unmap_raw(struct brw_context *brw, |
struct intel_mipmap_tree *mt); |
void |
intel_miptree_map(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice, |
unsigned int x, |
unsigned int y, |
unsigned int w, |
unsigned int h, |
GLbitfield mode, |
void **out_ptr, |
int *out_stride); |
void |
intel_miptree_unmap(struct brw_context *brw, |
struct intel_mipmap_tree *mt, |
unsigned int level, |
unsigned int slice); |
void |
intel_hiz_exec(struct brw_context *brw, struct intel_mipmap_tree *mt, |
unsigned int level, unsigned int layer, enum gen6_hiz_op op); |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_pixel.c |
---|
0,0 → 1,135 |
/************************************************************************** |
* |
* 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 portionsalloc |
* 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 "main/accum.h" |
#include "main/enums.h" |
#include "main/state.h" |
#include "main/bufferobj.h" |
#include "main/context.h" |
#include "swrast/swrast.h" |
#include "brw_context.h" |
#include "intel_pixel.h" |
#include "intel_regions.h" |
#define FILE_DEBUG_FLAG DEBUG_PIXEL |
static GLenum |
effective_func(GLenum func, bool src_alpha_is_one) |
{ |
if (src_alpha_is_one) { |
if (func == GL_SRC_ALPHA) |
return GL_ONE; |
if (func == GL_ONE_MINUS_SRC_ALPHA) |
return GL_ZERO; |
} |
return func; |
} |
/** |
* Check if any fragment operations are in effect which might effect |
* glDraw/CopyPixels. |
*/ |
bool |
intel_check_blit_fragment_ops(struct gl_context * ctx, bool src_alpha_is_one) |
{ |
if (ctx->NewState) |
_mesa_update_state(ctx); |
if (ctx->FragmentProgram._Enabled) { |
DBG("fallback due to fragment program\n"); |
return false; |
} |
if (ctx->Color.BlendEnabled && |
(effective_func(ctx->Color.Blend[0].SrcRGB, src_alpha_is_one) != GL_ONE || |
effective_func(ctx->Color.Blend[0].DstRGB, src_alpha_is_one) != GL_ZERO || |
ctx->Color.Blend[0].EquationRGB != GL_FUNC_ADD || |
effective_func(ctx->Color.Blend[0].SrcA, src_alpha_is_one) != GL_ONE || |
effective_func(ctx->Color.Blend[0].DstA, src_alpha_is_one) != GL_ZERO || |
ctx->Color.Blend[0].EquationA != GL_FUNC_ADD)) { |
DBG("fallback due to blend\n"); |
return false; |
} |
if (ctx->Texture._EnabledUnits) { |
DBG("fallback due to texturing\n"); |
return false; |
} |
if (!(ctx->Color.ColorMask[0][0] && |
ctx->Color.ColorMask[0][1] && |
ctx->Color.ColorMask[0][2] && |
ctx->Color.ColorMask[0][3])) { |
DBG("fallback due to color masking\n"); |
return false; |
} |
if (ctx->Color.AlphaEnabled) { |
DBG("fallback due to alpha\n"); |
return false; |
} |
if (ctx->Depth.Test) { |
DBG("fallback due to depth test\n"); |
return false; |
} |
if (ctx->Fog.Enabled) { |
DBG("fallback due to fog\n"); |
return false; |
} |
if (ctx->_ImageTransferState) { |
DBG("fallback due to image transfer\n"); |
return false; |
} |
if (ctx->Stencil._Enabled) { |
DBG("fallback due to image stencil\n"); |
return false; |
} |
if (ctx->RenderMode != GL_RENDER) { |
DBG("fallback due to render mode\n"); |
return false; |
} |
return true; |
} |
void |
intelInitPixelFuncs(struct dd_function_table *functions) |
{ |
functions->Accum = _mesa_accum; |
functions->Bitmap = intelBitmap; |
functions->CopyPixels = intelCopyPixels; |
functions->DrawPixels = intelDrawPixels; |
functions->ReadPixels = intelReadPixels; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_pixel.h |
---|
0,0 → 1,63 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_PIXEL_H |
#define INTEL_PIXEL_H |
#include "main/mtypes.h" |
void intelInitPixelFuncs(struct dd_function_table *functions); |
bool intel_check_blit_fragment_ops(struct gl_context * ctx, |
bool src_alpha_is_one); |
void intelReadPixels(struct gl_context * ctx, |
GLint x, GLint y, |
GLsizei width, GLsizei height, |
GLenum format, GLenum type, |
const struct gl_pixelstore_attrib *pack, |
GLvoid * pixels); |
void intelDrawPixels(struct gl_context * ctx, |
GLint x, GLint y, |
GLsizei width, GLsizei height, |
GLenum format, |
GLenum type, |
const struct gl_pixelstore_attrib *unpack, |
const GLvoid * pixels); |
void intelCopyPixels(struct gl_context * ctx, |
GLint srcx, GLint srcy, |
GLsizei width, GLsizei height, |
GLint destx, GLint desty, GLenum type); |
void intelBitmap(struct gl_context * ctx, |
GLint x, GLint y, |
GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte * pixels); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_pixel_bitmap.c |
---|
0,0 → 1,364 |
/************************************************************************** |
* |
* 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 portionsalloc |
* 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 "main/blend.h" |
#include "main/glheader.h" |
#include "main/enums.h" |
#include "main/image.h" |
#include "main/colormac.h" |
#include "main/condrender.h" |
#include "main/mtypes.h" |
#include "main/macros.h" |
#include "main/pbo.h" |
#include "main/bufferobj.h" |
#include "main/state.h" |
#include "main/texobj.h" |
#include "main/context.h" |
#include "main/fbobject.h" |
#include "swrast/swrast.h" |
#include "drivers/common/meta.h" |
#include "brw_context.h" |
#include "intel_screen.h" |
#include "intel_batchbuffer.h" |
#include "intel_blit.h" |
#include "intel_fbo.h" |
#include "intel_regions.h" |
#include "intel_buffers.h" |
#include "intel_pixel.h" |
#include "intel_reg.h" |
#define FILE_DEBUG_FLAG DEBUG_PIXEL |
/* Unlike the other intel_pixel_* functions, the expectation here is |
* that the incoming data is not in a PBO. With the XY_TEXT blit |
* method, there's no benefit haveing it in a PBO, but we could |
* implement a path based on XY_MONO_SRC_COPY_BLIT which might benefit |
* PBO bitmaps. I think they are probably pretty rare though - I |
* wonder if Xgl uses them? |
*/ |
static const GLubyte *map_pbo( struct gl_context *ctx, |
GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte *bitmap ) |
{ |
GLubyte *buf; |
if (!_mesa_validate_pbo_access(2, unpack, width, height, 1, |
GL_COLOR_INDEX, GL_BITMAP, |
INT_MAX, (const GLvoid *) bitmap)) { |
_mesa_error(ctx, GL_INVALID_OPERATION,"glBitmap(invalid PBO access)"); |
return NULL; |
} |
buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, |
GL_MAP_READ_BIT, |
unpack->BufferObj); |
if (!buf) { |
_mesa_error(ctx, GL_INVALID_OPERATION, "glBitmap(PBO is mapped)"); |
return NULL; |
} |
return ADD_POINTERS(buf, bitmap); |
} |
static bool test_bit( const GLubyte *src, GLuint bit ) |
{ |
return (src[bit/8] & (1<<(bit % 8))) ? 1 : 0; |
} |
static void set_bit( GLubyte *dest, GLuint bit ) |
{ |
dest[bit/8] |= 1 << (bit % 8); |
} |
/* Extract a rectangle's worth of data from the bitmap. Called |
* per chunk of HW-sized bitmap. |
*/ |
static GLuint get_bitmap_rect(GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte *bitmap, |
GLuint x, GLuint y, |
GLuint w, GLuint h, |
GLubyte *dest, |
GLuint row_align, |
bool invert) |
{ |
GLuint src_offset = (x + unpack->SkipPixels) & 0x7; |
GLuint mask = unpack->LsbFirst ? 0 : 7; |
GLuint bit = 0; |
GLint row, col; |
GLint first, last; |
GLint incr; |
GLuint count = 0; |
DBG("%s %d,%d %dx%d bitmap %dx%d skip %d src_offset %d mask %d\n", |
__FUNCTION__, x,y,w,h,width,height,unpack->SkipPixels, src_offset, mask); |
if (invert) { |
first = h-1; |
last = 0; |
incr = -1; |
} |
else { |
first = 0; |
last = h-1; |
incr = 1; |
} |
/* Require that dest be pre-zero'd. |
*/ |
for (row = first; row != (last+incr); row += incr) { |
const GLubyte *rowsrc = _mesa_image_address2d(unpack, bitmap, |
width, height, |
GL_COLOR_INDEX, GL_BITMAP, |
y + row, x); |
for (col = 0; col < w; col++, bit++) { |
if (test_bit(rowsrc, (col + src_offset) ^ mask)) { |
set_bit(dest, bit ^ 7); |
count++; |
} |
} |
if (row_align) |
bit = ALIGN(bit, row_align); |
} |
return count; |
} |
/** |
* Returns the low Y value of the vertical range given, flipped according to |
* whether the framebuffer is or not. |
*/ |
static INLINE int |
y_flip(struct gl_framebuffer *fb, int y, int height) |
{ |
if (_mesa_is_user_fbo(fb)) |
return y; |
else |
return fb->Height - y - height; |
} |
/* |
* Render a bitmap. |
*/ |
static bool |
do_blit_bitmap( struct gl_context *ctx, |
GLint dstx, GLint dsty, |
GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte *bitmap ) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct intel_renderbuffer *irb; |
GLfloat tmpColor[4]; |
GLubyte ubcolor[4]; |
GLuint color; |
GLsizei bitmap_width = width; |
GLsizei bitmap_height = height; |
GLint px, py; |
GLuint stipple[32]; |
GLint orig_dstx = dstx; |
GLint orig_dsty = dsty; |
/* Update draw buffer bounds */ |
_mesa_update_state(ctx); |
if (ctx->Depth.Test) { |
/* The blit path produces incorrect results when depth testing is on. |
* It seems the blit Z coord is always 1.0 (the far plane) so fragments |
* will likely be obscured by other, closer geometry. |
*/ |
return false; |
} |
intel_prepare_render(brw); |
if (fb->_NumColorDrawBuffers != 1) { |
perf_debug("accelerated glBitmap() only supports rendering to a " |
"single color buffer\n"); |
return false; |
} |
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); |
if (_mesa_is_bufferobj(unpack->BufferObj)) { |
bitmap = map_pbo(ctx, width, height, unpack, bitmap); |
if (bitmap == NULL) |
return true; /* even though this is an error, we're done */ |
} |
COPY_4V(tmpColor, ctx->Current.RasterColor); |
if (_mesa_need_secondary_color(ctx)) { |
ADD_3V(tmpColor, tmpColor, ctx->Current.RasterSecondaryColor); |
} |
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[0], tmpColor[0]); |
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[1], tmpColor[1]); |
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[2], tmpColor[2]); |
UNCLAMPED_FLOAT_TO_UBYTE(ubcolor[3], tmpColor[3]); |
switch (_mesa_get_render_format(ctx, intel_rb_format(irb))) { |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_XRGB8888: |
color = PACK_COLOR_8888(ubcolor[3], ubcolor[0], ubcolor[1], ubcolor[2]); |
break; |
case MESA_FORMAT_RGB565: |
color = PACK_COLOR_565(ubcolor[0], ubcolor[1], ubcolor[2]); |
break; |
default: |
perf_debug("Unsupported format %s in accelerated glBitmap()\n", |
_mesa_get_format_name(irb->mt->format)); |
return false; |
} |
if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F)) |
return false; |
/* Clip to buffer bounds and scissor. */ |
if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, |
fb->_Xmax, fb->_Ymax, |
&dstx, &dsty, &width, &height)) |
goto out; |
dsty = y_flip(fb, dsty, height); |
#define DY 32 |
#define DX 32 |
/* The blitter has no idea about fast color clears, so we need to resolve |
* the miptree before we do anything. |
*/ |
intel_miptree_resolve_color(brw, irb->mt); |
/* Chop it all into chunks that can be digested by hardware: */ |
for (py = 0; py < height; py += DY) { |
for (px = 0; px < width; px += DX) { |
int h = MIN2(DY, height - py); |
int w = MIN2(DX, width - px); |
GLuint sz = ALIGN(ALIGN(w,8) * h, 64)/8; |
GLenum logic_op = ctx->Color.ColorLogicOpEnabled ? |
ctx->Color.LogicOp : GL_COPY; |
assert(sz <= sizeof(stipple)); |
memset(stipple, 0, sz); |
/* May need to adjust this when padding has been introduced in |
* sz above: |
* |
* Have to translate destination coordinates back into source |
* coordinates. |
*/ |
int count = get_bitmap_rect(bitmap_width, bitmap_height, unpack, |
bitmap, |
-orig_dstx + (dstx + px), |
-orig_dsty + y_flip(fb, dsty + py, h), |
w, h, |
(GLubyte *)stipple, |
8, |
_mesa_is_winsys_fbo(fb)); |
if (count == 0) |
continue; |
if (!intelEmitImmediateColorExpandBlit(brw, |
irb->mt->cpp, |
(GLubyte *)stipple, |
sz, |
color, |
irb->mt->region->pitch, |
irb->mt->region->bo, |
0, |
irb->mt->region->tiling, |
dstx + px, |
dsty + py, |
w, h, |
logic_op)) { |
return false; |
} |
if (ctx->Query.CurrentOcclusionObject) |
ctx->Query.CurrentOcclusionObject->Result += count; |
} |
} |
out: |
if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) |
intel_batchbuffer_flush(brw); |
if (_mesa_is_bufferobj(unpack->BufferObj)) { |
/* done with PBO so unmap it now */ |
ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); |
} |
intel_check_front_buffer_rendering(brw); |
return true; |
} |
/* There are a large number of possible ways to implement bitmap on |
* this hardware, most of them have some sort of drawback. Here are a |
* few that spring to mind: |
* |
* Blit: |
* - XY_MONO_SRC_BLT_CMD |
* - use XY_SETUP_CLIP_BLT for cliprect clipping. |
* - XY_TEXT_BLT |
* - XY_TEXT_IMMEDIATE_BLT |
* - blit per cliprect, subject to maximum immediate data size. |
* - XY_COLOR_BLT |
* - per pixel or run of pixels |
* - XY_PIXEL_BLT |
* - good for sparse bitmaps |
* |
* 3D engine: |
* - Point per pixel |
* - Translate bitmap to an alpha texture and render as a quad |
* - Chop bitmap up into 32x32 squares and render w/polygon stipple. |
*/ |
void |
intelBitmap(struct gl_context * ctx, |
GLint x, GLint y, |
GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte * pixels) |
{ |
if (!_mesa_check_conditional_render(ctx)) |
return; |
if (do_blit_bitmap(ctx, x, y, width, height, |
unpack, pixels)) |
return; |
_mesa_meta_Bitmap(ctx, x, y, width, height, unpack, pixels); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_pixel_copy.c |
---|
0,0 → 1,210 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/image.h" |
#include "main/state.h" |
#include "main/mtypes.h" |
#include "main/condrender.h" |
#include "main/fbobject.h" |
#include "drivers/common/meta.h" |
#include "brw_context.h" |
#include "intel_buffers.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_pixel.h" |
#include "intel_fbo.h" |
#include "intel_blit.h" |
#define FILE_DEBUG_FLAG DEBUG_PIXEL |
/** |
* CopyPixels with the blitter. Don't support zooming, pixel transfer, etc. |
*/ |
static bool |
do_blit_copypixels(struct gl_context * ctx, |
GLint srcx, GLint srcy, |
GLsizei width, GLsizei height, |
GLint dstx, GLint dsty, GLenum type) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct gl_framebuffer *read_fb = ctx->ReadBuffer; |
GLint orig_dstx; |
GLint orig_dsty; |
GLint orig_srcx; |
GLint orig_srcy; |
struct intel_renderbuffer *draw_irb = NULL; |
struct intel_renderbuffer *read_irb = NULL; |
/* Update draw buffer bounds */ |
_mesa_update_state(ctx); |
switch (type) { |
case GL_COLOR: |
if (fb->_NumColorDrawBuffers != 1) { |
perf_debug("glCopyPixels() fallback: MRT\n"); |
return false; |
} |
draw_irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]); |
read_irb = intel_renderbuffer(read_fb->_ColorReadBuffer); |
break; |
case GL_DEPTH_STENCIL_EXT: |
draw_irb = intel_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); |
read_irb = |
intel_renderbuffer(read_fb->Attachment[BUFFER_DEPTH].Renderbuffer); |
break; |
case GL_DEPTH: |
perf_debug("glCopyPixels() fallback: GL_DEPTH\n"); |
return false; |
case GL_STENCIL: |
perf_debug("glCopyPixels() fallback: GL_STENCIL\n"); |
return false; |
default: |
perf_debug("glCopyPixels(): Unknown type\n"); |
return false; |
} |
if (!draw_irb) { |
perf_debug("glCopyPixels() fallback: missing draw buffer\n"); |
return false; |
} |
if (!read_irb) { |
perf_debug("glCopyPixels() fallback: missing read buffer\n"); |
return false; |
} |
if (ctx->_ImageTransferState) { |
perf_debug("glCopyPixels(): Unsupported image transfer state\n"); |
return false; |
} |
if (ctx->Depth.Test) { |
perf_debug("glCopyPixels(): Unsupported depth test state\n"); |
return false; |
} |
if (ctx->Stencil._Enabled) { |
perf_debug("glCopyPixels(): Unsupported stencil test state\n"); |
return false; |
} |
if (ctx->Fog.Enabled || |
ctx->Texture._EnabledUnits || |
ctx->FragmentProgram._Enabled) { |
perf_debug("glCopyPixels(): Unsupported fragment shader state\n"); |
return false; |
} |
if (ctx->Color.AlphaEnabled || |
ctx->Color.BlendEnabled) { |
perf_debug("glCopyPixels(): Unsupported blend state\n"); |
return false; |
} |
if (!ctx->Color.ColorMask[0][0] || |
!ctx->Color.ColorMask[0][1] || |
!ctx->Color.ColorMask[0][2] || |
!ctx->Color.ColorMask[0][3]) { |
perf_debug("glCopyPixels(): Unsupported color mask state\n"); |
return false; |
} |
if (ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F) { |
perf_debug("glCopyPixles(): Unsupported pixel zoom\n"); |
return false; |
} |
intel_prepare_render(brw); |
intel_flush(&brw->ctx); |
/* Clip to destination buffer. */ |
orig_dstx = dstx; |
orig_dsty = dsty; |
if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, |
fb->_Xmax, fb->_Ymax, |
&dstx, &dsty, &width, &height)) |
goto out; |
/* Adjust src coords for our post-clipped destination origin */ |
srcx += dstx - orig_dstx; |
srcy += dsty - orig_dsty; |
/* Clip to source buffer. */ |
orig_srcx = srcx; |
orig_srcy = srcy; |
if (!_mesa_clip_to_region(0, 0, |
read_fb->Width, read_fb->Height, |
&srcx, &srcy, &width, &height)) |
goto out; |
/* Adjust dst coords for our post-clipped source origin */ |
dstx += srcx - orig_srcx; |
dsty += srcy - orig_srcy; |
if (!intel_miptree_blit(brw, |
read_irb->mt, read_irb->mt_level, read_irb->mt_layer, |
srcx, srcy, _mesa_is_winsys_fbo(read_fb), |
draw_irb->mt, draw_irb->mt_level, draw_irb->mt_layer, |
dstx, dsty, _mesa_is_winsys_fbo(fb), |
width, height, |
(ctx->Color.ColorLogicOpEnabled ? |
ctx->Color.LogicOp : GL_COPY))) { |
DBG("%s: blit failure\n", __FUNCTION__); |
return false; |
} |
if (ctx->Query.CurrentOcclusionObject) |
ctx->Query.CurrentOcclusionObject->Result += width * height; |
out: |
intel_check_front_buffer_rendering(brw); |
DBG("%s: success\n", __FUNCTION__); |
return true; |
} |
void |
intelCopyPixels(struct gl_context * ctx, |
GLint srcx, GLint srcy, |
GLsizei width, GLsizei height, |
GLint destx, GLint desty, GLenum type) |
{ |
DBG("%s\n", __FUNCTION__); |
if (!_mesa_check_conditional_render(ctx)) |
return; |
if (do_blit_copypixels(ctx, srcx, srcy, width, height, destx, desty, type)) |
return; |
/* this will use swrast if needed */ |
_mesa_meta_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_pixel_draw.c |
---|
0,0 → 1,58 |
/************************************************************************** |
* |
* 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 portionsalloc |
* 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 "main/glheader.h" |
#include "main/enums.h" |
#include "main/image.h" |
#include "main/mtypes.h" |
#include "main/teximage.h" |
#include "main/texobj.h" |
#include "main/texstate.h" |
#include "swrast/swrast.h" |
#include "drivers/common/meta.h" |
#include "brw_context.h" |
#include "intel_pixel.h" |
void |
intelDrawPixels(struct gl_context * ctx, |
GLint x, GLint y, |
GLsizei width, GLsizei height, |
GLenum format, |
GLenum type, |
const struct gl_pixelstore_attrib *unpack, |
const GLvoid * pixels) |
{ |
if (format == GL_STENCIL_INDEX) { |
_swrast_DrawPixels(ctx, x, y, width, height, format, type, |
unpack, pixels); |
return; |
} |
_mesa_meta_DrawPixels(ctx, x, y, width, height, format, type, |
unpack, pixels); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_pixel_read.c |
---|
0,0 → 1,200 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/enums.h" |
#include "main/mtypes.h" |
#include "main/macros.h" |
#include "main/fbobject.h" |
#include "main/image.h" |
#include "main/bufferobj.h" |
#include "main/readpix.h" |
#include "main/state.h" |
#include "brw_context.h" |
#include "intel_screen.h" |
#include "intel_blit.h" |
#include "intel_buffers.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_pixel.h" |
#include "intel_buffer_objects.h" |
#define FILE_DEBUG_FLAG DEBUG_PIXEL |
/* For many applications, the new ability to pull the source buffers |
* back out of the GTT and then do the packing/conversion operations |
* in software will be as much of an improvement as trying to get the |
* blitter and/or texture engine to do the work. |
* |
* This step is gated on private backbuffers. |
* |
* Obviously the frontbuffer can't be pulled back, so that is either |
* an argument for blit/texture readpixels, or for blitting to a |
* temporary and then pulling that back. |
* |
* When the destination is a pbo, however, it's not clear if it is |
* ever going to be pulled to main memory (though the access param |
* will be a good hint). So it sounds like we do want to be able to |
* choose between blit/texture implementation on the gpu and pullback |
* and cpu-based copying. |
* |
* Unless you can magically turn client memory into a PBO for the |
* duration of this call, there will be a cpu-based copying step in |
* any case. |
*/ |
static bool |
do_blit_readpixels(struct gl_context * ctx, |
GLint x, GLint y, GLsizei width, GLsizei height, |
GLenum format, GLenum type, |
const struct gl_pixelstore_attrib *pack, GLvoid * pixels) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj); |
GLuint dst_offset; |
drm_intel_bo *dst_buffer; |
bool all; |
GLint dst_x, dst_y; |
GLuint dirty; |
DBG("%s\n", __FUNCTION__); |
assert(_mesa_is_bufferobj(pack->BufferObj)); |
struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; |
struct intel_renderbuffer *irb = intel_renderbuffer(rb); |
if (ctx->_ImageTransferState || |
!_mesa_format_matches_format_and_type(irb->mt->format, format, type, |
false)) { |
DBG("%s - bad format for blit\n", __FUNCTION__); |
return false; |
} |
if (pack->SwapBytes || pack->LsbFirst) { |
DBG("%s: bad packing params\n", __FUNCTION__); |
return false; |
} |
int dst_stride = _mesa_image_row_stride(pack, width, format, type); |
bool dst_flip = false; |
/* Mesa flips the dst_stride for pack->Invert, but we want our mt to have a |
* normal dst_stride. |
*/ |
if (pack->Invert) { |
dst_stride = -dst_stride; |
dst_flip = true; |
} |
dst_offset = (GLintptr)pixels; |
dst_offset += _mesa_image_offset(2, pack, width, height, |
format, type, 0, 0, 0); |
if (!_mesa_clip_copytexsubimage(ctx, |
&dst_x, &dst_y, |
&x, &y, |
&width, &height)) { |
return true; |
} |
dirty = brw->front_buffer_dirty; |
intel_prepare_render(brw); |
brw->front_buffer_dirty = dirty; |
all = (width * height * irb->mt->cpp == dst->Base.Size && |
x == 0 && dst_offset == 0); |
dst_buffer = intel_bufferobj_buffer(brw, dst, |
all ? INTEL_WRITE_FULL : |
INTEL_WRITE_PART); |
struct intel_mipmap_tree *pbo_mt = |
intel_miptree_create_for_bo(brw, |
dst_buffer, |
irb->mt->format, |
dst_offset, |
width, height, |
dst_stride, I915_TILING_NONE); |
if (!intel_miptree_blit(brw, |
irb->mt, irb->mt_level, irb->mt_layer, |
x, y, _mesa_is_winsys_fbo(ctx->ReadBuffer), |
pbo_mt, 0, 0, |
0, 0, dst_flip, |
width, height, GL_COPY)) { |
return false; |
} |
intel_miptree_release(&pbo_mt); |
DBG("%s - DONE\n", __FUNCTION__); |
return true; |
} |
void |
intelReadPixels(struct gl_context * ctx, |
GLint x, GLint y, GLsizei width, GLsizei height, |
GLenum format, GLenum type, |
const struct gl_pixelstore_attrib *pack, GLvoid * pixels) |
{ |
struct brw_context *brw = brw_context(ctx); |
bool dirty; |
DBG("%s\n", __FUNCTION__); |
if (_mesa_is_bufferobj(pack->BufferObj)) { |
/* Using PBOs, so try the BLT based path. */ |
if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, |
pixels)) { |
return; |
} |
perf_debug("%s: fallback to CPU mapping in PBO case\n", __FUNCTION__); |
} |
/* glReadPixels() wont dirty the front buffer, so reset the dirty |
* flag after calling intel_prepare_render(). */ |
dirty = brw->front_buffer_dirty; |
intel_prepare_render(brw); |
brw->front_buffer_dirty = dirty; |
/* Update Mesa state before calling _mesa_readpixels(). |
* XXX this may not be needed since ReadPixels no longer uses the |
* span code. |
*/ |
if (ctx->NewState) |
_mesa_update_state(ctx); |
_mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels); |
/* There's an intel_prepare_render() call in intelSpanRenderStart(). */ |
brw->front_buffer_dirty = dirty; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_reg.h |
---|
0,0 → 1,130 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#define CMD_MI (0x0 << 29) |
#define CMD_2D (0x2 << 29) |
#define CMD_3D (0x3 << 29) |
#define MI_NOOP (CMD_MI | 0) |
#define MI_BATCH_BUFFER_END (CMD_MI | 0xA << 23) |
#define MI_FLUSH (CMD_MI | (4 << 23)) |
#define FLUSH_MAP_CACHE (1 << 0) |
#define INHIBIT_FLUSH_RENDER_CACHE (1 << 2) |
#define MI_LOAD_REGISTER_IMM (CMD_MI | (0x22 << 23)) |
#define MI_FLUSH_DW (CMD_MI | (0x26 << 23) | 2) |
#define MI_STORE_REGISTER_MEM (CMD_MI | (0x24 << 23)) |
# define MI_STORE_REGISTER_MEM_USE_GGTT (1 << 22) |
/** @{ |
* |
* PIPE_CONTROL operation, a combination MI_FLUSH and register write with |
* additional flushing control. |
*/ |
#define _3DSTATE_PIPE_CONTROL (CMD_3D | (3 << 27) | (2 << 24)) |
#define PIPE_CONTROL_CS_STALL (1 << 20) |
#define PIPE_CONTROL_GLOBAL_SNAPSHOT_COUNT_RESET (1 << 19) |
#define PIPE_CONTROL_TLB_INVALIDATE (1 << 18) |
#define PIPE_CONTROL_SYNC_GFDT (1 << 17) |
#define PIPE_CONTROL_MEDIA_STATE_CLEAR (1 << 16) |
#define PIPE_CONTROL_NO_WRITE (0 << 14) |
#define PIPE_CONTROL_WRITE_IMMEDIATE (1 << 14) |
#define PIPE_CONTROL_WRITE_DEPTH_COUNT (2 << 14) |
#define PIPE_CONTROL_WRITE_TIMESTAMP (3 << 14) |
#define PIPE_CONTROL_DEPTH_STALL (1 << 13) |
#define PIPE_CONTROL_WRITE_FLUSH (1 << 12) |
#define PIPE_CONTROL_INSTRUCTION_FLUSH (1 << 11) |
#define PIPE_CONTROL_TC_FLUSH (1 << 10) /* GM45+ only */ |
#define PIPE_CONTROL_ISP_DIS (1 << 9) |
#define PIPE_CONTROL_INTERRUPT_ENABLE (1 << 8) |
/* GT */ |
#define PIPE_CONTROL_VF_CACHE_INVALIDATE (1 << 4) |
#define PIPE_CONTROL_CONST_CACHE_INVALIDATE (1 << 3) |
#define PIPE_CONTROL_STATE_CACHE_INVALIDATE (1 << 2) |
#define PIPE_CONTROL_STALL_AT_SCOREBOARD (1 << 1) |
#define PIPE_CONTROL_DEPTH_CACHE_FLUSH (1 << 0) |
#define PIPE_CONTROL_PPGTT_WRITE (0 << 2) |
#define PIPE_CONTROL_GLOBAL_GTT_WRITE (1 << 2) |
/** @} */ |
#define XY_SETUP_BLT_CMD (CMD_2D | (0x01 << 22)) |
#define XY_COLOR_BLT_CMD (CMD_2D | (0x50 << 22)) |
#define XY_SRC_COPY_BLT_CMD (CMD_2D | (0x53 << 22)) |
#define XY_TEXT_IMMEDIATE_BLIT_CMD (CMD_2D | (0x31 << 22)) |
# define XY_TEXT_BYTE_PACKED (1 << 16) |
/* BR00 */ |
#define XY_BLT_WRITE_ALPHA (1 << 21) |
#define XY_BLT_WRITE_RGB (1 << 20) |
#define XY_SRC_TILED (1 << 15) |
#define XY_DST_TILED (1 << 11) |
/* BR13 */ |
#define BR13_8 (0x0 << 24) |
#define BR13_565 (0x1 << 24) |
#define BR13_8888 (0x3 << 24) |
/* Pipeline Statistics Counter Registers */ |
#define IA_VERTICES_COUNT 0x2310 |
#define IA_PRIMITIVES_COUNT 0x2318 |
#define VS_INVOCATION_COUNT 0x2320 |
#define HS_INVOCATION_COUNT 0x2300 |
#define DS_INVOCATION_COUNT 0x2308 |
#define GS_INVOCATION_COUNT 0x2328 |
#define GS_PRIMITIVES_COUNT 0x2330 |
#define CL_INVOCATION_COUNT 0x2338 |
#define CL_PRIMITIVES_COUNT 0x2340 |
#define PS_INVOCATION_COUNT 0x2348 |
#define PS_DEPTH_COUNT 0x2350 |
#define SO_NUM_PRIM_STORAGE_NEEDED 0x2280 |
#define SO_PRIM_STORAGE_NEEDED0_IVB 0x5240 |
#define SO_PRIM_STORAGE_NEEDED1_IVB 0x5248 |
#define SO_PRIM_STORAGE_NEEDED2_IVB 0x5250 |
#define SO_PRIM_STORAGE_NEEDED3_IVB 0x5258 |
#define SO_NUM_PRIMS_WRITTEN 0x2288 |
#define SO_NUM_PRIMS_WRITTEN0_IVB 0x5200 |
#define SO_NUM_PRIMS_WRITTEN1_IVB 0x5208 |
#define SO_NUM_PRIMS_WRITTEN2_IVB 0x5210 |
#define SO_NUM_PRIMS_WRITTEN3_IVB 0x5218 |
#define GEN7_SO_WRITE_OFFSET(n) (0x5280 + (n) * 4) |
#define TIMESTAMP 0x2358 |
#define BCS_SWCTRL 0x22200 |
# define BCS_SWCTRL_SRC_Y (1 << 0) |
# define BCS_SWCTRL_DST_Y (1 << 1) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_regions.c |
---|
0,0 → 1,355 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
/* Provide additional functionality on top of bufmgr buffers: |
* - 2d semantics and blit operations |
* - refcounting of buffers for multiple images in a buffer. |
* - refcounting of buffer mappings. |
* - some logic for moving the buffers to the best memory pools for |
* given operations. |
* |
* Most of this is to make it easier to implement the fixed-layout |
* mipmap tree required by intel hardware in the face of GL's |
* programming interface where each image can be specifed in random |
* order and it isn't clear what layout the tree should have until the |
* last moment. |
*/ |
//#include <sys/ioctl.h> |
#include <errno.h> |
#include "main/hash.h" |
#include "brw_context.h" |
#include "intel_regions.h" |
#include "intel_blit.h" |
#include "intel_buffer_objects.h" |
#include "intel_bufmgr.h" |
#include "intel_batchbuffer.h" |
#define FILE_DEBUG_FLAG DEBUG_REGION |
/* This should be set to the maximum backtrace size desired. |
* Set it to 0 to disable backtrace debugging. |
*/ |
#define DEBUG_BACKTRACE_SIZE 0 |
#if DEBUG_BACKTRACE_SIZE == 0 |
/* Use the standard debug output */ |
#define _DBG(...) DBG(__VA_ARGS__) |
#else |
/* Use backtracing debug output */ |
#define _DBG(...) {debug_backtrace(); DBG(__VA_ARGS__);} |
/* Backtracing debug support */ |
#include <execinfo.h> |
static void |
debug_backtrace(void) |
{ |
void *trace[DEBUG_BACKTRACE_SIZE]; |
char **strings = NULL; |
int traceSize; |
register int i; |
traceSize = backtrace(trace, DEBUG_BACKTRACE_SIZE); |
strings = backtrace_symbols(trace, traceSize); |
if (strings == NULL) { |
DBG("no backtrace:"); |
return; |
} |
/* Spit out all the strings with a colon separator. Ignore |
* the first, since we don't really care about the call |
* to debug_backtrace() itself. Skip until the final "/" in |
* the trace to avoid really long lines. |
*/ |
for (i = 1; i < traceSize; i++) { |
char *p = strings[i], *slash = strings[i]; |
while (*p) { |
if (*p++ == '/') { |
slash = p; |
} |
} |
DBG("%s:", slash); |
} |
/* Free up the memory, and we're done */ |
free(strings); |
} |
#endif |
static struct intel_region * |
intel_region_alloc_internal(struct intel_screen *screen, |
GLuint cpp, |
GLuint width, GLuint height, GLuint pitch, |
uint32_t tiling, drm_intel_bo *buffer) |
{ |
struct intel_region *region; |
region = calloc(sizeof(*region), 1); |
if (region == NULL) |
return region; |
region->cpp = cpp; |
region->width = width; |
region->height = height; |
region->pitch = pitch; |
region->refcount = 1; |
region->bo = buffer; |
region->tiling = tiling; |
_DBG("%s <-- %p\n", __FUNCTION__, region); |
return region; |
} |
struct intel_region * |
intel_region_alloc(struct intel_screen *screen, |
uint32_t tiling, |
GLuint cpp, GLuint width, GLuint height, |
bool expect_accelerated_upload) |
{ |
drm_intel_bo *buffer; |
unsigned long flags = 0; |
unsigned long aligned_pitch; |
struct intel_region *region; |
if (expect_accelerated_upload) |
flags |= BO_ALLOC_FOR_RENDER; |
buffer = drm_intel_bo_alloc_tiled(screen->bufmgr, "region", |
width, height, cpp, |
&tiling, &aligned_pitch, flags); |
if (buffer == NULL) |
return NULL; |
region = intel_region_alloc_internal(screen, cpp, width, height, |
aligned_pitch, tiling, buffer); |
if (region == NULL) { |
drm_intel_bo_unreference(buffer); |
return NULL; |
} |
return region; |
} |
bool |
intel_region_flink(struct intel_region *region, uint32_t *name) |
{ |
if (region->name == 0) { |
if (drm_intel_bo_flink(region->bo, ®ion->name)) |
return false; |
} |
*name = region->name; |
return true; |
} |
struct intel_region * |
intel_region_alloc_for_handle(struct intel_screen *screen, |
GLuint cpp, |
GLuint width, GLuint height, GLuint pitch, |
GLuint handle, const char *name) |
{ |
struct intel_region *region; |
drm_intel_bo *buffer; |
int ret; |
uint32_t bit_6_swizzle, tiling; |
buffer = intel_bo_gem_create_from_name(screen->bufmgr, name, handle); |
if (buffer == NULL) |
return NULL; |
ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle); |
if (ret != 0) { |
fprintf(stderr, "Couldn't get tiling of buffer %d (%s): %s\n", |
handle, name, strerror(-ret)); |
drm_intel_bo_unreference(buffer); |
return NULL; |
} |
region = intel_region_alloc_internal(screen, cpp, |
width, height, pitch, tiling, buffer); |
if (region == NULL) { |
drm_intel_bo_unreference(buffer); |
return NULL; |
} |
region->name = handle; |
return region; |
} |
#if 0 |
struct intel_region * |
intel_region_alloc_for_fd(struct intel_screen *screen, |
GLuint cpp, |
GLuint width, GLuint height, GLuint pitch, |
int fd, const char *name) |
{ |
struct intel_region *region; |
drm_intel_bo *buffer; |
int ret; |
uint32_t bit_6_swizzle, tiling; |
buffer = drm_intel_bo_gem_create_from_prime(screen->bufmgr, |
fd, height * pitch); |
if (buffer == NULL) |
return NULL; |
ret = drm_intel_bo_get_tiling(buffer, &tiling, &bit_6_swizzle); |
if (ret != 0) { |
fprintf(stderr, "Couldn't get tiling of buffer (%s): %s\n", |
name, strerror(-ret)); |
drm_intel_bo_unreference(buffer); |
return NULL; |
} |
region = intel_region_alloc_internal(screen, cpp, |
width, height, pitch, tiling, buffer); |
if (region == NULL) { |
drm_intel_bo_unreference(buffer); |
return NULL; |
} |
return region; |
} |
#endif |
void |
intel_region_reference(struct intel_region **dst, struct intel_region *src) |
{ |
_DBG("%s: %p(%d) -> %p(%d)\n", __FUNCTION__, |
*dst, *dst ? (*dst)->refcount : 0, src, src ? src->refcount : 0); |
if (src != *dst) { |
if (*dst) |
intel_region_release(dst); |
if (src) |
src->refcount++; |
*dst = src; |
} |
} |
void |
intel_region_release(struct intel_region **region_handle) |
{ |
struct intel_region *region = *region_handle; |
if (region == NULL) { |
_DBG("%s NULL\n", __FUNCTION__); |
return; |
} |
_DBG("%s %p %d\n", __FUNCTION__, region, region->refcount - 1); |
ASSERT(region->refcount > 0); |
region->refcount--; |
if (region->refcount == 0) { |
drm_intel_bo_unreference(region->bo); |
free(region); |
} |
*region_handle = NULL; |
} |
/** |
* This function computes masks that may be used to select the bits of the X |
* and Y coordinates that indicate the offset within a tile. If the region is |
* untiled, the masks are set to 0. |
*/ |
void |
intel_region_get_tile_masks(struct intel_region *region, |
uint32_t *mask_x, uint32_t *mask_y, |
bool map_stencil_as_y_tiled) |
{ |
int cpp = region->cpp; |
uint32_t tiling = region->tiling; |
if (map_stencil_as_y_tiled) |
tiling = I915_TILING_Y; |
switch (tiling) { |
default: |
assert(false); |
case I915_TILING_NONE: |
*mask_x = *mask_y = 0; |
break; |
case I915_TILING_X: |
*mask_x = 512 / cpp - 1; |
*mask_y = 7; |
break; |
case I915_TILING_Y: |
*mask_x = 128 / cpp - 1; |
*mask_y = 31; |
break; |
} |
} |
/** |
* Compute the offset (in bytes) from the start of the region to the given x |
* and y coordinate. For tiled regions, caller must ensure that x and y are |
* multiples of the tile size. |
*/ |
uint32_t |
intel_region_get_aligned_offset(struct intel_region *region, uint32_t x, |
uint32_t y, bool map_stencil_as_y_tiled) |
{ |
int cpp = region->cpp; |
uint32_t pitch = region->pitch; |
uint32_t tiling = region->tiling; |
if (map_stencil_as_y_tiled) { |
tiling = I915_TILING_Y; |
/* When mapping a W-tiled stencil buffer as Y-tiled, each 64-high W-tile |
* gets transformed into a 32-high Y-tile. Accordingly, the pitch of |
* the resulting region is twice the pitch of the original region, since |
* each row in the Y-tiled view corresponds to two rows in the actual |
* W-tiled surface. So we need to correct the pitch before computing |
* the offsets. |
*/ |
pitch *= 2; |
} |
switch (tiling) { |
default: |
assert(false); |
case I915_TILING_NONE: |
return y * pitch + x * cpp; |
case I915_TILING_X: |
assert((x % (512 / cpp)) == 0); |
assert((y % 8) == 0); |
return y * pitch + x / (512 / cpp) * 4096; |
case I915_TILING_Y: |
assert((x % (128 / cpp)) == 0); |
assert((y % 32) == 0); |
return y * pitch + x / (128 / cpp) * 4096; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_regions.h |
---|
0,0 → 1,159 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTEL_REGIONS_H |
#define INTEL_REGIONS_H |
/** @file intel_regions.h |
* |
* Structure definitions and prototypes for intel_region handling, |
* which is the basic structure for rectangular collections of pixels |
* stored in a drm_intel_bo. |
*/ |
#include <stdbool.h> |
#include <xf86drm.h> |
#include "main/mtypes.h" |
#include "intel_bufmgr.h" |
#ifdef __cplusplus |
extern "C" { |
#endif |
struct brw_context; |
struct intel_screen; |
struct intel_buffer_object; |
/** |
* A layer on top of the bufmgr buffers that adds a few useful things: |
* |
* - Refcounting for local buffer references. |
* - Refcounting for buffer maps |
* - Buffer dimensions - pitch and height. |
* - Blitter commands for copying 2D regions between buffers. (really???) |
*/ |
struct intel_region |
{ |
drm_intel_bo *bo; /**< buffer manager's buffer */ |
GLuint refcount; /**< Reference count for region */ |
GLuint cpp; /**< bytes per pixel */ |
GLuint width; /**< in pixels */ |
GLuint height; /**< in pixels */ |
GLuint pitch; /**< in bytes */ |
uint32_t tiling; /**< Which tiling mode the region is in */ |
uint32_t name; /**< Global name for the bo */ |
}; |
/* Allocate a refcounted region. Pointers to regions should only be |
* copied by calling intel_reference_region(). |
*/ |
struct intel_region *intel_region_alloc(struct intel_screen *screen, |
uint32_t tiling, |
GLuint cpp, GLuint width, |
GLuint height, |
bool expect_accelerated_upload); |
struct intel_region * |
intel_region_alloc_for_handle(struct intel_screen *screen, |
GLuint cpp, |
GLuint width, GLuint height, GLuint pitch, |
unsigned int handle, const char *name); |
struct intel_region * |
intel_region_alloc_for_fd(struct intel_screen *screen, |
GLuint cpp, |
GLuint width, GLuint height, GLuint pitch, |
int fd, const char *name); |
bool |
intel_region_flink(struct intel_region *region, uint32_t *name); |
void intel_region_reference(struct intel_region **dst, |
struct intel_region *src); |
void intel_region_release(struct intel_region **ib); |
void |
intel_region_get_tile_masks(struct intel_region *region, |
uint32_t *mask_x, uint32_t *mask_y, |
bool map_stencil_as_y_tiled); |
uint32_t |
intel_region_get_aligned_offset(struct intel_region *region, uint32_t x, |
uint32_t y, bool map_stencil_as_y_tiled); |
/** |
* Used with images created with image_from_names |
* to help support planar images. |
*/ |
struct intel_image_format { |
int fourcc; |
int components; |
int nplanes; |
struct { |
int buffer_index; |
int width_shift; |
int height_shift; |
uint32_t dri_format; |
int cpp; |
} planes[3]; |
}; |
struct __DRIimageRec { |
struct intel_region *region; |
GLenum internal_format; |
uint32_t dri_format; |
GLuint format; |
uint32_t offset; |
/* |
* Need to save these here between calls to |
* image_from_names and calls to image_from_planar. |
*/ |
uint32_t strides[3]; |
uint32_t offsets[3]; |
struct intel_image_format *planar_format; |
/* particular miptree level */ |
GLuint width; |
GLuint height; |
GLuint tile_x; |
GLuint tile_y; |
bool has_depthstencil; |
void *data; |
}; |
#ifdef __cplusplus |
} |
#endif |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_resolve_map.c |
---|
0,0 → 1,111 |
/* |
* Copyright © 2011 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 "intel_resolve_map.h" |
#include <assert.h> |
#include <stdlib.h> |
/** |
* \brief Set that the miptree slice at (level, layer) needs a resolve. |
* |
* If a map element already exists with the given key, then the value is |
* changed to the given value of \c need. |
*/ |
void |
intel_resolve_map_set(struct intel_resolve_map *head, |
uint32_t level, |
uint32_t layer, |
enum gen6_hiz_op need) |
{ |
struct intel_resolve_map **tail = &head->next; |
struct intel_resolve_map *prev = head; |
while (*tail) { |
if ((*tail)->level == level && (*tail)->layer == layer) { |
(*tail)->need = need; |
return; |
} |
prev = *tail; |
tail = &(*tail)->next; |
} |
*tail = malloc(sizeof(**tail)); |
(*tail)->prev = prev; |
(*tail)->next = NULL; |
(*tail)->level = level; |
(*tail)->layer = layer; |
(*tail)->need = need; |
} |
/** |
* \brief Get an element from the map. |
* \return null if element is not contained in map. |
*/ |
struct intel_resolve_map* |
intel_resolve_map_get(struct intel_resolve_map *head, |
uint32_t level, |
uint32_t layer) |
{ |
struct intel_resolve_map *item = head->next; |
while (item) { |
if (item->level == level && item->layer == layer) |
break; |
else |
item = item->next; |
} |
return item; |
} |
/** |
* \brief Remove and free an element from the map. |
*/ |
void |
intel_resolve_map_remove(struct intel_resolve_map *elem) |
{ |
if (elem->prev) |
elem->prev->next = elem->next; |
if (elem->next) |
elem->next->prev = elem->prev; |
free(elem); |
} |
/** |
* \brief Remove and free all elements of the map. |
*/ |
void |
intel_resolve_map_clear(struct intel_resolve_map *head) |
{ |
struct intel_resolve_map *next = head->next; |
struct intel_resolve_map *trash; |
while (next) { |
trash = next; |
next = next->next; |
free(trash); |
} |
head->next = NULL; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_resolve_map.h |
---|
0,0 → 1,104 |
/* |
* Copyright © 2011 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. |
*/ |
#pragma once |
#include <stdint.h> |
#ifdef __cplusplus |
extern "C" { |
#endif |
/** |
* For an overview of the HiZ operations, see the following sections of the |
* Sandy Bridge PRM, Volume 1, Part2: |
* - 7.5.3.1 Depth Buffer Clear |
* - 7.5.3.2 Depth Buffer Resolve |
* - 7.5.3.3 Hierarchical Depth Buffer Resolve |
* |
* Of these, two get entered in the resolve map as needing to be done to the |
* buffer: depth resolve and hiz resolve. |
*/ |
enum gen6_hiz_op { |
GEN6_HIZ_OP_DEPTH_CLEAR, |
GEN6_HIZ_OP_DEPTH_RESOLVE, |
GEN6_HIZ_OP_HIZ_RESOLVE, |
GEN6_HIZ_OP_NONE, |
}; |
/** |
* \brief Map of miptree slices to needed resolves. |
* |
* The map is implemented as a linear doubly-linked list. |
* |
* In the intel_resolve_map*() functions, the \c head argument is not |
* inspected for its data. It only serves as an anchor for the list. |
* |
* \par Design Discussion |
* |
* There are two possible ways to record which miptree slices need |
* resolves. 1) Maintain a flag for every miptree slice in the texture, |
* likely in intel_mipmap_level::slice, or 2) maintain a list of only |
* those slices that need a resolve. |
* |
* Immediately before drawing, a full depth resolve performed on each |
* enabled depth texture. If design 1 were chosen, then at each draw call |
* it would be necessary to iterate over each miptree slice of each |
* enabled depth texture in order to query if each slice needed a resolve. |
* In the worst case, this would require 2^16 iterations: 16 texture |
* units, 16 miplevels, and 256 depth layers (assuming maximums for OpenGL |
* 2.1). |
* |
* By choosing design 2, the number of iterations is exactly the minimum |
* necessary. |
*/ |
struct intel_resolve_map { |
uint32_t level; |
uint32_t layer; |
enum gen6_hiz_op need; |
struct intel_resolve_map *next; |
struct intel_resolve_map *prev; |
}; |
void |
intel_resolve_map_set(struct intel_resolve_map *head, |
uint32_t level, |
uint32_t layer, |
enum gen6_hiz_op need); |
struct intel_resolve_map* |
intel_resolve_map_get(struct intel_resolve_map *head, |
uint32_t level, |
uint32_t layer); |
void |
intel_resolve_map_remove(struct intel_resolve_map *elem); |
void |
intel_resolve_map_clear(struct intel_resolve_map *head); |
#ifdef __cplusplus |
} /* extern "C" */ |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_screen.c |
---|
0,0 → 1,1332 |
/************************************************************************** |
* |
* 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 <errno.h> |
#include <time.h> |
#include "main/glheader.h" |
#include "main/context.h" |
#include "main/framebuffer.h" |
#include "main/renderbuffer.h" |
#include "main/texobj.h" |
#include "main/hash.h" |
#include "main/fbobject.h" |
#include "main/version.h" |
#include "swrast/s_renderbuffer.h" |
#include "utils.h" |
#include "xmlpool.h" |
PUBLIC const char __driConfigOptions[] = |
DRI_CONF_BEGIN |
DRI_CONF_SECTION_PERFORMANCE |
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_ALWAYS_SYNC) |
/* Options correspond to DRI_CONF_BO_REUSE_DISABLED, |
* DRI_CONF_BO_REUSE_ALL |
*/ |
DRI_CONF_OPT_BEGIN_V(bo_reuse, enum, 1, "0:1") |
DRI_CONF_DESC_BEGIN(en, "Buffer object reuse") |
DRI_CONF_ENUM(0, "Disable buffer object reuse") |
DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects") |
DRI_CONF_DESC_END |
DRI_CONF_OPT_END |
DRI_CONF_OPT_BEGIN_B(hiz, "true") |
DRI_CONF_DESC(en, "Enable Hierarchical Z on gen6+") |
DRI_CONF_OPT_END |
DRI_CONF_SECTION_END |
DRI_CONF_SECTION_QUALITY |
DRI_CONF_FORCE_S3TC_ENABLE("false") |
DRI_CONF_SECTION_END |
DRI_CONF_SECTION_DEBUG |
DRI_CONF_NO_RAST("false") |
DRI_CONF_ALWAYS_FLUSH_BATCH("false") |
DRI_CONF_ALWAYS_FLUSH_CACHE("false") |
DRI_CONF_DISABLE_THROTTLING("false") |
DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN("false") |
DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS("false") |
DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED("false") |
DRI_CONF_OPT_BEGIN_B(shader_precompile, "true") |
DRI_CONF_DESC(en, "Perform code generation at shader link time.") |
DRI_CONF_OPT_END |
DRI_CONF_SECTION_END |
DRI_CONF_END; |
const GLuint __driNConfigOptions = 12; |
#include "intel_batchbuffer.h" |
#include "intel_buffers.h" |
#include "intel_bufmgr.h" |
#include "intel_chipset.h" |
#include "intel_fbo.h" |
#include "intel_mipmap_tree.h" |
#include "intel_screen.h" |
#include "intel_tex.h" |
#include "intel_regions.h" |
#include "brw_context.h" |
#include "i915_drm.h" |
#ifdef USE_NEW_INTERFACE |
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; |
#endif /*USE_NEW_INTERFACE */ |
/** |
* For debugging purposes, this returns a time in seconds. |
*/ |
double |
get_time(void) |
{ |
struct timespec tp; |
// clock_gettime(CLOCK_MONOTONIC, &tp); |
return tp.tv_sec + tp.tv_nsec / 1000000000.0; |
} |
void |
aub_dump_bmp(struct gl_context *ctx) |
{ |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
for (int i = 0; i < fb->_NumColorDrawBuffers; i++) { |
struct intel_renderbuffer *irb = |
intel_renderbuffer(fb->_ColorDrawBuffers[i]); |
if (irb && irb->mt) { |
enum aub_dump_bmp_format format; |
switch (irb->Base.Base.Format) { |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_XRGB8888: |
format = AUB_DUMP_BMP_FORMAT_ARGB_8888; |
break; |
default: |
continue; |
} |
assert(irb->mt->region->pitch % irb->mt->region->cpp == 0); |
drm_intel_gem_bo_aub_dump_bmp(irb->mt->region->bo, |
irb->draw_x, |
irb->draw_y, |
irb->Base.Base.Width, |
irb->Base.Base.Height, |
format, |
irb->mt->region->pitch, |
0); |
} |
} |
} |
static const __DRItexBufferExtension intelTexBufferExtension = { |
.base = { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, |
.setTexBuffer = intelSetTexBuffer, |
.setTexBuffer2 = intelSetTexBuffer2, |
.releaseTexBuffer = NULL, |
}; |
static void |
intelDRI2Flush(__DRIdrawable *drawable) |
{ |
GET_CURRENT_CONTEXT(ctx); |
struct brw_context *brw = brw_context(ctx); |
if (brw == NULL) |
return; |
intel_resolve_for_dri2_flush(brw, drawable); |
brw->need_throttle = true; |
if (brw->batch.used) |
intel_batchbuffer_flush(brw); |
if (INTEL_DEBUG & DEBUG_AUB) { |
aub_dump_bmp(ctx); |
} |
} |
static const struct __DRI2flushExtensionRec intelFlushExtension = { |
.base = { __DRI2_FLUSH, 3 }, |
.flush = intelDRI2Flush, |
.invalidate = dri2InvalidateDrawable, |
}; |
static struct intel_image_format intel_image_formats[] = { |
{ __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } }, |
{ __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_COMPONENTS_RGB, 1, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } }, |
{ __DRI_IMAGE_FOURCC_YUV410, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } }, |
{ __DRI_IMAGE_FOURCC_YUV411, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, |
{ __DRI_IMAGE_FOURCC_YUV420, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } }, |
{ __DRI_IMAGE_FOURCC_YUV422, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, |
{ __DRI_IMAGE_FOURCC_YUV444, __DRI_IMAGE_COMPONENTS_Y_U_V, 3, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, |
{ __DRI_IMAGE_FOURCC_NV12, __DRI_IMAGE_COMPONENTS_Y_UV, 2, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } }, |
{ __DRI_IMAGE_FOURCC_NV16, __DRI_IMAGE_COMPONENTS_Y_UV, 2, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, |
{ 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } }, |
/* For YUYV buffers, we set up two overlapping DRI images and treat |
* them as planar buffers in the compositors. Plane 0 is GR88 and |
* samples YU or YV pairs and places Y into the R component, while |
* plane 1 is ARGB and samples YUYV clusters and places pairs and |
* places U into the G component and V into A. This lets the |
* texture sampler interpolate the Y components correctly when |
* sampling from plane 0, and interpolate U and V correctly when |
* sampling from plane 1. */ |
{ __DRI_IMAGE_FOURCC_YUYV, __DRI_IMAGE_COMPONENTS_Y_XUXV, 2, |
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, |
{ 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } } |
}; |
static __DRIimage * |
intel_allocate_image(int dri_format, void *loaderPrivate) |
{ |
__DRIimage *image; |
image = calloc(1, sizeof *image); |
if (image == NULL) |
return NULL; |
image->dri_format = dri_format; |
image->offset = 0; |
switch (dri_format) { |
case __DRI_IMAGE_FORMAT_RGB565: |
image->format = MESA_FORMAT_RGB565; |
break; |
case __DRI_IMAGE_FORMAT_XRGB8888: |
image->format = MESA_FORMAT_XRGB8888; |
break; |
case __DRI_IMAGE_FORMAT_ARGB8888: |
image->format = MESA_FORMAT_ARGB8888; |
break; |
case __DRI_IMAGE_FORMAT_ABGR8888: |
image->format = MESA_FORMAT_RGBA8888_REV; |
break; |
case __DRI_IMAGE_FORMAT_XBGR8888: |
image->format = MESA_FORMAT_RGBX8888_REV; |
break; |
case __DRI_IMAGE_FORMAT_R8: |
image->format = MESA_FORMAT_R8; |
break; |
case __DRI_IMAGE_FORMAT_GR88: |
image->format = MESA_FORMAT_GR88; |
break; |
case __DRI_IMAGE_FORMAT_NONE: |
image->format = MESA_FORMAT_NONE; |
break; |
default: |
free(image); |
return NULL; |
} |
image->internal_format = _mesa_get_format_base_format(image->format); |
image->data = loaderPrivate; |
return image; |
} |
/** |
* Sets up a DRIImage structure to point to our shared image in a region |
*/ |
static void |
intel_setup_image_from_mipmap_tree(struct brw_context *brw, __DRIimage *image, |
struct intel_mipmap_tree *mt, GLuint level, |
GLuint zoffset) |
{ |
unsigned int draw_x, draw_y; |
uint32_t mask_x, mask_y; |
intel_miptree_make_shareable(brw, mt); |
intel_miptree_check_level_layer(mt, level, zoffset); |
intel_region_get_tile_masks(mt->region, &mask_x, &mask_y, false); |
intel_miptree_get_image_offset(mt, level, zoffset, &draw_x, &draw_y); |
image->width = mt->level[level].width; |
image->height = mt->level[level].height; |
image->tile_x = draw_x & mask_x; |
image->tile_y = draw_y & mask_y; |
image->offset = intel_region_get_aligned_offset(mt->region, |
draw_x & ~mask_x, |
draw_y & ~mask_y, |
false); |
intel_region_reference(&image->region, mt->region); |
} |
static void |
intel_setup_image_from_dimensions(__DRIimage *image) |
{ |
image->width = image->region->width; |
image->height = image->region->height; |
image->tile_x = 0; |
image->tile_y = 0; |
image->has_depthstencil = false; |
} |
static inline uint32_t |
intel_dri_format(GLuint format) |
{ |
switch (format) { |
case MESA_FORMAT_RGB565: |
return __DRI_IMAGE_FORMAT_RGB565; |
case MESA_FORMAT_XRGB8888: |
return __DRI_IMAGE_FORMAT_XRGB8888; |
case MESA_FORMAT_ARGB8888: |
return __DRI_IMAGE_FORMAT_ARGB8888; |
case MESA_FORMAT_RGBA8888_REV: |
return __DRI_IMAGE_FORMAT_ABGR8888; |
case MESA_FORMAT_R8: |
return __DRI_IMAGE_FORMAT_R8; |
case MESA_FORMAT_RG88: |
return __DRI_IMAGE_FORMAT_GR88; |
} |
return MESA_FORMAT_NONE; |
} |
static __DRIimage * |
intel_create_image_from_name(__DRIscreen *screen, |
int width, int height, int format, |
int name, int pitch, void *loaderPrivate) |
{ |
struct intel_screen *intelScreen = screen->driverPrivate; |
__DRIimage *image; |
int cpp; |
image = intel_allocate_image(format, loaderPrivate); |
if (image == NULL) |
return NULL; |
if (image->format == MESA_FORMAT_NONE) |
cpp = 1; |
else |
cpp = _mesa_get_format_bytes(image->format); |
image->region = intel_region_alloc_for_handle(intelScreen, |
cpp, width, height, |
pitch * cpp, name, "image"); |
if (image->region == NULL) { |
free(image); |
return NULL; |
} |
intel_setup_image_from_dimensions(image); |
return image; |
} |
static __DRIimage * |
intel_create_image_from_renderbuffer(__DRIcontext *context, |
int renderbuffer, void *loaderPrivate) |
{ |
__DRIimage *image; |
struct brw_context *brw = context->driverPrivate; |
struct gl_context *ctx = &brw->ctx; |
struct gl_renderbuffer *rb; |
struct intel_renderbuffer *irb; |
rb = _mesa_lookup_renderbuffer(ctx, renderbuffer); |
if (!rb) { |
_mesa_error(ctx, GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); |
return NULL; |
} |
irb = intel_renderbuffer(rb); |
intel_miptree_make_shareable(brw, irb->mt); |
image = calloc(1, sizeof *image); |
if (image == NULL) |
return NULL; |
image->internal_format = rb->InternalFormat; |
image->format = rb->Format; |
image->offset = 0; |
image->data = loaderPrivate; |
intel_region_reference(&image->region, irb->mt->region); |
intel_setup_image_from_dimensions(image); |
image->dri_format = intel_dri_format(image->format); |
image->has_depthstencil = irb->mt->stencil_mt? true : false; |
rb->NeedsFinishRenderTexture = true; |
return image; |
} |
static __DRIimage * |
intel_create_image_from_texture(__DRIcontext *context, int target, |
unsigned texture, int zoffset, |
int level, |
unsigned *error, |
void *loaderPrivate) |
{ |
__DRIimage *image; |
struct brw_context *brw = context->driverPrivate; |
struct gl_texture_object *obj; |
struct intel_texture_object *iobj; |
GLuint face = 0; |
obj = _mesa_lookup_texture(&brw->ctx, texture); |
if (!obj || obj->Target != target) { |
*error = __DRI_IMAGE_ERROR_BAD_PARAMETER; |
return NULL; |
} |
if (target == GL_TEXTURE_CUBE_MAP) |
face = zoffset; |
_mesa_test_texobj_completeness(&brw->ctx, obj); |
iobj = intel_texture_object(obj); |
if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) { |
*error = __DRI_IMAGE_ERROR_BAD_PARAMETER; |
return NULL; |
} |
if (level < obj->BaseLevel || level > obj->_MaxLevel) { |
*error = __DRI_IMAGE_ERROR_BAD_MATCH; |
return NULL; |
} |
if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < zoffset) { |
*error = __DRI_IMAGE_ERROR_BAD_MATCH; |
return NULL; |
} |
image = calloc(1, sizeof *image); |
if (image == NULL) { |
*error = __DRI_IMAGE_ERROR_BAD_ALLOC; |
return NULL; |
} |
image->internal_format = obj->Image[face][level]->InternalFormat; |
image->format = obj->Image[face][level]->TexFormat; |
image->data = loaderPrivate; |
intel_setup_image_from_mipmap_tree(brw, image, iobj->mt, level, zoffset); |
image->dri_format = intel_dri_format(image->format); |
image->has_depthstencil = iobj->mt->stencil_mt? true : false; |
if (image->dri_format == MESA_FORMAT_NONE) { |
*error = __DRI_IMAGE_ERROR_BAD_PARAMETER; |
free(image); |
return NULL; |
} |
*error = __DRI_IMAGE_ERROR_SUCCESS; |
return image; |
} |
static void |
intel_destroy_image(__DRIimage *image) |
{ |
intel_region_release(&image->region); |
free(image); |
} |
static __DRIimage * |
intel_create_image(__DRIscreen *screen, |
int width, int height, int format, |
unsigned int use, |
void *loaderPrivate) |
{ |
__DRIimage *image; |
struct intel_screen *intelScreen = screen->driverPrivate; |
uint32_t tiling; |
int cpp; |
tiling = I915_TILING_X; |
if (use & __DRI_IMAGE_USE_CURSOR) { |
if (width != 64 || height != 64) |
return NULL; |
tiling = I915_TILING_NONE; |
} |
image = intel_allocate_image(format, loaderPrivate); |
if (image == NULL) |
return NULL; |
cpp = _mesa_get_format_bytes(image->format); |
image->region = |
intel_region_alloc(intelScreen, tiling, cpp, width, height, true); |
if (image->region == NULL) { |
free(image); |
return NULL; |
} |
intel_setup_image_from_dimensions(image); |
return image; |
} |
static GLboolean |
intel_query_image(__DRIimage *image, int attrib, int *value) |
{ |
switch (attrib) { |
case __DRI_IMAGE_ATTRIB_STRIDE: |
*value = image->region->pitch; |
return true; |
case __DRI_IMAGE_ATTRIB_HANDLE: |
*value = image->region->bo->handle; |
return true; |
case __DRI_IMAGE_ATTRIB_NAME: |
return intel_region_flink(image->region, (uint32_t *) value); |
case __DRI_IMAGE_ATTRIB_FORMAT: |
*value = image->dri_format; |
return true; |
case __DRI_IMAGE_ATTRIB_WIDTH: |
*value = image->region->width; |
return true; |
case __DRI_IMAGE_ATTRIB_HEIGHT: |
*value = image->region->height; |
return true; |
case __DRI_IMAGE_ATTRIB_COMPONENTS: |
if (image->planar_format == NULL) |
return false; |
*value = image->planar_format->components; |
return true; |
case __DRI_IMAGE_ATTRIB_FD: |
// if (drm_intel_bo_gem_export_to_prime(image->region->bo, value) == 0) |
// return true; |
return false; |
default: |
return false; |
} |
} |
static __DRIimage * |
intel_dup_image(__DRIimage *orig_image, void *loaderPrivate) |
{ |
__DRIimage *image; |
image = calloc(1, sizeof *image); |
if (image == NULL) |
return NULL; |
intel_region_reference(&image->region, orig_image->region); |
if (image->region == NULL) { |
free(image); |
return NULL; |
} |
image->internal_format = orig_image->internal_format; |
image->planar_format = orig_image->planar_format; |
image->dri_format = orig_image->dri_format; |
image->format = orig_image->format; |
image->offset = orig_image->offset; |
image->width = orig_image->width; |
image->height = orig_image->height; |
image->tile_x = orig_image->tile_x; |
image->tile_y = orig_image->tile_y; |
image->has_depthstencil = orig_image->has_depthstencil; |
image->data = loaderPrivate; |
memcpy(image->strides, orig_image->strides, sizeof(image->strides)); |
memcpy(image->offsets, orig_image->offsets, sizeof(image->offsets)); |
return image; |
} |
static GLboolean |
intel_validate_usage(__DRIimage *image, unsigned int use) |
{ |
if (use & __DRI_IMAGE_USE_CURSOR) { |
if (image->region->width != 64 || image->region->height != 64) |
return GL_FALSE; |
} |
return GL_TRUE; |
} |
static __DRIimage * |
intel_create_image_from_names(__DRIscreen *screen, |
int width, int height, int fourcc, |
int *names, int num_names, |
int *strides, int *offsets, |
void *loaderPrivate) |
{ |
struct intel_image_format *f = NULL; |
__DRIimage *image; |
int i, index; |
if (screen == NULL || names == NULL || num_names != 1) |
return NULL; |
for (i = 0; i < ARRAY_SIZE(intel_image_formats); i++) { |
if (intel_image_formats[i].fourcc == fourcc) { |
f = &intel_image_formats[i]; |
} |
} |
if (f == NULL) |
return NULL; |
image = intel_create_image_from_name(screen, width, height, |
__DRI_IMAGE_FORMAT_NONE, |
names[0], strides[0], |
loaderPrivate); |
if (image == NULL) |
return NULL; |
image->planar_format = f; |
for (i = 0; i < f->nplanes; i++) { |
index = f->planes[i].buffer_index; |
image->offsets[index] = offsets[index]; |
image->strides[index] = strides[index]; |
} |
return image; |
} |
#if 0 |
static __DRIimage * |
intel_create_image_from_fds(__DRIscreen *screen, |
int width, int height, int fourcc, |
int *fds, int num_fds, int *strides, int *offsets, |
void *loaderPrivate) |
{ |
struct intel_screen *intelScreen = screen->driverPrivate; |
struct intel_image_format *f = NULL; |
__DRIimage *image; |
int i, index; |
if (fds == NULL || num_fds != 1) |
return NULL; |
for (i = 0; i < ARRAY_SIZE(intel_image_formats); i++) { |
if (intel_image_formats[i].fourcc == fourcc) { |
f = &intel_image_formats[i]; |
} |
} |
if (f == NULL) |
return NULL; |
image = intel_allocate_image(__DRI_IMAGE_FORMAT_NONE, loaderPrivate); |
if (image == NULL) |
return NULL; |
image->region = intel_region_alloc_for_fd(intelScreen, |
1, width, height, |
strides[0], fds[0], "image"); |
if (image->region == NULL) { |
free(image); |
return NULL; |
} |
image->planar_format = f; |
for (i = 0; i < f->nplanes; i++) { |
index = f->planes[i].buffer_index; |
image->offsets[index] = offsets[index]; |
image->strides[index] = strides[index]; |
} |
return image; |
} |
#endif |
static __DRIimage * |
intel_from_planar(__DRIimage *parent, int plane, void *loaderPrivate) |
{ |
int width, height, offset, stride, dri_format, index; |
struct intel_image_format *f; |
uint32_t mask_x, mask_y; |
__DRIimage *image; |
if (parent == NULL || parent->planar_format == NULL) |
return NULL; |
f = parent->planar_format; |
if (plane >= f->nplanes) |
return NULL; |
width = parent->region->width >> f->planes[plane].width_shift; |
height = parent->region->height >> f->planes[plane].height_shift; |
dri_format = f->planes[plane].dri_format; |
index = f->planes[plane].buffer_index; |
offset = parent->offsets[index]; |
stride = parent->strides[index]; |
image = intel_allocate_image(dri_format, loaderPrivate); |
if (image == NULL) |
return NULL; |
if (offset + height * stride > parent->region->bo->size) { |
_mesa_warning(NULL, "intel_create_sub_image: subimage out of bounds"); |
free(image); |
return NULL; |
} |
image->region = calloc(sizeof(*image->region), 1); |
if (image->region == NULL) { |
free(image); |
return NULL; |
} |
image->region->cpp = _mesa_get_format_bytes(image->format); |
image->region->width = width; |
image->region->height = height; |
image->region->pitch = stride; |
image->region->refcount = 1; |
image->region->bo = parent->region->bo; |
drm_intel_bo_reference(image->region->bo); |
image->region->tiling = parent->region->tiling; |
image->offset = offset; |
intel_setup_image_from_dimensions(image); |
intel_region_get_tile_masks(image->region, &mask_x, &mask_y, false); |
if (offset & mask_x) |
_mesa_warning(NULL, |
"intel_create_sub_image: offset not on tile boundary"); |
return image; |
} |
static struct __DRIimageExtensionRec intelImageExtension = { |
.base = { __DRI_IMAGE, 7 }, |
.createImageFromName = intel_create_image_from_name, |
.createImageFromRenderbuffer = intel_create_image_from_renderbuffer, |
.destroyImage = intel_destroy_image, |
.createImage = intel_create_image, |
.queryImage = intel_query_image, |
.dupImage = intel_dup_image, |
.validateUsage = intel_validate_usage, |
.createImageFromNames = intel_create_image_from_names, |
.fromPlanar = intel_from_planar, |
.createImageFromTexture = intel_create_image_from_texture, |
// .createImageFromFds = intel_create_image_from_fds |
}; |
static const __DRIextension *intelScreenExtensions[] = { |
&intelTexBufferExtension.base, |
&intelFlushExtension.base, |
&intelImageExtension.base, |
&dri2ConfigQueryExtension.base, |
NULL |
}; |
static bool |
intel_get_param(__DRIscreen *psp, int param, int *value) |
{ |
int ret; |
struct drm_i915_getparam gp; |
memset(&gp, 0, sizeof(gp)); |
gp.param = param; |
gp.value = value; |
ret = drmIoctl(psp->fd, DRM_IOCTL_I915_GETPARAM, &gp); |
if (ret) { |
if (ret != -EINVAL) |
_mesa_warning(NULL, "drm_i915_getparam: %d", ret); |
return false; |
} |
return true; |
} |
static bool |
intel_get_boolean(__DRIscreen *psp, int param) |
{ |
int value = 0; |
return intel_get_param(psp, param, &value) && value; |
} |
static void |
intelDestroyScreen(__DRIscreen * sPriv) |
{ |
struct intel_screen *intelScreen = sPriv->driverPrivate; |
dri_bufmgr_destroy(intelScreen->bufmgr); |
driDestroyOptionInfo(&intelScreen->optionCache); |
free(intelScreen); |
sPriv->driverPrivate = NULL; |
} |
/** |
* This is called when we need to set up GL rendering to a new X window. |
*/ |
static GLboolean |
intelCreateBuffer(__DRIscreen * driScrnPriv, |
__DRIdrawable * driDrawPriv, |
const struct gl_config * mesaVis, GLboolean isPixmap) |
{ |
struct intel_renderbuffer *rb; |
struct intel_screen *screen = (struct intel_screen*) driScrnPriv->driverPrivate; |
gl_format rgbFormat; |
unsigned num_samples = intel_quantize_num_samples(screen, mesaVis->samples); |
struct gl_framebuffer *fb; |
if (isPixmap) |
return false; |
fb = CALLOC_STRUCT(gl_framebuffer); |
if (!fb) |
return false; |
_mesa_initialize_window_framebuffer(fb, mesaVis); |
if (mesaVis->redBits == 5) |
rgbFormat = MESA_FORMAT_RGB565; |
else if (mesaVis->sRGBCapable) |
rgbFormat = MESA_FORMAT_SARGB8; |
else if (mesaVis->alphaBits == 0) |
rgbFormat = MESA_FORMAT_XRGB8888; |
else { |
rgbFormat = MESA_FORMAT_SARGB8; |
fb->Visual.sRGBCapable = true; |
} |
printf("\n%s doubleBufferMode %d\n\n", __FUNCTION__,mesaVis->doubleBufferMode ); |
/* setup the hardware-based renderbuffers */ |
rb = intel_create_renderbuffer(rgbFormat, num_samples); |
_mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &rb->Base.Base); |
if (mesaVis->doubleBufferMode) { |
rb = intel_create_renderbuffer(rgbFormat, num_samples); |
_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &rb->Base.Base); |
} |
/* |
* Assert here that the gl_config has an expected depth/stencil bit |
* combination: one of d24/s8, d16/s0, d0/s0. (See intelInitScreen2(), |
* which constructs the advertised configs.) |
*/ |
if (mesaVis->depthBits == 24) { |
assert(mesaVis->stencilBits == 8); |
if (screen->hw_has_separate_stencil) { |
rb = intel_create_private_renderbuffer(MESA_FORMAT_X8_Z24, |
num_samples); |
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base); |
rb = intel_create_private_renderbuffer(MESA_FORMAT_S8, |
num_samples); |
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &rb->Base.Base); |
} else { |
/* |
* Use combined depth/stencil. Note that the renderbuffer is |
* attached to two attachment points. |
*/ |
rb = intel_create_private_renderbuffer(MESA_FORMAT_S8_Z24, |
num_samples); |
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base); |
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, &rb->Base.Base); |
} |
} |
else if (mesaVis->depthBits == 16) { |
assert(mesaVis->stencilBits == 0); |
rb = intel_create_private_renderbuffer(MESA_FORMAT_Z16, |
num_samples); |
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, &rb->Base.Base); |
} |
else { |
assert(mesaVis->depthBits == 0); |
assert(mesaVis->stencilBits == 0); |
} |
/* now add any/all software-based renderbuffers we may need */ |
_swrast_add_soft_renderbuffers(fb, |
false, /* never sw color */ |
false, /* never sw depth */ |
false, /* never sw stencil */ |
mesaVis->accumRedBits > 0, |
false, /* never sw alpha */ |
false /* never sw aux */ ); |
driDrawPriv->driverPrivate = fb; |
return true; |
} |
static void |
intelDestroyBuffer(__DRIdrawable * driDrawPriv) |
{ |
struct gl_framebuffer *fb = driDrawPriv->driverPrivate; |
_mesa_reference_framebuffer(&fb, NULL); |
} |
static GLboolean |
intelCreateContext(gl_api api, |
const struct gl_config * mesaVis, |
__DRIcontext * driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
uint32_t flags, |
unsigned *error, |
void *sharedContextPrivate) |
{ |
bool success = false; |
success = brwCreateContext(api, mesaVis, |
driContextPriv, |
major_version, minor_version, flags, |
error, sharedContextPrivate); |
if (success) |
return true; |
if (driContextPriv->driverPrivate != NULL) |
intelDestroyContext(driContextPriv); |
return false; |
} |
static bool |
intel_init_bufmgr(struct intel_screen *intelScreen) |
{ |
__DRIscreen *spriv = intelScreen->driScrnPriv; |
intelScreen->no_hw = getenv("INTEL_NO_HW") != NULL; |
intelScreen->bufmgr = intel_bufmgr_gem_init(spriv->fd, BATCH_SZ); |
if (intelScreen->bufmgr == NULL) { |
fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n", |
__func__, __LINE__); |
return false; |
} |
drm_intel_bufmgr_gem_enable_fenced_relocs(intelScreen->bufmgr); |
if (!intel_get_boolean(spriv, I915_PARAM_HAS_RELAXED_DELTA)) { |
fprintf(stderr, "[%s: %u] Kernel 2.6.39 required.\n", __func__, __LINE__); |
return false; |
} |
return true; |
} |
/** |
* Override intel_screen.hw_has_separate_stencil with environment variable |
* INTEL_SEPARATE_STENCIL. |
* |
* Valid values for INTEL_SEPARATE_STENCIL are "0" and "1". If an invalid |
* valid value is encountered, a warning is emitted and INTEL_SEPARATE_STENCIL |
* is ignored. |
*/ |
static void |
intel_override_separate_stencil(struct intel_screen *screen) |
{ |
const char *s = getenv("INTEL_SEPARATE_STENCIL"); |
if (!s) { |
return; |
} else if (!strncmp("0", s, 2)) { |
screen->hw_has_separate_stencil = false; |
} else if (!strncmp("1", s, 2)) { |
screen->hw_has_separate_stencil = true; |
} else { |
fprintf(stderr, |
"warning: env variable INTEL_SEPARATE_STENCIL=\"%s\" has " |
"invalid value and is ignored", s); |
} |
} |
static bool |
intel_detect_swizzling(struct intel_screen *screen) |
{ |
drm_intel_bo *buffer; |
unsigned long flags = 0; |
unsigned long aligned_pitch; |
uint32_t tiling = I915_TILING_X; |
uint32_t swizzle_mode = 0; |
buffer = drm_intel_bo_alloc_tiled(screen->bufmgr, "swizzle test", |
64, 64, 4, |
&tiling, &aligned_pitch, flags); |
if (buffer == NULL) |
return false; |
drm_intel_bo_get_tiling(buffer, &tiling, &swizzle_mode); |
drm_intel_bo_unreference(buffer); |
if (swizzle_mode == I915_BIT_6_SWIZZLE_NONE) |
return false; |
else |
return true; |
} |
static __DRIconfig** |
intel_screen_make_configs(__DRIscreen *dri_screen) |
{ |
static const gl_format formats[] = { |
MESA_FORMAT_RGB565, |
MESA_FORMAT_ARGB8888 |
}; |
/* GLX_SWAP_COPY_OML is not supported due to page flipping. */ |
static const GLenum back_buffer_modes[] = { |
GLX_SWAP_UNDEFINED_OML, GLX_NONE, |
}; |
static const uint8_t singlesample_samples[1] = {0}; |
static const uint8_t multisample_samples[2] = {4, 8}; |
struct intel_screen *screen = dri_screen->driverPrivate; |
uint8_t depth_bits[4], stencil_bits[4]; |
__DRIconfig **configs = NULL; |
/* Generate singlesample configs without accumulation buffer. */ |
for (int i = 0; i < ARRAY_SIZE(formats); i++) { |
__DRIconfig **new_configs; |
int num_depth_stencil_bits = 2; |
/* Starting with DRI2 protocol version 1.1 we can request a depth/stencil |
* buffer that has a different number of bits per pixel than the color |
* buffer, gen >= 6 supports this. |
*/ |
depth_bits[0] = 0; |
stencil_bits[0] = 0; |
if (formats[i] == MESA_FORMAT_RGB565) { |
depth_bits[1] = 16; |
stencil_bits[1] = 0; |
if (screen->gen >= 6) { |
depth_bits[2] = 24; |
stencil_bits[2] = 8; |
num_depth_stencil_bits = 3; |
} |
} else { |
depth_bits[1] = 24; |
stencil_bits[1] = 8; |
} |
new_configs = driCreateConfigs(formats[i], |
depth_bits, |
stencil_bits, |
num_depth_stencil_bits, |
back_buffer_modes, 2, |
singlesample_samples, 1, |
false); |
configs = driConcatConfigs(configs, new_configs); |
} |
/* Generate the minimum possible set of configs that include an |
* accumulation buffer. |
*/ |
for (int i = 0; i < ARRAY_SIZE(formats); i++) { |
__DRIconfig **new_configs; |
if (formats[i] == MESA_FORMAT_RGB565) { |
depth_bits[0] = 16; |
stencil_bits[0] = 0; |
} else { |
depth_bits[0] = 24; |
stencil_bits[0] = 8; |
} |
new_configs = driCreateConfigs(formats[i], |
depth_bits, stencil_bits, 1, |
back_buffer_modes, 1, |
singlesample_samples, 1, |
true); |
configs = driConcatConfigs(configs, new_configs); |
} |
/* Generate multisample configs. |
* |
* This loop breaks early, and hence is a no-op, on gen < 6. |
* |
* Multisample configs must follow the singlesample configs in order to |
* work around an X server bug present in 1.12. The X server chooses to |
* associate the first listed RGBA888-Z24S8 config, regardless of its |
* sample count, with the 32-bit depth visual used for compositing. |
* |
* Only doublebuffer configs with GLX_SWAP_UNDEFINED_OML behavior are |
* supported. Singlebuffer configs are not supported because no one wants |
* them. |
*/ |
for (int i = 0; i < ARRAY_SIZE(formats); i++) { |
if (screen->gen < 6) |
break; |
__DRIconfig **new_configs; |
const int num_depth_stencil_bits = 2; |
int num_msaa_modes = 0; |
depth_bits[0] = 0; |
stencil_bits[0] = 0; |
if (formats[i] == MESA_FORMAT_RGB565) { |
depth_bits[1] = 16; |
stencil_bits[1] = 0; |
} else { |
depth_bits[1] = 24; |
stencil_bits[1] = 8; |
} |
if (screen->gen >= 7) |
num_msaa_modes = 2; |
else if (screen->gen == 6) |
num_msaa_modes = 1; |
new_configs = driCreateConfigs(formats[i], |
depth_bits, |
stencil_bits, |
num_depth_stencil_bits, |
back_buffer_modes, 1, |
multisample_samples, |
num_msaa_modes, |
false); |
configs = driConcatConfigs(configs, new_configs); |
} |
if (configs == NULL) { |
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, |
__LINE__); |
return NULL; |
} |
return configs; |
} |
static void |
set_max_gl_versions(struct intel_screen *screen) |
{ |
int gl_version_override = _mesa_get_gl_version_override(); |
switch (screen->gen) { |
case 7: |
screen->max_gl_core_version = 31; |
screen->max_gl_compat_version = 30; |
screen->max_gl_es1_version = 11; |
screen->max_gl_es2_version = 30; |
break; |
case 6: |
screen->max_gl_core_version = 31; |
screen->max_gl_compat_version = 30; |
screen->max_gl_es1_version = 11; |
screen->max_gl_es2_version = 30; |
break; |
case 5: |
case 4: |
screen->max_gl_core_version = 0; |
screen->max_gl_compat_version = 21; |
screen->max_gl_es1_version = 11; |
screen->max_gl_es2_version = 20; |
break; |
default: |
assert(!"unrecognized intel_screen::gen"); |
break; |
} |
if (gl_version_override >= 31) { |
screen->max_gl_core_version = MAX2(screen->max_gl_core_version, |
gl_version_override); |
} else { |
screen->max_gl_compat_version = MAX2(screen->max_gl_compat_version, |
gl_version_override); |
} |
#ifndef FEATURE_ES1 |
screen->max_gl_es1_version = 0; |
#endif |
#ifndef FEATURE_ES2 |
screen->max_gl_es2_version = 0; |
#endif |
} |
/** |
* This is the driver specific part of the createNewScreen entry point. |
* Called when using DRI2. |
* |
* \return the struct gl_config supported by this driver |
*/ |
static const |
__DRIconfig **intelInitScreen2(__DRIscreen *psp) |
{ |
struct intel_screen *intelScreen; |
if (psp->dri2.loader->base.version <= 2 || |
psp->dri2.loader->getBuffersWithFormat == NULL) { |
fprintf(stderr, |
"\nERROR! DRI2 loader with getBuffersWithFormat() " |
"support required\n"); |
return false; |
} |
/* Allocate the private area */ |
intelScreen = calloc(1, sizeof *intelScreen); |
if (!intelScreen) { |
fprintf(stderr, "\nERROR! Allocating private area failed\n"); |
return false; |
} |
/* parse information in __driConfigOptions */ |
driParseOptionInfo(&intelScreen->optionCache, |
__driConfigOptions, __driNConfigOptions); |
intelScreen->driScrnPriv = psp; |
psp->driverPrivate = (void *) intelScreen; |
if (!intel_init_bufmgr(intelScreen)) |
return false; |
intelScreen->deviceID = drm_intel_bufmgr_gem_get_devid(intelScreen->bufmgr); |
if (IS_GEN7(intelScreen->deviceID)) { |
intelScreen->gen = 7; |
} else if (IS_GEN6(intelScreen->deviceID)) { |
intelScreen->gen = 6; |
} else if (IS_GEN5(intelScreen->deviceID)) { |
intelScreen->gen = 5; |
} else { |
intelScreen->gen = 4; |
} |
intelScreen->hw_has_separate_stencil = intelScreen->gen >= 6; |
intelScreen->hw_must_use_separate_stencil = intelScreen->gen >= 7; |
int has_llc = 0; |
bool success = intel_get_param(intelScreen->driScrnPriv, I915_PARAM_HAS_LLC, |
&has_llc); |
if (success && has_llc) |
intelScreen->hw_has_llc = true; |
else if (!success && intelScreen->gen >= 6) |
intelScreen->hw_has_llc = true; |
intel_override_separate_stencil(intelScreen); |
intelScreen->hw_has_swizzling = intel_detect_swizzling(intelScreen); |
set_max_gl_versions(intelScreen); |
psp->api_mask = (1 << __DRI_API_OPENGL); |
if (intelScreen->max_gl_core_version > 0) |
psp->api_mask |= (1 << __DRI_API_OPENGL_CORE); |
if (intelScreen->max_gl_es1_version > 0) |
psp->api_mask |= (1 << __DRI_API_GLES); |
if (intelScreen->max_gl_es2_version > 0) |
psp->api_mask |= (1 << __DRI_API_GLES2); |
if (intelScreen->max_gl_es2_version >= 30) |
psp->api_mask |= (1 << __DRI_API_GLES3); |
psp->extensions = intelScreenExtensions; |
return (const __DRIconfig**) intel_screen_make_configs(psp); |
} |
struct intel_buffer { |
__DRIbuffer base; |
struct intel_region *region; |
}; |
static __DRIbuffer * |
intelAllocateBuffer(__DRIscreen *screen, |
unsigned attachment, unsigned format, |
int width, int height) |
{ |
struct intel_buffer *intelBuffer; |
struct intel_screen *intelScreen = screen->driverPrivate; |
assert(attachment == __DRI_BUFFER_FRONT_LEFT || |
attachment == __DRI_BUFFER_BACK_LEFT); |
intelBuffer = calloc(1, sizeof *intelBuffer); |
if (intelBuffer == NULL) |
return NULL; |
/* The front and back buffers are color buffers, which are X tiled. */ |
intelBuffer->region = intel_region_alloc(intelScreen, |
I915_TILING_X, |
format / 8, |
width, |
height, |
true); |
if (intelBuffer->region == NULL) { |
free(intelBuffer); |
return NULL; |
} |
intel_region_flink(intelBuffer->region, &intelBuffer->base.name); |
intelBuffer->base.attachment = attachment; |
intelBuffer->base.cpp = intelBuffer->region->cpp; |
intelBuffer->base.pitch = intelBuffer->region->pitch; |
return &intelBuffer->base; |
} |
static void |
intelReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) |
{ |
struct intel_buffer *intelBuffer = (struct intel_buffer *) buffer; |
intel_region_release(&intelBuffer->region); |
free(intelBuffer); |
} |
const struct __DriverAPIRec driDriverAPI = { |
.InitScreen = intelInitScreen2, |
.DestroyScreen = intelDestroyScreen, |
.CreateContext = intelCreateContext, |
.DestroyContext = intelDestroyContext, |
.CreateBuffer = intelCreateBuffer, |
.DestroyBuffer = intelDestroyBuffer, |
.MakeCurrent = intelMakeCurrent, |
.UnbindContext = intelUnbindContext, |
.AllocateBuffer = intelAllocateBuffer, |
.ReleaseBuffer = intelReleaseBuffer |
}; |
/* This is the table of extensions that the loader will dlsym() for. */ |
__declspec(dllexport) const __DRIextension *__driDriverExtensions[] = { |
&driCoreExtension.base, |
&driDRI2Extension.base, |
NULL |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_screen.h |
---|
0,0 → 1,88 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef _INTEL_INIT_H_ |
#define _INTEL_INIT_H_ |
#include <stdbool.h> |
#include <sys/time.h> |
#include "dri_util.h" |
#include "intel_bufmgr.h" |
#include "i915_drm.h" |
#include "xmlconfig.h" |
struct intel_screen |
{ |
int deviceID; |
int gen; |
int max_gl_core_version; |
int max_gl_compat_version; |
int max_gl_es1_version; |
int max_gl_es2_version; |
__DRIscreen *driScrnPriv; |
bool no_hw; |
/* |
* The hardware hiz and separate stencil fields are needed in intel_screen, |
* rather than solely in brw_context, because glXCreatePbuffer and |
* glXCreatePixmap are not passed a GLXContext. |
*/ |
bool hw_has_separate_stencil; |
bool hw_must_use_separate_stencil; |
bool hw_has_llc; |
bool hw_has_swizzling; |
dri_bufmgr *bufmgr; |
/** |
* A unique ID for shader programs. |
*/ |
unsigned program_id; |
/** |
* Configuration cache with default values for all contexts |
*/ |
driOptionCache optionCache; |
}; |
extern void intelDestroyContext(__DRIcontext * driContextPriv); |
extern GLboolean intelUnbindContext(__DRIcontext * driContextPriv); |
extern GLboolean |
intelMakeCurrent(__DRIcontext * driContextPriv, |
__DRIdrawable * driDrawPriv, |
__DRIdrawable * driReadPriv); |
double get_time(void); |
void aub_dump_bmp(struct gl_context *ctx); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_state.c |
---|
0,0 → 1,156 |
/************************************************************************** |
* |
* 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 "main/glheader.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "main/colormac.h" |
#include "main/dd.h" |
#include "intel_screen.h" |
#include "brw_context.h" |
#include "brw_defines.h" |
int |
intel_translate_shadow_compare_func(GLenum func) |
{ |
switch (func) { |
case GL_NEVER: |
return BRW_COMPAREFUNCTION_ALWAYS; |
case GL_LESS: |
return BRW_COMPAREFUNCTION_LEQUAL; |
case GL_LEQUAL: |
return BRW_COMPAREFUNCTION_LESS; |
case GL_GREATER: |
return BRW_COMPAREFUNCTION_GEQUAL; |
case GL_GEQUAL: |
return BRW_COMPAREFUNCTION_GREATER; |
case GL_NOTEQUAL: |
return BRW_COMPAREFUNCTION_EQUAL; |
case GL_EQUAL: |
return BRW_COMPAREFUNCTION_NOTEQUAL; |
case GL_ALWAYS: |
return BRW_COMPAREFUNCTION_NEVER; |
} |
assert(!"Invalid shadow comparison function."); |
return BRW_COMPAREFUNCTION_NEVER; |
} |
int |
intel_translate_compare_func(GLenum func) |
{ |
switch (func) { |
case GL_NEVER: |
return BRW_COMPAREFUNCTION_NEVER; |
case GL_LESS: |
return BRW_COMPAREFUNCTION_LESS; |
case GL_LEQUAL: |
return BRW_COMPAREFUNCTION_LEQUAL; |
case GL_GREATER: |
return BRW_COMPAREFUNCTION_GREATER; |
case GL_GEQUAL: |
return BRW_COMPAREFUNCTION_GEQUAL; |
case GL_NOTEQUAL: |
return BRW_COMPAREFUNCTION_NOTEQUAL; |
case GL_EQUAL: |
return BRW_COMPAREFUNCTION_EQUAL; |
case GL_ALWAYS: |
return BRW_COMPAREFUNCTION_ALWAYS; |
} |
assert(!"Invalid comparison function."); |
return BRW_COMPAREFUNCTION_ALWAYS; |
} |
int |
intel_translate_stencil_op(GLenum op) |
{ |
switch (op) { |
case GL_KEEP: |
return BRW_STENCILOP_KEEP; |
case GL_ZERO: |
return BRW_STENCILOP_ZERO; |
case GL_REPLACE: |
return BRW_STENCILOP_REPLACE; |
case GL_INCR: |
return BRW_STENCILOP_INCRSAT; |
case GL_DECR: |
return BRW_STENCILOP_DECRSAT; |
case GL_INCR_WRAP: |
return BRW_STENCILOP_INCR; |
case GL_DECR_WRAP: |
return BRW_STENCILOP_DECR; |
case GL_INVERT: |
return BRW_STENCILOP_INVERT; |
default: |
return BRW_STENCILOP_ZERO; |
} |
} |
int |
intel_translate_logic_op(GLenum opcode) |
{ |
switch (opcode) { |
case GL_CLEAR: |
return BRW_LOGICOPFUNCTION_CLEAR; |
case GL_AND: |
return BRW_LOGICOPFUNCTION_AND; |
case GL_AND_REVERSE: |
return BRW_LOGICOPFUNCTION_AND_REVERSE; |
case GL_COPY: |
return BRW_LOGICOPFUNCTION_COPY; |
case GL_COPY_INVERTED: |
return BRW_LOGICOPFUNCTION_COPY_INVERTED; |
case GL_AND_INVERTED: |
return BRW_LOGICOPFUNCTION_AND_INVERTED; |
case GL_NOOP: |
return BRW_LOGICOPFUNCTION_NOOP; |
case GL_XOR: |
return BRW_LOGICOPFUNCTION_XOR; |
case GL_OR: |
return BRW_LOGICOPFUNCTION_OR; |
case GL_OR_INVERTED: |
return BRW_LOGICOPFUNCTION_OR_INVERTED; |
case GL_NOR: |
return BRW_LOGICOPFUNCTION_NOR; |
case GL_EQUIV: |
return BRW_LOGICOPFUNCTION_EQUIV; |
case GL_INVERT: |
return BRW_LOGICOPFUNCTION_INVERT; |
case GL_OR_REVERSE: |
return BRW_LOGICOPFUNCTION_OR_REVERSE; |
case GL_NAND: |
return BRW_LOGICOPFUNCTION_NAND; |
case GL_SET: |
return BRW_LOGICOPFUNCTION_SET; |
default: |
return BRW_LOGICOPFUNCTION_SET; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_syncobj.c |
---|
0,0 → 1,124 |
/* |
* Copyright © 2008 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. |
* |
* Authors: |
* Eric Anholt <eric@anholt.net> |
* |
*/ |
/** @file intel_syncobj.c |
* |
* Support for ARB_sync |
* |
* ARB_sync is implemented by flushing the current batchbuffer and keeping a |
* reference on it. We can then check for completion or wait for completion |
* using the normal buffer object mechanisms. This does mean that if an |
* application is using many sync objects, it will emit small batchbuffers |
* which may end up being a significant overhead. In other tests of removing |
* gratuitous batchbuffer syncs in Mesa, it hasn't appeared to be a significant |
* performance bottleneck, though. |
*/ |
#include "main/simple_list.h" |
#include "main/imports.h" |
#include "brw_context.h" |
#include "intel_batchbuffer.h" |
#include "intel_reg.h" |
static struct gl_sync_object * |
intel_new_sync_object(struct gl_context *ctx, GLuint id) |
{ |
struct intel_sync_object *sync; |
sync = calloc(1, sizeof(struct intel_sync_object)); |
return &sync->Base; |
} |
static void |
intel_delete_sync_object(struct gl_context *ctx, struct gl_sync_object *s) |
{ |
struct intel_sync_object *sync = (struct intel_sync_object *)s; |
drm_intel_bo_unreference(sync->bo); |
free(sync); |
} |
static void |
intel_fence_sync(struct gl_context *ctx, struct gl_sync_object *s, |
GLenum condition, GLbitfield flags) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_sync_object *sync = (struct intel_sync_object *)s; |
assert(condition == GL_SYNC_GPU_COMMANDS_COMPLETE); |
intel_batchbuffer_emit_mi_flush(brw); |
sync->bo = brw->batch.bo; |
drm_intel_bo_reference(sync->bo); |
intel_flush(ctx); |
} |
static void intel_client_wait_sync(struct gl_context *ctx, struct gl_sync_object *s, |
GLbitfield flags, GLuint64 timeout) |
{ |
struct intel_sync_object *sync = (struct intel_sync_object *)s; |
if (sync->bo && drm_intel_gem_bo_wait(sync->bo, timeout) == 0) { |
s->StatusFlag = 1; |
drm_intel_bo_unreference(sync->bo); |
sync->bo = NULL; |
} |
} |
/* We have nothing to do for WaitSync. Our GL command stream is sequential, |
* so given that the sync object has already flushed the batchbuffer, |
* any batchbuffers coming after this waitsync will naturally not occur until |
* the previous one is done. |
*/ |
static void intel_server_wait_sync(struct gl_context *ctx, struct gl_sync_object *s, |
GLbitfield flags, GLuint64 timeout) |
{ |
} |
static void intel_check_sync(struct gl_context *ctx, struct gl_sync_object *s) |
{ |
struct intel_sync_object *sync = (struct intel_sync_object *)s; |
if (sync->bo && !drm_intel_bo_busy(sync->bo)) { |
drm_intel_bo_unreference(sync->bo); |
sync->bo = NULL; |
s->StatusFlag = 1; |
} |
} |
void intel_init_syncobj_functions(struct dd_function_table *functions) |
{ |
functions->NewSyncObject = intel_new_sync_object; |
functions->DeleteSyncObject = intel_delete_sync_object; |
functions->FenceSync = intel_fence_sync; |
functions->CheckSync = intel_check_sync; |
functions->ClientWaitSync = intel_client_wait_sync; |
functions->ServerWaitSync = intel_server_wait_sync; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_tex.c |
---|
0,0 → 1,189 |
#include "swrast/swrast.h" |
#include "main/renderbuffer.h" |
#include "main/texobj.h" |
#include "main/teximage.h" |
#include "main/mipmap.h" |
#include "drivers/common/meta.h" |
#include "brw_context.h" |
#include "intel_mipmap_tree.h" |
#include "intel_tex.h" |
#include "intel_fbo.h" |
#define FILE_DEBUG_FLAG DEBUG_TEXTURE |
static struct gl_texture_image * |
intelNewTextureImage(struct gl_context * ctx) |
{ |
DBG("%s\n", __FUNCTION__); |
(void) ctx; |
return (struct gl_texture_image *) CALLOC_STRUCT(intel_texture_image); |
} |
static void |
intelDeleteTextureImage(struct gl_context * ctx, struct gl_texture_image *img) |
{ |
/* nothing special (yet) for intel_texture_image */ |
_mesa_delete_texture_image(ctx, img); |
} |
static struct gl_texture_object * |
intelNewTextureObject(struct gl_context * ctx, GLuint name, GLenum target) |
{ |
struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object); |
(void) ctx; |
DBG("%s\n", __FUNCTION__); |
if (obj == NULL) |
return NULL; |
_mesa_initialize_texture_object(ctx, &obj->base, name, target); |
obj->needs_validate = true; |
return &obj->base; |
} |
static void |
intelDeleteTextureObject(struct gl_context *ctx, |
struct gl_texture_object *texObj) |
{ |
struct intel_texture_object *intelObj = intel_texture_object(texObj); |
intel_miptree_release(&intelObj->mt); |
_mesa_delete_texture_object(ctx, texObj); |
} |
static GLboolean |
intel_alloc_texture_image_buffer(struct gl_context *ctx, |
struct gl_texture_image *image) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_texture_image *intel_image = intel_texture_image(image); |
struct gl_texture_object *texobj = image->TexObject; |
struct intel_texture_object *intel_texobj = intel_texture_object(texobj); |
assert(image->Border == 0); |
/* Quantize sample count */ |
if (image->NumSamples) { |
image->NumSamples = intel_quantize_num_samples(brw->intelScreen, image->NumSamples); |
if (!image->NumSamples) |
return false; |
} |
/* Because the driver uses AllocTextureImageBuffer() internally, it may end |
* up mismatched with FreeTextureImageBuffer(), but that is safe to call |
* multiple times. |
*/ |
ctx->Driver.FreeTextureImageBuffer(ctx, image); |
if (!_swrast_init_texture_image(image)) |
return false; |
if (intel_texobj->mt && |
intel_miptree_match_image(intel_texobj->mt, image)) { |
intel_miptree_reference(&intel_image->mt, intel_texobj->mt); |
DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n", |
__FUNCTION__, texobj, image->Level, |
image->Width, image->Height, image->Depth, intel_texobj->mt); |
} else { |
intel_image->mt = intel_miptree_create_for_teximage(brw, intel_texobj, |
intel_image, |
false); |
/* Even if the object currently has a mipmap tree associated |
* with it, this one is a more likely candidate to represent the |
* whole object since our level didn't fit what was there |
* before, and any lower levels would fit into our miptree. |
*/ |
intel_miptree_reference(&intel_texobj->mt, intel_image->mt); |
DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n", |
__FUNCTION__, texobj, image->Level, |
image->Width, image->Height, image->Depth, intel_image->mt); |
} |
intel_texobj->needs_validate = true; |
return true; |
} |
static void |
intel_free_texture_image_buffer(struct gl_context * ctx, |
struct gl_texture_image *texImage) |
{ |
struct intel_texture_image *intelImage = intel_texture_image(texImage); |
DBG("%s\n", __FUNCTION__); |
intel_miptree_release(&intelImage->mt); |
_swrast_free_texture_image_buffer(ctx, texImage); |
} |
/** |
* Map texture memory/buffer into user space. |
* Note: the region of interest parameters are ignored here. |
* \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT |
* \param mapOut returns start of mapping of region of interest |
* \param rowStrideOut returns row stride in bytes |
*/ |
static void |
intel_map_texture_image(struct gl_context *ctx, |
struct gl_texture_image *tex_image, |
GLuint slice, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **map, |
GLint *stride) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_texture_image *intel_image = intel_texture_image(tex_image); |
struct intel_mipmap_tree *mt = intel_image->mt; |
/* Our texture data is always stored in a miptree. */ |
assert(mt); |
/* Check that our caller wasn't confused about how to map a 1D texture. */ |
assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY || |
h == 1); |
/* intel_miptree_map operates on a unified "slice" number that references the |
* cube face, since it's all just slices to the miptree code. |
*/ |
if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP) |
slice = tex_image->Face; |
intel_miptree_map(brw, mt, tex_image->Level, slice, x, y, w, h, mode, |
(void **)map, stride); |
} |
static void |
intel_unmap_texture_image(struct gl_context *ctx, |
struct gl_texture_image *tex_image, GLuint slice) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_texture_image *intel_image = intel_texture_image(tex_image); |
struct intel_mipmap_tree *mt = intel_image->mt; |
if (tex_image->TexObject->Target == GL_TEXTURE_CUBE_MAP) |
slice = tex_image->Face; |
intel_miptree_unmap(brw, mt, tex_image->Level, slice); |
} |
void |
intelInitTextureFuncs(struct dd_function_table *functions) |
{ |
functions->NewTextureObject = intelNewTextureObject; |
functions->NewTextureImage = intelNewTextureImage; |
functions->DeleteTextureImage = intelDeleteTextureImage; |
functions->DeleteTexture = intelDeleteTextureObject; |
functions->AllocTextureImageBuffer = intel_alloc_texture_image_buffer; |
functions->FreeTextureImageBuffer = intel_free_texture_image_buffer; |
functions->MapTextureImage = intel_map_texture_image; |
functions->UnmapTextureImage = intel_unmap_texture_image; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_tex.h |
---|
0,0 → 1,69 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef INTELTEX_INC |
#define INTELTEX_INC |
#include "main/mtypes.h" |
#include "main/formats.h" |
#include "brw_context.h" |
struct intel_renderbuffer; |
void intelInitTextureFuncs(struct dd_function_table *functions); |
void intelInitTextureImageFuncs(struct dd_function_table *functions); |
void intelInitTextureSubImageFuncs(struct dd_function_table *functions); |
void intelInitTextureCopyImageFuncs(struct dd_function_table *functions); |
void intelSetTexBuffer(__DRIcontext *pDRICtx, |
GLint target, __DRIdrawable *pDraw); |
void intelSetTexBuffer2(__DRIcontext *pDRICtx, |
GLint target, GLint format, __DRIdrawable *pDraw); |
struct intel_mipmap_tree * |
intel_miptree_create_for_teximage(struct brw_context *brw, |
struct intel_texture_object *intelObj, |
struct intel_texture_image *intelImage, |
bool expect_accelerated_upload); |
GLuint intel_finalize_mipmap_tree(struct brw_context *brw, GLuint unit); |
bool |
intel_texsubimage_tiled_memcpy(struct gl_context *ctx, |
GLuint dims, |
struct gl_texture_image *texImage, |
GLint xoffset, GLint yoffset, GLint zoffset, |
GLsizei width, GLsizei height, GLsizei depth, |
GLenum format, GLenum type, |
const GLvoid *pixels, |
const struct gl_pixelstore_attrib *packing, |
bool for_glTexImage); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_tex_copy.c |
---|
0,0 → 1,127 |
/************************************************************************** |
* |
* 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 "main/mtypes.h" |
#include "main/enums.h" |
#include "main/image.h" |
#include "main/teximage.h" |
#include "main/texstate.h" |
#include "main/fbobject.h" |
#include "drivers/common/meta.h" |
#include "intel_screen.h" |
#include "intel_mipmap_tree.h" |
#include "intel_regions.h" |
#include "intel_fbo.h" |
#include "intel_tex.h" |
#include "intel_blit.h" |
#include "brw_context.h" |
#define FILE_DEBUG_FLAG DEBUG_TEXTURE |
static bool |
intel_copy_texsubimage(struct brw_context *brw, |
struct intel_texture_image *intelImage, |
GLint dstx, GLint dsty, GLint slice, |
struct intel_renderbuffer *irb, |
GLint x, GLint y, GLsizei width, GLsizei height) |
{ |
const GLenum internalFormat = intelImage->base.Base.InternalFormat; |
intel_prepare_render(brw); |
/* glCopyTexSubImage() can be called on a multisampled renderbuffer (if |
* that renderbuffer is associated with the window system framebuffer), |
* however the hardware blitter can't handle this case, so fall back to |
* meta (which can, since it uses ReadPixels). |
*/ |
if (irb->Base.Base.NumSamples != 0) |
return false; |
/* glCopyTexSubImage() can't be called on a multisampled texture. */ |
assert(intelImage->base.Base.NumSamples == 0); |
if (!intelImage->mt || !irb || !irb->mt) { |
if (unlikely(INTEL_DEBUG & DEBUG_PERF)) |
fprintf(stderr, "%s fail %p %p (0x%08x)\n", |
__FUNCTION__, intelImage->mt, irb, internalFormat); |
return false; |
} |
/* blit from src buffer to texture */ |
if (!intel_miptree_blit(brw, |
irb->mt, irb->mt_level, irb->mt_layer, |
x, y, irb->Base.Base.Name == 0, |
intelImage->mt, intelImage->base.Base.Level, |
intelImage->base.Base.Face + slice, |
dstx, dsty, false, |
width, height, GL_COPY)) { |
return false; |
} |
return true; |
} |
static void |
intelCopyTexSubImage(struct gl_context *ctx, GLuint dims, |
struct gl_texture_image *texImage, |
GLint xoffset, GLint yoffset, GLint slice, |
struct gl_renderbuffer *rb, |
GLint x, GLint y, |
GLsizei width, GLsizei height) |
{ |
struct brw_context *brw = brw_context(ctx); |
/* Try BLORP first. It can handle almost everything. */ |
if (brw_blorp_copytexsubimage(brw, rb, texImage, slice, x, y, |
xoffset, yoffset, width, height)) |
return; |
/* Next, try the BLT engine. */ |
if (intel_copy_texsubimage(brw, |
intel_texture_image(texImage), |
xoffset, yoffset, slice, |
intel_renderbuffer(rb), x, y, width, height)) { |
return; |
} |
/* Finally, fall back to meta. This will likely be slow. */ |
perf_debug("%s - fallback to swrast\n", __FUNCTION__); |
_mesa_meta_CopyTexSubImage(ctx, dims, texImage, |
xoffset, yoffset, slice, |
rb, x, y, width, height); |
} |
void |
intelInitTextureCopyImageFuncs(struct dd_function_table *functions) |
{ |
functions->CopyTexSubImage = intelCopyTexSubImage; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_tex_image.c |
---|
0,0 → 1,392 |
#include "main/glheader.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/enums.h" |
#include "main/bufferobj.h" |
#include "main/context.h" |
#include "main/formats.h" |
#include "main/image.h" |
#include "main/pbo.h" |
#include "main/renderbuffer.h" |
#include "main/texcompress.h" |
#include "main/texgetimage.h" |
#include "main/texobj.h" |
#include "main/teximage.h" |
#include "main/texstore.h" |
#include "intel_mipmap_tree.h" |
#include "intel_buffer_objects.h" |
#include "intel_batchbuffer.h" |
#include "intel_tex.h" |
#include "intel_blit.h" |
#include "intel_fbo.h" |
#include "brw_context.h" |
#define FILE_DEBUG_FLAG DEBUG_TEXTURE |
/* Work back from the specified level of the image to the baselevel and create a |
* miptree of that size. |
*/ |
struct intel_mipmap_tree * |
intel_miptree_create_for_teximage(struct brw_context *brw, |
struct intel_texture_object *intelObj, |
struct intel_texture_image *intelImage, |
bool expect_accelerated_upload) |
{ |
GLuint firstLevel; |
GLuint lastLevel; |
int width, height, depth; |
GLuint i; |
intel_miptree_get_dimensions_for_image(&intelImage->base.Base, |
&width, &height, &depth); |
DBG("%s\n", __FUNCTION__); |
if (intelImage->base.Base.Level > intelObj->base.BaseLevel && |
(width == 1 || |
(intelObj->base.Target != GL_TEXTURE_1D && height == 1) || |
(intelObj->base.Target == GL_TEXTURE_3D && depth == 1))) { |
/* For this combination, we're at some lower mipmap level and |
* some important dimension is 1. We can't extrapolate up to a |
* likely base level width/height/depth for a full mipmap stack |
* from this info, so just allocate this one level. |
*/ |
firstLevel = intelImage->base.Base.Level; |
lastLevel = intelImage->base.Base.Level; |
} else { |
/* If this image disrespects BaseLevel, allocate from level zero. |
* Usually BaseLevel == 0, so it's unlikely to happen. |
*/ |
if (intelImage->base.Base.Level < intelObj->base.BaseLevel) |
firstLevel = 0; |
else |
firstLevel = intelObj->base.BaseLevel; |
/* Figure out image dimensions at start level. */ |
for (i = intelImage->base.Base.Level; i > firstLevel; i--) { |
width <<= 1; |
if (height != 1) |
height <<= 1; |
if (depth != 1) |
depth <<= 1; |
} |
/* Guess a reasonable value for lastLevel. This is probably going |
* to be wrong fairly often and might mean that we have to look at |
* resizable buffers, or require that buffers implement lazy |
* pagetable arrangements. |
*/ |
if ((intelObj->base.Sampler.MinFilter == GL_NEAREST || |
intelObj->base.Sampler.MinFilter == GL_LINEAR) && |
intelImage->base.Base.Level == firstLevel && |
firstLevel == 0) { |
lastLevel = firstLevel; |
} else { |
lastLevel = (firstLevel + |
_mesa_get_tex_max_num_levels(intelObj->base.Target, |
width, height, depth) - 1); |
} |
} |
return intel_miptree_create(brw, |
intelObj->base.Target, |
intelImage->base.Base.TexFormat, |
firstLevel, |
lastLevel, |
width, |
height, |
depth, |
expect_accelerated_upload, |
intelImage->base.Base.NumSamples, |
INTEL_MIPTREE_TILING_ANY); |
} |
/* XXX: Do this for TexSubImage also: |
*/ |
static bool |
try_pbo_upload(struct gl_context *ctx, |
struct gl_texture_image *image, |
const struct gl_pixelstore_attrib *unpack, |
GLenum format, GLenum type, const void *pixels) |
{ |
struct intel_texture_image *intelImage = intel_texture_image(image); |
struct brw_context *brw = brw_context(ctx); |
struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj); |
GLuint src_offset; |
drm_intel_bo *src_buffer; |
if (!_mesa_is_bufferobj(unpack->BufferObj)) |
return false; |
DBG("trying pbo upload\n"); |
if (ctx->_ImageTransferState || unpack->SkipPixels || unpack->SkipRows) { |
DBG("%s: image transfer\n", __FUNCTION__); |
return false; |
} |
ctx->Driver.AllocTextureImageBuffer(ctx, image); |
if (!intelImage->mt) { |
DBG("%s: no miptree\n", __FUNCTION__); |
return false; |
} |
if (!_mesa_format_matches_format_and_type(intelImage->mt->format, |
format, type, false)) { |
DBG("%s: format mismatch (upload to %s with format 0x%x, type 0x%x)\n", |
__FUNCTION__, _mesa_get_format_name(intelImage->mt->format), |
format, type); |
return false; |
} |
if (image->TexObject->Target == GL_TEXTURE_1D_ARRAY || |
image->TexObject->Target == GL_TEXTURE_2D_ARRAY) { |
DBG("%s: no support for array textures\n", __FUNCTION__); |
return false; |
} |
src_buffer = intel_bufferobj_source(brw, pbo, 64, &src_offset); |
/* note: potential 64-bit ptr to 32-bit int cast */ |
src_offset += (GLuint) (unsigned long) pixels; |
int src_stride = |
_mesa_image_row_stride(unpack, image->Width, format, type); |
struct intel_mipmap_tree *pbo_mt = |
intel_miptree_create_for_bo(brw, |
src_buffer, |
intelImage->mt->format, |
src_offset, |
image->Width, image->Height, |
src_stride, I915_TILING_NONE); |
if (!pbo_mt) |
return false; |
if (!intel_miptree_blit(brw, |
pbo_mt, 0, 0, |
0, 0, false, |
intelImage->mt, image->Level, image->Face, |
0, 0, false, |
image->Width, image->Height, GL_COPY)) { |
DBG("%s: blit failed\n", __FUNCTION__); |
intel_miptree_release(&pbo_mt); |
return false; |
} |
intel_miptree_release(&pbo_mt); |
DBG("%s: success\n", __FUNCTION__); |
return true; |
} |
static void |
intelTexImage(struct gl_context * ctx, |
GLuint dims, |
struct gl_texture_image *texImage, |
GLenum format, GLenum type, const void *pixels, |
const struct gl_pixelstore_attrib *unpack) |
{ |
bool ok; |
DBG("%s target %s level %d %dx%dx%d\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr(texImage->TexObject->Target), |
texImage->Level, texImage->Width, texImage->Height, texImage->Depth); |
ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage, |
0, 0, 0, /*x,y,z offsets*/ |
texImage->Width, |
texImage->Height, |
texImage->Depth, |
format, type, pixels, unpack, |
true /*for_glTexImage*/); |
if (ok) |
return; |
/* Attempt to use the blitter for PBO image uploads. |
*/ |
if (dims <= 2 && |
try_pbo_upload(ctx, texImage, unpack, format, type, pixels)) { |
return; |
} |
DBG("%s: upload image %dx%dx%d pixels %p\n", |
__FUNCTION__, texImage->Width, texImage->Height, texImage->Depth, |
pixels); |
_mesa_store_teximage(ctx, dims, texImage, |
format, type, pixels, unpack); |
} |
/** |
* Binds a region to a texture image, like it was uploaded by glTexImage2D(). |
* |
* Used for GLX_EXT_texture_from_pixmap and EGL image extensions, |
*/ |
static void |
intel_set_texture_image_region(struct gl_context *ctx, |
struct gl_texture_image *image, |
struct intel_region *region, |
GLenum target, |
GLenum internalFormat, |
gl_format format, |
uint32_t offset, |
GLuint width, |
GLuint height, |
GLuint tile_x, |
GLuint tile_y) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_texture_image *intel_image = intel_texture_image(image); |
struct gl_texture_object *texobj = image->TexObject; |
struct intel_texture_object *intel_texobj = intel_texture_object(texobj); |
uint32_t draw_x, draw_y; |
_mesa_init_teximage_fields(&brw->ctx, image, |
width, height, 1, |
0, internalFormat, format); |
ctx->Driver.FreeTextureImageBuffer(ctx, image); |
intel_image->mt = intel_miptree_create_layout(brw, target, image->TexFormat, |
0, 0, |
width, height, 1, |
true, 0 /* num_samples */); |
if (intel_image->mt == NULL) |
return; |
intel_region_reference(&intel_image->mt->region, region); |
intel_image->mt->total_width = width; |
intel_image->mt->total_height = height; |
intel_image->mt->level[0].slice[0].x_offset = tile_x; |
intel_image->mt->level[0].slice[0].y_offset = tile_y; |
intel_miptree_get_tile_offsets(intel_image->mt, 0, 0, &draw_x, &draw_y); |
/* From "OES_EGL_image" error reporting. We report GL_INVALID_OPERATION |
* for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has |
* trouble resolving back to destination image due to alignment issues. |
*/ |
if (!brw->has_surface_tile_offset && |
(draw_x != 0 || draw_y != 0)) { |
_mesa_error(ctx, GL_INVALID_OPERATION, __func__); |
intel_miptree_release(&intel_image->mt); |
return; |
} |
intel_texobj->needs_validate = true; |
intel_image->mt->offset = offset; |
assert(region->pitch % region->cpp == 0); |
intel_image->base.RowStride = region->pitch / region->cpp; |
/* Immediately validate the image to the object. */ |
intel_miptree_reference(&intel_texobj->mt, intel_image->mt); |
} |
void |
intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, |
GLint texture_format, |
__DRIdrawable *dPriv) |
{ |
struct gl_framebuffer *fb = dPriv->driverPrivate; |
struct brw_context *brw = pDRICtx->driverPrivate; |
struct gl_context *ctx = &brw->ctx; |
struct intel_texture_object *intelObj; |
struct intel_renderbuffer *rb; |
struct gl_texture_object *texObj; |
struct gl_texture_image *texImage; |
int level = 0, internalFormat = 0; |
gl_format texFormat = MESA_FORMAT_NONE; |
texObj = _mesa_get_current_tex_object(ctx, target); |
intelObj = intel_texture_object(texObj); |
if (!intelObj) |
return; |
if (dPriv->lastStamp != dPriv->dri2.stamp || |
!pDRICtx->driScreenPriv->dri2.useInvalidate) |
intel_update_renderbuffers(pDRICtx, dPriv); |
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); |
/* If the region isn't set, then intel_update_renderbuffers was unable |
* to get the buffers for the drawable. |
*/ |
if (!rb || !rb->mt) |
return; |
if (rb->mt->cpp == 4) { |
if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { |
internalFormat = GL_RGB; |
texFormat = MESA_FORMAT_XRGB8888; |
} |
else { |
internalFormat = GL_RGBA; |
texFormat = MESA_FORMAT_ARGB8888; |
} |
} else if (rb->mt->cpp == 2) { |
internalFormat = GL_RGB; |
texFormat = MESA_FORMAT_RGB565; |
} |
_mesa_lock_texture(&brw->ctx, texObj); |
texImage = _mesa_get_tex_image(ctx, texObj, target, level); |
intel_miptree_make_shareable(brw, rb->mt); |
intel_set_texture_image_region(ctx, texImage, rb->mt->region, target, |
internalFormat, texFormat, 0, |
rb->mt->region->width, |
rb->mt->region->height, |
0, 0); |
_mesa_unlock_texture(&brw->ctx, texObj); |
} |
void |
intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv) |
{ |
/* The old interface didn't have the format argument, so copy our |
* implementation's behavior at the time. |
*/ |
intelSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); |
} |
static void |
intel_image_target_texture_2d(struct gl_context *ctx, GLenum target, |
struct gl_texture_object *texObj, |
struct gl_texture_image *texImage, |
GLeglImageOES image_handle) |
{ |
struct brw_context *brw = brw_context(ctx); |
__DRIscreen *screen; |
__DRIimage *image; |
screen = brw->intelScreen->driScrnPriv; |
image = screen->dri2.image->lookupEGLImage(screen, image_handle, |
screen->loaderPrivate); |
if (image == NULL) |
return; |
/* Disallow depth/stencil textures: we don't have a way to pass the |
* separate stencil miptree of a GL_DEPTH_STENCIL texture through. |
*/ |
if (image->has_depthstencil) { |
_mesa_error(ctx, GL_INVALID_OPERATION, __func__); |
return; |
} |
intel_set_texture_image_region(ctx, texImage, image->region, |
target, image->internal_format, |
image->format, image->offset, |
image->width, image->height, |
image->tile_x, image->tile_y); |
} |
void |
intelInitTextureImageFuncs(struct dd_function_table *functions) |
{ |
functions->TexImage = intelTexImage; |
functions->EGLImageTargetTexture2D = intel_image_target_texture_2d; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_tex_obj.h |
---|
0,0 → 1,84 |
/************************************************************************** |
* |
* 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. |
* |
**************************************************************************/ |
#ifndef _INTEL_TEX_OBJ_H |
#define _INTEL_TEX_OBJ_H |
#include "swrast/s_context.h" |
struct intel_texture_object |
{ |
struct gl_texture_object base; |
/* This is a mirror of base._MaxLevel, updated at validate time, |
* except that we don't bother with the non-base levels for |
* non-mipmapped textures. |
*/ |
unsigned int _MaxLevel; |
/* On validation any active images held in main memory or in other |
* regions will be copied to this region and the old storage freed. |
*/ |
struct intel_mipmap_tree *mt; |
/** |
* Set when mipmap trees in the texture images of this texture object |
* might not all be the mipmap tree above. |
*/ |
bool needs_validate; |
}; |
/** |
* intel_texture_image is a subclass of swrast_texture_image because we |
* sometimes fall back to using the swrast module for software rendering. |
*/ |
struct intel_texture_image |
{ |
struct swrast_texture_image base; |
/* If intelImage->mt != NULL, image data is stored here. |
* Else if intelImage->base.Buffer != NULL, image is stored there. |
* Else there is no image data. |
*/ |
struct intel_mipmap_tree *mt; |
}; |
static INLINE struct intel_texture_object * |
intel_texture_object(struct gl_texture_object *obj) |
{ |
return (struct intel_texture_object *) obj; |
} |
static INLINE struct intel_texture_image * |
intel_texture_image(struct gl_texture_image *img) |
{ |
return (struct intel_texture_image *) img; |
} |
#endif /* _INTEL_TEX_OBJ_H */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_tex_subimage.c |
---|
0,0 → 1,335 |
/************************************************************************** |
* |
* 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 "main/bufferobj.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/pbo.h" |
#include "main/texobj.h" |
#include "main/texstore.h" |
#include "main/texcompress.h" |
#include "main/enums.h" |
#include "brw_context.h" |
#include "intel_batchbuffer.h" |
#include "intel_tex.h" |
#include "intel_mipmap_tree.h" |
#include "intel_blit.h" |
#define FILE_DEBUG_FLAG DEBUG_TEXTURE |
static bool |
intel_blit_texsubimage(struct gl_context * ctx, |
struct gl_texture_image *texImage, |
GLint xoffset, GLint yoffset, |
GLint width, GLint height, |
GLenum format, GLenum type, const void *pixels, |
const struct gl_pixelstore_attrib *packing) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_texture_image *intelImage = intel_texture_image(texImage); |
/* Try to do a blit upload of the subimage if the texture is |
* currently busy. |
*/ |
if (!intelImage->mt) |
return false; |
/* The blitter can't handle Y tiling */ |
if (intelImage->mt->region->tiling == I915_TILING_Y) |
return false; |
if (texImage->TexObject->Target != GL_TEXTURE_2D) |
return false; |
/* On gen6, it's probably not worth swapping to the blit ring to do |
* this because of all the overhead involved. |
*/ |
if (brw->gen >= 6) |
return false; |
if (!drm_intel_bo_busy(intelImage->mt->region->bo)) |
return false; |
DBG("BLT subimage %s target %s level %d offset %d,%d %dx%d\n", |
__FUNCTION__, |
_mesa_lookup_enum_by_nr(texImage->TexObject->Target), |
texImage->Level, xoffset, yoffset, width, height); |
pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, |
format, type, pixels, packing, |
"glTexSubImage"); |
if (!pixels) |
return false; |
struct intel_mipmap_tree *temp_mt = |
intel_miptree_create(brw, GL_TEXTURE_2D, texImage->TexFormat, |
0, 0, |
width, height, 1, |
false, 0, INTEL_MIPTREE_TILING_NONE); |
if (!temp_mt) |
goto err; |
GLubyte *dst = intel_miptree_map_raw(brw, temp_mt); |
if (!dst) |
goto err; |
if (!_mesa_texstore(ctx, 2, texImage->_BaseFormat, |
texImage->TexFormat, |
temp_mt->region->pitch, |
&dst, |
width, height, 1, |
format, type, pixels, packing)) { |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); |
} |
intel_miptree_unmap_raw(brw, temp_mt); |
bool ret; |
ret = intel_miptree_blit(brw, |
temp_mt, 0, 0, |
0, 0, false, |
intelImage->mt, texImage->Level, texImage->Face, |
xoffset, yoffset, false, |
width, height, GL_COPY); |
assert(ret); |
intel_miptree_release(&temp_mt); |
_mesa_unmap_teximage_pbo(ctx, packing); |
return ret; |
err: |
_mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); |
intel_miptree_release(&temp_mt); |
_mesa_unmap_teximage_pbo(ctx, packing); |
return false; |
} |
/** |
* \brief A fast path for glTexImage and glTexSubImage. |
* |
* \param for_glTexImage Was this called from glTexImage or glTexSubImage? |
* |
* This fast path is taken when the hardware natively supports the texture |
* format (such as GL_BGRA) and when the texture memory is X-tiled. It uploads |
* the texture data by mapping the texture memory without a GTT fence, thus |
* acquiring a tiled view of the memory, and then memcpy'ing sucessive |
* subspans within each tile. |
* |
* This is a performance win over the conventional texture upload path because |
* it avoids the performance penalty of writing through the write-combine |
* buffer. In the conventional texture upload path, |
* texstore.c:store_texsubimage(), the texture memory is mapped through a GTT |
* fence, thus acquiring a linear view of the memory, then each row in the |
* image is memcpy'd. In this fast path, we replace each row's memcpy with |
* a sequence of memcpy's over each bit6 swizzle span in the row. |
* |
* This fast path's use case is Google Chrome's paint rectangles. Chrome (as |
* of version 21) renders each page as a tiling of 256x256 GL_BGRA textures. |
* Each page's content is initially uploaded with glTexImage2D and damaged |
* regions are updated with glTexSubImage2D. On some workloads, the |
* performance gain of this fastpath on Sandybridge is over 5x. |
*/ |
bool |
intel_texsubimage_tiled_memcpy(struct gl_context * ctx, |
GLuint dims, |
struct gl_texture_image *texImage, |
GLint xoffset, GLint yoffset, GLint zoffset, |
GLsizei width, GLsizei height, GLsizei depth, |
GLenum format, GLenum type, |
const GLvoid *pixels, |
const struct gl_pixelstore_attrib *packing, |
bool for_glTexImage) |
{ |
struct brw_context *brw = brw_context(ctx); |
struct intel_texture_image *image = intel_texture_image(texImage); |
/* The miptree's buffer. */ |
drm_intel_bo *bo; |
int error = 0; |
/* This fastpath is restricted to a specific texture type: level 0 of |
* a 2D BGRA texture. It could be generalized to support more types by |
* varying the arithmetic loop below. |
*/ |
if (!brw->has_llc || |
format != GL_BGRA || |
type != GL_UNSIGNED_BYTE || |
texImage->TexFormat != MESA_FORMAT_ARGB8888 || |
texImage->TexObject->Target != GL_TEXTURE_2D || |
texImage->Level != 0 || |
pixels == NULL || |
_mesa_is_bufferobj(packing->BufferObj) || |
packing->Alignment > 4 || |
packing->SkipPixels > 0 || |
packing->SkipRows > 0 || |
(packing->RowLength != 0 && packing->RowLength != width) || |
packing->SwapBytes || |
packing->LsbFirst || |
packing->Invert) |
return false; |
if (for_glTexImage) |
ctx->Driver.AllocTextureImageBuffer(ctx, texImage); |
if (!image->mt || |
image->mt->region->tiling != I915_TILING_X) { |
/* The algorithm below is written only for X-tiled memory. */ |
return false; |
} |
/* Since we are going to write raw data to the miptree, we need to resolve |
* any pending fast color clears before we start. |
*/ |
intel_miptree_resolve_color(brw, image->mt); |
bo = image->mt->region->bo; |
if (drm_intel_bo_references(brw->batch.bo, bo)) { |
perf_debug("Flushing before mapping a referenced bo.\n"); |
intel_batchbuffer_flush(brw); |
} |
if (unlikely(brw->perf_debug)) { |
if (drm_intel_bo_busy(bo)) { |
perf_debug("Mapping a busy BO, causing a stall on the GPU.\n"); |
} |
} |
error = drm_intel_bo_map(bo, true /*write_enable*/); |
if (error || bo->virtual == NULL) { |
DBG("%s: failed to map bo\n", __FUNCTION__); |
return false; |
} |
/* We postponed printing this message until having committed to executing |
* the function. |
*/ |
DBG("%s: level=%d offset=(%d,%d) (w,h)=(%d,%d)\n", |
__FUNCTION__, texImage->Level, xoffset, yoffset, width, height); |
/* In the tiling algorithm below, some variables are in units of pixels, |
* others are in units of bytes, and others (such as height) are unitless. |
* Each variable name is suffixed with its units. |
*/ |
const uint32_t x_max_pixels = xoffset + width; |
const uint32_t y_max_pixels = yoffset + height; |
const uint32_t tile_size_bytes = 4096; |
const uint32_t tile_width_bytes = 512; |
const uint32_t tile_width_pixels = 128; |
const uint32_t tile_height = 8; |
const uint32_t cpp = 4; /* chars per pixel of GL_BGRA */ |
const uint32_t swizzle_width_pixels = 16; |
const uint32_t stride_bytes = image->mt->region->pitch; |
const uint32_t width_tiles = stride_bytes / tile_width_bytes; |
for (uint32_t y_pixels = yoffset; y_pixels < y_max_pixels; ++y_pixels) { |
const uint32_t y_offset_bytes = (y_pixels / tile_height) * width_tiles * tile_size_bytes |
+ (y_pixels % tile_height) * tile_width_bytes; |
for (uint32_t x_pixels = xoffset; x_pixels < x_max_pixels; x_pixels += swizzle_width_pixels) { |
const uint32_t x_offset_bytes = (x_pixels / tile_width_pixels) * tile_size_bytes |
+ (x_pixels % tile_width_pixels) * cpp; |
intptr_t offset_bytes = y_offset_bytes + x_offset_bytes; |
if (brw->has_swizzling) { |
#if 0 |
/* Clear, unoptimized version. */ |
bool bit6 = (offset_bytes >> 6) & 1; |
bool bit9 = (offset_bytes >> 9) & 1; |
bool bit10 = (offset_bytes >> 10) & 1; |
if (bit9 ^ bit10) |
offset_bytes ^= (1 << 6); |
#else |
/* Optimized, obfuscated version. */ |
offset_bytes ^= ((offset_bytes >> 3) ^ (offset_bytes >> 4)) |
& (1 << 6); |
#endif |
} |
const uint32_t swizzle_bound_pixels = ALIGN(x_pixels + 1, swizzle_width_pixels); |
const uint32_t memcpy_bound_pixels = MIN2(x_max_pixels, swizzle_bound_pixels); |
const uint32_t copy_size = cpp * (memcpy_bound_pixels - x_pixels); |
memcpy(bo->virtual + offset_bytes, pixels, copy_size); |
pixels += copy_size; |
x_pixels -= (x_pixels % swizzle_width_pixels); |
} |
} |
drm_intel_bo_unmap(bo); |
return true; |
} |
static void |
intelTexSubImage(struct gl_context * ctx, |
GLuint dims, |
struct gl_texture_image *texImage, |
GLint xoffset, GLint yoffset, GLint zoffset, |
GLsizei width, GLsizei height, GLsizei depth, |
GLenum format, GLenum type, |
const GLvoid * pixels, |
const struct gl_pixelstore_attrib *packing) |
{ |
bool ok; |
ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage, |
xoffset, yoffset, zoffset, |
width, height, depth, |
format, type, pixels, packing, |
false /*for_glTexImage*/); |
if (ok) |
return; |
/* The intel_blit_texsubimage() function only handles 2D images */ |
if (dims != 2 || !intel_blit_texsubimage(ctx, texImage, |
xoffset, yoffset, |
width, height, |
format, type, pixels, packing)) { |
_mesa_store_texsubimage(ctx, dims, texImage, |
xoffset, yoffset, zoffset, |
width, height, depth, |
format, type, pixels, packing); |
} |
} |
void |
intelInitTextureSubImageFuncs(struct dd_function_table *functions) |
{ |
functions->TexSubImage = intelTexSubImage; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/intel_tex_validate.c |
---|
0,0 → 1,140 |
#include "main/mtypes.h" |
#include "main/macros.h" |
#include "main/samplerobj.h" |
#include "main/texobj.h" |
#include "brw_context.h" |
#include "intel_mipmap_tree.h" |
#include "intel_blit.h" |
#include "intel_tex.h" |
#define FILE_DEBUG_FLAG DEBUG_TEXTURE |
/** |
* When validating, we only care about the texture images that could |
* be seen, so for non-mipmapped modes we want to ignore everything |
* but BaseLevel. |
*/ |
static void |
intel_update_max_level(struct intel_texture_object *intelObj, |
struct gl_sampler_object *sampler) |
{ |
struct gl_texture_object *tObj = &intelObj->base; |
int maxlevel; |
if (sampler->MinFilter == GL_NEAREST || |
sampler->MinFilter == GL_LINEAR) { |
maxlevel = tObj->BaseLevel; |
} else { |
maxlevel = tObj->_MaxLevel; |
} |
if (intelObj->_MaxLevel != maxlevel) { |
intelObj->_MaxLevel = maxlevel; |
intelObj->needs_validate = true; |
} |
} |
/* |
*/ |
GLuint |
intel_finalize_mipmap_tree(struct brw_context *brw, GLuint unit) |
{ |
struct gl_context *ctx = &brw->ctx; |
struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; |
struct intel_texture_object *intelObj = intel_texture_object(tObj); |
struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); |
GLuint face, i; |
GLuint nr_faces = 0; |
struct intel_texture_image *firstImage; |
int width, height, depth; |
/* TBOs require no validation -- they always just point to their BO. */ |
if (tObj->Target == GL_TEXTURE_BUFFER) |
return true; |
/* We know/require this is true by now: |
*/ |
assert(intelObj->base._BaseComplete); |
/* What levels must the tree include at a minimum? |
*/ |
intel_update_max_level(intelObj, sampler); |
if (intelObj->mt && intelObj->mt->first_level != tObj->BaseLevel) |
intelObj->needs_validate = true; |
if (!intelObj->needs_validate) |
return true; |
firstImage = intel_texture_image(tObj->Image[0][tObj->BaseLevel]); |
/* Check tree can hold all active levels. Check tree matches |
* target, imageFormat, etc. |
* |
* For pre-gen4, we have to match first_level == tObj->BaseLevel, |
* because we don't have the control that gen4 does to make min/mag |
* determination happen at a nonzero (hardware) baselevel. Because |
* of that, we just always relayout on baselevel change. |
*/ |
if (intelObj->mt && |
(!intel_miptree_match_image(intelObj->mt, &firstImage->base.Base) || |
intelObj->mt->first_level != tObj->BaseLevel || |
intelObj->mt->last_level < intelObj->_MaxLevel)) { |
intel_miptree_release(&intelObj->mt); |
} |
/* May need to create a new tree: |
*/ |
if (!intelObj->mt) { |
intel_miptree_get_dimensions_for_image(&firstImage->base.Base, |
&width, &height, &depth); |
perf_debug("Creating new %s %dx%dx%d %d..%d miptree to handle finalized " |
"texture miptree.\n", |
_mesa_get_format_name(firstImage->base.Base.TexFormat), |
width, height, depth, tObj->BaseLevel, intelObj->_MaxLevel); |
intelObj->mt = intel_miptree_create(brw, |
intelObj->base.Target, |
firstImage->base.Base.TexFormat, |
tObj->BaseLevel, |
intelObj->_MaxLevel, |
width, |
height, |
depth, |
true, |
0 /* num_samples */, |
INTEL_MIPTREE_TILING_ANY); |
if (!intelObj->mt) |
return false; |
} |
/* Pull in any images not in the object's tree: |
*/ |
nr_faces = _mesa_num_tex_faces(intelObj->base.Target); |
for (face = 0; face < nr_faces; face++) { |
for (i = tObj->BaseLevel; i <= intelObj->_MaxLevel; i++) { |
struct intel_texture_image *intelImage = |
intel_texture_image(intelObj->base.Image[face][i]); |
/* skip too small size mipmap */ |
if (intelImage == NULL) |
break; |
if (intelObj->mt != intelImage->mt) { |
intel_miptree_copy_teximage(brw, intelImage, intelObj->mt, |
false /* invalidate */); |
} |
/* After we're done, we'd better agree that our layout is |
* appropriate, or we'll end up hitting this function again on the |
* next draw |
*/ |
assert(intel_miptree_match_image(intelObj->mt, &intelImage->base.Base)); |
} |
} |
intelObj->needs_validate = false; |
return true; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/test_eu_compact.c |
---|
0,0 → 1,306 |
/* |
* 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 <stdlib.h> |
#include <stdio.h> |
#include <stdbool.h> |
#include "glsl/ralloc.h" |
#include "brw_context.h" |
#include "brw_eu.h" |
static bool |
test_compact_instruction(struct brw_compile *p, struct brw_instruction src) |
{ |
struct brw_context *brw = p->brw; |
struct brw_compact_instruction dst; |
memset(&dst, 0xd0, sizeof(dst)); |
if (brw_try_compact_instruction(p, &dst, &src)) { |
struct brw_instruction uncompacted; |
brw_uncompact_instruction(brw, &uncompacted, &dst); |
if (memcmp(&uncompacted, &src, sizeof(src))) { |
brw_debug_compact_uncompact(brw, &src, &uncompacted); |
return false; |
} |
} else { |
struct brw_compact_instruction unchanged; |
memset(&unchanged, 0xd0, sizeof(unchanged)); |
/* It's not supposed to change dst unless it compacted. */ |
if (memcmp(&unchanged, &dst, sizeof(dst))) { |
fprintf(stderr, "Failed to compact, but dst changed\n"); |
fprintf(stderr, " Instruction: "); |
brw_disasm(stderr, &src, brw->gen); |
return false; |
} |
} |
return true; |
} |
/** |
* When doing fuzz testing, pad bits won't round-trip. |
* |
* This sort of a superset of skip_bit, which is testing for changing bits that |
* aren't worth testing for fuzzing. We also just want to clear bits that |
* become meaningless once fuzzing twiddles a related bit. |
*/ |
static void |
clear_pad_bits(struct brw_instruction *inst) |
{ |
if (inst->header.opcode != BRW_OPCODE_SEND && |
inst->header.opcode != BRW_OPCODE_SENDC && |
inst->header.opcode != BRW_OPCODE_BREAK && |
inst->header.opcode != BRW_OPCODE_CONTINUE && |
inst->bits1.da1.src0_reg_file != BRW_IMMEDIATE_VALUE && |
inst->bits1.da1.src1_reg_file != BRW_IMMEDIATE_VALUE) { |
if (inst->bits3.da1.src1_address_mode) |
inst->bits3.ia1.pad1 = 0; |
else |
inst->bits3.da1.pad0 = 0; |
} |
} |
static bool |
skip_bit(struct brw_instruction *src, int bit) |
{ |
/* pad bit */ |
if (bit == 7) |
return true; |
/* The compact bit -- uncompacted can't have it set. */ |
if (bit == 29) |
return true; |
/* pad bit */ |
if (bit == 47) |
return true; |
/* pad bits */ |
if (bit >= 90 && bit <= 95) |
return true; |
/* sometimes these are pad bits. */ |
if (src->header.opcode != BRW_OPCODE_SEND && |
src->header.opcode != BRW_OPCODE_SENDC && |
src->header.opcode != BRW_OPCODE_BREAK && |
src->header.opcode != BRW_OPCODE_CONTINUE && |
src->bits1.da1.src0_reg_file != BRW_IMMEDIATE_VALUE && |
src->bits1.da1.src1_reg_file != BRW_IMMEDIATE_VALUE && |
bit >= 121) { |
return true; |
} |
return false; |
} |
static bool |
test_fuzz_compact_instruction(struct brw_compile *p, |
struct brw_instruction src) |
{ |
for (int bit0 = 0; bit0 < 128; bit0++) { |
if (skip_bit(&src, bit0)) |
continue; |
for (int bit1 = 0; bit1 < 128; bit1++) { |
struct brw_instruction instr = src; |
uint32_t *bits = (uint32_t *)&instr; |
if (skip_bit(&src, bit1)) |
continue; |
bits[bit0 / 32] ^= (1 << (bit0 & 31)); |
bits[bit1 / 32] ^= (1 << (bit1 & 31)); |
clear_pad_bits(&instr); |
if (!test_compact_instruction(p, instr)) { |
printf(" twiddled bits for fuzzing %d, %d\n", bit0, bit1); |
return false; |
} |
} |
} |
return true; |
} |
static void |
gen_ADD_GRF_GRF_GRF(struct brw_compile *p) |
{ |
struct brw_reg g0 = brw_vec8_grf(0, 0); |
struct brw_reg g2 = brw_vec8_grf(2, 0); |
struct brw_reg g4 = brw_vec8_grf(4, 0); |
brw_ADD(p, g0, g2, g4); |
} |
static void |
gen_ADD_GRF_GRF_IMM(struct brw_compile *p) |
{ |
struct brw_reg g0 = brw_vec8_grf(0, 0); |
struct brw_reg g2 = brw_vec8_grf(2, 0); |
brw_ADD(p, g0, g2, brw_imm_f(1.0)); |
} |
static void |
gen_ADD_GRF_GRF_IMM_d(struct brw_compile *p) |
{ |
struct brw_reg g0 = retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_D); |
struct brw_reg g2 = retype(brw_vec8_grf(2, 0), BRW_REGISTER_TYPE_D); |
brw_ADD(p, g0, g2, brw_imm_d(1)); |
} |
static void |
gen_MOV_GRF_GRF(struct brw_compile *p) |
{ |
struct brw_reg g0 = brw_vec8_grf(0, 0); |
struct brw_reg g2 = brw_vec8_grf(2, 0); |
brw_MOV(p, g0, g2); |
} |
static void |
gen_ADD_MRF_GRF_GRF(struct brw_compile *p) |
{ |
struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0); |
struct brw_reg g2 = brw_vec8_grf(2, 0); |
struct brw_reg g4 = brw_vec8_grf(4, 0); |
brw_ADD(p, m6, g2, g4); |
} |
static void |
gen_ADD_vec1_GRF_GRF_GRF(struct brw_compile *p) |
{ |
struct brw_reg g0 = brw_vec1_grf(0, 0); |
struct brw_reg g2 = brw_vec1_grf(2, 0); |
struct brw_reg g4 = brw_vec1_grf(4, 0); |
brw_ADD(p, g0, g2, g4); |
} |
static void |
gen_PLN_MRF_GRF_GRF(struct brw_compile *p) |
{ |
struct brw_reg m6 = brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, 6, 0); |
struct brw_reg interp = brw_vec1_grf(2, 0); |
struct brw_reg g4 = brw_vec8_grf(4, 0); |
brw_PLN(p, m6, interp, g4); |
} |
static void |
gen_f0_0_MOV_GRF_GRF(struct brw_compile *p) |
{ |
struct brw_reg g0 = brw_vec8_grf(0, 0); |
struct brw_reg g2 = brw_vec8_grf(2, 0); |
brw_push_insn_state(p); |
brw_set_predicate_control(p, true); |
brw_MOV(p, g0, g2); |
brw_pop_insn_state(p); |
} |
/* The handling of f0.1 vs f0.0 changes between gen6 and gen7. Explicitly test |
* it, so that we run the fuzzing can run over all the other bits that might |
* interact with it. |
*/ |
static void |
gen_f0_1_MOV_GRF_GRF(struct brw_compile *p) |
{ |
struct brw_reg g0 = brw_vec8_grf(0, 0); |
struct brw_reg g2 = brw_vec8_grf(2, 0); |
brw_push_insn_state(p); |
brw_set_predicate_control(p, true); |
current_insn(p)->bits2.da1.flag_subreg_nr = 1; |
brw_MOV(p, g0, g2); |
brw_pop_insn_state(p); |
} |
struct { |
void (*func)(struct brw_compile *p); |
} tests[] = { |
{ gen_MOV_GRF_GRF }, |
{ gen_ADD_GRF_GRF_GRF }, |
{ gen_ADD_GRF_GRF_IMM }, |
{ gen_ADD_GRF_GRF_IMM_d }, |
{ gen_ADD_MRF_GRF_GRF }, |
{ gen_ADD_vec1_GRF_GRF_GRF }, |
{ gen_PLN_MRF_GRF_GRF }, |
{ gen_f0_0_MOV_GRF_GRF }, |
{ gen_f0_1_MOV_GRF_GRF }, |
}; |
static bool |
run_tests(struct brw_context *brw) |
{ |
bool fail = false; |
for (int i = 0; i < ARRAY_SIZE(tests); i++) { |
for (int align_16 = 0; align_16 <= 1; align_16++) { |
struct brw_compile *p = rzalloc(NULL, struct brw_compile); |
brw_init_compile(brw, p, p); |
brw_set_predicate_control(p, BRW_PREDICATE_NONE); |
if (align_16) |
brw_set_access_mode(p, BRW_ALIGN_16); |
else |
brw_set_access_mode(p, BRW_ALIGN_1); |
tests[i].func(p); |
assert(p->nr_insn == 1); |
if (!test_compact_instruction(p, p->store[0])) { |
fail = true; |
continue; |
} |
if (!test_fuzz_compact_instruction(p, p->store[0])) { |
fail = true; |
continue; |
} |
ralloc_free(p); |
} |
} |
return fail; |
} |
int |
main(int argc, char **argv) |
{ |
struct brw_context *brw = calloc(1, sizeof(*brw)); |
brw->gen = 6; |
bool fail = false; |
for (brw->gen = 6; brw->gen <= 7; brw->gen++) { |
fail |= run_tests(brw); |
} |
return fail; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/i965/test_vec4_register_coalesce.cpp |
---|
0,0 → 1,247 |
/* |
* 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 <gtest/gtest.h> |
#include "brw_vec4.h" |
using namespace brw; |
int ret = 0; |
#define register_coalesce(v) _register_coalesce(v, __FUNCTION__) |
class register_coalesce_test : public ::testing::Test { |
virtual void SetUp(); |
public: |
struct brw_context *brw; |
struct gl_context *ctx; |
struct gl_shader_program *shader_prog; |
struct brw_vertex_program *vp; |
vec4_visitor *v; |
}; |
class register_coalesce_vec4_visitor : public vec4_visitor |
{ |
public: |
register_coalesce_vec4_visitor(struct brw_context *brw, |
struct gl_shader_program *shader_prog) |
: vec4_visitor(brw, NULL, NULL, NULL, NULL, shader_prog, NULL, NULL, |
false) |
{ |
} |
protected: |
virtual dst_reg *make_reg_for_system_value(ir_variable *ir) |
{ |
assert(!"Not reached"); |
return NULL; |
} |
virtual int setup_attributes(int payload_reg) |
{ |
assert(!"Not reached"); |
return 0; |
} |
virtual void emit_prolog() |
{ |
assert(!"Not reached"); |
} |
virtual void emit_program_code() |
{ |
assert(!"Not reached"); |
} |
virtual void emit_thread_end() |
{ |
assert(!"Not reached"); |
} |
virtual void emit_urb_write_header(int mrf) |
{ |
assert(!"Not reached"); |
} |
virtual vec4_instruction *emit_urb_write_opcode(bool complete) |
{ |
assert(!"Not reached"); |
} |
}; |
void register_coalesce_test::SetUp() |
{ |
brw = (struct brw_context *)calloc(1, sizeof(*brw)); |
ctx = &brw->ctx; |
vp = ralloc(NULL, struct brw_vertex_program); |
shader_prog = ralloc(NULL, struct gl_shader_program); |
v = new register_coalesce_vec4_visitor(brw, shader_prog); |
_mesa_init_vertex_program(ctx, &vp->program, GL_VERTEX_SHADER, 0); |
brw->gen = 4; |
} |
static void |
_register_coalesce(vec4_visitor *v, const char *func) |
{ |
bool print = false; |
if (print) { |
printf("%s: instructions before:\n", func); |
v->dump_instructions(); |
} |
v->opt_register_coalesce(); |
if (print) { |
printf("%s: instructions after:\n", func); |
v->dump_instructions(); |
} |
} |
TEST_F(register_coalesce_test, test_compute_to_mrf) |
{ |
src_reg something = src_reg(v, glsl_type::float_type); |
dst_reg temp = dst_reg(v, glsl_type::float_type); |
dst_reg init; |
dst_reg m0 = dst_reg(MRF, 0); |
m0.writemask = WRITEMASK_X; |
m0.type = BRW_REGISTER_TYPE_F; |
vec4_instruction *mul = v->emit(v->MUL(temp, something, src_reg(1.0f))); |
v->emit(v->MOV(m0, src_reg(temp))); |
register_coalesce(v); |
EXPECT_EQ(mul->dst.file, MRF); |
} |
TEST_F(register_coalesce_test, test_multiple_use) |
{ |
src_reg something = src_reg(v, glsl_type::float_type); |
dst_reg temp = dst_reg(v, glsl_type::vec4_type); |
dst_reg init; |
dst_reg m0 = dst_reg(MRF, 0); |
m0.writemask = WRITEMASK_X; |
m0.type = BRW_REGISTER_TYPE_F; |
dst_reg m1 = dst_reg(MRF, 1); |
m1.writemask = WRITEMASK_XYZW; |
m1.type = BRW_REGISTER_TYPE_F; |
src_reg src = src_reg(temp); |
vec4_instruction *mul = v->emit(v->MUL(temp, something, src_reg(1.0f))); |
src.swizzle = BRW_SWIZZLE_XXXX; |
v->emit(v->MOV(m0, src)); |
src.swizzle = BRW_SWIZZLE_XYZW; |
v->emit(v->MOV(m1, src)); |
register_coalesce(v); |
EXPECT_NE(mul->dst.file, MRF); |
} |
TEST_F(register_coalesce_test, test_dp4_mrf) |
{ |
src_reg some_src_1 = src_reg(v, glsl_type::vec4_type); |
src_reg some_src_2 = src_reg(v, glsl_type::vec4_type); |
dst_reg init; |
dst_reg m0 = dst_reg(MRF, 0); |
m0.writemask = WRITEMASK_Y; |
m0.type = BRW_REGISTER_TYPE_F; |
dst_reg temp = dst_reg(v, glsl_type::float_type); |
vec4_instruction *dp4 = v->emit(v->DP4(temp, some_src_1, some_src_2)); |
v->emit(v->MOV(m0, src_reg(temp))); |
register_coalesce(v); |
EXPECT_EQ(dp4->dst.file, MRF); |
EXPECT_EQ(dp4->dst.writemask, WRITEMASK_Y); |
} |
TEST_F(register_coalesce_test, test_dp4_grf) |
{ |
src_reg some_src_1 = src_reg(v, glsl_type::vec4_type); |
src_reg some_src_2 = src_reg(v, glsl_type::vec4_type); |
dst_reg init; |
dst_reg to = dst_reg(v, glsl_type::vec4_type); |
dst_reg temp = dst_reg(v, glsl_type::float_type); |
vec4_instruction *dp4 = v->emit(v->DP4(temp, some_src_1, some_src_2)); |
to.writemask = WRITEMASK_Y; |
v->emit(v->MOV(to, src_reg(temp))); |
/* if we don't do something with the result, the automatic dead code |
* elimination will remove all our instructions. |
*/ |
src_reg src = src_reg(to); |
src.negate = true; |
v->emit(v->MOV(dst_reg(MRF, 0), src)); |
register_coalesce(v); |
EXPECT_EQ(dp4->dst.reg, to.reg); |
EXPECT_EQ(dp4->dst.writemask, WRITEMASK_Y); |
} |
TEST_F(register_coalesce_test, test_channel_mul_grf) |
{ |
src_reg some_src_1 = src_reg(v, glsl_type::vec4_type); |
src_reg some_src_2 = src_reg(v, glsl_type::vec4_type); |
dst_reg init; |
dst_reg to = dst_reg(v, glsl_type::vec4_type); |
dst_reg temp = dst_reg(v, glsl_type::float_type); |
vec4_instruction *mul = v->emit(v->MUL(temp, some_src_1, some_src_2)); |
to.writemask = WRITEMASK_Y; |
v->emit(v->MOV(to, src_reg(temp))); |
/* if we don't do something with the result, the automatic dead code |
* elimination will remove all our instructions. |
*/ |
src_reg src = src_reg(to); |
src.negate = true; |
v->emit(v->MOV(dst_reg(MRF, 0), src)); |
register_coalesce(v); |
/* This path isn't supported yet in the reswizzling code, so we're checking |
* that we haven't done anything bad to scalar non-DP[234]s. |
*/ |
EXPECT_NE(mul->dst.reg, to.reg); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/Makefile.am |
---|
0,0 → 1,55 |
# Copyright © 2012 Matt Turner <mattst88@gmail.com> |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
# copy of this software and associated documentation files (the "Software"), |
# to deal in the Software without restriction, including without limitation |
# the rights to use, copy, modify, merge, publish, distribute, sublicense, |
# and/or sell copies of the Software, and to permit persons to whom the |
# Software is furnished to do so, subject to the following conditions: |
# |
# The above copyright notice and this permission notice (including the next |
# paragraph) shall be included in all copies or substantial portions of the |
# Software. |
# |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
# IN THE SOFTWARE. |
include Makefile.sources |
AM_CFLAGS = \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
-I$(top_srcdir)/src/mesa/drivers/dri/common \ |
$(DEFINES) \ |
$(VISIBILITY_CFLAGS) \ |
$(NOUVEAU_CFLAGS) |
dridir = $(DRI_DRIVER_INSTALL_DIR) |
if HAVE_NOUVEAU_DRI |
dri_LTLIBRARIES = nouveau_vieux_dri.la |
endif |
nouveau_vieux_dri_la_SOURCES = \ |
$(NOUVEAU_C_FILES) |
nouveau_vieux_dri_la_LDFLAGS = -module -avoid-version -shared |
nouveau_vieux_dri_la_LIBADD = \ |
../common/libdricommon.la \ |
$(DRI_LIB_DEPS) \ |
$(NOUVEAU_LIBS) |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
all-local: nouveau_vieux_dri.la |
$(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
ln -f .libs/nouveau_vieux_dri.so $(top_builddir)/$(LIB_DIR)/nouveau_vieux_dri.so; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/Makefile.in |
---|
0,0 → 1,939 |
# 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 Matt Turner <mattst88@gmail.com> |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
# copy of this software and associated documentation files (the "Software"), |
# to deal in the Software without restriction, including without limitation |
# the rights to use, copy, modify, merge, publish, distribute, 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 = $(srcdir)/Makefile.sources $(srcdir)/Makefile.in \ |
$(srcdir)/Makefile.am $(top_srcdir)/bin/depcomp |
subdir = src/mesa/drivers/dri/nouveau |
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 = |
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; |
am__vpath_adj = case $$p in \ |
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |
*) f=$$p;; \ |
esac; |
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; |
am__install_max = 40 |
am__nobase_strip_setup = \ |
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` |
am__nobase_strip = \ |
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" |
am__nobase_list = $(am__nobase_strip_setup); \ |
for p in $$list; do echo "$$p $$p"; done | \ |
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ |
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ |
if (++n[$$2] == $(am__install_max)) \ |
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ |
END { for (dir in files) print dir, files[dir] }' |
am__base_list = \ |
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ |
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' |
am__uninstall_files_from_dir = { \ |
test -z "$$files" \ |
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ |
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \ |
$(am__cd) "$$dir" && rm -f $$files; }; \ |
} |
am__installdirs = "$(DESTDIR)$(dridir)" |
LTLIBRARIES = $(dri_LTLIBRARIES) |
am__DEPENDENCIES_1 = |
nouveau_vieux_dri_la_DEPENDENCIES = ../common/libdricommon.la \ |
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) |
am__objects_1 = nouveau_screen.lo nouveau_context.lo nouveau_fbo.lo \ |
nouveau_driver.lo nouveau_state.lo nouveau_bufferobj.lo \ |
nouveau_span.lo nouveau_texture.lo nouveau_surface.lo \ |
nouveau_scratch.lo nouveau_array.lo nv04_context.lo \ |
nv04_render.lo nv04_state_fb.lo nv04_state_raster.lo \ |
nv04_state_tex.lo nv04_state_frag.lo nv04_surface.lo \ |
nv10_context.lo nv10_render.lo nv10_state_fb.lo \ |
nv10_state_polygon.lo nv10_state_raster.lo nv10_state_tex.lo \ |
nv10_state_frag.lo nv10_state_tnl.lo nv20_context.lo \ |
nv20_render.lo nv20_state_fb.lo nv20_state_polygon.lo \ |
nv20_state_raster.lo nv20_state_tex.lo nv20_state_frag.lo \ |
nv20_state_tnl.lo |
am__objects_2 = $(am__objects_1) |
am_nouveau_vieux_dri_la_OBJECTS = $(am__objects_2) |
nouveau_vieux_dri_la_OBJECTS = $(am_nouveau_vieux_dri_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 = |
nouveau_vieux_dri_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ |
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ |
$(AM_CFLAGS) $(CFLAGS) $(nouveau_vieux_dri_la_LDFLAGS) \ |
$(LDFLAGS) -o $@ |
@HAVE_NOUVEAU_DRI_TRUE@am_nouveau_vieux_dri_la_rpath = -rpath \ |
@HAVE_NOUVEAU_DRI_TRUE@ $(dridir) |
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 = $(nouveau_vieux_dri_la_SOURCES) |
DIST_SOURCES = $(nouveau_vieux_dri_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@ |
NOUVEAU_DRIVER_FILES = \ |
nouveau_screen.c \ |
nouveau_context.c \ |
nouveau_fbo.c \ |
nouveau_driver.c \ |
nouveau_state.c \ |
nouveau_bufferobj.c \ |
nouveau_span.c \ |
nouveau_texture.c \ |
nouveau_surface.c \ |
nouveau_scratch.c \ |
nouveau_array.c \ |
nv04_context.c \ |
nv04_render.c \ |
nv04_state_fb.c \ |
nv04_state_raster.c \ |
nv04_state_tex.c \ |
nv04_state_frag.c \ |
nv04_surface.c \ |
nv10_context.c \ |
nv10_render.c \ |
nv10_state_fb.c \ |
nv10_state_polygon.c \ |
nv10_state_raster.c \ |
nv10_state_tex.c \ |
nv10_state_frag.c \ |
nv10_state_tnl.c \ |
nv20_context.c \ |
nv20_render.c \ |
nv20_state_fb.c \ |
nv20_state_polygon.c \ |
nv20_state_raster.c \ |
nv20_state_tex.c \ |
nv20_state_frag.c \ |
nv20_state_tnl.c |
NOUVEAU_C_FILES = \ |
$(NOUVEAU_DRIVER_FILES) |
AM_CFLAGS = \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
-I$(top_srcdir)/src/mesa/drivers/dri/common \ |
$(DEFINES) \ |
$(VISIBILITY_CFLAGS) \ |
$(NOUVEAU_CFLAGS) |
dridir = $(DRI_DRIVER_INSTALL_DIR) |
@HAVE_NOUVEAU_DRI_TRUE@dri_LTLIBRARIES = nouveau_vieux_dri.la |
nouveau_vieux_dri_la_SOURCES = \ |
$(NOUVEAU_C_FILES) |
nouveau_vieux_dri_la_LDFLAGS = -module -avoid-version -shared |
nouveau_vieux_dri_la_LIBADD = \ |
../common/libdricommon.la \ |
$(DRI_LIB_DEPS) \ |
$(NOUVEAU_LIBS) |
all: all-am |
.SUFFIXES: |
.SUFFIXES: .c .lo .o .obj |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(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/mesa/drivers/dri/nouveau/Makefile'; \ |
$(am__cd) $(top_srcdir) && \ |
$(AUTOMAKE) --foreign src/mesa/drivers/dri/nouveau/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; |
$(srcdir)/Makefile.sources: |
$(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): |
install-driLTLIBRARIES: $(dri_LTLIBRARIES) |
@$(NORMAL_INSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
list2=; for p in $$list; do \ |
if test -f $$p; then \ |
list2="$$list2 $$p"; \ |
else :; fi; \ |
done; \ |
test -z "$$list2" || { \ |
echo " $(MKDIR_P) '$(DESTDIR)$(dridir)'"; \ |
$(MKDIR_P) "$(DESTDIR)$(dridir)" || exit 1; \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(dridir)'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(dridir)"; \ |
} |
uninstall-driLTLIBRARIES: |
@$(NORMAL_UNINSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
for p in $$list; do \ |
$(am__strip_dir) \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(dridir)/$$f'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(dridir)/$$f"; \ |
done |
clean-driLTLIBRARIES: |
-test -z "$(dri_LTLIBRARIES)" || rm -f $(dri_LTLIBRARIES) |
@list='$(dri_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}; \ |
} |
nouveau_vieux_dri.la: $(nouveau_vieux_dri_la_OBJECTS) $(nouveau_vieux_dri_la_DEPENDENCIES) $(EXTRA_nouveau_vieux_dri_la_DEPENDENCIES) |
$(AM_V_CCLD)$(nouveau_vieux_dri_la_LINK) $(am_nouveau_vieux_dri_la_rpath) $(nouveau_vieux_dri_la_OBJECTS) $(nouveau_vieux_dri_la_LIBADD) $(LIBS) |
mostlyclean-compile: |
-rm -f *.$(OBJEXT) |
distclean-compile: |
-rm -f *.tab.c |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nouveau_array.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nouveau_bufferobj.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nouveau_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nouveau_driver.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nouveau_fbo.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nouveau_scratch.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nouveau_screen.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nouveau_span.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nouveau_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nouveau_surface.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nouveau_texture.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv04_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv04_render.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv04_state_fb.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv04_state_frag.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv04_state_raster.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv04_state_tex.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv04_surface.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv10_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv10_render.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv10_state_fb.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv10_state_frag.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv10_state_polygon.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv10_state_raster.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv10_state_tex.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv10_state_tnl.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv20_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv20_render.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv20_state_fb.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv20_state_frag.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv20_state_polygon.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv20_state_raster.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv20_state_tex.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nv20_state_tnl.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) all-local |
installdirs: |
for dir in "$(DESTDIR)$(dridir)"; do \ |
test -z "$$dir" || $(MKDIR_P) "$$dir"; \ |
done |
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-driLTLIBRARIES clean-generic clean-libtool \ |
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-driLTLIBRARIES |
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: uninstall-driLTLIBRARIES |
.MAKE: install-am install-strip |
.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \ |
clean-driLTLIBRARIES clean-generic clean-libtool 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-driLTLIBRARIES 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 \ |
uninstall-driLTLIBRARIES |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
all-local: nouveau_vieux_dri.la |
$(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
ln -f .libs/nouveau_vieux_dri.so $(top_builddir)/$(LIB_DIR)/nouveau_vieux_dri.so; |
# 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/src/mesa/drivers/dri/nouveau/Makefile.sources |
---|
0,0 → 1,38 |
NOUVEAU_DRIVER_FILES = \ |
nouveau_screen.c \ |
nouveau_context.c \ |
nouveau_fbo.c \ |
nouveau_driver.c \ |
nouveau_state.c \ |
nouveau_bufferobj.c \ |
nouveau_span.c \ |
nouveau_texture.c \ |
nouveau_surface.c \ |
nouveau_scratch.c \ |
nouveau_array.c \ |
nv04_context.c \ |
nv04_render.c \ |
nv04_state_fb.c \ |
nv04_state_raster.c \ |
nv04_state_tex.c \ |
nv04_state_frag.c \ |
nv04_surface.c \ |
nv10_context.c \ |
nv10_render.c \ |
nv10_state_fb.c \ |
nv10_state_polygon.c \ |
nv10_state_raster.c \ |
nv10_state_tex.c \ |
nv10_state_frag.c \ |
nv10_state_tnl.c \ |
nv20_context.c \ |
nv20_render.c \ |
nv20_state_fb.c \ |
nv20_state_polygon.c \ |
nv20_state_raster.c \ |
nv20_state_tex.c \ |
nv20_state_frag.c \ |
nv20_state_tnl.c |
NOUVEAU_C_FILES = \ |
$(NOUVEAU_DRIVER_FILES) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_array.c |
---|
0,0 → 1,151 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "main/bufferobj.h" |
#include "nouveau_driver.h" |
#include "nouveau_array.h" |
#include "nouveau_bufferobj.h" |
#include "nouveau_context.h" |
#define EXTRACT(in_t, out_t) extract_func_##in_t##_to_##out_t |
#define EXTRACT_FUNC(in_t, out_t, k) \ |
static out_t EXTRACT(in_t, out_t) \ |
(struct nouveau_array *a, int i, int j) { \ |
in_t x = ((in_t *)(a->buf + i * a->stride))[j]; \ |
\ |
return (out_t)x / (k); \ |
} |
EXTRACT_FUNC(GLchar, unsigned, 1); |
EXTRACT_FUNC(GLchar, float, SCHAR_MAX); |
EXTRACT_FUNC(GLubyte, unsigned, 1); |
EXTRACT_FUNC(GLubyte, float, UCHAR_MAX); |
EXTRACT_FUNC(GLshort, unsigned, 1); |
EXTRACT_FUNC(GLshort, float, SHRT_MAX); |
EXTRACT_FUNC(GLushort, unsigned, 1); |
EXTRACT_FUNC(GLushort, float, USHRT_MAX); |
EXTRACT_FUNC(GLint, unsigned, 1); |
EXTRACT_FUNC(GLint, float, INT_MAX); |
EXTRACT_FUNC(GLuint, unsigned, 1); |
EXTRACT_FUNC(GLuint, float, UINT_MAX); |
EXTRACT_FUNC(GLfloat, unsigned, 1.0 / UINT_MAX); |
EXTRACT_FUNC(GLfloat, float, 1); |
#undef EXTRACT_FUNC |
static void |
get_array_extract(struct nouveau_array *a, extract_u_t *extract_u, |
extract_f_t *extract_f) |
{ |
switch (a->type) { |
case GL_BYTE: |
*extract_u = EXTRACT(GLchar, unsigned); |
*extract_f = EXTRACT(GLchar, float); |
break; |
case GL_UNSIGNED_BYTE: |
*extract_u = EXTRACT(GLubyte, unsigned); |
*extract_f = EXTRACT(GLubyte, float); |
break; |
case GL_SHORT: |
*extract_u = EXTRACT(GLshort, unsigned); |
*extract_f = EXTRACT(GLshort, float); |
break; |
case GL_UNSIGNED_SHORT: |
*extract_u = EXTRACT(GLushort, unsigned); |
*extract_f = EXTRACT(GLushort, float); |
break; |
case GL_INT: |
*extract_u = EXTRACT(GLint, unsigned); |
*extract_f = EXTRACT(GLint, float); |
break; |
case GL_UNSIGNED_INT: |
*extract_u = EXTRACT(GLuint, unsigned); |
*extract_f = EXTRACT(GLuint, float); |
break; |
case GL_FLOAT: |
*extract_u = EXTRACT(GLfloat, unsigned); |
*extract_f = EXTRACT(GLfloat, float); |
break; |
default: |
assert(0); |
} |
} |
#undef EXTRACT |
void |
nouveau_init_array(struct nouveau_array *a, int attr, int stride, |
int fields, int type, struct gl_buffer_object *obj, |
const void *ptr, GLboolean map, struct gl_context *ctx) |
{ |
struct nouveau_client *client = context_client(ctx); |
a->attr = attr; |
a->stride = stride; |
a->fields = fields; |
a->type = type; |
a->buf = NULL; |
if (obj) { |
if (nouveau_bufferobj_hw(obj)) { |
struct nouveau_bufferobj *nbo = |
to_nouveau_bufferobj(obj); |
nouveau_bo_ref(nbo->bo, &a->bo); |
a->offset = (intptr_t)ptr; |
if (map) { |
nouveau_bo_map(a->bo, NOUVEAU_BO_RD, client); |
a->buf = a->bo->map + a->offset; |
} |
} else { |
nouveau_bo_ref(NULL, &a->bo); |
a->offset = 0; |
if (map) |
a->buf = ADD_POINTERS( |
nouveau_bufferobj_sys(obj), ptr); |
} |
} |
if (a->buf) |
get_array_extract(a, &a->extract_u, &a->extract_f); |
} |
void |
nouveau_deinit_array(struct nouveau_array *a) |
{ |
a->buf = NULL; |
a->fields = 0; |
} |
void |
nouveau_cleanup_array(struct nouveau_array *a) |
{ |
nouveau_deinit_array(a); |
nouveau_bo_ref(NULL, &a->bo); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_array.h |
---|
0,0 → 1,58 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_ARRAY_H__ |
#define __NOUVEAU_ARRAY_H__ |
struct nouveau_array; |
typedef unsigned (*extract_u_t)(struct nouveau_array *, int, int); |
typedef float (*extract_f_t)(struct nouveau_array *, int, int); |
struct nouveau_array { |
int attr; |
int stride, fields, type; |
struct nouveau_bo *bo; |
unsigned offset; |
const void *buf; |
extract_u_t extract_u; |
extract_f_t extract_f; |
}; |
void |
nouveau_init_array(struct nouveau_array *a, int attr, int stride, |
int fields, int type, struct gl_buffer_object *obj, |
const void *ptr, GLboolean map, struct gl_context *ctx); |
void |
nouveau_deinit_array(struct nouveau_array *a); |
void |
nouveau_cleanup_array(struct nouveau_array *a); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c |
---|
0,0 → 1,177 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_bufferobj.h" |
#include "nouveau_context.h" |
#include "main/bufferobj.h" |
static inline char * |
get_bufferobj_map(struct gl_context *ctx, struct gl_buffer_object *obj, |
unsigned flags) |
{ |
struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); |
void *map = NULL; |
if (nbo->sys) { |
map = nbo->sys; |
} else if (nbo->bo) { |
nouveau_bo_map(nbo->bo, flags, context_client(ctx)); |
map = nbo->bo->map; |
} |
return map; |
} |
static struct gl_buffer_object * |
nouveau_bufferobj_new(struct gl_context *ctx, GLuint buffer, GLenum target) |
{ |
struct nouveau_bufferobj *nbo; |
nbo = CALLOC_STRUCT(nouveau_bufferobj); |
if (!nbo) |
return NULL; |
_mesa_initialize_buffer_object(ctx, &nbo->base, buffer, target); |
return &nbo->base; |
} |
static void |
nouveau_bufferobj_del(struct gl_context *ctx, struct gl_buffer_object *obj) |
{ |
struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); |
nouveau_bo_ref(NULL, &nbo->bo); |
free(nbo->sys); |
free(nbo); |
} |
static GLboolean |
nouveau_bufferobj_data(struct gl_context *ctx, GLenum target, GLsizeiptrARB size, |
const GLvoid *data, GLenum usage, |
struct gl_buffer_object *obj) |
{ |
struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); |
int ret; |
obj->Size = size; |
obj->Usage = usage; |
/* Free previous storage */ |
nouveau_bo_ref(NULL, &nbo->bo); |
free(nbo->sys); |
if (target == GL_ELEMENT_ARRAY_BUFFER_ARB || |
(size < 512 && usage == GL_DYNAMIC_DRAW_ARB) || |
context_chipset(ctx) < 0x10) { |
/* Heuristic: keep it in system ram */ |
nbo->sys = malloc(size); |
} else { |
/* Get a hardware BO */ |
ret = nouveau_bo_new(context_dev(ctx), |
NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, |
size, NULL, &nbo->bo); |
assert(!ret); |
} |
if (data) |
memcpy(get_bufferobj_map(ctx, obj, NOUVEAU_BO_WR), data, size); |
return GL_TRUE; |
} |
static void |
nouveau_bufferobj_subdata(struct gl_context *ctx, GLintptrARB offset, |
GLsizeiptrARB size, const GLvoid *data, |
struct gl_buffer_object *obj) |
{ |
memcpy(get_bufferobj_map(ctx, obj, NOUVEAU_BO_WR) + offset, data, size); |
} |
static void |
nouveau_bufferobj_get_subdata(struct gl_context *ctx, GLintptrARB offset, |
GLsizeiptrARB size, GLvoid *data, |
struct gl_buffer_object *obj) |
{ |
memcpy(data, get_bufferobj_map(ctx, obj, NOUVEAU_BO_RD) + offset, size); |
} |
static void * |
nouveau_bufferobj_map_range(struct gl_context *ctx, GLintptr offset, |
GLsizeiptr length, GLbitfield access, |
struct gl_buffer_object *obj) |
{ |
unsigned flags = 0; |
char *map; |
assert(!obj->Pointer); |
if (!(access & GL_MAP_UNSYNCHRONIZED_BIT)) { |
if (access & GL_MAP_READ_BIT) |
flags |= NOUVEAU_BO_RD; |
if (access & GL_MAP_WRITE_BIT) |
flags |= NOUVEAU_BO_WR; |
} |
map = get_bufferobj_map(ctx, obj, flags); |
if (!map) |
return NULL; |
obj->Pointer = map + offset; |
obj->Offset = offset; |
obj->Length = length; |
obj->AccessFlags = access; |
return obj->Pointer; |
} |
static GLboolean |
nouveau_bufferobj_unmap(struct gl_context *ctx, struct gl_buffer_object *obj) |
{ |
assert(obj->Pointer); |
obj->Pointer = NULL; |
obj->Offset = 0; |
obj->Length = 0; |
obj->AccessFlags = 0; |
return GL_TRUE; |
} |
void |
nouveau_bufferobj_functions_init(struct dd_function_table *functions) |
{ |
functions->NewBufferObject = nouveau_bufferobj_new; |
functions->DeleteBuffer = nouveau_bufferobj_del; |
functions->BufferData = nouveau_bufferobj_data; |
functions->BufferSubData = nouveau_bufferobj_subdata; |
functions->GetBufferSubData = nouveau_bufferobj_get_subdata; |
functions->MapBufferRange = nouveau_bufferobj_map_range; |
functions->UnmapBuffer = nouveau_bufferobj_unmap; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h |
---|
0,0 → 1,46 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_BUFFEROBJ_H__ |
#define __NOUVEAU_BUFFEROBJ_H__ |
struct nouveau_bufferobj { |
struct gl_buffer_object base; |
struct nouveau_bo *bo; |
void *sys; |
}; |
#define to_nouveau_bufferobj(x) ((struct nouveau_bufferobj *)(x)) |
#define nouveau_bufferobj_hw(x) \ |
(_mesa_is_bufferobj(x) ? to_nouveau_bufferobj(x)->bo : NULL) |
#define nouveau_bufferobj_sys(x) \ |
(_mesa_is_bufferobj(x) ? to_nouveau_bufferobj(x)->sys : NULL) |
void |
nouveau_bufferobj_functions_init(struct dd_function_table *functions); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_context.c |
---|
0,0 → 1,440 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 <stdbool.h> |
#include "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_bufferobj.h" |
#include "nouveau_fbo.h" |
#include "nv_object.xml.h" |
#include "main/api_exec.h" |
#include "main/dd.h" |
#include "main/framebuffer.h" |
#include "main/fbobject.h" |
#include "main/light.h" |
#include "main/state.h" |
#include "main/version.h" |
#include "main/vtxfmt.h" |
#include "drivers/common/meta.h" |
#include "drivers/common/driverfuncs.h" |
#include "swrast/swrast.h" |
#include "swrast/s_context.h" |
#include "vbo/vbo.h" |
#include "tnl/tnl.h" |
#include "tnl/t_context.h" |
GLboolean |
nouveau_context_create(gl_api api, |
const struct gl_config *visual, __DRIcontext *dri_ctx, |
unsigned major_version, |
unsigned minor_version, |
uint32_t flags, |
unsigned *error, |
void *share_ctx) |
{ |
__DRIscreen *dri_screen = dri_ctx->driScreenPriv; |
struct nouveau_screen *screen = dri_screen->driverPrivate; |
struct nouveau_context *nctx; |
struct gl_context *ctx; |
switch (api) { |
case API_OPENGL_COMPAT: |
/* Do after-the-fact version checking (below). |
*/ |
break; |
case API_OPENGLES: |
/* NV10 and NV20 can support OpenGL ES 1.0 only. Older chips |
* cannot do even that. |
*/ |
if ((screen->device->chipset & 0xf0) == 0x00) { |
*error = __DRI_CTX_ERROR_BAD_API; |
return GL_FALSE; |
} else if (minor_version != 0) { |
*error = __DRI_CTX_ERROR_BAD_VERSION; |
return GL_FALSE; |
} |
break; |
case API_OPENGLES2: |
case API_OPENGL_CORE: |
*error = __DRI_CTX_ERROR_BAD_API; |
return GL_FALSE; |
} |
/* API and flag filtering is handled in dri2CreateContextAttribs. |
*/ |
(void) flags; |
ctx = screen->driver->context_create(screen, visual, share_ctx); |
if (!ctx) { |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
return GL_FALSE; |
} |
nctx = to_nouveau_context(ctx); |
nctx->dri_context = dri_ctx; |
dri_ctx->driverPrivate = ctx; |
_mesa_compute_version(ctx); |
if (ctx->Version < major_version * 10 + minor_version) { |
nouveau_context_destroy(dri_ctx); |
*error = __DRI_CTX_ERROR_BAD_VERSION; |
return GL_FALSE; |
} |
/* Exec table initialization requires the version to be computed */ |
_mesa_initialize_dispatch_tables(ctx); |
_mesa_initialize_vbo_vtxfmt(ctx); |
if (nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_VRAM, 0, 4096, |
NULL, &nctx->fence)) { |
nouveau_context_destroy(dri_ctx); |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
return GL_FALSE; |
} |
*error = __DRI_CTX_ERROR_SUCCESS; |
return GL_TRUE; |
} |
GLboolean |
nouveau_context_init(struct gl_context *ctx, struct nouveau_screen *screen, |
const struct gl_config *visual, struct gl_context *share_ctx) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct dd_function_table functions; |
int ret; |
nctx->screen = screen; |
nctx->fallback = HWTNL; |
/* Initialize the function pointers. */ |
_mesa_init_driver_functions(&functions); |
nouveau_driver_functions_init(&functions); |
nouveau_bufferobj_functions_init(&functions); |
nouveau_texture_functions_init(&functions); |
nouveau_fbo_functions_init(&functions); |
/* Initialize the mesa context. */ |
_mesa_initialize_context(ctx, API_OPENGL_COMPAT, visual, |
share_ctx, &functions); |
nouveau_state_init(ctx); |
nouveau_scratch_init(ctx); |
_mesa_meta_init(ctx); |
_swrast_CreateContext(ctx); |
_vbo_CreateContext(ctx); |
_tnl_CreateContext(ctx); |
nouveau_span_functions_init(ctx); |
_mesa_allow_light_in_model(ctx, GL_FALSE); |
/* Allocate a hardware channel. */ |
ret = nouveau_object_new(&context_dev(ctx)->object, 0xbeef0000, |
NOUVEAU_FIFO_CHANNEL_CLASS, |
&(struct nv04_fifo){ |
.vram = 0xbeef0201, |
.gart = 0xbeef0202 |
}, sizeof(struct nv04_fifo), &nctx->hw.chan); |
if (ret) { |
nouveau_error("Error initializing the FIFO.\n"); |
return GL_FALSE; |
} |
/* Allocate a client (thread data) */ |
ret = nouveau_client_new(context_dev(ctx), &nctx->hw.client); |
if (ret) { |
nouveau_error("Error creating thread data\n"); |
return GL_FALSE; |
} |
/* Allocate a push buffer */ |
ret = nouveau_pushbuf_new(nctx->hw.client, nctx->hw.chan, 4, |
512 * 1024, true, &nctx->hw.pushbuf); |
if (ret) { |
nouveau_error("Error allocating DMA push buffer\n"); |
return GL_FALSE; |
} |
/* Allocate buffer context */ |
ret = nouveau_bufctx_new(nctx->hw.client, 16, &nctx->hw.bufctx); |
if (ret) { |
nouveau_error("Error allocating buffer context\n"); |
return GL_FALSE; |
} |
nctx->hw.pushbuf->user_priv = nctx->hw.bufctx; |
/* Allocate NULL object */ |
ret = nouveau_object_new(nctx->hw.chan, 0x00000000, NV01_NULL_CLASS, |
NULL, 0, &nctx->hw.null); |
if (ret) { |
nouveau_error("Error allocating NULL object\n"); |
return GL_FALSE; |
} |
/* Enable any supported extensions. */ |
ctx->Extensions.EXT_blend_color = true; |
ctx->Extensions.EXT_blend_minmax = true; |
ctx->Extensions.EXT_framebuffer_blit = true; |
ctx->Extensions.EXT_packed_depth_stencil = true; |
ctx->Extensions.EXT_texture_filter_anisotropic = true; |
ctx->Extensions.NV_texture_env_combine4 = true; |
return GL_TRUE; |
} |
void |
nouveau_context_deinit(struct gl_context *ctx) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
if (TNL_CONTEXT(ctx)) |
_tnl_DestroyContext(ctx); |
if (vbo_context(ctx)) |
_vbo_DestroyContext(ctx); |
if (SWRAST_CONTEXT(ctx)) |
_swrast_DestroyContext(ctx); |
if (ctx->Meta) |
_mesa_meta_free(ctx); |
nouveau_bufctx_del(&nctx->hw.bufctx); |
nouveau_pushbuf_del(&nctx->hw.pushbuf); |
nouveau_client_del(&nctx->hw.client); |
nouveau_object_del(&nctx->hw.chan); |
nouveau_scratch_destroy(ctx); |
_mesa_free_context_data(ctx); |
} |
void |
nouveau_context_destroy(__DRIcontext *dri_ctx) |
{ |
struct nouveau_context *nctx = dri_ctx->driverPrivate; |
struct gl_context *ctx = &nctx->base; |
nouveau_bo_ref(NULL, &nctx->fence); |
context_drv(ctx)->context_destroy(ctx); |
} |
void |
nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw) |
{ |
struct gl_context *ctx = dri_ctx->driverPrivate; |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
__DRIscreen *screen = dri_ctx->driScreenPriv; |
struct gl_framebuffer *fb = draw->driverPrivate; |
struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb); |
unsigned int attachments[10]; |
__DRIbuffer *buffers = NULL; |
int i = 0, count, ret; |
if (draw->lastStamp == draw->dri2.stamp) |
return; |
draw->lastStamp = draw->dri2.stamp; |
if (nfb->need_front) |
attachments[i++] = __DRI_BUFFER_FRONT_LEFT; |
if (fb->Visual.doubleBufferMode) |
attachments[i++] = __DRI_BUFFER_BACK_LEFT; |
if (fb->Visual.haveDepthBuffer && fb->Visual.haveStencilBuffer) |
attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; |
else if (fb->Visual.haveDepthBuffer) |
attachments[i++] = __DRI_BUFFER_DEPTH; |
else if (fb->Visual.haveStencilBuffer) |
attachments[i++] = __DRI_BUFFER_STENCIL; |
buffers = (*screen->dri2.loader->getBuffers)(draw, &draw->w, &draw->h, |
attachments, i, &count, |
draw->loaderPrivate); |
if (buffers == NULL) |
return; |
for (i = 0; i < count; i++) { |
struct gl_renderbuffer *rb; |
struct nouveau_surface *s; |
uint32_t old_name; |
int index; |
switch (buffers[i].attachment) { |
case __DRI_BUFFER_FRONT_LEFT: |
case __DRI_BUFFER_FAKE_FRONT_LEFT: |
index = BUFFER_FRONT_LEFT; |
break; |
case __DRI_BUFFER_BACK_LEFT: |
index = BUFFER_BACK_LEFT; |
break; |
case __DRI_BUFFER_DEPTH: |
case __DRI_BUFFER_DEPTH_STENCIL: |
index = BUFFER_DEPTH; |
break; |
case __DRI_BUFFER_STENCIL: |
index = BUFFER_STENCIL; |
break; |
default: |
assert(0); |
} |
rb = fb->Attachment[index].Renderbuffer; |
s = &to_nouveau_renderbuffer(rb)->surface; |
s->width = draw->w; |
s->height = draw->h; |
s->pitch = buffers[i].pitch; |
s->cpp = buffers[i].cpp; |
if (index == BUFFER_DEPTH && s->bo) { |
ret = nouveau_bo_name_get(s->bo, &old_name); |
/* |
* Disable fast Z clears in the next frame, the |
* depth buffer contents are undefined. |
*/ |
if (!ret && old_name != buffers[i].name) |
nctx->hierz.clear_seq = 0; |
} |
nouveau_bo_ref(NULL, &s->bo); |
ret = nouveau_bo_name_ref(context_dev(ctx), |
buffers[i].name, &s->bo); |
assert(!ret); |
} |
_mesa_resize_framebuffer(ctx, fb, draw->w, draw->h); |
} |
static void |
update_framebuffer(__DRIcontext *dri_ctx, __DRIdrawable *draw, |
int *stamp) |
{ |
struct gl_context *ctx = dri_ctx->driverPrivate; |
struct gl_framebuffer *fb = draw->driverPrivate; |
*stamp = draw->dri2.stamp; |
nouveau_update_renderbuffers(dri_ctx, draw); |
_mesa_resize_framebuffer(ctx, fb, draw->w, draw->h); |
/* Clean up references to the old framebuffer objects. */ |
context_dirty(ctx, FRAMEBUFFER); |
nouveau_bufctx_reset(to_nouveau_context(ctx)->hw.bufctx, BUFCTX_FB); |
PUSH_KICK(context_push(ctx)); |
} |
GLboolean |
nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *dri_draw, |
__DRIdrawable *dri_read) |
{ |
if (dri_ctx) { |
struct nouveau_context *nctx = dri_ctx->driverPrivate; |
struct gl_context *ctx = &nctx->base; |
/* Ask the X server for new renderbuffers. */ |
if (dri_draw->driverPrivate != ctx->WinSysDrawBuffer) |
update_framebuffer(dri_ctx, dri_draw, |
&dri_ctx->dri2.draw_stamp); |
if (dri_draw != dri_read && |
dri_read->driverPrivate != ctx->WinSysReadBuffer) |
update_framebuffer(dri_ctx, dri_read, |
&dri_ctx->dri2.read_stamp); |
/* Pass it down to mesa. */ |
_mesa_make_current(ctx, dri_draw->driverPrivate, |
dri_read->driverPrivate); |
_mesa_update_state(ctx); |
} else { |
_mesa_make_current(NULL, NULL, NULL); |
} |
return GL_TRUE; |
} |
GLboolean |
nouveau_context_unbind(__DRIcontext *dri_ctx) |
{ |
/* Unset current context and dispatch table */ |
_mesa_make_current(NULL, NULL, NULL); |
return GL_TRUE; |
} |
void |
nouveau_fallback(struct gl_context *ctx, enum nouveau_fallback mode) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
nctx->fallback = MAX2(HWTNL, mode); |
if (mode < SWRAST) { |
nouveau_state_emit(ctx); |
#if 0 |
nouveau_bo_state_emit(ctx); |
#endif |
} else { |
PUSH_KICK(context_push(ctx)); |
} |
} |
static void |
validate_framebuffer(__DRIcontext *dri_ctx, __DRIdrawable *draw, |
int *stamp) |
{ |
struct gl_framebuffer *fb = draw->driverPrivate; |
struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb); |
GLboolean need_front = |
(fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT || |
fb->_ColorReadBufferIndex == BUFFER_FRONT_LEFT); |
if (nfb->need_front != need_front) { |
nfb->need_front = need_front; |
dri2InvalidateDrawable(draw); |
} |
if (draw->dri2.stamp != *stamp) |
update_framebuffer(dri_ctx, draw, stamp); |
} |
void |
nouveau_validate_framebuffer(struct gl_context *ctx) |
{ |
__DRIcontext *dri_ctx = to_nouveau_context(ctx)->dri_context; |
__DRIdrawable *dri_draw = dri_ctx->driDrawablePriv; |
__DRIdrawable *dri_read = dri_ctx->driReadablePriv; |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) |
validate_framebuffer(dri_ctx, dri_draw, |
&dri_ctx->dri2.draw_stamp); |
if (_mesa_is_winsys_fbo(ctx->ReadBuffer)) |
validate_framebuffer(dri_ctx, dri_read, |
&dri_ctx->dri2.read_stamp); |
if (ctx->NewState & _NEW_BUFFERS) |
_mesa_update_state(ctx); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_context.h |
---|
0,0 → 1,143 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_CONTEXT_H__ |
#define __NOUVEAU_CONTEXT_H__ |
#include "nouveau_screen.h" |
#include "nouveau_state.h" |
#include "nouveau_scratch.h" |
#include "nouveau_render.h" |
#include "main/bitset.h" |
enum nouveau_fallback { |
HWTNL = 0, |
SWTNL, |
SWRAST, |
}; |
#define BUFCTX_FB 0 |
#define BUFCTX_VTX 1 |
#define BUFCTX_TEX(i) (2 + (i)) |
struct nouveau_hw_state { |
struct nouveau_object *chan; |
struct nouveau_client *client; |
struct nouveau_pushbuf *pushbuf; |
struct nouveau_bufctx *bufctx; |
struct nouveau_object *null; |
struct nouveau_object *ntfy; |
struct nouveau_object *eng3d; |
struct nouveau_object *eng3dm; |
struct nouveau_object *surf3d; |
struct nouveau_object *m2mf; |
struct nouveau_object *surf2d; |
struct nouveau_object *rop; |
struct nouveau_object *patt; |
struct nouveau_object *rect; |
struct nouveau_object *swzsurf; |
struct nouveau_object *sifm; |
}; |
struct nouveau_context { |
struct gl_context base; |
__DRIcontext *dri_context; |
struct nouveau_screen *screen; |
BITSET_DECLARE(dirty, MAX_NOUVEAU_STATE); |
enum nouveau_fallback fallback; |
struct nouveau_bo *fence; |
struct nouveau_hw_state hw; |
struct nouveau_render_state render; |
struct nouveau_scratch_state scratch; |
struct { |
GLboolean clear_blocked; |
int clear_seq; |
} hierz; |
}; |
#define to_nouveau_context(ctx) ((struct nouveau_context *)(ctx)) |
#define context_dev(ctx) \ |
(to_nouveau_context(ctx)->screen->device) |
#define context_chipset(ctx) \ |
(context_dev(ctx)->chipset) |
#define context_chan(ctx) \ |
(to_nouveau_context(ctx)->hw.chan) |
#define context_client(ctx) \ |
(to_nouveau_context(ctx)->hw.client) |
#define context_push(ctx) \ |
(to_nouveau_context(ctx)->hw.pushbuf) |
#define context_eng3d(ctx) \ |
(to_nouveau_context(ctx)->hw.eng3d) |
#define context_drv(ctx) \ |
(to_nouveau_context(ctx)->screen->driver) |
#define context_dirty(ctx, s) \ |
BITSET_SET(to_nouveau_context(ctx)->dirty, NOUVEAU_STATE_##s) |
#define context_dirty_i(ctx, s, i) \ |
BITSET_SET(to_nouveau_context(ctx)->dirty, NOUVEAU_STATE_##s##0 + i) |
#define context_emit(ctx, s) \ |
context_drv(ctx)->emit[NOUVEAU_STATE_##s](ctx, NOUVEAU_STATE_##s) |
GLboolean |
nouveau_context_create(gl_api api, |
const struct gl_config *visual, __DRIcontext *dri_ctx, |
unsigned major_version, unsigned minor_version, |
uint32_t flags, unsigned *error, void *share_ctx); |
GLboolean |
nouveau_context_init(struct gl_context *ctx, struct nouveau_screen *screen, |
const struct gl_config *visual, struct gl_context *share_ctx); |
void |
nouveau_context_deinit(struct gl_context *ctx); |
void |
nouveau_context_destroy(__DRIcontext *dri_ctx); |
void |
nouveau_update_renderbuffers(__DRIcontext *dri_ctx, __DRIdrawable *draw); |
GLboolean |
nouveau_context_make_current(__DRIcontext *dri_ctx, __DRIdrawable *ddraw, |
__DRIdrawable *rdraw); |
GLboolean |
nouveau_context_unbind(__DRIcontext *dri_ctx); |
void |
nouveau_fallback(struct gl_context *ctx, enum nouveau_fallback mode); |
void |
nouveau_validate_framebuffer(struct gl_context *ctx); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_driver.c |
---|
0,0 → 1,159 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "main/mtypes.h" |
#include "main/fbobject.h" |
#include "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_fbo.h" |
#include "nouveau_util.h" |
#include "drivers/common/meta.h" |
static const GLubyte * |
nouveau_get_string(struct gl_context *ctx, GLenum name) |
{ |
static char buffer[128]; |
char hardware_name[32]; |
switch (name) { |
case GL_VENDOR: |
return (GLubyte *)"Nouveau"; |
case GL_RENDERER: |
sprintf(hardware_name, "nv%02X", context_chipset(ctx)); |
driGetRendererString(buffer, hardware_name, 0); |
return (GLubyte *)buffer; |
default: |
return NULL; |
} |
} |
static void |
nouveau_flush(struct gl_context *ctx) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
PUSH_KICK(push); |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer) && |
ctx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { |
__DRIscreen *screen = nctx->screen->dri_screen; |
__DRIdri2LoaderExtension *dri2 = screen->dri2.loader; |
__DRIdrawable *drawable = nctx->dri_context->driDrawablePriv; |
if (drawable && drawable->loaderPrivate) |
dri2->flushFrontBuffer(drawable, drawable->loaderPrivate); |
} |
} |
static void |
nouveau_finish(struct gl_context *ctx) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_pushbuf_refn refn = |
{ nctx->fence, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR }; |
nouveau_flush(ctx); |
if (!nouveau_pushbuf_space(push, 16, 0, 0) && |
!nouveau_pushbuf_refn(push, &refn, 1)) { |
PUSH_DATA(push, 0); |
PUSH_KICK(push); |
} |
nouveau_bo_wait(nctx->fence, NOUVEAU_BO_RDWR, context_client(ctx)); |
} |
void |
nouveau_clear(struct gl_context *ctx, GLbitfield buffers) |
{ |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
int x, y, w, h; |
int i, buf; |
nouveau_validate_framebuffer(ctx); |
get_scissors(fb, &x, &y, &w, &h); |
for (i = 0; i < BUFFER_COUNT; i++) { |
struct nouveau_surface *s; |
unsigned mask, value; |
buf = buffers & (1 << i); |
if (!buf) |
continue; |
s = &to_nouveau_renderbuffer( |
fb->Attachment[i].Renderbuffer)->surface; |
if (buf & BUFFER_BITS_COLOR) { |
mask = pack_rgba_i(s->format, ctx->Color.ColorMask[0]); |
value = pack_rgba_clamp_f(s->format, ctx->Color.ClearColor.f); |
if (mask) |
context_drv(ctx)->surface_fill( |
ctx, s, mask, value, x, y, w, h); |
buffers &= ~buf; |
} else if (buf & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) { |
mask = pack_zs_i(s->format, |
(buffers & BUFFER_BIT_DEPTH && |
ctx->Depth.Mask) ? ~0 : 0, |
(buffers & BUFFER_BIT_STENCIL ? |
ctx->Stencil.WriteMask[0] : 0)); |
value = pack_zs_f(s->format, |
ctx->Depth.Clear, |
ctx->Stencil.Clear); |
if (mask) |
context_drv(ctx)->surface_fill( |
ctx, s, mask, value, x, y, w, h); |
buffers &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); |
} |
} |
if (buffers) |
_mesa_meta_Clear(ctx, buffers); |
} |
void |
nouveau_driver_functions_init(struct dd_function_table *functions) |
{ |
functions->GetString = nouveau_get_string; |
functions->Flush = nouveau_flush; |
functions->Finish = nouveau_finish; |
functions->Clear = nouveau_clear; |
functions->DrawPixels = _mesa_meta_DrawPixels; |
functions->CopyPixels = _mesa_meta_CopyPixels; |
functions->Bitmap = _mesa_meta_Bitmap; |
functions->BlitFramebuffer = _mesa_meta_BlitFramebuffer; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_driver.h |
---|
0,0 → 1,83 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_DRIVER_H__ |
#define __NOUVEAU_DRIVER_H__ |
#include "main/imports.h" |
#include "main/mtypes.h" |
#include "main/macros.h" |
#include "main/formats.h" |
#include "main/state.h" |
#include "utils.h" |
#include "dri_util.h" |
#undef NDEBUG |
#include <assert.h> |
#include <libdrm/nouveau.h> |
#include "nouveau_screen.h" |
#include "nouveau_state.h" |
#include "nouveau_surface.h" |
#include "nouveau_local.h" |
#define DRIVER_AUTHOR "Nouveau" |
struct nouveau_driver { |
struct gl_context *(*context_create)(struct nouveau_screen *screen, |
const struct gl_config *visual, |
struct gl_context *share_ctx); |
void (*context_destroy)(struct gl_context *ctx); |
void (*surface_copy)(struct gl_context *ctx, |
struct nouveau_surface *dst, |
struct nouveau_surface *src, |
int dx, int dy, int sx, int sy, int w, int h); |
void (*surface_fill)(struct gl_context *ctx, |
struct nouveau_surface *dst, |
unsigned mask, unsigned value, |
int dx, int dy, int w, int h); |
nouveau_state_func *emit; |
int num_emit; |
}; |
#define nouveau_error(format, ...) \ |
fprintf(stderr, "%s: " format, __func__, ## __VA_ARGS__) |
void |
nouveau_clear(struct gl_context *ctx, GLbitfield buffers); |
void |
nouveau_span_functions_init(struct gl_context *ctx); |
void |
nouveau_driver_functions_init(struct dd_function_table *functions); |
void |
nouveau_texture_functions_init(struct dd_function_table *functions); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_fbo.c |
---|
0,0 → 1,282 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_fbo.h" |
#include "nouveau_context.h" |
#include "nouveau_texture.h" |
#include "main/framebuffer.h" |
#include "main/renderbuffer.h" |
#include "main/fbobject.h" |
static GLboolean |
set_renderbuffer_format(struct gl_renderbuffer *rb, GLenum internalFormat) |
{ |
struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; |
rb->InternalFormat = internalFormat; |
switch (internalFormat) { |
case GL_RGB: |
case GL_RGB8: |
rb->_BaseFormat = GL_RGB; |
rb->Format = MESA_FORMAT_XRGB8888; |
s->cpp = 4; |
break; |
case GL_RGBA: |
case GL_RGBA8: |
rb->_BaseFormat = GL_RGBA; |
rb->Format = MESA_FORMAT_ARGB8888; |
s->cpp = 4; |
break; |
case GL_RGB5: |
rb->_BaseFormat = GL_RGB; |
rb->Format = MESA_FORMAT_RGB565; |
s->cpp = 2; |
break; |
case GL_DEPTH_COMPONENT16: |
rb->_BaseFormat = GL_DEPTH_COMPONENT; |
rb->Format = MESA_FORMAT_Z16; |
s->cpp = 2; |
break; |
case GL_DEPTH_COMPONENT: |
case GL_DEPTH_COMPONENT24: |
case GL_STENCIL_INDEX8_EXT: |
case GL_DEPTH24_STENCIL8_EXT: |
rb->_BaseFormat = GL_DEPTH_STENCIL; |
rb->Format = MESA_FORMAT_Z24_S8; |
s->cpp = 4; |
break; |
default: |
return GL_FALSE; |
} |
s->format = rb->Format; |
return GL_TRUE; |
} |
static GLboolean |
nouveau_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, |
GLuint width, GLuint height) |
{ |
struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; |
if (!set_renderbuffer_format(rb, internalFormat)) |
return GL_FALSE; |
rb->Width = width; |
rb->Height = height; |
nouveau_surface_alloc(ctx, s, TILED, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, |
rb->Format, width, height); |
context_dirty(ctx, FRAMEBUFFER); |
return GL_TRUE; |
} |
static void |
nouveau_renderbuffer_del(struct gl_context *ctx, struct gl_renderbuffer *rb) |
{ |
struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; |
nouveau_surface_ref(NULL, s); |
_mesa_delete_renderbuffer(ctx, rb); |
} |
static struct gl_renderbuffer * |
nouveau_renderbuffer_new(struct gl_context *ctx, GLuint name) |
{ |
struct gl_renderbuffer *rb; |
rb = (struct gl_renderbuffer *) |
CALLOC_STRUCT(nouveau_renderbuffer); |
if (!rb) |
return NULL; |
_mesa_init_renderbuffer(rb, name); |
rb->AllocStorage = nouveau_renderbuffer_storage; |
rb->Delete = nouveau_renderbuffer_del; |
return rb; |
} |
static void |
nouveau_renderbuffer_map(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **out_map, |
GLint *out_stride) |
{ |
struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; |
GLubyte *map; |
int stride; |
int flags = 0; |
if (mode & GL_MAP_READ_BIT) |
flags |= NOUVEAU_BO_RD; |
if (mode & GL_MAP_WRITE_BIT) |
flags |= NOUVEAU_BO_WR; |
nouveau_bo_map(s->bo, flags, context_client(ctx)); |
map = s->bo->map; |
stride = s->pitch; |
if (rb->Name == 0) { |
map += stride * (rb->Height - 1); |
stride = -stride; |
} |
map += x * s->cpp; |
map += (int)y * stride; |
*out_map = map; |
*out_stride = stride; |
} |
static void |
nouveau_renderbuffer_unmap(struct gl_context *ctx, |
struct gl_renderbuffer *rb) |
{ |
} |
static GLboolean |
nouveau_renderbuffer_dri_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, |
GLuint width, GLuint height) |
{ |
if (!set_renderbuffer_format(rb, internalFormat)) |
return GL_FALSE; |
rb->Width = width; |
rb->Height = height; |
return GL_TRUE; |
} |
struct gl_renderbuffer * |
nouveau_renderbuffer_dri_new(GLenum format, __DRIdrawable *drawable) |
{ |
struct gl_renderbuffer *rb; |
rb = nouveau_renderbuffer_new(NULL, 0); |
if (!rb) |
return NULL; |
rb->AllocStorage = nouveau_renderbuffer_dri_storage; |
if (!set_renderbuffer_format(rb, format)) { |
nouveau_renderbuffer_del(NULL, rb); |
return NULL; |
} |
return rb; |
} |
static struct gl_framebuffer * |
nouveau_framebuffer_new(struct gl_context *ctx, GLuint name) |
{ |
struct nouveau_framebuffer *nfb; |
nfb = CALLOC_STRUCT(nouveau_framebuffer); |
if (!nfb) |
return NULL; |
_mesa_initialize_user_framebuffer(&nfb->base, name); |
return &nfb->base; |
} |
struct gl_framebuffer * |
nouveau_framebuffer_dri_new(const struct gl_config *visual) |
{ |
struct nouveau_framebuffer *nfb; |
nfb = CALLOC_STRUCT(nouveau_framebuffer); |
if (!nfb) |
return NULL; |
_mesa_initialize_window_framebuffer(&nfb->base, visual); |
nfb->need_front = !visual->doubleBufferMode; |
return &nfb->base; |
} |
static void |
nouveau_bind_framebuffer(struct gl_context *ctx, GLenum target, |
struct gl_framebuffer *dfb, |
struct gl_framebuffer *rfb) |
{ |
context_dirty(ctx, FRAMEBUFFER); |
} |
static void |
nouveau_framebuffer_renderbuffer(struct gl_context *ctx, struct gl_framebuffer *fb, |
GLenum attachment, struct gl_renderbuffer *rb) |
{ |
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); |
context_dirty(ctx, FRAMEBUFFER); |
} |
static void |
nouveau_render_texture(struct gl_context *ctx, struct gl_framebuffer *fb, |
struct gl_renderbuffer_attachment *att) |
{ |
struct gl_renderbuffer *rb = att->Renderbuffer; |
struct gl_texture_image *ti = rb->TexImage; |
/* Update the renderbuffer fields from the texture. */ |
nouveau_surface_ref(&to_nouveau_teximage(ti)->surface, |
&to_nouveau_renderbuffer(rb)->surface); |
context_dirty(ctx, FRAMEBUFFER); |
} |
static void |
nouveau_finish_render_texture(struct gl_context *ctx, |
struct gl_renderbuffer *rb) |
{ |
texture_dirty(rb->TexImage->TexObject); |
} |
void |
nouveau_fbo_functions_init(struct dd_function_table *functions) |
{ |
functions->NewFramebuffer = nouveau_framebuffer_new; |
functions->NewRenderbuffer = nouveau_renderbuffer_new; |
functions->MapRenderbuffer = nouveau_renderbuffer_map; |
functions->UnmapRenderbuffer = nouveau_renderbuffer_unmap; |
functions->BindFramebuffer = nouveau_bind_framebuffer; |
functions->FramebufferRenderbuffer = nouveau_framebuffer_renderbuffer; |
functions->RenderTexture = nouveau_render_texture; |
functions->FinishRenderTexture = nouveau_finish_render_texture; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_fbo.h |
---|
0,0 → 1,56 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_FBO_H__ |
#define __NOUVEAU_FBO_H__ |
struct nouveau_framebuffer { |
struct gl_framebuffer base; |
GLboolean need_front; |
struct { |
struct nouveau_bo *bo; |
uint32_t clear_value; |
} hierz; |
}; |
#define to_nouveau_framebuffer(x) ((struct nouveau_framebuffer *)(x)) |
struct nouveau_renderbuffer { |
struct gl_renderbuffer base; |
struct nouveau_surface surface; |
}; |
#define to_nouveau_renderbuffer(x) ((struct nouveau_renderbuffer *)(x)) |
struct gl_framebuffer * |
nouveau_framebuffer_dri_new(const struct gl_config *visual); |
struct gl_renderbuffer * |
nouveau_renderbuffer_dri_new(GLenum format, __DRIdrawable *drawable); |
void |
nouveau_fbo_functions_init(struct dd_function_table *functions); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_gldefs.h |
---|
0,0 → 1,281 |
/* |
* Copyright (C) 2007-2010 The Nouveau Project. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_GLDEFS_H__ |
#define __NOUVEAU_GLDEFS_H__ |
static inline unsigned |
nvgl_blend_func(unsigned func) |
{ |
switch (func) { |
case GL_ZERO: |
return 0x0000; |
case GL_ONE: |
return 0x0001; |
case GL_SRC_COLOR: |
return 0x0300; |
case GL_ONE_MINUS_SRC_COLOR: |
return 0x0301; |
case GL_SRC_ALPHA: |
return 0x0302; |
case GL_ONE_MINUS_SRC_ALPHA: |
return 0x0303; |
case GL_DST_ALPHA: |
return 0x0304; |
case GL_ONE_MINUS_DST_ALPHA: |
return 0x0305; |
case GL_DST_COLOR: |
return 0x0306; |
case GL_ONE_MINUS_DST_COLOR: |
return 0x0307; |
case GL_SRC_ALPHA_SATURATE: |
return 0x0308; |
case GL_CONSTANT_COLOR: |
return 0x8001; |
case GL_ONE_MINUS_CONSTANT_COLOR: |
return 0x8002; |
case GL_CONSTANT_ALPHA: |
return 0x8003; |
case GL_ONE_MINUS_CONSTANT_ALPHA: |
return 0x8004; |
default: |
assert(0); |
} |
} |
static inline unsigned |
nvgl_blend_eqn(unsigned eqn) |
{ |
switch (eqn) { |
case GL_FUNC_ADD: |
return 0x8006; |
case GL_MIN: |
return 0x8007; |
case GL_MAX: |
return 0x8008; |
case GL_FUNC_SUBTRACT: |
return 0x800a; |
case GL_FUNC_REVERSE_SUBTRACT: |
return 0x800b; |
default: |
assert(0); |
} |
} |
static inline unsigned |
nvgl_logicop_func(unsigned func) |
{ |
switch (func) { |
case GL_CLEAR: |
return 0x1500; |
case GL_NOR: |
return 0x1508; |
case GL_AND_INVERTED: |
return 0x1504; |
case GL_COPY_INVERTED: |
return 0x150c; |
case GL_AND_REVERSE: |
return 0x1502; |
case GL_INVERT: |
return 0x150a; |
case GL_XOR: |
return 0x1506; |
case GL_NAND: |
return 0x150e; |
case GL_AND: |
return 0x1501; |
case GL_EQUIV: |
return 0x1509; |
case GL_NOOP: |
return 0x1505; |
case GL_OR_INVERTED: |
return 0x150d; |
case GL_COPY: |
return 0x1503; |
case GL_OR_REVERSE: |
return 0x150b; |
case GL_OR: |
return 0x1507; |
case GL_SET: |
return 0x150f; |
default: |
assert(0); |
} |
} |
static inline unsigned |
nvgl_comparison_op(unsigned op) |
{ |
switch (op) { |
case GL_NEVER: |
return 0x0200; |
case GL_LESS: |
return 0x0201; |
case GL_EQUAL: |
return 0x0202; |
case GL_LEQUAL: |
return 0x0203; |
case GL_GREATER: |
return 0x0204; |
case GL_NOTEQUAL: |
return 0x0205; |
case GL_GEQUAL: |
return 0x0206; |
case GL_ALWAYS: |
return 0x0207; |
default: |
assert(0); |
} |
} |
static inline unsigned |
nvgl_polygon_mode(unsigned mode) |
{ |
switch (mode) { |
case GL_POINT: |
return 0x1b00; |
case GL_LINE: |
return 0x1b01; |
case GL_FILL: |
return 0x1b02; |
default: |
assert(0); |
} |
} |
static inline unsigned |
nvgl_stencil_op(unsigned op) |
{ |
switch (op) { |
case GL_ZERO: |
return 0x0000; |
case GL_INVERT: |
return 0x150a; |
case GL_KEEP: |
return 0x1e00; |
case GL_REPLACE: |
return 0x1e01; |
case GL_INCR: |
return 0x1e02; |
case GL_DECR: |
return 0x1e03; |
case GL_INCR_WRAP_EXT: |
return 0x8507; |
case GL_DECR_WRAP_EXT: |
return 0x8508; |
default: |
assert(0); |
} |
} |
static inline unsigned |
nvgl_primitive(unsigned prim) |
{ |
switch (prim) { |
case GL_POINTS: |
return 0x0001; |
case GL_LINES: |
return 0x0002; |
case GL_LINE_LOOP: |
return 0x0003; |
case GL_LINE_STRIP: |
return 0x0004; |
case GL_TRIANGLES: |
return 0x0005; |
case GL_TRIANGLE_STRIP: |
return 0x0006; |
case GL_TRIANGLE_FAN: |
return 0x0007; |
case GL_QUADS: |
return 0x0008; |
case GL_QUAD_STRIP: |
return 0x0009; |
case GL_POLYGON: |
return 0x000a; |
default: |
assert(0); |
} |
} |
static inline unsigned |
nvgl_wrap_mode(unsigned wrap) |
{ |
switch (wrap) { |
case GL_REPEAT: |
return 0x1; |
case GL_MIRRORED_REPEAT: |
return 0x2; |
case GL_CLAMP: |
case GL_CLAMP_TO_EDGE: |
return 0x3; |
case GL_CLAMP_TO_BORDER: |
return 0x4; |
default: |
assert(0); |
} |
} |
static inline unsigned |
nvgl_filter_mode(unsigned filter) |
{ |
switch (filter) { |
case GL_NEAREST: |
return 0x1; |
case GL_LINEAR: |
return 0x2; |
case GL_NEAREST_MIPMAP_NEAREST: |
return 0x3; |
case GL_LINEAR_MIPMAP_NEAREST: |
return 0x4; |
case GL_NEAREST_MIPMAP_LINEAR: |
return 0x5; |
case GL_LINEAR_MIPMAP_LINEAR: |
return 0x6; |
default: |
assert(0); |
} |
} |
static inline unsigned |
nvgl_texgen_mode(unsigned mode) |
{ |
switch (mode) { |
case GL_EYE_LINEAR: |
return 0x2400; |
case GL_OBJECT_LINEAR: |
return 0x2401; |
case GL_SPHERE_MAP: |
return 0x2402; |
case GL_NORMAL_MAP: |
return 0x8511; |
case GL_REFLECTION_MAP: |
return 0x8512; |
default: |
assert(0); |
} |
} |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_local.h |
---|
0,0 → 1,191 |
/* |
* Copyright 2007 Nouveau Project |
* |
* 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. |
*/ |
#ifndef __NOUVEAU_LOCAL_H__ |
#define __NOUVEAU_LOCAL_H__ |
static inline uint32_t |
PUSH_AVAIL(struct nouveau_pushbuf *push) |
{ |
return push->end - push->cur; |
} |
static inline int |
PUSH_SPACE(struct nouveau_pushbuf *push, uint32_t size) |
{ |
if (PUSH_AVAIL(push) < size) |
return nouveau_pushbuf_space(push, size, 0, 0) == 0; |
return 1; |
} |
static inline void |
PUSH_DATA(struct nouveau_pushbuf *push, uint32_t data) |
{ |
*push->cur++ = data; |
} |
static inline void |
PUSH_DATAf(struct nouveau_pushbuf *push, float v) |
{ |
union { float f; uint32_t i; } d = { .f = v }; |
PUSH_DATA(push, d.i); |
} |
static inline void |
PUSH_DATAb(struct nouveau_pushbuf *push, GLboolean x) |
{ |
PUSH_DATA(push, x ? 1 : 0); |
} |
static inline void |
PUSH_DATAm(struct nouveau_pushbuf *push, float m[16]) |
{ |
int i, j; |
for (i = 0; i < 4; i++) |
for (j = 0; j < 4; j++) |
PUSH_DATAf(push, m[4*j + i]); |
} |
static inline void |
PUSH_DATAp(struct nouveau_pushbuf *push, const void *data, uint32_t size) |
{ |
memcpy(push->cur, data, size * 4); |
push->cur += size; |
} |
static inline void |
PUSH_RELOC(struct nouveau_pushbuf *push, struct nouveau_bo *bo, uint32_t offset, |
uint32_t flags, uint32_t vor, uint32_t tor) |
{ |
nouveau_pushbuf_reloc(push, bo, offset, flags, vor, tor); |
} |
static inline void |
PUSH_KICK(struct nouveau_pushbuf *push) |
{ |
nouveau_pushbuf_kick(push, push->channel); |
} |
static struct nouveau_bufctx * |
BUFCTX(struct nouveau_pushbuf *push) |
{ |
return push->user_priv; |
} |
static inline void |
PUSH_RESET(struct nouveau_pushbuf *push, int bin) |
{ |
nouveau_bufctx_reset(BUFCTX(push), bin); |
} |
static inline void |
PUSH_MTHDl(struct nouveau_pushbuf *push, int subc, int mthd, int bin, |
struct nouveau_bo *bo, uint32_t offset, uint32_t access) |
{ |
nouveau_bufctx_mthd(BUFCTX(push), bin, (1 << 18) | (subc << 13) | mthd, |
bo, offset, access | NOUVEAU_BO_LOW, 0, 0); |
PUSH_DATA(push, bo->offset + offset); |
} |
static inline void |
PUSH_MTHDs(struct nouveau_pushbuf *push, int subc, int mthd, int bin, |
struct nouveau_bo *bo, uint32_t data, uint32_t access, |
uint32_t vor, uint32_t tor) |
{ |
nouveau_bufctx_mthd(BUFCTX(push), bin, (1 << 18) | (subc << 13) | mthd, |
bo, data, access | NOUVEAU_BO_OR, vor, tor); |
if (bo->flags & NOUVEAU_BO_VRAM) |
PUSH_DATA(push, data | vor); |
else |
PUSH_DATA(push, data | tor); |
} |
static inline void |
PUSH_MTHD(struct nouveau_pushbuf *push, int subc, int mthd, int bin, |
struct nouveau_bo *bo, uint32_t data, uint32_t access, |
uint32_t vor, uint32_t tor) |
{ |
nouveau_bufctx_mthd(BUFCTX(push), bin, (1 << 18) | (subc << 13) | mthd, |
bo, data, access | NOUVEAU_BO_OR, vor, tor); |
if (access & NOUVEAU_BO_LOW) |
data += bo->offset; |
if (access & NOUVEAU_BO_OR) { |
if (bo->flags & NOUVEAU_BO_VRAM) |
data |= vor; |
else |
data |= tor; |
} |
PUSH_DATA(push, data); |
} |
static inline void |
BEGIN_NV04(struct nouveau_pushbuf *push, int subc, int mthd, int size) |
{ |
PUSH_SPACE(push, size + 1); |
PUSH_DATA (push, 0x00000000 | (size << 18) | (subc << 13) | mthd); |
} |
static inline void |
BEGIN_NI04(struct nouveau_pushbuf *push, int subc, int mthd, int size) |
{ |
PUSH_SPACE(push, size + 1); |
PUSH_DATA (push, 0x40000000 | (size << 18) | (subc << 13) | mthd); |
} |
/* subchannel assignment */ |
#define SUBC_M2MF(mthd) 0, (mthd) |
#define NV03_M2MF(mthd) SUBC_M2MF(NV04_M2MF_##mthd) |
#define SUBC_NVSW(mthd) 1, (mthd) |
#define SUBC_SF2D(mthd) 2, (mthd) |
#define NV04_SF2D(mthd) SUBC_SF2D(NV04_CONTEXT_SURFACES_2D_##mthd) |
#define NV10_SF2D(mthd) SUBC_SF2D(NV10_CONTEXT_SURFACES_2D_##mthd) |
#define SUBC_PATT(mthd) 3, (mthd) |
#define NV01_PATT(mthd) SUBC_PATT(NV04_IMAGE_PATTERN_##mthd) |
#define NV01_ROP(mthd) SUBC_PATT(NV03_CONTEXT_ROP_##mthd) |
#define SUBC_GDI(mthd) 4, (mthd) |
#define NV04_GDI(mthd) SUBC_GDI(NV04_GDI_RECTANGLE_TEXT_##mthd) |
#define SUBC_SIFM(mthd) 5, (mthd) |
#define NV03_SIFM(mthd) SUBC_SIFM(NV03_SCALED_IMAGE_FROM_MEMORY_##mthd) |
#define NV05_SIFM(mthd) SUBC_SIFM(NV05_SCALED_IMAGE_FROM_MEMORY_##mthd) |
#define SUBC_SURF(mthd) 6, (mthd) |
#define NV04_SSWZ(mthd) SUBC_SURF(NV04_SWIZZLED_SURFACE_##mthd) |
#define NV04_SF3D(mthd) SUBC_SURF(NV04_CONTEXT_SURFACES_3D_##mthd) |
#define SUBC_3D(mthd) 7, (mthd) |
#define NV04_TTRI(mthd) SUBC_3D(NV04_TEXTURED_TRIANGLE_##mthd) |
#define NV04_MTRI(mthd) SUBC_3D(NV04_MULTITEX_TRIANGLE_##mthd) |
#define NV10_3D(mthd) SUBC_3D(NV10_3D_##mthd) |
#define NV11_3D(mthd) SUBC_3D(NV11_3D_##mthd) |
#define NV17_3D(mthd) SUBC_3D(NV17_3D_##mthd) |
#define NV20_3D(mthd) SUBC_3D(NV20_3D_##mthd) |
#define NV25_3D(mthd) SUBC_3D(NV25_3D_##mthd) |
#define NV01_SUBC(subc, mthd) SUBC_##subc((NV01_SUBCHAN_##mthd)) |
#define NV11_SUBC(subc, mthd) SUBC_##subc((NV11_SUBCHAN_##mthd)) |
#define NV04_GRAPH(subc, mthd) SUBC_##subc((NV04_GRAPH_##mthd)) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_render.h |
---|
0,0 → 1,80 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_RENDER_H__ |
#define __NOUVEAU_RENDER_H__ |
#include "vbo/vbo_context.h" |
#include "nouveau_array.h" |
typedef void (*dispatch_t)(struct gl_context *, unsigned int, int, unsigned int); |
typedef void (*emit_t)(struct gl_context *, struct nouveau_array *, const void *); |
struct nouveau_attr_info { |
int vbo_index; |
int imm_method; |
int imm_fields; |
emit_t emit; |
}; |
struct nouveau_swtnl_state { |
struct nouveau_bo *vbo; |
unsigned offset; |
void *buf; |
unsigned vertex_count; |
GLenum primitive; |
}; |
struct nouveau_render_state { |
enum { |
VBO, |
IMM |
} mode; |
struct nouveau_array ib; |
struct nouveau_array attrs[VERT_ATTRIB_MAX]; |
/* Maps a HW VBO index or IMM emission order to an index in |
* the attrs array above (or -1 if unused). */ |
int map[VERT_ATTRIB_MAX]; |
int attr_count; |
int vertex_size; |
struct nouveau_swtnl_state swtnl; |
}; |
#define to_render_state(ctx) (&to_nouveau_context(ctx)->render) |
#define FOR_EACH_ATTR(render, i, attr) \ |
for (i = 0; attr = (render)->map[i], i < NUM_VERTEX_ATTRS; i++) |
#define FOR_EACH_BOUND_ATTR(render, i, attr) \ |
for (i = 0; attr = (render)->map[i], i < render->attr_count; i++) \ |
if (attr >= 0) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_render_t.c |
---|
0,0 → 1,209 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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. |
* |
*/ |
/* |
* Vertex submission helper definitions shared among the software and |
* hardware TnL paths. |
*/ |
#include "nouveau_gldefs.h" |
#include "main/light.h" |
#include "vbo/vbo.h" |
#include "tnl/tnl.h" |
#define OUT_INDICES_L(r, i, d, n) \ |
BATCH_OUT_L(i + d, n); \ |
(void)r |
#define OUT_INDICES_I16(r, i, d, n) \ |
BATCH_OUT_I16(r->ib.extract_u(&r->ib, 0, i) + d, \ |
r->ib.extract_u(&r->ib, 0, i + 1) + d) |
#define OUT_INDICES_I32(r, i, d, n) \ |
BATCH_OUT_I32(r->ib.extract_u(&r->ib, 0, i) + d) |
/* |
* Emit <n> vertices using BATCH_OUT_<out>, MAX_OUT_<out> at a time, |
* grouping them in packets of length MAX_PACKET. |
* |
* out: hardware index data type. |
* ctx: GL context. |
* start: element within the index buffer to begin with. |
* delta: integer correction that will be added to each index found in |
* the index buffer. |
*/ |
#define EMIT_VBO(out, ctx, start, delta, n) do { \ |
struct nouveau_render_state *render = to_render_state(ctx); \ |
int npush = n; \ |
\ |
while (npush) { \ |
int npack = MIN2(npush, MAX_PACKET * MAX_OUT_##out); \ |
npush -= npack; \ |
\ |
BATCH_PACKET_##out((npack + MAX_OUT_##out - 1) \ |
/ MAX_OUT_##out); \ |
while (npack) { \ |
int nout = MIN2(npack, MAX_OUT_##out); \ |
npack -= nout; \ |
\ |
OUT_INDICES_##out(render, start, delta, \ |
nout); \ |
start += nout; \ |
} \ |
} \ |
} while (0) |
/* |
* Emit the <n>-th element of the array <a>, using IMM_OUT. |
*/ |
#define EMIT_IMM(ctx, a, n) do { \ |
struct nouveau_attr_info *info = \ |
&TAG(vertex_attrs)[(a)->attr]; \ |
int m; \ |
\ |
if (!info->emit) { \ |
IMM_PACKET(info->imm_method, info->imm_fields); \ |
\ |
for (m = 0; m < (a)->fields; m++) \ |
IMM_OUT((a)->extract_f(a, n, m)); \ |
\ |
for (m = (a)->fields; m < info->imm_fields; m++) \ |
IMM_OUT(((float []){0, 0, 0, 1})[m]); \ |
\ |
} else { \ |
info->emit(ctx, a, (a)->buf + n * (a)->stride); \ |
} \ |
} while (0) |
static void |
dispatch_l(struct gl_context *ctx, unsigned int start, int delta, |
unsigned int n) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
RENDER_LOCALS(ctx); |
EMIT_VBO(L, ctx, start, delta, n); |
} |
static void |
dispatch_i32(struct gl_context *ctx, unsigned int start, int delta, |
unsigned int n) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
RENDER_LOCALS(ctx); |
EMIT_VBO(I32, ctx, start, delta, n); |
} |
static void |
dispatch_i16(struct gl_context *ctx, unsigned int start, int delta, |
unsigned int n) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
RENDER_LOCALS(ctx); |
EMIT_VBO(I32, ctx, start, delta, n & 1); |
EMIT_VBO(I16, ctx, start, delta, n & ~1); |
} |
/* |
* Select an appropriate dispatch function for the given index buffer. |
*/ |
static dispatch_t |
get_array_dispatch(struct nouveau_array *a) |
{ |
if (!a->fields) |
return dispatch_l; |
else if (a->type == GL_UNSIGNED_INT) |
return dispatch_i32; |
else |
return dispatch_i16; |
} |
/* |
* Returns how many vertices you can draw using <n> pushbuf dwords. |
*/ |
static inline unsigned |
get_max_vertices(struct gl_context *ctx, const struct _mesa_index_buffer *ib, |
int n) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
if (render->mode == IMM) { |
return MAX2(0, n - 4) / (render->vertex_size / 4 + |
render->attr_count); |
} else { |
unsigned max_out; |
if (ib) { |
switch (ib->type) { |
case GL_UNSIGNED_INT: |
max_out = MAX_OUT_I32; |
break; |
case GL_UNSIGNED_SHORT: |
max_out = MAX_OUT_I16; |
break; |
case GL_UNSIGNED_BYTE: |
max_out = MAX_OUT_I16; |
break; |
default: |
assert(0); |
max_out = 0; |
break; |
} |
} else { |
max_out = MAX_OUT_L; |
} |
return MAX2(0, n - 7) * max_out * MAX_PACKET / (1 + MAX_PACKET); |
} |
} |
static void |
TAG(emit_material)(struct gl_context *ctx, struct nouveau_array *a, |
const void *v) |
{ |
int attr = a->attr - VERT_ATTRIB_GENERIC0; |
int state = ((int []) { |
NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT, |
NOUVEAU_STATE_MATERIAL_BACK_AMBIENT, |
NOUVEAU_STATE_MATERIAL_FRONT_DIFFUSE, |
NOUVEAU_STATE_MATERIAL_BACK_DIFFUSE, |
NOUVEAU_STATE_MATERIAL_FRONT_SPECULAR, |
NOUVEAU_STATE_MATERIAL_BACK_SPECULAR, |
NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT, |
NOUVEAU_STATE_MATERIAL_BACK_AMBIENT, |
NOUVEAU_STATE_MATERIAL_FRONT_SHININESS, |
NOUVEAU_STATE_MATERIAL_BACK_SHININESS |
}) [attr]; |
COPY_4V(ctx->Light.Material.Attrib[attr], (float *)v); |
_mesa_update_material(ctx, 1 << attr); |
context_drv(ctx)->emit[state](ctx, state); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_scratch.c |
---|
0,0 → 1,97 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
/* |
* Returns a pointer to a chunk of 'size' bytes long GART memory. 'bo' |
* and 'offset' will point to the returned memory. |
*/ |
void * |
nouveau_get_scratch(struct gl_context *ctx, unsigned size, |
struct nouveau_bo **bo, unsigned *offset) |
{ |
struct nouveau_client *client = context_client(ctx); |
struct nouveau_scratch_state *scratch = |
&to_nouveau_context(ctx)->scratch; |
void *buf; |
if (scratch->buf && size <= NOUVEAU_SCRATCH_SIZE - scratch->offset) { |
nouveau_bo_ref(scratch->bo[scratch->index], bo); |
buf = scratch->buf + scratch->offset; |
*offset = scratch->offset; |
scratch->offset += size; |
} else if (size <= NOUVEAU_SCRATCH_SIZE) { |
scratch->index = (scratch->index + 1) % NOUVEAU_SCRATCH_COUNT; |
nouveau_bo_ref(scratch->bo[scratch->index], bo); |
nouveau_bo_map(*bo, NOUVEAU_BO_WR, client); |
buf = scratch->buf = (*bo)->map; |
*offset = 0; |
scratch->offset = size; |
} else { |
nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_GART | |
NOUVEAU_BO_MAP, 0, size, NULL, bo); |
nouveau_bo_map(*bo, NOUVEAU_BO_WR, client); |
buf = (*bo)->map; |
*offset = 0; |
} |
return buf; |
} |
void |
nouveau_scratch_init(struct gl_context *ctx) |
{ |
struct nouveau_scratch_state *scratch = |
&to_nouveau_context(ctx)->scratch; |
int ret, i; |
for (i = 0; i < NOUVEAU_SCRATCH_COUNT; i++) { |
ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_GART | |
NOUVEAU_BO_MAP, 0, NOUVEAU_SCRATCH_SIZE, |
NULL, &scratch->bo[i]); |
assert(!ret); |
} |
} |
void |
nouveau_scratch_destroy(struct gl_context *ctx) |
{ |
struct nouveau_scratch_state *scratch = |
&to_nouveau_context(ctx)->scratch; |
int i; |
for (i = 0; i < NOUVEAU_SCRATCH_COUNT; i++) |
nouveau_bo_ref(NULL, &scratch->bo[i]); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_scratch.h |
---|
0,0 → 1,51 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_SCRATCH_H__ |
#define __NOUVEAU_SCRATCH_H__ |
#define NOUVEAU_SCRATCH_COUNT 2 |
#define NOUVEAU_SCRATCH_SIZE 3*1024*1024 |
struct nouveau_scratch_state { |
struct nouveau_bo *bo[NOUVEAU_SCRATCH_COUNT]; |
int index; |
int offset; |
void *buf; |
}; |
void * |
nouveau_get_scratch(struct gl_context *ctx, unsigned size, |
struct nouveau_bo **bo, unsigned *offset); |
void |
nouveau_scratch_init(struct gl_context *ctx); |
void |
nouveau_scratch_destroy(struct gl_context *ctx); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_screen.c |
---|
0,0 → 1,253 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_fbo.h" |
#include "nouveau_texture.h" |
#include "nv04_driver.h" |
#include "nv10_driver.h" |
#include "nv20_driver.h" |
#include "main/framebuffer.h" |
#include "main/fbobject.h" |
#include "main/renderbuffer.h" |
#include "swrast/s_renderbuffer.h" |
static const __DRIextension *nouveau_screen_extensions[]; |
static void |
nouveau_destroy_screen(__DRIscreen *dri_screen); |
static const __DRIconfig ** |
nouveau_get_configs(void) |
{ |
__DRIconfig **configs = NULL; |
int i; |
const uint8_t depth_bits[] = { 0, 16, 24, 24 }; |
const uint8_t stencil_bits[] = { 0, 0, 0, 8 }; |
const uint8_t msaa_samples[] = { 0 }; |
static const gl_format formats[3] = { |
MESA_FORMAT_RGB565, |
MESA_FORMAT_ARGB8888, |
MESA_FORMAT_XRGB8888, |
}; |
const GLenum back_buffer_modes[] = { |
GLX_NONE, GLX_SWAP_UNDEFINED_OML |
}; |
for (i = 0; i < Elements(formats); i++) { |
__DRIconfig **config; |
config = driCreateConfigs(formats[i], |
depth_bits, stencil_bits, |
Elements(depth_bits), |
back_buffer_modes, |
Elements(back_buffer_modes), |
msaa_samples, |
Elements(msaa_samples), |
GL_TRUE); |
assert(config); |
configs = driConcatConfigs(configs, config); |
} |
return (const __DRIconfig **)configs; |
} |
static const __DRIconfig ** |
nouveau_init_screen2(__DRIscreen *dri_screen) |
{ |
const __DRIconfig **configs; |
struct nouveau_screen *screen; |
int ret; |
/* Allocate the screen. */ |
screen = CALLOC_STRUCT(nouveau_screen); |
if (!screen) |
return NULL; |
dri_screen->driverPrivate = screen; |
dri_screen->extensions = nouveau_screen_extensions; |
screen->dri_screen = dri_screen; |
/* Open the DRM device. */ |
ret = nouveau_device_wrap(dri_screen->fd, 0, &screen->device); |
if (ret) { |
nouveau_error("Error opening the DRM device.\n"); |
goto fail; |
} |
/* Choose the card specific function pointers. */ |
switch (screen->device->chipset & 0xf0) { |
case 0x00: |
screen->driver = &nv04_driver; |
break; |
case 0x10: |
screen->driver = &nv10_driver; |
break; |
case 0x20: |
screen->driver = &nv20_driver; |
break; |
default: |
assert(0); |
} |
configs = nouveau_get_configs(); |
if (!configs) |
goto fail; |
return configs; |
fail: |
nouveau_destroy_screen(dri_screen); |
return NULL; |
} |
static void |
nouveau_destroy_screen(__DRIscreen *dri_screen) |
{ |
struct nouveau_screen *screen = dri_screen->driverPrivate; |
if (!screen) |
return; |
nouveau_device_del(&screen->device); |
free(screen); |
dri_screen->driverPrivate = NULL; |
} |
static GLboolean |
nouveau_create_buffer(__DRIscreen *dri_screen, |
__DRIdrawable *drawable, |
const struct gl_config *visual, |
GLboolean is_pixmap) |
{ |
struct gl_renderbuffer *rb; |
struct gl_framebuffer *fb; |
GLenum color_format; |
if (is_pixmap) |
return GL_FALSE; /* not implemented */ |
if (visual->redBits == 5) |
color_format = GL_RGB5; |
else if (visual->alphaBits == 0) |
color_format = GL_RGB8; |
else |
color_format = GL_RGBA8; |
fb = nouveau_framebuffer_dri_new(visual); |
if (!fb) |
return GL_FALSE; |
/* Front buffer. */ |
rb = nouveau_renderbuffer_dri_new(color_format, drawable); |
_mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, rb); |
/* Back buffer */ |
if (visual->doubleBufferMode) { |
rb = nouveau_renderbuffer_dri_new(color_format, drawable); |
_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, rb); |
} |
/* Depth/stencil buffer. */ |
if (visual->depthBits == 24 && visual->stencilBits == 8) { |
rb = nouveau_renderbuffer_dri_new(GL_DEPTH24_STENCIL8_EXT, drawable); |
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); |
_mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb); |
} else if (visual->depthBits == 24) { |
rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT24, drawable); |
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); |
} else if (visual->depthBits == 16) { |
rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT16, drawable); |
_mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb); |
} |
/* Software renderbuffers. */ |
_swrast_add_soft_renderbuffers(fb, GL_FALSE, GL_FALSE, GL_FALSE, |
visual->accumRedBits > 0, |
GL_FALSE, GL_FALSE); |
drawable->driverPrivate = fb; |
return GL_TRUE; |
} |
static void |
nouveau_destroy_buffer(__DRIdrawable *drawable) |
{ |
_mesa_reference_framebuffer( |
(struct gl_framebuffer **)&drawable->driverPrivate, NULL); |
} |
static void |
nouveau_drawable_flush(__DRIdrawable *draw) |
{ |
} |
static const struct __DRI2flushExtensionRec nouveau_flush_extension = { |
{ __DRI2_FLUSH, 3 }, |
nouveau_drawable_flush, |
dri2InvalidateDrawable, |
}; |
static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = { |
{ __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, |
NULL, |
nouveau_set_texbuffer, |
}; |
static const __DRIextension *nouveau_screen_extensions[] = { |
&nouveau_flush_extension.base, |
&nouveau_texbuffer_extension.base, |
&dri2ConfigQueryExtension.base, |
NULL |
}; |
const struct __DriverAPIRec driDriverAPI = { |
.InitScreen = nouveau_init_screen2, |
.DestroyScreen = nouveau_destroy_screen, |
.CreateBuffer = nouveau_create_buffer, |
.DestroyBuffer = nouveau_destroy_buffer, |
.CreateContext = nouveau_context_create, |
.DestroyContext = nouveau_context_destroy, |
.MakeCurrent = nouveau_context_make_current, |
.UnbindContext = nouveau_context_unbind, |
}; |
/* This is the table of extensions that the loader will dlsym() for. */ |
PUBLIC const __DRIextension *__driDriverExtensions[] = { |
&driCoreExtension.base, |
&driDRI2Extension.base, |
NULL |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_screen.h |
---|
0,0 → 1,38 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_SCREEN_H__ |
#define __NOUVEAU_SCREEN_H__ |
struct nouveau_context; |
struct nouveau_screen { |
__DRIscreen *dri_screen; |
struct nouveau_device *device; |
const struct nouveau_driver *driver; |
}; |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_span.c |
---|
0,0 → 1,99 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_fbo.h" |
#include "nouveau_context.h" |
#include "swrast/swrast.h" |
#include "swrast/s_context.h" |
static void |
renderbuffer_map_unmap(struct gl_context *ctx, struct gl_renderbuffer *rb, |
GLboolean map) |
{ |
struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; |
if (map) |
nouveau_bo_map(s->bo, NOUVEAU_BO_RDWR, context_client(ctx)); |
} |
static void |
framebuffer_map_unmap(struct gl_context *ctx, struct gl_framebuffer *fb, GLboolean map) |
{ |
int i; |
for (i = 0; i < fb->_NumColorDrawBuffers; i++) |
renderbuffer_map_unmap(ctx, fb->_ColorDrawBuffers[i], map); |
renderbuffer_map_unmap(ctx, fb->_ColorReadBuffer, map); |
if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) |
renderbuffer_map_unmap(ctx, fb->Attachment[BUFFER_DEPTH].Renderbuffer, map); |
} |
static void |
span_map_unmap(struct gl_context *ctx, GLboolean map) |
{ |
int i; |
framebuffer_map_unmap(ctx, ctx->DrawBuffer, map); |
if (ctx->ReadBuffer != ctx->DrawBuffer) |
framebuffer_map_unmap(ctx, ctx->ReadBuffer, map); |
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) |
if (map) |
_swrast_map_texture(ctx, ctx->Texture.Unit[i]._Current); |
else |
_swrast_unmap_texture(ctx, ctx->Texture.Unit[i]._Current); |
} |
static void |
nouveau_span_start(struct gl_context *ctx) |
{ |
nouveau_fallback(ctx, SWRAST); |
span_map_unmap(ctx, GL_TRUE); |
} |
static void |
nouveau_span_finish(struct gl_context *ctx) |
{ |
span_map_unmap(ctx, GL_FALSE); |
nouveau_fallback(ctx, HWTNL); |
} |
void |
nouveau_span_functions_init(struct gl_context *ctx) |
{ |
struct swrast_device_driver *swdd = |
_swrast_GetDeviceDriverReference(ctx); |
swdd->SpanRenderStart = nouveau_span_start; |
swdd->SpanRenderFinish = nouveau_span_finish; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state.c |
---|
0,0 → 1,556 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_texture.h" |
#include "nouveau_util.h" |
#include "swrast/swrast.h" |
#include "tnl/tnl.h" |
static void |
nouveau_alpha_func(struct gl_context *ctx, GLenum func, GLfloat ref) |
{ |
context_dirty(ctx, ALPHA_FUNC); |
} |
static void |
nouveau_blend_color(struct gl_context *ctx, const GLfloat color[4]) |
{ |
context_dirty(ctx, BLEND_COLOR); |
} |
static void |
nouveau_blend_equation_separate(struct gl_context *ctx, GLenum modeRGB, GLenum modeA) |
{ |
context_dirty(ctx, BLEND_EQUATION); |
} |
static void |
nouveau_blend_func_separate(struct gl_context *ctx, GLenum sfactorRGB, |
GLenum dfactorRGB, GLenum sfactorA, GLenum dfactorA) |
{ |
context_dirty(ctx, BLEND_FUNC); |
} |
static void |
nouveau_clip_plane(struct gl_context *ctx, GLenum plane, const GLfloat *equation) |
{ |
context_dirty_i(ctx, CLIP_PLANE, plane - GL_CLIP_PLANE0); |
} |
static void |
nouveau_color_mask(struct gl_context *ctx, GLboolean rmask, GLboolean gmask, |
GLboolean bmask, GLboolean amask) |
{ |
context_dirty(ctx, COLOR_MASK); |
} |
static void |
nouveau_color_material(struct gl_context *ctx, GLenum face, GLenum mode) |
{ |
context_dirty(ctx, COLOR_MATERIAL); |
context_dirty(ctx, MATERIAL_FRONT_AMBIENT); |
context_dirty(ctx, MATERIAL_BACK_AMBIENT); |
context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); |
context_dirty(ctx, MATERIAL_BACK_DIFFUSE); |
context_dirty(ctx, MATERIAL_FRONT_SPECULAR); |
context_dirty(ctx, MATERIAL_BACK_SPECULAR); |
} |
static void |
nouveau_cull_face(struct gl_context *ctx, GLenum mode) |
{ |
context_dirty(ctx, CULL_FACE); |
} |
static void |
nouveau_front_face(struct gl_context *ctx, GLenum mode) |
{ |
context_dirty(ctx, FRONT_FACE); |
} |
static void |
nouveau_depth_func(struct gl_context *ctx, GLenum func) |
{ |
context_dirty(ctx, DEPTH); |
} |
static void |
nouveau_depth_mask(struct gl_context *ctx, GLboolean flag) |
{ |
context_dirty(ctx, DEPTH); |
} |
static void |
nouveau_depth_range(struct gl_context *ctx, GLclampd nearval, GLclampd farval) |
{ |
context_dirty(ctx, VIEWPORT); |
} |
static void |
nouveau_read_buffer(struct gl_context *ctx, GLenum buffer) |
{ |
nouveau_validate_framebuffer(ctx); |
} |
static void |
nouveau_draw_buffers(struct gl_context *ctx, GLsizei n, const GLenum *buffers) |
{ |
nouveau_validate_framebuffer(ctx); |
context_dirty(ctx, FRAMEBUFFER); |
} |
static void |
nouveau_enable(struct gl_context *ctx, GLenum cap, GLboolean state) |
{ |
int i; |
switch (cap) { |
case GL_ALPHA_TEST: |
context_dirty(ctx, ALPHA_FUNC); |
break; |
case GL_BLEND: |
context_dirty(ctx, BLEND_EQUATION); |
break; |
case GL_COLOR_LOGIC_OP: |
context_dirty(ctx, LOGIC_OPCODE); |
break; |
case GL_COLOR_MATERIAL: |
context_dirty(ctx, COLOR_MATERIAL); |
context_dirty(ctx, MATERIAL_FRONT_AMBIENT); |
context_dirty(ctx, MATERIAL_BACK_AMBIENT); |
context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); |
context_dirty(ctx, MATERIAL_BACK_DIFFUSE); |
context_dirty(ctx, MATERIAL_FRONT_SPECULAR); |
context_dirty(ctx, MATERIAL_BACK_SPECULAR); |
break; |
case GL_COLOR_SUM_EXT: |
context_dirty(ctx, FRAG); |
context_dirty(ctx, LIGHT_MODEL); |
break; |
case GL_CULL_FACE: |
context_dirty(ctx, CULL_FACE); |
break; |
case GL_DEPTH_TEST: |
context_dirty(ctx, DEPTH); |
break; |
case GL_DITHER: |
context_dirty(ctx, DITHER); |
break; |
case GL_FOG: |
context_dirty(ctx, FOG); |
context_dirty(ctx, FRAG); |
context_dirty(ctx, MODELVIEW); |
break; |
case GL_LIGHT0: |
case GL_LIGHT1: |
case GL_LIGHT2: |
case GL_LIGHT3: |
case GL_LIGHT4: |
case GL_LIGHT5: |
case GL_LIGHT6: |
case GL_LIGHT7: |
context_dirty(ctx, MODELVIEW); |
context_dirty(ctx, LIGHT_ENABLE); |
context_dirty_i(ctx, LIGHT_SOURCE, cap - GL_LIGHT0); |
context_dirty(ctx, MATERIAL_FRONT_AMBIENT); |
context_dirty(ctx, MATERIAL_BACK_AMBIENT); |
context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); |
context_dirty(ctx, MATERIAL_BACK_DIFFUSE); |
context_dirty(ctx, MATERIAL_FRONT_SPECULAR); |
context_dirty(ctx, MATERIAL_BACK_SPECULAR); |
context_dirty(ctx, MATERIAL_FRONT_SHININESS); |
context_dirty(ctx, MATERIAL_BACK_SHININESS); |
break; |
case GL_LIGHTING: |
context_dirty(ctx, FRAG); |
context_dirty(ctx, MODELVIEW); |
context_dirty(ctx, LIGHT_MODEL); |
context_dirty(ctx, LIGHT_ENABLE); |
for (i = 0; i < MAX_LIGHTS; i++) { |
if (ctx->Light.Light[i].Enabled) |
context_dirty_i(ctx, LIGHT_SOURCE, i); |
} |
context_dirty(ctx, MATERIAL_FRONT_AMBIENT); |
context_dirty(ctx, MATERIAL_BACK_AMBIENT); |
context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); |
context_dirty(ctx, MATERIAL_BACK_DIFFUSE); |
context_dirty(ctx, MATERIAL_FRONT_SPECULAR); |
context_dirty(ctx, MATERIAL_BACK_SPECULAR); |
context_dirty(ctx, MATERIAL_FRONT_SHININESS); |
context_dirty(ctx, MATERIAL_BACK_SHININESS); |
break; |
case GL_LINE_SMOOTH: |
context_dirty(ctx, LINE_MODE); |
break; |
case GL_NORMALIZE: |
context_dirty(ctx, LIGHT_ENABLE); |
break; |
case GL_POINT_SMOOTH: |
context_dirty(ctx, POINT_MODE); |
break; |
case GL_POLYGON_OFFSET_POINT: |
case GL_POLYGON_OFFSET_LINE: |
case GL_POLYGON_OFFSET_FILL: |
context_dirty(ctx, POLYGON_OFFSET); |
break; |
case GL_POLYGON_SMOOTH: |
context_dirty(ctx, POLYGON_MODE); |
break; |
case GL_SCISSOR_TEST: |
context_dirty(ctx, SCISSOR); |
break; |
case GL_STENCIL_TEST: |
context_dirty(ctx, STENCIL_FUNC); |
break; |
case GL_TEXTURE_1D: |
case GL_TEXTURE_2D: |
case GL_TEXTURE_3D: |
case GL_TEXTURE_RECTANGLE: |
context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); |
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); |
break; |
case GL_TEXTURE_GEN_S: |
case GL_TEXTURE_GEN_T: |
case GL_TEXTURE_GEN_R: |
case GL_TEXTURE_GEN_Q: |
context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); |
context_dirty(ctx, MODELVIEW); |
break; |
} |
} |
static void |
nouveau_fog(struct gl_context *ctx, GLenum pname, const GLfloat *params) |
{ |
context_dirty(ctx, FOG); |
} |
static void |
nouveau_light(struct gl_context *ctx, GLenum light, GLenum pname, const GLfloat *params) |
{ |
switch (pname) { |
case GL_AMBIENT: |
context_dirty(ctx, MATERIAL_FRONT_AMBIENT); |
context_dirty(ctx, MATERIAL_BACK_AMBIENT); |
break; |
case GL_DIFFUSE: |
context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); |
context_dirty(ctx, MATERIAL_BACK_DIFFUSE); |
break; |
case GL_SPECULAR: |
context_dirty(ctx, MATERIAL_FRONT_SPECULAR); |
context_dirty(ctx, MATERIAL_BACK_SPECULAR); |
break; |
case GL_SPOT_CUTOFF: |
case GL_POSITION: |
context_dirty(ctx, MODELVIEW); |
context_dirty(ctx, LIGHT_ENABLE); |
context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0); |
break; |
default: |
context_dirty_i(ctx, LIGHT_SOURCE, light - GL_LIGHT0); |
break; |
} |
} |
static void |
nouveau_light_model(struct gl_context *ctx, GLenum pname, const GLfloat *params) |
{ |
context_dirty(ctx, LIGHT_MODEL); |
context_dirty(ctx, MODELVIEW); |
} |
static void |
nouveau_line_stipple(struct gl_context *ctx, GLint factor, GLushort pattern ) |
{ |
context_dirty(ctx, LINE_STIPPLE); |
} |
static void |
nouveau_line_width(struct gl_context *ctx, GLfloat width) |
{ |
context_dirty(ctx, LINE_MODE); |
} |
static void |
nouveau_logic_opcode(struct gl_context *ctx, GLenum opcode) |
{ |
context_dirty(ctx, LOGIC_OPCODE); |
} |
static void |
nouveau_point_parameter(struct gl_context *ctx, GLenum pname, const GLfloat *params) |
{ |
context_dirty(ctx, POINT_PARAMETER); |
} |
static void |
nouveau_point_size(struct gl_context *ctx, GLfloat size) |
{ |
context_dirty(ctx, POINT_MODE); |
} |
static void |
nouveau_polygon_mode(struct gl_context *ctx, GLenum face, GLenum mode) |
{ |
context_dirty(ctx, POLYGON_MODE); |
} |
static void |
nouveau_polygon_offset(struct gl_context *ctx, GLfloat factor, GLfloat units) |
{ |
context_dirty(ctx, POLYGON_OFFSET); |
} |
static void |
nouveau_polygon_stipple(struct gl_context *ctx, const GLubyte *mask) |
{ |
context_dirty(ctx, POLYGON_STIPPLE); |
} |
static void |
nouveau_render_mode(struct gl_context *ctx, GLenum mode) |
{ |
context_dirty(ctx, RENDER_MODE); |
} |
static void |
nouveau_scissor(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
{ |
context_dirty(ctx, SCISSOR); |
} |
static void |
nouveau_shade_model(struct gl_context *ctx, GLenum mode) |
{ |
context_dirty(ctx, SHADE_MODEL); |
} |
static void |
nouveau_stencil_func_separate(struct gl_context *ctx, GLenum face, GLenum func, |
GLint ref, GLuint mask) |
{ |
context_dirty(ctx, STENCIL_FUNC); |
} |
static void |
nouveau_stencil_mask_separate(struct gl_context *ctx, GLenum face, GLuint mask) |
{ |
context_dirty(ctx, STENCIL_MASK); |
} |
static void |
nouveau_stencil_op_separate(struct gl_context *ctx, GLenum face, GLenum fail, |
GLenum zfail, GLenum zpass) |
{ |
context_dirty(ctx, STENCIL_OP); |
} |
static void |
nouveau_tex_gen(struct gl_context *ctx, GLenum coord, GLenum pname, |
const GLfloat *params) |
{ |
switch (pname) { |
case GL_TEXTURE_GEN_MODE: |
context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); |
context_dirty(ctx, MODELVIEW); |
break; |
default: |
context_dirty_i(ctx, TEX_GEN, ctx->Texture.CurrentUnit); |
break; |
} |
} |
static void |
nouveau_tex_env(struct gl_context *ctx, GLenum target, GLenum pname, |
const GLfloat *param) |
{ |
switch (target) { |
case GL_TEXTURE_FILTER_CONTROL_EXT: |
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); |
break; |
default: |
context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); |
break; |
} |
} |
static void |
nouveau_tex_parameter(struct gl_context *ctx, GLenum target, |
struct gl_texture_object *t, GLenum pname, |
const GLfloat *params) |
{ |
switch (pname) { |
case GL_TEXTURE_MAG_FILTER: |
case GL_TEXTURE_WRAP_S: |
case GL_TEXTURE_WRAP_T: |
case GL_TEXTURE_WRAP_R: |
case GL_TEXTURE_MIN_LOD: |
case GL_TEXTURE_MAX_LOD: |
case GL_TEXTURE_MAX_ANISOTROPY_EXT: |
case GL_TEXTURE_LOD_BIAS: |
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); |
break; |
case GL_TEXTURE_MIN_FILTER: |
case GL_TEXTURE_BASE_LEVEL: |
case GL_TEXTURE_MAX_LEVEL: |
nouveau_texture_reallocate(ctx, t); |
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); |
break; |
} |
} |
static void |
nouveau_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
{ |
context_dirty(ctx, VIEWPORT); |
} |
void |
nouveau_emit_nothing(struct gl_context *ctx, int emit) |
{ |
} |
int |
nouveau_next_dirty_state(struct gl_context *ctx) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
int i = BITSET_FFS(nctx->dirty) - 1; |
if (i < 0 || i >= context_drv(ctx)->num_emit) |
return -1; |
return i; |
} |
void |
nouveau_state_emit(struct gl_context *ctx) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
const struct nouveau_driver *drv = context_drv(ctx); |
int i; |
while ((i = nouveau_next_dirty_state(ctx)) >= 0) { |
BITSET_CLEAR(nctx->dirty, i); |
drv->emit[i](ctx, i); |
} |
BITSET_ZERO(nctx->dirty); |
} |
static void |
nouveau_update_state(struct gl_context *ctx, GLbitfield new_state) |
{ |
int i; |
if (new_state & (_NEW_PROJECTION | _NEW_MODELVIEW)) |
context_dirty(ctx, PROJECTION); |
if (new_state & _NEW_MODELVIEW) |
context_dirty(ctx, MODELVIEW); |
if (new_state & _NEW_TEXTURE_MATRIX) { |
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) |
context_dirty_i(ctx, TEX_MAT, i); |
} |
if (new_state & _NEW_CURRENT_ATTRIB && |
new_state & _NEW_LIGHT) { |
context_dirty(ctx, MATERIAL_FRONT_AMBIENT); |
context_dirty(ctx, MATERIAL_BACK_AMBIENT); |
context_dirty(ctx, MATERIAL_FRONT_DIFFUSE); |
context_dirty(ctx, MATERIAL_BACK_DIFFUSE); |
context_dirty(ctx, MATERIAL_FRONT_SPECULAR); |
context_dirty(ctx, MATERIAL_BACK_SPECULAR); |
context_dirty(ctx, MATERIAL_FRONT_SHININESS); |
context_dirty(ctx, MATERIAL_BACK_SHININESS); |
} |
if (new_state & _NEW_TEXTURE) { |
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { |
if (ctx->Texture.Unit[i].Sampler) |
context_dirty_i(ctx, TEX_OBJ, i); |
} |
} |
_swrast_InvalidateState(ctx, new_state); |
_tnl_InvalidateState(ctx, new_state); |
nouveau_state_emit(ctx); |
} |
void |
nouveau_state_init(struct gl_context *ctx) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
ctx->Driver.AlphaFunc = nouveau_alpha_func; |
ctx->Driver.BlendColor = nouveau_blend_color; |
ctx->Driver.BlendEquationSeparate = nouveau_blend_equation_separate; |
ctx->Driver.BlendFuncSeparate = nouveau_blend_func_separate; |
ctx->Driver.ClipPlane = nouveau_clip_plane; |
ctx->Driver.ColorMask = nouveau_color_mask; |
ctx->Driver.ColorMaterial = nouveau_color_material; |
ctx->Driver.CullFace = nouveau_cull_face; |
ctx->Driver.FrontFace = nouveau_front_face; |
ctx->Driver.DepthFunc = nouveau_depth_func; |
ctx->Driver.DepthMask = nouveau_depth_mask; |
ctx->Driver.DepthRange = nouveau_depth_range; |
ctx->Driver.ReadBuffer = nouveau_read_buffer; |
ctx->Driver.DrawBuffers = nouveau_draw_buffers; |
ctx->Driver.Enable = nouveau_enable; |
ctx->Driver.Fogfv = nouveau_fog; |
ctx->Driver.Lightfv = nouveau_light; |
ctx->Driver.LightModelfv = nouveau_light_model; |
ctx->Driver.LineStipple = nouveau_line_stipple; |
ctx->Driver.LineWidth = nouveau_line_width; |
ctx->Driver.LogicOpcode = nouveau_logic_opcode; |
ctx->Driver.PointParameterfv = nouveau_point_parameter; |
ctx->Driver.PointSize = nouveau_point_size; |
ctx->Driver.PolygonMode = nouveau_polygon_mode; |
ctx->Driver.PolygonOffset = nouveau_polygon_offset; |
ctx->Driver.PolygonStipple = nouveau_polygon_stipple; |
ctx->Driver.RenderMode = nouveau_render_mode; |
ctx->Driver.Scissor = nouveau_scissor; |
ctx->Driver.ShadeModel = nouveau_shade_model; |
ctx->Driver.StencilFuncSeparate = nouveau_stencil_func_separate; |
ctx->Driver.StencilMaskSeparate = nouveau_stencil_mask_separate; |
ctx->Driver.StencilOpSeparate = nouveau_stencil_op_separate; |
ctx->Driver.TexGen = nouveau_tex_gen; |
ctx->Driver.TexEnv = nouveau_tex_env; |
ctx->Driver.TexParameter = nouveau_tex_parameter; |
ctx->Driver.Viewport = nouveau_viewport; |
ctx->Driver.UpdateState = nouveau_update_state; |
BITSET_ONES(nctx->dirty); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_state.h |
---|
0,0 → 1,122 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_STATE_H__ |
#define __NOUVEAU_STATE_H__ |
enum { |
NOUVEAU_STATE_ALPHA_FUNC, |
NOUVEAU_STATE_BLEND_COLOR, |
NOUVEAU_STATE_BLEND_EQUATION, |
NOUVEAU_STATE_BLEND_FUNC, |
NOUVEAU_STATE_CLIP_PLANE0, |
NOUVEAU_STATE_CLIP_PLANE1, |
NOUVEAU_STATE_CLIP_PLANE2, |
NOUVEAU_STATE_CLIP_PLANE3, |
NOUVEAU_STATE_CLIP_PLANE4, |
NOUVEAU_STATE_CLIP_PLANE5, |
NOUVEAU_STATE_COLOR_MASK, |
NOUVEAU_STATE_COLOR_MATERIAL, |
NOUVEAU_STATE_CULL_FACE, |
NOUVEAU_STATE_FRONT_FACE, |
NOUVEAU_STATE_DEPTH, |
NOUVEAU_STATE_DITHER, |
NOUVEAU_STATE_FRAG, |
NOUVEAU_STATE_FRAMEBUFFER, |
NOUVEAU_STATE_FOG, |
NOUVEAU_STATE_LIGHT_ENABLE, |
NOUVEAU_STATE_LIGHT_MODEL, |
NOUVEAU_STATE_LIGHT_SOURCE0, |
NOUVEAU_STATE_LIGHT_SOURCE1, |
NOUVEAU_STATE_LIGHT_SOURCE2, |
NOUVEAU_STATE_LIGHT_SOURCE3, |
NOUVEAU_STATE_LIGHT_SOURCE4, |
NOUVEAU_STATE_LIGHT_SOURCE5, |
NOUVEAU_STATE_LIGHT_SOURCE6, |
NOUVEAU_STATE_LIGHT_SOURCE7, |
NOUVEAU_STATE_LINE_STIPPLE, |
NOUVEAU_STATE_LINE_MODE, |
NOUVEAU_STATE_LOGIC_OPCODE, |
NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT, |
NOUVEAU_STATE_MATERIAL_BACK_AMBIENT, |
NOUVEAU_STATE_MATERIAL_FRONT_DIFFUSE, |
NOUVEAU_STATE_MATERIAL_BACK_DIFFUSE, |
NOUVEAU_STATE_MATERIAL_FRONT_SPECULAR, |
NOUVEAU_STATE_MATERIAL_BACK_SPECULAR, |
NOUVEAU_STATE_MATERIAL_FRONT_SHININESS, |
NOUVEAU_STATE_MATERIAL_BACK_SHININESS, |
NOUVEAU_STATE_MODELVIEW, |
NOUVEAU_STATE_POINT_MODE, |
NOUVEAU_STATE_POINT_PARAMETER, |
NOUVEAU_STATE_POLYGON_MODE, |
NOUVEAU_STATE_POLYGON_OFFSET, |
NOUVEAU_STATE_POLYGON_STIPPLE, |
NOUVEAU_STATE_PROJECTION, |
NOUVEAU_STATE_RENDER_MODE, |
NOUVEAU_STATE_SCISSOR, |
NOUVEAU_STATE_SHADE_MODEL, |
NOUVEAU_STATE_STENCIL_FUNC, |
NOUVEAU_STATE_STENCIL_MASK, |
NOUVEAU_STATE_STENCIL_OP, |
NOUVEAU_STATE_TEX_ENV0, |
NOUVEAU_STATE_TEX_ENV1, |
NOUVEAU_STATE_TEX_ENV2, |
NOUVEAU_STATE_TEX_ENV3, |
NOUVEAU_STATE_TEX_GEN0, |
NOUVEAU_STATE_TEX_GEN1, |
NOUVEAU_STATE_TEX_GEN2, |
NOUVEAU_STATE_TEX_GEN3, |
NOUVEAU_STATE_TEX_MAT0, |
NOUVEAU_STATE_TEX_MAT1, |
NOUVEAU_STATE_TEX_MAT2, |
NOUVEAU_STATE_TEX_MAT3, |
NOUVEAU_STATE_TEX_OBJ0, |
NOUVEAU_STATE_TEX_OBJ1, |
NOUVEAU_STATE_TEX_OBJ2, |
NOUVEAU_STATE_TEX_OBJ3, |
NOUVEAU_STATE_VIEWPORT, |
NUM_NOUVEAU_STATE, |
/* Room for card-specific states. */ |
MAX_NOUVEAU_STATE = NUM_NOUVEAU_STATE + 16, |
}; |
typedef void (*nouveau_state_func)(struct gl_context *ctx, int emit); |
void |
nouveau_state_init(struct gl_context *ctx); |
void |
nouveau_emit_nothing(struct gl_context *ctx, int emit); |
int |
nouveau_next_dirty_state(struct gl_context *ctx); |
void |
nouveau_state_emit(struct gl_context *ctx); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_surface.c |
---|
0,0 → 1,92 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_util.h" |
#include "main/formats.h" |
void |
nouveau_surface_alloc(struct gl_context *ctx, struct nouveau_surface *s, |
enum nouveau_surface_layout layout, |
unsigned flags, unsigned format, |
unsigned width, unsigned height) |
{ |
union nouveau_bo_config config = {}; |
int ret, cpp = _mesa_get_format_bytes(format); |
nouveau_bo_ref(NULL, &s->bo); |
*s = (struct nouveau_surface) { |
.layout = layout, |
.format = format, |
.width = width, |
.height = height, |
.cpp = cpp, |
.pitch = _mesa_format_row_stride(format, width), |
}; |
if (layout == TILED) { |
s->pitch = align(s->pitch, 256); |
config.nv04.surf_pitch = s->pitch; |
if (cpp == 4) |
config.nv04.surf_flags = NV04_BO_32BPP; |
else if (cpp == 2) |
config.nv04.surf_flags = NV04_BO_16BPP; |
if (_mesa_get_format_bits(format, GL_DEPTH_BITS)) |
config.nv04.surf_flags |= NV04_BO_ZETA; |
} else { |
s->pitch = align(s->pitch, 64); |
} |
ret = nouveau_bo_new(context_dev(ctx), flags, 0, |
get_format_blocksy(format, height) * s->pitch, |
&config, &s->bo); |
assert(!ret); |
} |
void |
nouveau_surface_ref(struct nouveau_surface *src, |
struct nouveau_surface *dst) |
{ |
if (src) { |
dst->offset = src->offset; |
dst->layout = src->layout; |
dst->format = src->format; |
dst->width = src->width; |
dst->height = src->height; |
dst->cpp = src->cpp; |
dst->pitch = src->pitch; |
nouveau_bo_ref(src->bo, &dst->bo); |
} else { |
nouveau_bo_ref(NULL, &dst->bo); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_surface.h |
---|
0,0 → 1,58 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_SURFACE_H__ |
#define __NOUVEAU_SURFACE_H__ |
enum nouveau_surface_layout { |
LINEAR = 0, |
TILED, |
SWIZZLED, |
}; |
struct nouveau_surface { |
struct nouveau_bo *bo; |
unsigned offset; |
enum nouveau_surface_layout layout; |
gl_format format; |
unsigned cpp, pitch; |
unsigned width, height; |
}; |
void |
nouveau_surface_alloc(struct gl_context *ctx, struct nouveau_surface *s, |
enum nouveau_surface_layout layout, |
unsigned flags, unsigned format, |
unsigned width, unsigned height); |
void |
nouveau_surface_ref(struct nouveau_surface *src, |
struct nouveau_surface *dst); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_swtnl_t.c |
---|
0,0 → 1,350 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "tnl/t_context.h" |
#include "tnl/t_pipeline.h" |
#include "tnl/t_vertex.h" |
#define SWTNL_VBO_SIZE 65536 |
static enum tnl_attr_format |
swtnl_get_format(int type, int fields) { |
switch (type) { |
case GL_FLOAT: |
switch (fields){ |
case 1: |
return EMIT_1F; |
case 2: |
return EMIT_2F; |
case 3: |
return EMIT_3F; |
case 4: |
return EMIT_4F; |
default: |
assert(0); |
} |
case GL_UNSIGNED_BYTE: |
switch (fields) { |
case 4: |
return EMIT_4UB_4F_RGBA; |
default: |
assert(0); |
} |
default: |
assert(0); |
} |
} |
static struct swtnl_attr_info { |
int type; |
int fields; |
} swtnl_attrs[VERT_ATTRIB_MAX] = { |
[VERT_ATTRIB_POS] = { |
.type = GL_FLOAT, |
.fields = 4, |
}, |
[VERT_ATTRIB_NORMAL] = { |
.type = GL_FLOAT, |
.fields = -1, |
}, |
[VERT_ATTRIB_COLOR0] = { |
.type = GL_UNSIGNED_BYTE, |
.fields = 4, |
}, |
[VERT_ATTRIB_COLOR1] = { |
.type = GL_UNSIGNED_BYTE, |
.fields = 4, |
}, |
[VERT_ATTRIB_FOG] = { |
.type = GL_FLOAT, |
.fields = 1, |
}, |
[VERT_ATTRIB_TEX0] = { |
.type = GL_FLOAT, |
.fields = -1, |
}, |
[VERT_ATTRIB_TEX1] = { |
.type = GL_FLOAT, |
.fields = -1, |
}, |
[VERT_ATTRIB_TEX2] = { |
.type = GL_FLOAT, |
.fields = -1, |
}, |
[VERT_ATTRIB_TEX3] = { |
.type = GL_FLOAT, |
.fields = -1, |
}, |
}; |
static void |
swtnl_choose_attrs(struct gl_context *ctx) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct tnl_clipspace *vtx = &tnl->clipspace; |
static struct tnl_attr_map map[NUM_VERTEX_ATTRS]; |
int fields, attr, i, n = 0; |
render->mode = VBO; |
render->attr_count = NUM_VERTEX_ATTRS; |
/* We always want non Ndc coords format */ |
tnl->vb.AttribPtr[VERT_ATTRIB_POS] = tnl->vb.ClipPtr; |
for (i = 0; i < VERT_ATTRIB_MAX; i++) { |
struct nouveau_attr_info *ha = &TAG(vertex_attrs)[i]; |
struct swtnl_attr_info *sa = &swtnl_attrs[i]; |
struct nouveau_array *a = &render->attrs[i]; |
if (!sa->fields) |
continue; /* Unsupported attribute. */ |
if (tnl->render_inputs_bitset & BITFIELD64_BIT(i)) { |
if (sa->fields > 0) |
fields = sa->fields; |
else |
fields = tnl->vb.AttribPtr[i]->size; |
map[n++] = (struct tnl_attr_map) { |
.attrib = i, |
.format = swtnl_get_format(sa->type, fields), |
}; |
render->map[ha->vbo_index] = i; |
a->attr = i; |
a->fields = fields; |
a->type = sa->type; |
} |
} |
_tnl_install_attrs(ctx, map, n, NULL, 0); |
FOR_EACH_BOUND_ATTR(render, i, attr) |
render->attrs[attr].stride = vtx->vertex_size; |
TAG(render_set_format)(ctx); |
} |
static void |
swtnl_alloc_vertices(struct gl_context *ctx) |
{ |
struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl; |
nouveau_bo_ref(NULL, &swtnl->vbo); |
swtnl->buf = nouveau_get_scratch(ctx, SWTNL_VBO_SIZE, &swtnl->vbo, |
&swtnl->offset); |
swtnl->vertex_count = 0; |
} |
static void |
swtnl_bind_vertices(struct gl_context *ctx) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
struct nouveau_swtnl_state *swtnl = &render->swtnl; |
struct tnl_clipspace *vtx = &TNL_CONTEXT(ctx)->clipspace; |
int i; |
for (i = 0; i < vtx->attr_count; i++) { |
struct tnl_clipspace_attr *ta = &vtx->attr[i]; |
struct nouveau_array *a = &render->attrs[ta->attrib]; |
nouveau_bo_ref(swtnl->vbo, &a->bo); |
a->offset = swtnl->offset + ta->vertoffset; |
} |
TAG(render_bind_vertices)(ctx); |
} |
static void |
swtnl_unbind_vertices(struct gl_context *ctx) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
int i, attr; |
TAG(render_release_vertices)(ctx); |
FOR_EACH_BOUND_ATTR(render, i, attr) { |
nouveau_bo_ref(NULL, &render->attrs[attr].bo); |
render->map[i] = -1; |
} |
render->attr_count = 0; |
} |
static void |
swtnl_flush_vertices(struct gl_context *ctx) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl; |
unsigned npush, start = 0, count = swtnl->vertex_count; |
RENDER_LOCALS(ctx); |
swtnl_bind_vertices(ctx); |
while (count) { |
npush = get_max_vertices(ctx, NULL, PUSH_AVAIL(push)); |
npush = MIN2(npush / 12 * 12, count); |
count -= npush; |
if (!npush) { |
PUSH_KICK(push); |
continue; |
} |
BATCH_BEGIN(nvgl_primitive(swtnl->primitive)); |
EMIT_VBO(L, ctx, start, 0, npush); |
BATCH_END(); |
PUSH_KICK(push); |
} |
swtnl_alloc_vertices(ctx); |
} |
/* TnL renderer entry points */ |
static void |
swtnl_start(struct gl_context *ctx) |
{ |
swtnl_choose_attrs(ctx); |
} |
static void |
swtnl_finish(struct gl_context *ctx) |
{ |
swtnl_flush_vertices(ctx); |
swtnl_unbind_vertices(ctx); |
} |
static void |
swtnl_primitive(struct gl_context *ctx, GLenum mode) |
{ |
} |
static void |
swtnl_reset_stipple(struct gl_context *ctx) |
{ |
} |
/* Primitive rendering */ |
#define BEGIN_PRIMITIVE(p, n) \ |
struct nouveau_swtnl_state *swtnl = &to_render_state(ctx)->swtnl; \ |
int vertex_len = TNL_CONTEXT(ctx)->clipspace.vertex_size; \ |
\ |
if (swtnl->vertex_count + (n) > SWTNL_VBO_SIZE/vertex_len \ |
|| (swtnl->vertex_count && swtnl->primitive != p)) \ |
swtnl_flush_vertices(ctx); \ |
\ |
swtnl->primitive = p; |
#define OUT_VERTEX(i) do { \ |
memcpy(swtnl->buf + swtnl->vertex_count * vertex_len, \ |
_tnl_get_vertex(ctx, (i)), vertex_len); \ |
swtnl->vertex_count++; \ |
} while (0) |
static void |
swtnl_points(struct gl_context *ctx, GLuint first, GLuint last) |
{ |
int i, count; |
while (first < last) { |
BEGIN_PRIMITIVE(GL_POINTS, last - first); |
count = MIN2(SWTNL_VBO_SIZE / vertex_len, last - first); |
for (i = 0; i < count; i++) |
OUT_VERTEX(first + i); |
first += count; |
} |
} |
static void |
swtnl_line(struct gl_context *ctx, GLuint v1, GLuint v2) |
{ |
BEGIN_PRIMITIVE(GL_LINES, 2); |
OUT_VERTEX(v1); |
OUT_VERTEX(v2); |
} |
static void |
swtnl_triangle(struct gl_context *ctx, GLuint v1, GLuint v2, GLuint v3) |
{ |
BEGIN_PRIMITIVE(GL_TRIANGLES, 3); |
OUT_VERTEX(v1); |
OUT_VERTEX(v2); |
OUT_VERTEX(v3); |
} |
static void |
swtnl_quad(struct gl_context *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4) |
{ |
BEGIN_PRIMITIVE(GL_QUADS, 4); |
OUT_VERTEX(v1); |
OUT_VERTEX(v2); |
OUT_VERTEX(v3); |
OUT_VERTEX(v4); |
} |
/* TnL initialization. */ |
void |
TAG(swtnl_init)(struct gl_context *ctx) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
tnl->Driver.RunPipeline = _tnl_run_pipeline; |
tnl->Driver.Render.Interp = _tnl_interp; |
tnl->Driver.Render.CopyPV = _tnl_copy_pv; |
tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; |
tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; |
tnl->Driver.Render.BuildVertices = _tnl_build_vertices; |
tnl->Driver.Render.Start = swtnl_start; |
tnl->Driver.Render.Finish = swtnl_finish; |
tnl->Driver.Render.PrimitiveNotify = swtnl_primitive; |
tnl->Driver.Render.ResetLineStipple = swtnl_reset_stipple; |
tnl->Driver.Render.Points = swtnl_points; |
tnl->Driver.Render.Line = swtnl_line; |
tnl->Driver.Render.Triangle = swtnl_triangle; |
tnl->Driver.Render.Quad = swtnl_quad; |
_tnl_init_vertices(ctx, tnl->vb.Size, |
NUM_VERTEX_ATTRS * 4 * sizeof(GLfloat)); |
_tnl_need_projected_coords(ctx, GL_FALSE); |
_tnl_allow_vertex_fog(ctx, GL_FALSE); |
_tnl_wakeup(ctx); |
swtnl_alloc_vertices(ctx); |
} |
void |
TAG(swtnl_destroy)(struct gl_context *ctx) |
{ |
nouveau_bo_ref(NULL, &to_render_state(ctx)->swtnl.vbo); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_texture.c |
---|
0,0 → 1,645 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_texture.h" |
#include "nouveau_fbo.h" |
#include "nouveau_util.h" |
#include "main/pbo.h" |
#include "main/texobj.h" |
#include "main/texstore.h" |
#include "main/texformat.h" |
#include "main/texcompress.h" |
#include "main/texgetimage.h" |
#include "main/mipmap.h" |
#include "main/teximage.h" |
#include "drivers/common/meta.h" |
#include "swrast/s_texfetch.h" |
static struct gl_texture_object * |
nouveau_texture_new(struct gl_context *ctx, GLuint name, GLenum target) |
{ |
struct nouveau_texture *nt = CALLOC_STRUCT(nouveau_texture); |
_mesa_initialize_texture_object(ctx, &nt->base, name, target); |
return &nt->base; |
} |
static void |
nouveau_texture_free(struct gl_context *ctx, struct gl_texture_object *t) |
{ |
struct nouveau_texture *nt = to_nouveau_texture(t); |
int i; |
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) |
nouveau_surface_ref(NULL, &nt->surfaces[i]); |
_mesa_delete_texture_object(ctx, t); |
} |
static struct gl_texture_image * |
nouveau_teximage_new(struct gl_context *ctx) |
{ |
struct nouveau_teximage *nti = CALLOC_STRUCT(nouveau_teximage); |
return &nti->base.Base; |
} |
static void |
nouveau_teximage_free(struct gl_context *ctx, struct gl_texture_image *ti) |
{ |
struct nouveau_teximage *nti = to_nouveau_teximage(ti); |
nouveau_surface_ref(NULL, &nti->surface); |
} |
static void |
nouveau_map_texture_image(struct gl_context *ctx, |
struct gl_texture_image *ti, |
GLuint slice, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **map, |
GLint *stride) |
{ |
struct nouveau_teximage *nti = to_nouveau_teximage(ti); |
struct nouveau_surface *s = &nti->surface; |
struct nouveau_surface *st = &nti->transfer.surface; |
struct nouveau_client *client = context_client(ctx); |
/* Nouveau has no support for 3D or cubemap textures. */ |
assert(slice == 0); |
if (s->bo) { |
if (!(mode & GL_MAP_READ_BIT) && |
nouveau_pushbuf_refd(context_push(ctx), s->bo)) { |
unsigned size; |
/* |
* Heuristic: use a bounce buffer to pipeline |
* teximage transfers. |
*/ |
st->layout = LINEAR; |
st->format = s->format; |
st->cpp = s->cpp; |
st->width = w; |
st->height = h; |
st->pitch = s->pitch; |
nti->transfer.x = x; |
nti->transfer.y = y; |
size = get_format_blocksy(st->format, h) * st->pitch; |
*map = nouveau_get_scratch(ctx, size, |
&st->bo, &st->offset); |
*stride = st->pitch; |
} else { |
int ret, flags = 0; |
if (mode & GL_MAP_READ_BIT) |
flags |= NOUVEAU_BO_RD; |
if (mode & GL_MAP_WRITE_BIT) |
flags |= NOUVEAU_BO_WR; |
if (!s->bo->map) { |
ret = nouveau_bo_map(s->bo, flags, client); |
assert(!ret); |
} |
*map = s->bo->map + |
get_format_blocksy(s->format, y) * s->pitch + |
get_format_blocksx(s->format, x) * s->cpp; |
*stride = s->pitch; |
} |
} else { |
*map = nti->base.Buffer + |
get_format_blocksy(s->format, y) * s->pitch + |
get_format_blocksx(s->format, x) * s->cpp; |
*stride = s->pitch; |
} |
} |
static void |
nouveau_unmap_texture_image(struct gl_context *ctx, struct gl_texture_image *ti, |
GLuint slice) |
{ |
struct nouveau_teximage *nti = to_nouveau_teximage(ti); |
struct nouveau_surface *s = &nti->surface; |
struct nouveau_surface *st = &nti->transfer.surface; |
if (st->bo) { |
context_drv(ctx)->surface_copy(ctx, s, st, nti->transfer.x, |
nti->transfer.y, 0, 0, |
st->width, st->height); |
nouveau_surface_ref(NULL, st); |
} |
} |
static gl_format |
nouveau_choose_tex_format(struct gl_context *ctx, GLenum target, |
GLint internalFormat, |
GLenum srcFormat, GLenum srcType) |
{ |
switch (internalFormat) { |
case 4: |
case GL_RGBA: |
case GL_RGBA2: |
case GL_RGBA4: |
case GL_RGBA8: |
case GL_RGBA12: |
case GL_RGBA16: |
case GL_RGB10_A2: |
case GL_COMPRESSED_RGBA: |
return MESA_FORMAT_ARGB8888; |
case GL_RGB5_A1: |
return MESA_FORMAT_ARGB1555; |
case GL_RGB: |
case GL_RGB8: |
case GL_RGB10: |
case GL_RGB12: |
case GL_RGB16: |
case GL_COMPRESSED_RGB: |
return MESA_FORMAT_XRGB8888; |
case 3: |
case GL_R3_G3_B2: |
case GL_RGB4: |
case GL_RGB5: |
return MESA_FORMAT_RGB565; |
case 2: |
case GL_LUMINANCE_ALPHA: |
case GL_LUMINANCE4_ALPHA4: |
case GL_LUMINANCE6_ALPHA2: |
case GL_LUMINANCE12_ALPHA4: |
case GL_LUMINANCE12_ALPHA12: |
case GL_LUMINANCE16_ALPHA16: |
case GL_LUMINANCE8_ALPHA8: |
case GL_COMPRESSED_LUMINANCE_ALPHA: |
return MESA_FORMAT_ARGB8888; |
case 1: |
case GL_LUMINANCE: |
case GL_LUMINANCE4: |
case GL_LUMINANCE12: |
case GL_LUMINANCE16: |
case GL_LUMINANCE8: |
case GL_COMPRESSED_LUMINANCE: |
return MESA_FORMAT_L8; |
case GL_ALPHA: |
case GL_ALPHA4: |
case GL_ALPHA12: |
case GL_ALPHA16: |
case GL_ALPHA8: |
case GL_COMPRESSED_ALPHA: |
return MESA_FORMAT_A8; |
case GL_INTENSITY: |
case GL_INTENSITY4: |
case GL_INTENSITY12: |
case GL_INTENSITY16: |
case GL_INTENSITY8: |
return MESA_FORMAT_I8; |
case GL_RGB_S3TC: |
case GL_RGB4_S3TC: |
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: |
return MESA_FORMAT_RGB_DXT1; |
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: |
return MESA_FORMAT_RGBA_DXT1; |
case GL_RGBA_S3TC: |
case GL_RGBA4_S3TC: |
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: |
return MESA_FORMAT_RGBA_DXT3; |
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: |
return MESA_FORMAT_RGBA_DXT5; |
default: |
assert(0); |
} |
} |
static GLboolean |
teximage_fits(struct gl_texture_object *t, int level) |
{ |
struct nouveau_surface *s = &to_nouveau_texture(t)->surfaces[level]; |
struct gl_texture_image *ti = t->Image[0][level]; |
if (!ti || !to_nouveau_teximage(ti)->surface.bo) |
return GL_FALSE; |
if (level == t->BaseLevel && (s->offset & 0x7f)) |
return GL_FALSE; |
return t->Target == GL_TEXTURE_RECTANGLE || |
(s->bo && s->format == ti->TexFormat && |
s->width == ti->Width && s->height == ti->Height); |
} |
static GLboolean |
validate_teximage(struct gl_context *ctx, struct gl_texture_object *t, |
int level, int x, int y, int z, |
int width, int height, int depth) |
{ |
struct gl_texture_image *ti = t->Image[0][level]; |
if (teximage_fits(t, level)) { |
struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces; |
struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; |
if (t->Target == GL_TEXTURE_RECTANGLE) |
nouveau_surface_ref(s, &ss[level]); |
else |
context_drv(ctx)->surface_copy(ctx, &ss[level], s, |
x, y, x, y, |
width, height); |
return GL_TRUE; |
} |
return GL_FALSE; |
} |
static int |
get_last_level(struct gl_texture_object *t) |
{ |
struct gl_texture_image *base = t->Image[0][t->BaseLevel]; |
if (t->Sampler.MinFilter == GL_NEAREST || |
t->Sampler.MinFilter == GL_LINEAR || !base) |
return t->BaseLevel; |
else |
return MIN2(t->BaseLevel + base->MaxNumLevels - 1, t->MaxLevel); |
} |
static void |
relayout_texture(struct gl_context *ctx, struct gl_texture_object *t) |
{ |
struct gl_texture_image *base = t->Image[0][t->BaseLevel]; |
if (base && t->Target != GL_TEXTURE_RECTANGLE) { |
struct nouveau_surface *ss = to_nouveau_texture(t)->surfaces; |
struct nouveau_surface *s = &to_nouveau_teximage(base)->surface; |
int i, ret, last = get_last_level(t); |
enum nouveau_surface_layout layout = |
(_mesa_is_format_compressed(s->format) ? LINEAR : SWIZZLED); |
unsigned size, pitch, offset = 0, |
width = s->width, |
height = s->height; |
/* Deallocate the old storage. */ |
for (i = 0; i < MAX_TEXTURE_LEVELS; i++) |
nouveau_bo_ref(NULL, &ss[i].bo); |
/* Relayout the mipmap tree. */ |
for (i = t->BaseLevel; i <= last; i++) { |
pitch = _mesa_format_row_stride(s->format, width); |
size = get_format_blocksy(s->format, height) * pitch; |
/* Images larger than 16B have to be aligned. */ |
if (size > 16) |
offset = align(offset, 64); |
ss[i] = (struct nouveau_surface) { |
.offset = offset, |
.layout = layout, |
.format = s->format, |
.width = width, |
.height = height, |
.cpp = s->cpp, |
.pitch = pitch, |
}; |
offset += size; |
width = minify(width, 1); |
height = minify(height, 1); |
} |
/* Get new storage. */ |
size = align(offset, 64); |
ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_MAP | |
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM, |
0, size, NULL, &ss[last].bo); |
assert(!ret); |
for (i = t->BaseLevel; i < last; i++) |
nouveau_bo_ref(ss[last].bo, &ss[i].bo); |
} |
} |
GLboolean |
nouveau_texture_validate(struct gl_context *ctx, struct gl_texture_object *t) |
{ |
struct nouveau_texture *nt = to_nouveau_texture(t); |
int i, last = get_last_level(t); |
if (!teximage_fits(t, t->BaseLevel) || |
!teximage_fits(t, last)) |
return GL_FALSE; |
if (nt->dirty) { |
nt->dirty = GL_FALSE; |
/* Copy the teximages to the actual miptree. */ |
for (i = t->BaseLevel; i <= last; i++) { |
struct nouveau_surface *s = &nt->surfaces[i]; |
validate_teximage(ctx, t, i, 0, 0, 0, |
s->width, s->height, 1); |
} |
PUSH_KICK(context_push(ctx)); |
} |
return GL_TRUE; |
} |
void |
nouveau_texture_reallocate(struct gl_context *ctx, struct gl_texture_object *t) |
{ |
if (!teximage_fits(t, t->BaseLevel) || |
!teximage_fits(t, get_last_level(t))) { |
texture_dirty(t); |
relayout_texture(ctx, t); |
nouveau_texture_validate(ctx, t); |
} |
} |
static unsigned |
get_teximage_placement(struct gl_texture_image *ti) |
{ |
if (ti->TexFormat == MESA_FORMAT_A8 || |
ti->TexFormat == MESA_FORMAT_L8 || |
ti->TexFormat == MESA_FORMAT_I8) |
/* 1 cpp formats will have to be swizzled by the CPU, |
* so leave them in system RAM for now. */ |
return NOUVEAU_BO_MAP; |
else |
return NOUVEAU_BO_GART | NOUVEAU_BO_MAP; |
} |
static void |
nouveau_teximage(struct gl_context *ctx, GLint dims, |
struct gl_texture_image *ti, |
GLsizei imageSize, |
GLenum format, GLenum type, const GLvoid *pixels, |
const struct gl_pixelstore_attrib *packing, |
GLboolean compressed) |
{ |
struct gl_texture_object *t = ti->TexObject; |
const GLuint level = ti->Level; |
struct nouveau_surface *s = &to_nouveau_teximage(ti)->surface; |
struct nouveau_teximage *nti = to_nouveau_teximage(ti); |
int ret; |
GLuint depth = compressed ? 1 : ti->Depth; |
/* Allocate a new bo for the image. */ |
nouveau_surface_alloc(ctx, s, LINEAR, get_teximage_placement(ti), |
ti->TexFormat, ti->Width, ti->Height); |
nti->base.RowStride = s->pitch / s->cpp; |
if (compressed) |
pixels = _mesa_validate_pbo_compressed_teximage(ctx, |
dims, imageSize, |
pixels, packing, "glCompressedTexImage"); |
else |
pixels = _mesa_validate_pbo_teximage(ctx, |
dims, ti->Width, ti->Height, depth, format, type, |
pixels, packing, "glTexImage"); |
if (pixels) { |
GLubyte *map; |
int row_stride; |
/* Store the pixel data. */ |
nouveau_map_texture_image(ctx, ti, 0, |
0, 0, ti->Width, ti->Height, |
GL_MAP_WRITE_BIT, |
&map, &row_stride); |
ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, |
ti->TexFormat, |
row_stride, |
&map, |
ti->Width, ti->Height, depth, |
format, type, pixels, packing); |
assert(ret); |
nouveau_unmap_texture_image(ctx, ti, 0); |
_mesa_unmap_teximage_pbo(ctx, packing); |
if (!validate_teximage(ctx, t, level, 0, 0, 0, |
ti->Width, ti->Height, depth)) |
/* It doesn't fit, mark it as dirty. */ |
texture_dirty(t); |
} |
if (level == t->BaseLevel) { |
if (!teximage_fits(t, level)) |
relayout_texture(ctx, t); |
nouveau_texture_validate(ctx, t); |
} |
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); |
context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); |
} |
static void |
nouveau_teximage_123d(struct gl_context *ctx, GLuint dims, |
struct gl_texture_image *ti, |
GLenum format, GLenum type, const GLvoid *pixels, |
const struct gl_pixelstore_attrib *packing) |
{ |
nouveau_teximage(ctx, dims, ti, 0, format, type, pixels, |
packing, GL_FALSE); |
} |
static void |
nouveau_compressed_teximage(struct gl_context *ctx, GLuint dims, |
struct gl_texture_image *ti, |
GLsizei imageSize, const GLvoid *data) |
{ |
nouveau_teximage(ctx, 2, ti, imageSize, 0, 0, data, |
&ctx->Unpack, GL_TRUE); |
} |
static void |
nouveau_texsubimage(struct gl_context *ctx, GLint dims, |
struct gl_texture_image *ti, |
GLint xoffset, GLint yoffset, GLint zoffset, |
GLint width, GLint height, GLint depth, |
GLsizei imageSize, |
GLenum format, GLenum type, const void *pixels, |
const struct gl_pixelstore_attrib *packing, |
GLboolean compressed) |
{ |
int ret; |
if (compressed) |
pixels = _mesa_validate_pbo_compressed_teximage(ctx, |
dims, imageSize, |
pixels, packing, "glCompressedTexSubImage"); |
else |
pixels = _mesa_validate_pbo_teximage(ctx, |
dims, width, height, depth, format, type, |
pixels, packing, "glTexSubImage"); |
if (pixels) { |
GLubyte *map; |
int row_stride; |
nouveau_map_texture_image(ctx, ti, 0, |
xoffset, yoffset, width, height, |
GL_MAP_WRITE_BIT, &map, &row_stride); |
ret = _mesa_texstore(ctx, dims, ti->_BaseFormat, ti->TexFormat, |
row_stride, &map, |
width, height, depth, |
format, type, pixels, packing); |
assert(ret); |
nouveau_unmap_texture_image(ctx, ti, 0); |
_mesa_unmap_teximage_pbo(ctx, packing); |
} |
if (!to_nouveau_texture(ti->TexObject)->dirty) |
validate_teximage(ctx, ti->TexObject, ti->Level, |
xoffset, yoffset, zoffset, |
width, height, depth); |
} |
static void |
nouveau_texsubimage_123d(struct gl_context *ctx, GLuint dims, |
struct gl_texture_image *ti, |
GLint xoffset, GLint yoffset, GLint zoffset, |
GLint width, GLint height, GLint depth, |
GLenum format, GLenum type, const void *pixels, |
const struct gl_pixelstore_attrib *packing) |
{ |
nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset, |
width, height, depth, 0, format, type, pixels, |
packing, GL_FALSE); |
} |
static void |
nouveau_compressed_texsubimage(struct gl_context *ctx, GLuint dims, |
struct gl_texture_image *ti, |
GLint xoffset, GLint yoffset, GLint zoffset, |
GLsizei width, GLint height, GLint depth, |
GLenum format, |
GLint imageSize, const void *data) |
{ |
nouveau_texsubimage(ctx, dims, ti, xoffset, yoffset, zoffset, |
width, height, depth, imageSize, format, 0, data, |
&ctx->Unpack, GL_TRUE); |
} |
static void |
nouveau_bind_texture(struct gl_context *ctx, GLenum target, |
struct gl_texture_object *t) |
{ |
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); |
context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); |
} |
static gl_format |
get_texbuffer_format(struct gl_renderbuffer *rb, GLint format) |
{ |
struct nouveau_surface *s = &to_nouveau_renderbuffer(rb)->surface; |
if (s->cpp < 4) |
return s->format; |
else if (format == __DRI_TEXTURE_FORMAT_RGBA) |
return MESA_FORMAT_ARGB8888; |
else |
return MESA_FORMAT_XRGB8888; |
} |
void |
nouveau_set_texbuffer(__DRIcontext *dri_ctx, |
GLint target, GLint format, |
__DRIdrawable *draw) |
{ |
struct nouveau_context *nctx = dri_ctx->driverPrivate; |
struct gl_context *ctx = &nctx->base; |
struct gl_framebuffer *fb = draw->driverPrivate; |
struct gl_renderbuffer *rb = |
fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; |
struct gl_texture_object *t = _mesa_get_current_tex_object(ctx, target); |
struct gl_texture_image *ti; |
struct nouveau_teximage *nti; |
struct nouveau_surface *s; |
_mesa_lock_texture(ctx, t); |
ti = _mesa_get_tex_image(ctx, t, target, 0); |
nti = to_nouveau_teximage(ti); |
s = &to_nouveau_teximage(ti)->surface; |
/* Update the texture surface with the given drawable. */ |
nouveau_update_renderbuffers(dri_ctx, draw); |
nouveau_surface_ref(&to_nouveau_renderbuffer(rb)->surface, s); |
s->format = get_texbuffer_format(rb, format); |
/* Update the image fields. */ |
_mesa_init_teximage_fields(ctx, ti, s->width, s->height, |
1, 0, s->cpp, s->format); |
nti->base.RowStride = s->pitch / s->cpp; |
/* Try to validate it. */ |
if (!validate_teximage(ctx, t, 0, 0, 0, 0, s->width, s->height, 1)) |
nouveau_texture_reallocate(ctx, t); |
context_dirty_i(ctx, TEX_OBJ, ctx->Texture.CurrentUnit); |
context_dirty_i(ctx, TEX_ENV, ctx->Texture.CurrentUnit); |
_mesa_unlock_texture(ctx, t); |
} |
void |
nouveau_texture_functions_init(struct dd_function_table *functions) |
{ |
functions->NewTextureObject = nouveau_texture_new; |
functions->DeleteTexture = nouveau_texture_free; |
functions->NewTextureImage = nouveau_teximage_new; |
functions->FreeTextureImageBuffer = nouveau_teximage_free; |
functions->ChooseTextureFormat = nouveau_choose_tex_format; |
functions->TexImage = nouveau_teximage_123d; |
functions->TexSubImage = nouveau_texsubimage_123d; |
functions->CompressedTexImage = nouveau_compressed_teximage; |
functions->CompressedTexSubImage = nouveau_compressed_texsubimage; |
functions->BindTexture = nouveau_bind_texture; |
functions->MapTextureImage = nouveau_map_texture_image; |
functions->UnmapTextureImage = nouveau_unmap_texture_image; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_texture.h |
---|
0,0 → 1,63 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_TEXTURE_H__ |
#define __NOUVEAU_TEXTURE_H__ |
#include "swrast/s_context.h" |
struct nouveau_teximage { |
struct swrast_texture_image base; |
struct nouveau_surface surface; |
struct { |
struct nouveau_surface surface; |
int x, y; |
} transfer; |
}; |
#define to_nouveau_teximage(x) ((struct nouveau_teximage *)(x)) |
struct nouveau_texture { |
struct gl_texture_object base; |
struct nouveau_surface surfaces[MAX_TEXTURE_LEVELS]; |
GLboolean dirty; |
}; |
#define to_nouveau_texture(x) ((struct nouveau_texture *)(x)) |
#define texture_dirty(t) \ |
to_nouveau_texture(t)->dirty = GL_TRUE |
void |
nouveau_set_texbuffer(__DRIcontext *dri_ctx, |
GLint target, GLint format, |
__DRIdrawable *draw); |
GLboolean |
nouveau_texture_validate(struct gl_context *ctx, struct gl_texture_object *t); |
void |
nouveau_texture_reallocate(struct gl_context *ctx, struct gl_texture_object *t); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_util.h |
---|
0,0 → 1,230 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NOUVEAU_UTIL_H__ |
#define __NOUVEAU_UTIL_H__ |
#include "main/formats.h" |
#include "main/colormac.h" |
static inline unsigned |
pack_rgba_i(gl_format f, uint8_t c[]) |
{ |
switch (f) { |
case MESA_FORMAT_ARGB8888: |
return PACK_COLOR_8888(c[ACOMP], c[RCOMP], c[GCOMP], c[BCOMP]); |
case MESA_FORMAT_ARGB8888_REV: |
return PACK_COLOR_8888(c[BCOMP], c[GCOMP], c[RCOMP], c[ACOMP]); |
case MESA_FORMAT_XRGB8888: |
return PACK_COLOR_8888(0, c[RCOMP], c[GCOMP], c[BCOMP]); |
case MESA_FORMAT_XRGB8888_REV: |
return PACK_COLOR_8888(c[BCOMP], c[GCOMP], c[RCOMP], 0); |
case MESA_FORMAT_RGBA8888: |
return PACK_COLOR_8888(c[RCOMP], c[GCOMP], c[BCOMP], c[ACOMP]); |
case MESA_FORMAT_RGBA8888_REV: |
return PACK_COLOR_8888(c[ACOMP], c[BCOMP], c[GCOMP], c[RCOMP]); |
case MESA_FORMAT_RGB565: |
return PACK_COLOR_565(c[RCOMP], c[GCOMP], c[BCOMP]); |
default: |
assert(0); |
} |
} |
static inline unsigned |
pack_zs_i(gl_format f, uint32_t z, uint8_t s) |
{ |
switch (f) { |
case MESA_FORMAT_Z24_S8: |
return (z & 0xffffff00) | (s & 0xff); |
case MESA_FORMAT_Z24_X8: |
return (z & 0xffffff00); |
case MESA_FORMAT_Z16: |
return (z & 0xffff0000) >> 16; |
default: |
assert(0); |
} |
} |
static inline unsigned |
pack_rgba_f(gl_format f, float c[]) |
{ |
return pack_rgba_i(f, (uint8_t []) { |
FLOAT_TO_UBYTE(c[RCOMP]), |
FLOAT_TO_UBYTE(c[GCOMP]), |
FLOAT_TO_UBYTE(c[BCOMP]), |
FLOAT_TO_UBYTE(c[ACOMP]) }); |
} |
static inline unsigned |
pack_rgba_clamp_f(gl_format f, float c[]) |
{ |
GLubyte bytes[4]; |
_mesa_unclamped_float_rgba_to_ubyte(bytes, c); |
return pack_rgba_i(f, bytes); |
} |
static inline unsigned |
pack_zs_f(gl_format f, float z, uint8_t s) |
{ |
return pack_zs_i(f, FLOAT_TO_UINT(z), s); |
} |
/* Integer base-2 logarithm, rounded towards zero. */ |
static inline unsigned |
log2i(unsigned i) |
{ |
unsigned r = 0; |
if (i & 0xffff0000) { |
i >>= 16; |
r += 16; |
} |
if (i & 0x0000ff00) { |
i >>= 8; |
r += 8; |
} |
if (i & 0x000000f0) { |
i >>= 4; |
r += 4; |
} |
if (i & 0x0000000c) { |
i >>= 2; |
r += 2; |
} |
if (i & 0x00000002) { |
r += 1; |
} |
return r; |
} |
static inline unsigned |
align(unsigned x, unsigned m) |
{ |
return (x + m - 1) & ~(m - 1); |
} |
static inline void |
get_scissors(struct gl_framebuffer *fb, int *x, int *y, int *w, int *h) |
{ |
*w = fb->_Xmax - fb->_Xmin; |
*h = fb->_Ymax - fb->_Ymin; |
*x = fb->_Xmin; |
*y = (fb->Name ? fb->_Ymin : |
/* Window system FBO: Flip the Y coordinate. */ |
fb->Height - fb->_Ymax); |
} |
static inline void |
get_viewport_scale(struct gl_context *ctx, float a[16]) |
{ |
struct gl_viewport_attrib *vp = &ctx->Viewport; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
a[MAT_SX] = (float)vp->Width / 2; |
if (fb->Name) |
a[MAT_SY] = (float)vp->Height / 2; |
else |
/* Window system FBO: Flip the Y coordinate. */ |
a[MAT_SY] = - (float)vp->Height / 2; |
a[MAT_SZ] = fb->_DepthMaxF * (vp->Far - vp->Near) / 2; |
} |
static inline void |
get_viewport_translate(struct gl_context *ctx, float a[4]) |
{ |
struct gl_viewport_attrib *vp = &ctx->Viewport; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
a[0] = (float)vp->Width / 2 + vp->X; |
if (fb->Name) |
a[1] = (float)vp->Height / 2 + vp->Y; |
else |
/* Window system FBO: Flip the Y coordinate. */ |
a[1] = fb->Height - (float)vp->Height / 2 - vp->Y; |
a[2] = fb->_DepthMaxF * (vp->Far + vp->Near) / 2; |
} |
static inline GLboolean |
is_color_operand(int op) |
{ |
return op == GL_SRC_COLOR || op == GL_ONE_MINUS_SRC_COLOR; |
} |
static inline GLboolean |
is_negative_operand(int op) |
{ |
return op == GL_ONE_MINUS_SRC_COLOR || op == GL_ONE_MINUS_SRC_ALPHA; |
} |
static inline GLboolean |
is_texture_source(int s) |
{ |
return s == GL_TEXTURE || (s >= GL_TEXTURE0 && s <= GL_TEXTURE31); |
} |
static inline struct gl_texgen * |
get_texgen_coord(struct gl_texture_unit *u, int i) |
{ |
return ((struct gl_texgen *[]) |
{ &u->GenS, &u->GenT, &u->GenR, &u->GenQ }) [i]; |
} |
static inline float * |
get_texgen_coeff(struct gl_texgen *c) |
{ |
if (c->Mode == GL_OBJECT_LINEAR) |
return c->ObjectPlane; |
else if (c->Mode == GL_EYE_LINEAR) |
return c->EyePlane; |
else |
return NULL; |
} |
static inline unsigned |
get_format_blocksx(gl_format format, |
unsigned x) |
{ |
GLuint blockwidth; |
GLuint blockheight; |
_mesa_get_format_block_size(format, &blockwidth, &blockheight); |
return (x + blockwidth - 1) / blockwidth; |
} |
static inline unsigned |
get_format_blocksy(gl_format format, |
unsigned y) |
{ |
GLuint blockwidth; |
GLuint blockheight; |
_mesa_get_format_block_size(format, &blockwidth, &blockheight); |
return (y + blockheight - 1) / blockheight; |
} |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c |
---|
0,0 → 1,525 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_bufferobj.h" |
#include "nouveau_util.h" |
#include "main/bufferobj.h" |
#include "main/glformats.h" |
#include "main/image.h" |
/* Arbitrary pushbuf length we can assume we can get with a single |
* call to WAIT_RING. */ |
#define PUSHBUF_DWORDS 65536 |
/* Functions to turn GL arrays or index buffers into nouveau_array |
* structures. */ |
static int |
get_array_stride(struct gl_context *ctx, const struct gl_client_array *a) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
if (render->mode == VBO && !_mesa_is_bufferobj(a->BufferObj)) |
/* Pack client buffers. */ |
return align(_mesa_sizeof_type(a->Type) * a->Size, 4); |
else |
return a->StrideB; |
} |
static void |
vbo_init_arrays(struct gl_context *ctx, const struct _mesa_index_buffer *ib, |
const struct gl_client_array **arrays) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
GLboolean imm = (render->mode == IMM); |
int i, attr; |
if (ib) |
nouveau_init_array(&render->ib, 0, 0, ib->count, ib->type, |
ib->obj, ib->ptr, GL_TRUE, ctx); |
FOR_EACH_BOUND_ATTR(render, i, attr) { |
const struct gl_client_array *array = arrays[attr]; |
nouveau_init_array(&render->attrs[attr], attr, |
get_array_stride(ctx, array), |
array->Size, array->Type, |
imm ? array->BufferObj : NULL, |
array->Ptr, imm, ctx); |
} |
} |
static void |
vbo_deinit_arrays(struct gl_context *ctx, const struct _mesa_index_buffer *ib, |
const struct gl_client_array **arrays) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
int i, attr; |
if (ib) |
nouveau_cleanup_array(&render->ib); |
FOR_EACH_BOUND_ATTR(render, i, attr) { |
struct nouveau_array *a = &render->attrs[attr]; |
if (render->mode == IMM) |
nouveau_bo_ref(NULL, &a->bo); |
nouveau_deinit_array(a); |
render->map[i] = -1; |
} |
render->attr_count = 0; |
} |
/* Make some rendering decisions from the GL context. */ |
static void |
vbo_choose_render_mode(struct gl_context *ctx, const struct gl_client_array **arrays) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
int i; |
render->mode = VBO; |
if (ctx->Light.Enabled) { |
for (i = 0; i < MAT_ATTRIB_MAX; i++) { |
if (arrays[VERT_ATTRIB_GENERIC0 + i]->StrideB) { |
render->mode = IMM; |
break; |
} |
} |
} |
} |
static void |
vbo_emit_attr(struct gl_context *ctx, const struct gl_client_array **arrays, |
int attr) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_render_state *render = to_render_state(ctx); |
const struct gl_client_array *array = arrays[attr]; |
struct nouveau_array *a = &render->attrs[attr]; |
RENDER_LOCALS(ctx); |
if (!array->StrideB) { |
if (attr >= VERT_ATTRIB_GENERIC0) |
/* nouveau_update_state takes care of materials. */ |
return; |
/* Constant attribute. */ |
nouveau_init_array(a, attr, array->StrideB, array->Size, |
array->Type, array->BufferObj, array->Ptr, |
GL_TRUE, ctx); |
EMIT_IMM(ctx, a, 0); |
nouveau_deinit_array(a); |
} else { |
/* Varying attribute. */ |
struct nouveau_attr_info *info = &TAG(vertex_attrs)[attr]; |
if (render->mode == VBO) { |
render->map[info->vbo_index] = attr; |
render->vertex_size += array->_ElementSize; |
render->attr_count = MAX2(render->attr_count, |
info->vbo_index + 1); |
} else { |
render->map[render->attr_count++] = attr; |
render->vertex_size += 4 * info->imm_fields; |
} |
} |
} |
#define MAT(a) (VERT_ATTRIB_GENERIC0 + MAT_ATTRIB_##a) |
static void |
vbo_choose_attrs(struct gl_context *ctx, const struct gl_client_array **arrays) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
int i; |
/* Reset the vertex size. */ |
render->vertex_size = 0; |
render->attr_count = 0; |
vbo_emit_attr(ctx, arrays, VERT_ATTRIB_COLOR0); |
if (ctx->Fog.ColorSumEnabled && !ctx->Light.Enabled) |
vbo_emit_attr(ctx, arrays, VERT_ATTRIB_COLOR1); |
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { |
if (ctx->Texture._EnabledCoordUnits & (1 << i)) |
vbo_emit_attr(ctx, arrays, VERT_ATTRIB_TEX0 + i); |
} |
if (ctx->Fog.Enabled && ctx->Fog.FogCoordinateSource == GL_FOG_COORD) |
vbo_emit_attr(ctx, arrays, VERT_ATTRIB_FOG); |
if (ctx->Light.Enabled || |
(ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)) |
vbo_emit_attr(ctx, arrays, VERT_ATTRIB_NORMAL); |
if (ctx->Light.Enabled && render->mode == IMM) { |
vbo_emit_attr(ctx, arrays, MAT(FRONT_AMBIENT)); |
vbo_emit_attr(ctx, arrays, MAT(FRONT_DIFFUSE)); |
vbo_emit_attr(ctx, arrays, MAT(FRONT_SPECULAR)); |
vbo_emit_attr(ctx, arrays, MAT(FRONT_SHININESS)); |
if (ctx->Light.Model.TwoSide) { |
vbo_emit_attr(ctx, arrays, MAT(BACK_AMBIENT)); |
vbo_emit_attr(ctx, arrays, MAT(BACK_DIFFUSE)); |
vbo_emit_attr(ctx, arrays, MAT(BACK_SPECULAR)); |
vbo_emit_attr(ctx, arrays, MAT(BACK_SHININESS)); |
} |
} |
vbo_emit_attr(ctx, arrays, VERT_ATTRIB_POS); |
} |
static int |
get_max_client_stride(struct gl_context *ctx, const struct gl_client_array **arrays) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
int i, attr, s = 0; |
FOR_EACH_BOUND_ATTR(render, i, attr) { |
const struct gl_client_array *a = arrays[attr]; |
if (!_mesa_is_bufferobj(a->BufferObj)) |
s = MAX2(s, get_array_stride(ctx, a)); |
} |
return s; |
} |
static void |
TAG(vbo_render_prims)(struct gl_context *ctx, |
const struct _mesa_prim *prims, GLuint nr_prims, |
const struct _mesa_index_buffer *ib, |
GLboolean index_bounds_valid, |
GLuint min_index, GLuint max_index, |
struct gl_transform_feedback_object *tfb_vertcount); |
static GLboolean |
vbo_maybe_split(struct gl_context *ctx, const struct gl_client_array **arrays, |
const struct _mesa_prim *prims, GLuint nr_prims, |
const struct _mesa_index_buffer *ib, |
GLuint min_index, GLuint max_index) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_render_state *render = to_render_state(ctx); |
struct nouveau_bufctx *bufctx = nctx->hw.bufctx; |
unsigned pushbuf_avail = PUSHBUF_DWORDS - 2 * (bufctx->relocs + |
render->attr_count), |
vert_avail = get_max_vertices(ctx, NULL, pushbuf_avail), |
idx_avail = get_max_vertices(ctx, ib, pushbuf_avail); |
int stride; |
/* Try to keep client buffers smaller than the scratch BOs. */ |
if (render->mode == VBO && |
(stride = get_max_client_stride(ctx, arrays))) |
vert_avail = MIN2(vert_avail, |
NOUVEAU_SCRATCH_SIZE / stride); |
if (max_index - min_index > vert_avail || |
(ib && ib->count > idx_avail)) { |
struct split_limits limits = { |
.max_verts = vert_avail, |
.max_indices = idx_avail, |
.max_vb_size = ~0, |
}; |
vbo_split_prims(ctx, arrays, prims, nr_prims, ib, min_index, |
max_index, TAG(vbo_render_prims), &limits); |
return GL_TRUE; |
} |
return GL_FALSE; |
} |
/* VBO rendering path. */ |
static GLboolean |
check_update_array(struct nouveau_array *a, unsigned offset, |
struct nouveau_bo *bo, int *pdelta) |
{ |
int delta = *pdelta; |
GLboolean dirty; |
if (a->bo == bo) { |
if (delta < 0) |
delta = ((int)offset - (int)a->offset) / a->stride; |
dirty = (delta < 0 || |
offset != (a->offset + delta * a->stride)); |
} else { |
dirty = GL_TRUE; |
} |
*pdelta = (dirty ? 0 : delta); |
return dirty; |
} |
static void |
vbo_bind_vertices(struct gl_context *ctx, const struct gl_client_array **arrays, |
int base, unsigned min_index, unsigned max_index, int *pdelta) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_bo *bo[NUM_VERTEX_ATTRS]; |
unsigned offset[NUM_VERTEX_ATTRS]; |
GLboolean dirty = GL_FALSE; |
int i, j, attr; |
RENDER_LOCALS(ctx); |
*pdelta = -1; |
FOR_EACH_BOUND_ATTR(render, i, attr) { |
const struct gl_client_array *array = arrays[attr]; |
struct gl_buffer_object *obj = array->BufferObj; |
struct nouveau_array *a = &render->attrs[attr]; |
unsigned delta = (base + min_index) * array->StrideB; |
bo[i] = NULL; |
if (nouveau_bufferobj_hw(obj)) { |
/* Array in a buffer obj. */ |
nouveau_bo_ref(to_nouveau_bufferobj(obj)->bo, &bo[i]); |
offset[i] = delta + (intptr_t)array->Ptr; |
} else { |
int n = max_index - min_index + 1; |
char *sp = (char *)ADD_POINTERS( |
nouveau_bufferobj_sys(obj), array->Ptr) + delta; |
char *dp = nouveau_get_scratch(ctx, n * a->stride, |
&bo[i], &offset[i]); |
/* Array in client memory, move it to a |
* scratch buffer obj. */ |
for (j = 0; j < n; j++) |
memcpy(dp + j * a->stride, |
sp + j * array->StrideB, |
a->stride); |
} |
dirty |= check_update_array(a, offset[i], bo[i], pdelta); |
} |
*pdelta -= min_index; |
if (dirty) { |
/* Buffers changed, update the attribute binding. */ |
FOR_EACH_BOUND_ATTR(render, i, attr) { |
struct nouveau_array *a = &render->attrs[attr]; |
nouveau_bo_ref(NULL, &a->bo); |
a->offset = offset[i]; |
a->bo = bo[i]; |
} |
TAG(render_release_vertices)(ctx); |
TAG(render_bind_vertices)(ctx); |
} else { |
/* Just cleanup. */ |
FOR_EACH_BOUND_ATTR(render, i, attr) |
nouveau_bo_ref(NULL, &bo[i]); |
} |
BATCH_VALIDATE(); |
} |
static void |
vbo_draw_vbo(struct gl_context *ctx, const struct gl_client_array **arrays, |
const struct _mesa_prim *prims, GLuint nr_prims, |
const struct _mesa_index_buffer *ib, GLuint min_index, |
GLuint max_index) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
dispatch_t dispatch = get_array_dispatch(&to_render_state(ctx)->ib); |
int i, delta = 0, basevertex = 0; |
RENDER_LOCALS(ctx); |
TAG(render_set_format)(ctx); |
for (i = 0; i < nr_prims; i++) { |
unsigned start = prims[i].start, |
count = prims[i].count; |
if (i == 0 || basevertex != prims[i].basevertex) { |
basevertex = prims[i].basevertex; |
vbo_bind_vertices(ctx, arrays, basevertex, min_index, |
max_index, &delta); |
nouveau_pushbuf_bufctx(push, nctx->hw.bufctx); |
if (nouveau_pushbuf_validate(push)) { |
nouveau_pushbuf_bufctx(push, NULL); |
return; |
} |
} |
if (count > get_max_vertices(ctx, ib, PUSH_AVAIL(push))) |
PUSH_SPACE(push, PUSHBUF_DWORDS); |
BATCH_BEGIN(nvgl_primitive(prims[i].mode)); |
dispatch(ctx, start, delta, count); |
BATCH_END(); |
} |
nouveau_pushbuf_bufctx(push, NULL); |
TAG(render_release_vertices)(ctx); |
} |
/* Immediate rendering path. */ |
static unsigned |
extract_id(struct nouveau_array *a, int i, int j) |
{ |
return j; |
} |
static void |
vbo_draw_imm(struct gl_context *ctx, const struct gl_client_array **arrays, |
const struct _mesa_prim *prims, GLuint nr_prims, |
const struct _mesa_index_buffer *ib, GLuint min_index, |
GLuint max_index) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
extract_u_t extract = ib ? render->ib.extract_u : extract_id; |
int i, j, k, attr; |
RENDER_LOCALS(ctx); |
nouveau_pushbuf_bufctx(push, nctx->hw.bufctx); |
if (nouveau_pushbuf_validate(push)) { |
nouveau_pushbuf_bufctx(push, NULL); |
return; |
} |
for (i = 0; i < nr_prims; i++) { |
unsigned start = prims[i].start, |
end = start + prims[i].count; |
if (prims[i].count > get_max_vertices(ctx, ib, |
PUSH_AVAIL(push))) |
PUSH_SPACE(push, PUSHBUF_DWORDS); |
BATCH_BEGIN(nvgl_primitive(prims[i].mode)); |
for (; start < end; start++) { |
j = prims[i].basevertex + |
extract(&render->ib, 0, start); |
FOR_EACH_BOUND_ATTR(render, k, attr) |
EMIT_IMM(ctx, &render->attrs[attr], j); |
} |
BATCH_END(); |
} |
nouveau_pushbuf_bufctx(push, NULL); |
} |
/* draw_prims entry point when we're doing hw-tnl. */ |
static void |
TAG(vbo_render_prims)(struct gl_context *ctx, |
const struct _mesa_prim *prims, GLuint nr_prims, |
const struct _mesa_index_buffer *ib, |
GLboolean index_bounds_valid, |
GLuint min_index, GLuint max_index, |
struct gl_transform_feedback_object *tfb_vertcount) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
const struct gl_client_array **arrays = ctx->Array._DrawArrays; |
if (!index_bounds_valid) |
vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index, |
nr_prims); |
vbo_choose_render_mode(ctx, arrays); |
vbo_choose_attrs(ctx, arrays); |
if (vbo_maybe_split(ctx, arrays, prims, nr_prims, ib, min_index, |
max_index)) |
return; |
vbo_init_arrays(ctx, ib, arrays); |
if (render->mode == VBO) |
vbo_draw_vbo(ctx, arrays, prims, nr_prims, ib, min_index, |
max_index); |
else |
vbo_draw_imm(ctx, arrays, prims, nr_prims, ib, min_index, |
max_index); |
vbo_deinit_arrays(ctx, ib, arrays); |
} |
/* VBO rendering entry points. */ |
static void |
TAG(vbo_check_render_prims)(struct gl_context *ctx, |
const struct _mesa_prim *prims, GLuint nr_prims, |
const struct _mesa_index_buffer *ib, |
GLboolean index_bounds_valid, |
GLuint min_index, GLuint max_index, |
struct gl_transform_feedback_object *tfb_vertcount) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
nouveau_validate_framebuffer(ctx); |
if (nctx->fallback == HWTNL) |
TAG(vbo_render_prims)(ctx, prims, nr_prims, ib, |
index_bounds_valid, min_index, max_index, |
tfb_vertcount); |
if (nctx->fallback == SWTNL) |
_tnl_vbo_draw_prims(ctx, prims, nr_prims, ib, |
index_bounds_valid, min_index, max_index, |
tfb_vertcount); |
} |
void |
TAG(vbo_init)(struct gl_context *ctx) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
int i; |
for (i = 0; i < VERT_ATTRIB_MAX; i++) |
render->map[i] = -1; |
vbo_set_draw_func(ctx, TAG(vbo_check_render_prims)); |
vbo_use_buffer_objects(ctx); |
} |
void |
TAG(vbo_destroy)(struct gl_context *ctx) |
{ |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv01_2d.xml.h |
---|
0,0 → 1,1343 |
#ifndef NV01_2D_XML |
#define NV01_2D_XML |
/* Autogenerated file, DO NOT EDIT manually! |
This file was generated by the rules-ng-ng headergen tool in this git repository: |
http://0x04.net/cgit/index.cgi/rules-ng-ng |
git clone git://0x04.net/rules-ng-ng |
The rules-ng-ng source files this header was generated from are: |
- nv01_2d.xml ( 33509 bytes, from 2010-11-13 23:32:57) |
- copyright.xml ( 6452 bytes, from 2010-11-15 15:10:58) |
- nv_defs.xml ( 4437 bytes, from 2010-11-01 00:28:46) |
- nv_object.xml ( 11547 bytes, from 2010-11-13 23:32:57) |
- nvchipsets.xml ( 3074 bytes, from 2010-11-13 23:32:57) |
Copyright (C) 2006-2010 by the following authors: |
- Artur Huillet <arthur.huillet@free.fr> (ahuillet) |
- Ben Skeggs (darktama, darktama_) |
- B. R. <koala_br@users.sourceforge.net> (koala_br) |
- Carlos Martin <carlosmn@users.sf.net> (carlosmn) |
- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr) |
- Dawid Gajownik <gajownik@users.sf.net> (gajownik) |
- Dmitry Baryshkov |
- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag) |
- EdB <edb_@users.sf.net> (edb_) |
- Erik Waling <erikwailing@users.sf.net> (erikwaling) |
- Francisco Jerez <currojerez@riseup.net> (curro) |
- imirkin <imirkin@users.sf.net> (imirkin) |
- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome) |
- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy) |
- Laurent Carlier <lordheavym@gmail.com> (lordheavy) |
- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1) |
- Maarten Maathuis <madman2003@gmail.com> (stillunknown) |
- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin) |
- Mark Carey <mark.carey@gmail.com> (careym) |
- Matthieu Castet <matthieu.castet@parrot.com> (mat-c) |
- nvidiaman <nvidiaman@users.sf.net> (nvidiaman) |
- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata) |
- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen) |
- Peter Popov <ironpeter@users.sf.net> (ironpeter) |
- Richard Hughes <hughsient@users.sf.net> (hughsient) |
- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar) |
- Serge Martin |
- Simon Raffeiner |
- Stephane Loeuillet <leroutier@users.sf.net> (leroutier) |
- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu) |
- sturmflut <sturmflut@users.sf.net> (sturmflut) |
- Sylvain Munaut <tnt@246tNt.com> |
- Victor Stinner <victor.stinner@haypocalc.com> (haypo) |
- Wladmir van der Laan <laanwj@gmail.com> (miathan6) |
- Younes Manton <younes.m@gmail.com> (ymanton) |
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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
*/ |
#define NV01_CONTEXT_BETA1_DMA_NOTIFY 0x00000180 |
#define NV01_CONTEXT_BETA1_BETA_1D31 0x00000300 |
#define NV04_BETA_SOLID_DMA_NOTIFY 0x00000180 |
#define NV04_BETA_SOLID_BETA_FACTOR 0x00000300 |
#define NV01_CONTEXT_COLOR_KEY_DMA_NOTIFY 0x00000180 |
#define NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT 0x00000300 |
#define NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_A16R5G6B5 0x00000001 |
#define NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_X16A1R5G5B5 0x00000002 |
#define NV01_CONTEXT_COLOR_KEY_COLOR_FORMAT_A8R8G8B8 0x00000003 |
#define NV01_CONTEXT_COLOR_KEY_COLOR 0x00000304 |
#define NV01_CONTEXT_PATTERN_DMA_NOTIFY 0x00000180 |
#define NV01_CONTEXT_PATTERN_COLOR_FORMAT 0x00000300 |
#define NV01_CONTEXT_PATTERN_MONOCHROME_FORMAT 0x00000304 |
#define NV01_CONTEXT_PATTERN_SHAPE 0x00000308 |
#define NV01_CONTEXT_PATTERN_COLOR(i0) (0x00000310 + 0x4*(i0)) |
#define NV01_CONTEXT_PATTERN_COLOR__ESIZE 0x00000004 |
#define NV01_CONTEXT_PATTERN_COLOR__LEN 0x00000002 |
#define NV01_CONTEXT_PATTERN_PATTERN(i0) (0x00000318 + 0x4*(i0)) |
#define NV01_CONTEXT_PATTERN_PATTERN__ESIZE 0x00000004 |
#define NV01_CONTEXT_PATTERN_PATTERN__LEN 0x00000002 |
#define NV01_CONTEXT_CLIP_RECTANGLE_DMA_NOTIFY 0x00000180 |
#define NV01_CONTEXT_CLIP_RECTANGLE_POINT 0x00000300 |
#define NV01_CONTEXT_CLIP_RECTANGLE_POINT_X__MASK 0x0000ffff |
#define NV01_CONTEXT_CLIP_RECTANGLE_POINT_X__SHIFT 0 |
#define NV01_CONTEXT_CLIP_RECTANGLE_POINT_Y__MASK 0xffff0000 |
#define NV01_CONTEXT_CLIP_RECTANGLE_POINT_Y__SHIFT 16 |
#define NV01_CONTEXT_CLIP_RECTANGLE_SIZE 0x00000304 |
#define NV01_CONTEXT_CLIP_RECTANGLE_SIZE_W__MASK 0x0000ffff |
#define NV01_CONTEXT_CLIP_RECTANGLE_SIZE_W__SHIFT 0 |
#define NV01_CONTEXT_CLIP_RECTANGLE_SIZE_H__MASK 0xffff0000 |
#define NV01_CONTEXT_CLIP_RECTANGLE_SIZE_H__SHIFT 16 |
#define NV04_CONTEXT_SURFACES_2D_DMA_NOTIFY 0x00000180 |
#define NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE 0x00000184 |
#define NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_DESTIN 0x00000188 |
#define NV50_CONTEXT_SURFACES_2D_SRC_LINEAR 0x00000200 |
#define NV50_CONTEXT_SURFACES_2D_SRC_TILE_MODE 0x00000204 |
#define NV50_CONTEXT_SURFACES_2D_SRC_WIDTH 0x00000208 |
#define NV50_CONTEXT_SURFACES_2D_SRC_HEIGHT 0x0000020c |
#define NV50_CONTEXT_SURFACES_2D_UNK0210 0x00000210 |
#define NV50_CONTEXT_SURFACES_2D_UNK0214 0x00000214 |
#define NV50_CONTEXT_SURFACES_2D_DST_LINEAR 0x00000218 |
#define NV50_CONTEXT_SURFACES_2D_DST_TILE_MODE 0x0000021c |
#define NV50_CONTEXT_SURFACES_2D_DST_WIDTH 0x00000220 |
#define NV50_CONTEXT_SURFACES_2D_DST_HEIGHT 0x00000224 |
#define NV50_CONTEXT_SURFACES_2D_UNK0228 0x00000228 |
#define NV50_CONTEXT_SURFACES_2D_UNK022C 0x0000022c |
#define NV50_CONTEXT_SURFACES_2D_OFFSET_SOURCE_HIGH 0x00000230 |
#define NV50_CONTEXT_SURFACES_2D_OFFSET_DESTIN_HIGH 0x00000234 |
#define NV04_CONTEXT_SURFACES_2D_FORMAT 0x00000300 |
#define NV04_CONTEXT_SURFACES_2D_FORMAT_Y8 0x00000001 |
#define NV04_CONTEXT_SURFACES_2D_FORMAT_X1R5G5B5_Z1R5G5B5 0x00000002 |
#define NV04_CONTEXT_SURFACES_2D_FORMAT_X1R5G5B5_X1R5G5B5 0x00000003 |
#define NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5 0x00000004 |
#define NV04_CONTEXT_SURFACES_2D_FORMAT_Y16 0x00000005 |
#define NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_Z8R8G8B8 0x00000006 |
#define NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_X8R8G8B8 0x00000007 |
#define NV04_CONTEXT_SURFACES_2D_FORMAT_X1A7R8G8B8_Z1A7R8G8B8 0x00000008 |
#define NV04_CONTEXT_SURFACES_2D_FORMAT_X1A7R8G8B8_X1A7R8G8B8 0x00000009 |
#define NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8 0x0000000a |
#define NV04_CONTEXT_SURFACES_2D_FORMAT_Y32 0x0000000b |
#define NV04_CONTEXT_SURFACES_2D_PITCH 0x00000304 |
#define NV04_CONTEXT_SURFACES_2D_PITCH_SOURCE__MASK 0x0000ffff |
#define NV04_CONTEXT_SURFACES_2D_PITCH_SOURCE__SHIFT 0 |
#define NV04_CONTEXT_SURFACES_2D_PITCH_DESTIN__MASK 0xffff0000 |
#define NV04_CONTEXT_SURFACES_2D_PITCH_DESTIN__SHIFT 16 |
#define NV04_CONTEXT_SURFACES_2D_OFFSET_SOURCE 0x00000308 |
#define NV04_CONTEXT_SURFACES_2D_OFFSET_DESTIN 0x0000030c |
#define NV04_SWIZZLED_SURFACE_DMA_NOTIFY 0x00000180 |
#define NV04_SWIZZLED_SURFACE_DMA_IMAGE 0x00000184 |
#define NV04_SWIZZLED_SURFACE_FORMAT 0x00000300 |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR__MASK 0x000000ff |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR__SHIFT 0 |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8 0x00000001 |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1R5G5B5_Z1R5G5B5 0x00000002 |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1R5G5B5_X1R5G5B5 0x00000003 |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5 0x00000004 |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y16 0x00000005 |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X8R8G8B8_Z8R8G8B8 0x00000006 |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X8R8G8B8_X8R8G8B8 0x00000007 |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1A7R8G8B8_Z1A7R8G8B8 0x00000008 |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR_X1A7R8G8B8_X1A7R8G8B8 0x00000009 |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8 0x0000000a |
#define NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y32 0x0000000b |
#define NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U__MASK 0x00ff0000 |
#define NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U__SHIFT 16 |
#define NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V__MASK 0xff000000 |
#define NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V__SHIFT 24 |
#define NV04_SWIZZLED_SURFACE_OFFSET 0x00000304 |
#define NV03_CONTEXT_ROP_DMA_NOTIFY 0x00000180 |
#define NV03_CONTEXT_ROP_ROP 0x00000300 |
#define NV04_IMAGE_PATTERN_DMA_NOTIFY 0x00000180 |
#define NV04_IMAGE_PATTERN_COLOR_FORMAT 0x00000300 |
#define NV04_IMAGE_PATTERN_COLOR_FORMAT_A16R5G6B5 0x00000001 |
#define NV04_IMAGE_PATTERN_COLOR_FORMAT_X16A1R5G5B5 0x00000002 |
#define NV04_IMAGE_PATTERN_COLOR_FORMAT_A8R8G8B8 0x00000003 |
#define NV04_IMAGE_PATTERN_MONOCHROME_FORMAT 0x00000304 |
#define NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_CGA6 0x00000001 |
#define NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE 0x00000002 |
#define NV04_IMAGE_PATTERN_MONOCHROME_SHAPE 0x00000308 |
#define NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8 0x00000000 |
#define NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_64X1 0x00000001 |
#define NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_1X64 0x00000002 |
#define NV04_IMAGE_PATTERN_PATTERN_SELECT 0x0000030c |
#define NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO 0x00000001 |
#define NV04_IMAGE_PATTERN_PATTERN_SELECT_COLOR 0x00000002 |
#define NV04_IMAGE_PATTERN_MONOCHROME_COLOR0 0x00000310 |
#define NV04_IMAGE_PATTERN_MONOCHROME_COLOR1 0x00000314 |
#define NV04_IMAGE_PATTERN_MONOCHROME_PATTERN0 0x00000318 |
#define NV04_IMAGE_PATTERN_MONOCHROME_PATTERN1 0x0000031c |
#define NV04_IMAGE_PATTERN_PATTERN_Y8(i0) (0x00000400 + 0x4*(i0)) |
#define NV04_IMAGE_PATTERN_PATTERN_Y8__ESIZE 0x00000004 |
#define NV04_IMAGE_PATTERN_PATTERN_Y8__LEN 0x00000010 |
#define NV04_IMAGE_PATTERN_PATTERN_Y8_Y0__MASK 0x000000ff |
#define NV04_IMAGE_PATTERN_PATTERN_Y8_Y0__SHIFT 0 |
#define NV04_IMAGE_PATTERN_PATTERN_Y8_Y1__MASK 0x0000ff00 |
#define NV04_IMAGE_PATTERN_PATTERN_Y8_Y1__SHIFT 8 |
#define NV04_IMAGE_PATTERN_PATTERN_Y8_Y2__MASK 0x00ff0000 |
#define NV04_IMAGE_PATTERN_PATTERN_Y8_Y2__SHIFT 16 |
#define NV04_IMAGE_PATTERN_PATTERN_Y8_Y3__MASK 0xff000000 |
#define NV04_IMAGE_PATTERN_PATTERN_Y8_Y3__SHIFT 24 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5(i0) (0x00000500 + 0x4*(i0)) |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5__ESIZE 0x00000004 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5__LEN 0x00000020 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B0__MASK 0x0000001f |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B0__SHIFT 0 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G0__MASK 0x000007e0 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G0__SHIFT 5 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R0__MASK 0x0000f800 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R0__SHIFT 11 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B1__MASK 0x001f0000 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_B1__SHIFT 16 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G1__MASK 0x07e00000 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_G1__SHIFT 21 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R1__MASK 0xf8000000 |
#define NV04_IMAGE_PATTERN_PATTERN_R5G6B5_R1__SHIFT 27 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5(i0) (0x00000600 + 0x4*(i0)) |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5__ESIZE 0x00000004 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5__LEN 0x00000020 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B0__MASK 0x0000001f |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B0__SHIFT 0 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G0__MASK 0x000003e0 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G0__SHIFT 5 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R0__MASK 0x00007c00 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R0__SHIFT 10 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B1__MASK 0x001f0000 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_B1__SHIFT 16 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G1__MASK 0x03e00000 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_G1__SHIFT 21 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R1__MASK 0x7c000000 |
#define NV04_IMAGE_PATTERN_PATTERN_X1R5G5B5_R1__SHIFT 26 |
#define NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8(i0) (0x00000700 + 0x4*(i0)) |
#define NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8__ESIZE 0x00000004 |
#define NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8__LEN 0x00000040 |
#define NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_B__MASK 0x000000ff |
#define NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_B__SHIFT 0 |
#define NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_G__MASK 0x0000ff00 |
#define NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_G__SHIFT 8 |
#define NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_R__MASK 0x00ff0000 |
#define NV04_IMAGE_PATTERN_PATTERN_X8R8G8B8_R__SHIFT 16 |
#define NV01_RENDER_SOLID_LINE_PATCH 0x0000010c |
#define NV01_RENDER_SOLID_LINE_DMA_NOTIFY 0x00000180 |
#define NV01_RENDER_SOLID_LINE_CLIP_RECTANGLE 0x00000184 |
#define NV01_RENDER_SOLID_LINE_PATTERN 0x00000188 |
#define NV04_RENDER_SOLID_LINE_PATTERN 0x00000188 |
#define NV01_RENDER_SOLID_LINE_ROP 0x0000018c |
#define NV01_RENDER_SOLID_LINE_BETA1 0x00000190 |
#define NV01_RENDER_SOLID_LINE_SURFACE_DST 0x00000194 |
#define NV04_RENDER_SOLID_LINE_BETA4 0x00000194 |
#define NV04_RENDER_SOLID_LINE_SURFACE 0x00000198 |
#define NV01_RENDER_SOLID_LINE_OPERATION 0x000002fc |
#define NV01_RENDER_SOLID_LINE_OPERATION_SRCCOPY_AND 0x00000000 |
#define NV01_RENDER_SOLID_LINE_OPERATION_ROP_AND 0x00000001 |
#define NV01_RENDER_SOLID_LINE_OPERATION_BLEND_AND 0x00000002 |
#define NV01_RENDER_SOLID_LINE_OPERATION_SRCCOPY 0x00000003 |
#define NV01_RENDER_SOLID_LINE_OPERATION_SRCCOPY_PREMULT 0x00000004 |
#define NV01_RENDER_SOLID_LINE_OPERATION_BLEND_PREMULT 0x00000005 |
#define NV01_RENDER_SOLID_LINE_COLOR_FORMAT 0x00000300 |
#define NV01_RENDER_SOLID_LINE_COLOR_FORMAT_A16R5G6B5 0x00000001 |
#define NV01_RENDER_SOLID_LINE_COLOR_FORMAT_X16A1R5G5B5 0x00000002 |
#define NV01_RENDER_SOLID_LINE_COLOR_FORMAT_A8R8G8B8 0x00000003 |
#define NV01_RENDER_SOLID_LINE_COLOR 0x00000304 |
#define NV01_RENDER_SOLID_LINE_LINE_POINT0(i0) (0x00000400 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_LINE_LINE_POINT0__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_LINE_LINE_POINT0__LEN 0x00000010 |
#define NV01_RENDER_SOLID_LINE_LINE_POINT0_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_LINE_LINE_POINT0_X__SHIFT 0 |
#define NV01_RENDER_SOLID_LINE_LINE_POINT0_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_LINE_LINE_POINT0_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_LINE_LINE_POINT1(i0) (0x00000404 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_LINE_LINE_POINT1__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_LINE_LINE_POINT1__LEN 0x00000010 |
#define NV01_RENDER_SOLID_LINE_LINE_POINT1_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_LINE_LINE_POINT1_X__SHIFT 0 |
#define NV01_RENDER_SOLID_LINE_LINE_POINT1_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_LINE_LINE_POINT1_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT0_X(i0) (0x00000480 + 0x10*(i0)) |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT0_X__ESIZE 0x00000010 |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT0_X__LEN 0x00000010 |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT0_Y(i0) (0x00000484 + 0x10*(i0)) |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT0_Y__ESIZE 0x00000010 |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT0_Y__LEN 0x00000010 |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT1_X(i0) (0x00000488 + 0x10*(i0)) |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT1_X__ESIZE 0x00000010 |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT1_X__LEN 0x00000010 |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT1_Y(i0) (0x0000048c + 0x10*(i0)) |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT1_Y__ESIZE 0x00000010 |
#define NV01_RENDER_SOLID_LINE_LINE32_POINT1_Y__LEN 0x00000010 |
#define NV01_RENDER_SOLID_LINE_POLYLINE(i0) (0x00000500 + 0x4*(i0)) |
#define NV01_RENDER_SOLID_LINE_POLYLINE__ESIZE 0x00000004 |
#define NV01_RENDER_SOLID_LINE_POLYLINE__LEN 0x00000020 |
#define NV01_RENDER_SOLID_LINE_POLYLINE_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_LINE_POLYLINE_X__SHIFT 0 |
#define NV01_RENDER_SOLID_LINE_POLYLINE_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_LINE_POLYLINE_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_X(i0) (0x00000580 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_X__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_X__LEN 0x00000010 |
#define NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_Y(i0) (0x00000584 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_Y__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_LINE_POLYLINE32_POINT_Y__LEN 0x00000010 |
#define NV01_RENDER_SOLID_LINE_CPOLYLINE_COLOR(i0) (0x00000600 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_LINE_CPOLYLINE_COLOR__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_LINE_CPOLYLINE_COLOR__LEN 0x00000010 |
#define NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT(i0) (0x00000604 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT__LEN 0x00000010 |
#define NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_X__SHIFT 0 |
#define NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_LINE_CPOLYLINE_POINT_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_TRIANGLE_PATCH 0x0000010c |
#define NV01_RENDER_SOLID_TRIANGLE_DMA_NOTIFY 0x00000180 |
#define NV01_RENDER_SOLID_TRIANGLE_CLIP_RECTANGLE 0x00000184 |
#define NV01_RENDER_SOLID_TRIANGLE_PATTERN 0x00000188 |
#define NV04_RENDER_SOLID_TRIANGLE_PATTERN 0x00000188 |
#define NV01_RENDER_SOLID_TRIANGLE_ROP 0x0000018c |
#define NV01_RENDER_SOLID_TRIANGLE_BETA1 0x00000190 |
#define NV01_RENDER_SOLID_TRIANGLE_SURFACE_DST 0x00000194 |
#define NV04_RENDER_SOLID_TRIANGLE_BETA4 0x00000194 |
#define NV04_RENDER_SOLID_TRIANGLE_SURFACE 0x00000198 |
#define NV01_RENDER_SOLID_TRIANGLE_OPERATION 0x000002fc |
#define NV01_RENDER_SOLID_TRIANGLE_OPERATION_SRCCOPY_AND 0x00000000 |
#define NV01_RENDER_SOLID_TRIANGLE_OPERATION_ROP_AND 0x00000001 |
#define NV01_RENDER_SOLID_TRIANGLE_OPERATION_BLEND_AND 0x00000002 |
#define NV01_RENDER_SOLID_TRIANGLE_OPERATION_SRCCOPY 0x00000003 |
#define NV01_RENDER_SOLID_TRIANGLE_OPERATION_SRCCOPY_PREMULT 0x00000004 |
#define NV01_RENDER_SOLID_TRIANGLE_OPERATION_BLEND_PREMULT 0x00000005 |
#define NV01_RENDER_SOLID_TRIANGLE_COLOR_FORMAT 0x00000300 |
#define NV01_RENDER_SOLID_TRIANGLE_COLOR_FORMAT_A16R5G6B5 0x00000001 |
#define NV01_RENDER_SOLID_TRIANGLE_COLOR_FORMAT_X16A1R5G5B5 0x00000002 |
#define NV01_RENDER_SOLID_TRIANGLE_COLOR_FORMAT_A8R8G8B8 0x00000003 |
#define NV01_RENDER_SOLID_TRIANGLE_COLOR 0x00000304 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0 0x00000310 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_X__SHIFT 0 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT0_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1 0x00000314 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_X__SHIFT 0 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT1_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2 0x00000318 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_X__SHIFT 0 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE_POINT2_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT0_X 0x00000320 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT0_Y 0x00000324 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT1_X 0x00000328 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT1_Y 0x0000032c |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT2_X 0x00000330 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIANGLE32_POINT2_Y 0x00000334 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH(i0) (0x00000400 + 0x4*(i0)) |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH__ESIZE 0x00000004 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH__LEN 0x00000020 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH_X__SHIFT 0 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_X(i0) (0x00000480 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_X__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_X__LEN 0x00000010 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_Y(i0) (0x00000484 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_Y__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_TRIANGLE_TRIMESH32_POINT_Y__LEN 0x00000010 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_COLOR(i0) (0x00000500 + 0x10*(i0)) |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_COLOR__ESIZE 0x00000010 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_COLOR__LEN 0x00000008 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0(i0) (0x00000504 + 0x10*(i0)) |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0__ESIZE 0x00000010 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0__LEN 0x00000008 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_X__SHIFT 0 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT0_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1(i0) (0x00000508 + 0x10*(i0)) |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1__ESIZE 0x00000010 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1__LEN 0x00000008 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_X__SHIFT 0 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT1_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2(i0) (0x0000050c + 0x10*(i0)) |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2__ESIZE 0x00000010 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2__LEN 0x00000008 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_X__SHIFT 0 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIANGLE_POINT2_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_COLOR(i0) (0x00000580 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_COLOR__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_COLOR__LEN 0x00000010 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT(i0) (0x00000584 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT__LEN 0x00000010 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_X__SHIFT 0 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_TRIANGLE_CTRIMESH_POINT_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_RECTANGLE_PATCH 0x0000010c |
#define NV01_RENDER_SOLID_RECTANGLE_DMA_NOTIFY 0x00000180 |
#define NV01_RENDER_SOLID_RECTANGLE_CLIP_RECTANGLE 0x00000184 |
#define NV01_RENDER_SOLID_RECTANGLE_PATTERN 0x00000188 |
#define NV04_RENDER_SOLID_RECTANGLE_PATTERN 0x00000188 |
#define NV01_RENDER_SOLID_RECTANGLE_ROP 0x0000018c |
#define NV01_RENDER_SOLID_RECTANGLE_BETA1 0x00000190 |
#define NV01_RENDER_SOLID_RECTANGLE_SURFACE_DST 0x00000194 |
#define NV04_RENDER_SOLID_RECTANGLE_BETA4 0x00000194 |
#define NV04_RENDER_SOLID_RECTANGLE_SURFACE 0x00000198 |
#define NV01_RENDER_SOLID_RECTANGLE_OPERATION 0x000002fc |
#define NV01_RENDER_SOLID_RECTANGLE_OPERATION_SRCCOPY_AND 0x00000000 |
#define NV01_RENDER_SOLID_RECTANGLE_OPERATION_ROP_AND 0x00000001 |
#define NV01_RENDER_SOLID_RECTANGLE_OPERATION_BLEND_AND 0x00000002 |
#define NV01_RENDER_SOLID_RECTANGLE_OPERATION_SRCCOPY 0x00000003 |
#define NV01_RENDER_SOLID_RECTANGLE_OPERATION_SRCCOPY_PREMULT 0x00000004 |
#define NV01_RENDER_SOLID_RECTANGLE_OPERATION_BLEND_PREMULT 0x00000005 |
#define NV01_RENDER_SOLID_RECTANGLE_COLOR_FORMAT 0x00000300 |
#define NV01_RENDER_SOLID_RECTANGLE_COLOR_FORMAT_A16R5G6B5 0x00000001 |
#define NV01_RENDER_SOLID_RECTANGLE_COLOR_FORMAT_X16A1R5G5B5 0x00000002 |
#define NV01_RENDER_SOLID_RECTANGLE_COLOR_FORMAT_A8R8G8B8 0x00000003 |
#define NV01_RENDER_SOLID_RECTANGLE_COLOR 0x00000304 |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT(i0) (0x00000400 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT__LEN 0x00000010 |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_X__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_X__SHIFT 0 |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_Y__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_POINT_Y__SHIFT 16 |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE(i0) (0x00000404 + 0x8*(i0)) |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE__ESIZE 0x00000008 |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE__LEN 0x00000010 |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_W__MASK 0x0000ffff |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_W__SHIFT 0 |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_H__MASK 0xffff0000 |
#define NV01_RENDER_SOLID_RECTANGLE_RECTANGLE_SIZE_H__SHIFT 16 |
#define NV01_IMAGE_BLIT_PATCH 0x0000010c |
#define NV11_IMAGE_BLIT_WAIT_FOR_IDLE 0x00000108 |
#define NV11_IMAGE_BLIT_FLIP_SET_READ 0x00000120 |
#define NV11_IMAGE_BLIT_FLIP_SET_WRITE 0x00000124 |
#define NV11_IMAGE_BLIT_FLIP_MAX 0x00000128 |
#define NV11_IMAGE_BLIT_FLIP_INCR_WRITE 0x0000012c |
#define NV11_IMAGE_BLIT_FLIP_WAIT 0x00000130 |
#define NV11_IMAGE_BLIT_FLIP_CRTC_INCR_READ 0x00000134 |
#define NV01_IMAGE_BLIT_DMA_NOTIFY 0x00000180 |
#define NV01_IMAGE_BLIT_COLOR_KEY 0x00000184 |
#define NV04_IMAGE_BLIT_COLOR_KEY 0x00000184 |
#define NV01_IMAGE_BLIT_CLIP_RECTANGLE 0x00000188 |
#define NV01_IMAGE_BLIT_PATTERN 0x0000018c |
#define NV04_IMAGE_BLIT_PATTERN 0x0000018c |
#define NV01_IMAGE_BLIT_ROP 0x00000190 |
#define NV01_IMAGE_BLIT_BETA1 0x00000194 |
#define NV01_IMAGE_BLIT_SURFACE_SRC 0x00000198 |
#define NV01_IMAGE_BLIT_SURFACE_DST 0x0000019c |
#define NV04_IMAGE_BLIT_BETA4 0x00000198 |
#define NV04_IMAGE_BLIT_SURFACES 0x0000019c |
#define NV01_IMAGE_BLIT_OPERATION 0x000002fc |
#define NV01_IMAGE_BLIT_OPERATION_SRCCOPY_AND 0x00000000 |
#define NV01_IMAGE_BLIT_OPERATION_ROP_AND 0x00000001 |
#define NV01_IMAGE_BLIT_OPERATION_BLEND_AND 0x00000002 |
#define NV01_IMAGE_BLIT_OPERATION_SRCCOPY 0x00000003 |
#define NV01_IMAGE_BLIT_OPERATION_SRCCOPY_PREMULT 0x00000004 |
#define NV01_IMAGE_BLIT_OPERATION_BLEND_PREMULT 0x00000005 |
#define NV01_IMAGE_BLIT_POINT_IN 0x00000300 |
#define NV01_IMAGE_BLIT_POINT_IN_X__MASK 0x0000ffff |
#define NV01_IMAGE_BLIT_POINT_IN_X__SHIFT 0 |
#define NV01_IMAGE_BLIT_POINT_IN_Y__MASK 0xffff0000 |
#define NV01_IMAGE_BLIT_POINT_IN_Y__SHIFT 16 |
#define NV01_IMAGE_BLIT_POINT_OUT 0x00000304 |
#define NV01_IMAGE_BLIT_POINT_OUT_X__MASK 0x0000ffff |
#define NV01_IMAGE_BLIT_POINT_OUT_X__SHIFT 0 |
#define NV01_IMAGE_BLIT_POINT_OUT_Y__MASK 0xffff0000 |
#define NV01_IMAGE_BLIT_POINT_OUT_Y__SHIFT 16 |
#define NV01_IMAGE_BLIT_SIZE 0x00000308 |
#define NV01_IMAGE_BLIT_SIZE_W__MASK 0x0000ffff |
#define NV01_IMAGE_BLIT_SIZE_W__SHIFT 0 |
#define NV01_IMAGE_BLIT_SIZE_H__MASK 0xffff0000 |
#define NV01_IMAGE_BLIT_SIZE_H__SHIFT 16 |
#define NV04_INDEXED_IMAGE_FROM_CPU_PATCH 0x0000010c |
#define NV04_INDEXED_IMAGE_FROM_CPU_DMA_NOTIFY 0x00000180 |
#define NV04_INDEXED_IMAGE_FROM_CPU_DMA_LUT 0x00000184 |
#define NV04_INDEXED_IMAGE_FROM_CPU_COLOR_KEY 0x00000188 |
#define NV04_INDEXED_IMAGE_FROM_CPU_CLIP_RECTANGLE 0x0000018c |
#define NV04_INDEXED_IMAGE_FROM_CPU_PATTERN 0x00000190 |
#define NV04_INDEXED_IMAGE_FROM_CPU_ROP 0x00000194 |
#define NV04_INDEXED_IMAGE_FROM_CPU_BETA1 0x00000198 |
#define NV04_INDEXED_IMAGE_FROM_CPU_BETA4 0x0000019c |
#define NV04_INDEXED_IMAGE_FROM_CPU_SURFACE 0x000001a0 |
#define NV05_INDEXED_IMAGE_FROM_CPU_SURFACE 0x000001a0 |
#define NV05_INDEXED_IMAGE_FROM_CPU_COLOR_CONVERSION 0x000003e0 |
#define NV04_INDEXED_IMAGE_FROM_CPU_OPERATION 0x000003e4 |
#define NV04_INDEXED_IMAGE_FROM_CPU_COLOR_FORMAT 0x000003e8 |
#define NV04_INDEXED_IMAGE_FROM_CPU_INDEX_FORMAT 0x000003ec |
#define NV04_INDEXED_IMAGE_FROM_CPU_LUT_OFFSET 0x000003f0 |
#define NV04_INDEXED_IMAGE_FROM_CPU_POINT 0x000003f4 |
#define NV04_INDEXED_IMAGE_FROM_CPU_SIZE_OUT 0x000003f8 |
#define NV04_INDEXED_IMAGE_FROM_CPU_SIZE_IN 0x000003fc |
#define NV04_INDEXED_IMAGE_FROM_CPU_COLOR(i0) (0x00000400 + 0x4*(i0)) |
#define NV04_INDEXED_IMAGE_FROM_CPU_COLOR__ESIZE 0x00000004 |
#define NV04_INDEXED_IMAGE_FROM_CPU_COLOR__LEN 0x00000700 |
#define NV10_IMAGE_FROM_CPU_WAIT_FOR_IDLE 0x00000108 |
#define NV01_IMAGE_FROM_CPU_PATCH 0x0000010c |
#define NV01_IMAGE_FROM_CPU_DMA_NOTIFY 0x00000180 |
#define NV01_IMAGE_FROM_CPU_COLOR_KEY 0x00000184 |
#define NV04_IMAGE_FROM_CPU_COLOR_KEY 0x00000184 |
#define NV01_IMAGE_FROM_CPU_CLIP_RECTANGLE 0x00000188 |
#define NV01_IMAGE_FROM_CPU_PATTERN 0x0000018c |
#define NV04_IMAGE_FROM_CPU_PATTERN 0x0000018c |
#define NV01_IMAGE_FROM_CPU_ROP 0x00000190 |
#define NV01_IMAGE_FROM_CPU_BETA1 0x00000194 |
#define NV01_IMAGE_FROM_CPU_SURFACE_DST 0x00000198 |
#define NV04_IMAGE_FROM_CPU_BETA4 0x00000198 |
#define NV04_IMAGE_FROM_CPU_SURFACE 0x0000019c |
#define NV05_IMAGE_FROM_CPU_COLOR_CONVERSION 0x000002f8 |
#define NV01_IMAGE_FROM_CPU_OPERATION 0x000002fc |
#define NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY_AND 0x00000000 |
#define NV01_IMAGE_FROM_CPU_OPERATION_ROP_AND 0x00000001 |
#define NV01_IMAGE_FROM_CPU_OPERATION_BLEND_AND 0x00000002 |
#define NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY 0x00000003 |
#define NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY_PREMULT 0x00000004 |
#define NV01_IMAGE_FROM_CPU_OPERATION_BLEND_PREMULT 0x00000005 |
#define NV01_IMAGE_FROM_CPU_COLOR_FORMAT 0x00000300 |
#define NV01_IMAGE_FROM_CPU_COLOR_FORMAT_R5G6G5 0x00000001 |
#define NV01_IMAGE_FROM_CPU_COLOR_FORMAT_A1R5G5B5 0x00000002 |
#define NV01_IMAGE_FROM_CPU_COLOR_FORMAT_X1R5G5B5 0x00000003 |
#define NV01_IMAGE_FROM_CPU_COLOR_FORMAT_A8R8G8B8 0x00000004 |
#define NV01_IMAGE_FROM_CPU_COLOR_FORMAT_X8R8G8B8 0x00000005 |
#define NV01_IMAGE_FROM_CPU_POINT 0x00000304 |
#define NV01_IMAGE_FROM_CPU_POINT_X__MASK 0x0000ffff |
#define NV01_IMAGE_FROM_CPU_POINT_X__SHIFT 0 |
#define NV01_IMAGE_FROM_CPU_POINT_Y__MASK 0xffff0000 |
#define NV01_IMAGE_FROM_CPU_POINT_Y__SHIFT 16 |
#define NV01_IMAGE_FROM_CPU_SIZE_OUT 0x00000308 |
#define NV01_IMAGE_FROM_CPU_SIZE_OUT_W__MASK 0x0000ffff |
#define NV01_IMAGE_FROM_CPU_SIZE_OUT_W__SHIFT 0 |
#define NV01_IMAGE_FROM_CPU_SIZE_OUT_H__MASK 0xffff0000 |
#define NV01_IMAGE_FROM_CPU_SIZE_OUT_H__SHIFT 16 |
#define NV01_IMAGE_FROM_CPU_SIZE_IN 0x0000030c |
#define NV01_IMAGE_FROM_CPU_SIZE_IN_W__MASK 0x0000ffff |
#define NV01_IMAGE_FROM_CPU_SIZE_IN_W__SHIFT 0 |
#define NV01_IMAGE_FROM_CPU_SIZE_IN_H__MASK 0xffff0000 |
#define NV01_IMAGE_FROM_CPU_SIZE_IN_H__SHIFT 16 |
#define NV01_IMAGE_FROM_CPU_COLOR(i0) (0x00000400 + 0x4*(i0)) |
#define NV01_IMAGE_FROM_CPU_COLOR__ESIZE 0x00000004 |
#define NV01_IMAGE_FROM_CPU_COLOR__LEN 0x00000020 |
#define NV04_IMAGE_FROM_CPU_COLOR(i0) (0x00000400 + 0x4*(i0)) |
#define NV04_IMAGE_FROM_CPU_COLOR__ESIZE 0x00000004 |
#define NV04_IMAGE_FROM_CPU_COLOR__LEN 0x00000700 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_PATCH 0x0000010c |
#define NV03_STRETCHED_IMAGE_FROM_CPU_DMA_NOTIFY 0x00000180 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_COLOR_KEY 0x00000184 |
#define NV04_STRETCHED_IMAGE_FROM_CPU_COLOR_KEY 0x00000184 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_PATTERN 0x00000188 |
#define NV04_STRETCHED_IMAGE_FROM_CPU_PATTERN 0x00000188 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_ROP 0x0000018c |
#define NV03_STRETCHED_IMAGE_FROM_CPU_BETA1 0x00000190 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_SURFACE_DST 0x00000194 |
#define NV04_STRETCHED_IMAGE_FROM_CPU_BETA4 0x00000194 |
#define NV04_STRETCHED_IMAGE_FROM_CPU_SURFACE 0x00000198 |
#define NV05_STRETCHED_IMAGE_FROM_CPU_COLOR_CONVERSION 0x000002f8 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_OPERATION 0x000002fc |
#define NV03_STRETCHED_IMAGE_FROM_CPU_COLOR_FORMAT 0x00000300 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN 0x00000304 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_W__MASK 0x0000ffff |
#define NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_W__SHIFT 0 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_H__MASK 0xffff0000 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_SIZE_IN_H__SHIFT 16 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_DX_DU 0x00000308 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_DY_DV 0x0000030c |
#define NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT 0x00000310 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_X__MASK 0x0000ffff |
#define NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_X__SHIFT 0 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_Y__MASK 0xffff0000 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_POINT_Y__SHIFT 16 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE 0x00000314 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_W__MASK 0x0000ffff |
#define NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_W__SHIFT 0 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_H__MASK 0xffff0000 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_CLIP_SIZE_H__SHIFT 16 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4 0x00000318 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_X__MASK 0x0000ffff |
#define NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_X__SHIFT 0 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_Y__MASK 0xffff0000 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_POINT12D4_Y__SHIFT 16 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_COLOR(i0) (0x00000400 + 0x4*(i0)) |
#define NV03_STRETCHED_IMAGE_FROM_CPU_COLOR__ESIZE 0x00000004 |
#define NV03_STRETCHED_IMAGE_FROM_CPU_COLOR__LEN 0x00000700 |
#define NV10_SCALED_IMAGE_FROM_MEMORY_WAIT_FOR_IDLE 0x00000108 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY 0x00000180 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE 0x00000184 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_PATTERN 0x00000188 |
#define NV04_SCALED_IMAGE_FROM_MEMORY_PATTERN 0x00000188 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_ROP 0x0000018c |
#define NV03_SCALED_IMAGE_FROM_MEMORY_BETA1 0x00000190 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_SURFACE_DST 0x00000194 |
#define NV04_SCALED_IMAGE_FROM_MEMORY_BETA4 0x00000194 |
#define NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE 0x00000198 |
#define NV05_SCALED_IMAGE_FROM_MEMORY_SURFACE 0x00000198 |
#define NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION 0x000002fc |
#define NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_DITHER 0x00000000 |
#define NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE 0x00000001 |
#define NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_SUBTR_TRUNCATE 0x00000002 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT 0x00000300 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5 0x00000001 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X1R5G5B5 0x00000002 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8 0x00000003 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8 0x00000004 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_V8YB8U8YA8 0x00000005 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_YB8V8YA8U8 0x00000006 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5 0x00000007 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8 0x00000008 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8 0x00000009 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION 0x00000304 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY_AND 0x00000000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_ROP_AND 0x00000001 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_BLEND_AND 0x00000002 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY 0x00000003 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY_PREMULT 0x00000004 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_BLEND_PREMULT 0x00000005 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT 0x00000308 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_X__MASK 0x0000ffff |
#define NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_X__SHIFT 0 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y__MASK 0xffff0000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y__SHIFT 16 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE 0x0000030c |
#define NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_W__MASK 0x0000ffff |
#define NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_W__SHIFT 0 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H__MASK 0xffff0000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H__SHIFT 16 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OUT_POINT 0x00000310 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_X__MASK 0x0000ffff |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_X__SHIFT 0 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y__MASK 0xffff0000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y__SHIFT 16 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE 0x00000314 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_W__MASK 0x0000ffff |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_W__SHIFT 0 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H__MASK 0xffff0000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H__SHIFT 16 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_DU_DX 0x00000318 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_DV_DY 0x0000031c |
#define NV03_SCALED_IMAGE_FROM_MEMORY_SIZE 0x00000400 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_SIZE_W__MASK 0x0000ffff |
#define NV03_SCALED_IMAGE_FROM_MEMORY_SIZE_W__SHIFT 0 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_SIZE_H__MASK 0xffff0000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_SIZE_H__SHIFT 16 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT 0x00000404 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_PITCH__MASK 0x0000ffff |
#define NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_PITCH__SHIFT 0 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN__MASK 0x00ff0000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN__SHIFT 16 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER 0x00010000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CORNER 0x00020000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER__MASK 0xff000000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER__SHIFT 24 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE 0x00000000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_BILINEAR 0x01000000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_OFFSET 0x00000408 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_POINT 0x0000040c |
#define NV03_SCALED_IMAGE_FROM_MEMORY_POINT_U__MASK 0x0000ffff |
#define NV03_SCALED_IMAGE_FROM_MEMORY_POINT_U__SHIFT 0 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_POINT_V__MASK 0xffff0000 |
#define NV03_SCALED_IMAGE_FROM_MEMORY_POINT_V__SHIFT 16 |
#define NV50_SCALED_IMAGE_FROM_MEMORY_OFFSET_HIGH 0x00000410 |
#define NV50_SCALED_IMAGE_FROM_MEMORY_SRC_LINEAR 0x00000414 |
#define NV50_SCALED_IMAGE_FROM_MEMORY_SRC_TILE_MODE 0x00000418 |
#define NV03_GDI_RECTANGLE_TEXT_DMA_NOTIFY 0x00000180 |
#define NV03_GDI_RECTANGLE_TEXT_PATTERN 0x00000184 |
#define NV03_GDI_RECTANGLE_TEXT_ROP 0x00000188 |
#define NV03_GDI_RECTANGLE_TEXT_BETA1 0x0000019c |
#define NV03_GDI_RECTANGLE_TEXT_SURFACE_DST 0x00000190 |
#define NV03_GDI_RECTANGLE_TEXT_OPERATION 0x000002fc |
#define NV03_GDI_RECTANGLE_TEXT_COLOR_FORMAT 0x00000300 |
#define NV03_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT 0x00000304 |
#define NV03_GDI_RECTANGLE_TEXT_COLOR1_A 0x000003fc |
#define NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT 0x00000400 |
#define NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE 0x00000404 |
#define NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B 0x000007f4 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_L__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_L__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_T__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_POINT0_B_T__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B 0x000007f8 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_R__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_R__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_B__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_POINT1_B_B__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_COLOR1_B 0x000007fc |
#define NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0 0x00000800 |
#define NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1 0x00000804 |
#define NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0 0x00000bec |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1 0x00000bf0 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_COLOR1_C 0x00000bf4 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_C 0x00000bf8 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_C_W__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_C_W__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_C_H__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_C_H__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_POINT_C 0x00000bfc |
#define NV03_GDI_RECTANGLE_TEXT_POINT_C_X__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_POINT_C_X__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_POINT_C_Y__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_POINT_C_Y__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C(i0) (0x00000c00 + 0x4*(i0)) |
#define NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C__ESIZE 0x00000004 |
#define NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C__LEN 0x00000020 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0 0x00000fe8 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_L__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_L__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_T__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT0_T__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1 0x00000fec |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_R__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_R__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_B__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_D_POINT1_B__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_COLOR1_D 0x00000ff0 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D 0x00000ff4 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_W__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_W__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_H__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_IN_D_H__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D 0x00000ff8 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_W__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_W__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_H__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_D_H__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_POINT_D 0x00000ffc |
#define NV03_GDI_RECTANGLE_TEXT_POINT_D_X__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_POINT_D_X__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_POINT_D_Y__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_POINT_D_Y__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_D(i0) (0x00001000 + 0x4*(i0)) |
#define NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_D__ESIZE 0x00000004 |
#define NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_D__LEN 0x00000020 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0 0x000013e4 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1 0x000013e8 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_COLOR0_E 0x000013ec |
#define NV03_GDI_RECTANGLE_TEXT_COLOR1_E 0x000013f0 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E 0x000013f4 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_W__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_W__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_H__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_IN_E_H__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E 0x000013f8 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_POINT_E 0x000013fc |
#define NV03_GDI_RECTANGLE_TEXT_POINT_E_X__MASK 0x0000ffff |
#define NV03_GDI_RECTANGLE_TEXT_POINT_E_X__SHIFT 0 |
#define NV03_GDI_RECTANGLE_TEXT_POINT_E_Y__MASK 0xffff0000 |
#define NV03_GDI_RECTANGLE_TEXT_POINT_E_Y__SHIFT 16 |
#define NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E(i0) (0x00001400 + 0x4*(i0)) |
#define NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E__ESIZE 0x00000004 |
#define NV03_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E__LEN 0x00000020 |
#define NV04_GDI_RECTANGLE_TEXT_PATCH 0x0000010c |
#define NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY 0x00000180 |
#define NV04_GDI_RECTANGLE_TEXT_DMA_FONTS 0x00000184 |
#define NV04_GDI_RECTANGLE_TEXT_PATTERN 0x00000188 |
#define NV04_GDI_RECTANGLE_TEXT_ROP 0x0000018c |
#define NV04_GDI_RECTANGLE_TEXT_BETA1 0x00000190 |
#define NV04_GDI_RECTANGLE_TEXT_BETA4 0x00000194 |
#define NV04_GDI_RECTANGLE_TEXT_SURFACE 0x00000198 |
#define NV04_GDI_RECTANGLE_TEXT_OPERATION 0x000002fc |
#define NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY_AND 0x00000000 |
#define NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND 0x00000001 |
#define NV04_GDI_RECTANGLE_TEXT_OPERATION_BLEND_AND 0x00000002 |
#define NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY 0x00000003 |
#define NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY_PREMULT 0x00000004 |
#define NV04_GDI_RECTANGLE_TEXT_OPERATION_BLEND_PREMULT 0x00000005 |
#define NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT 0x00000300 |
#define NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5 0x00000001 |
#define NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_X16A1R5G5B5 0x00000002 |
#define NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8 0x00000003 |
#define NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT 0x00000304 |
#define NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_CGA6 0x00000001 |
#define NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE 0x00000002 |
#define NV04_GDI_RECTANGLE_TEXT_COLOR1_A 0x000003fc |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(i0) (0x00000400 + 0x8*(i0)) |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT__ESIZE 0x00000008 |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT__LEN 0x00000020 |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_Y__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT_X__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE(i0) (0x00000404 + 0x8*(i0)) |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE__ESIZE 0x00000008 |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE__LEN 0x00000020 |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_H__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_SIZE_W__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0 0x000005f4 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_L__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_L__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_T__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT0_T__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1 0x000005f8 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_R__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_R__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_B__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_B_POINT1_B__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_COLOR1_B 0x000005fc |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0(i0) (0x00000600 + 0x8*(i0)) |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0__ESIZE 0x00000008 |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0__LEN 0x00000020 |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_L__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_0_T__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1(i0) (0x00000604 + 0x8*(i0)) |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1__ESIZE 0x00000008 |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1__LEN 0x00000020 |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_R__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIPPED_RECTANGLE_POINT_1_B__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0 0x000007ec |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_L__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT0_T__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1 0x000007f0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_R__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_C_POINT1_B__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_COLOR1_C 0x000007f4 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_C 0x000007f8 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_C_W__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_C_W__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_C_H__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_C_H__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_POINT_C 0x000007fc |
#define NV04_GDI_RECTANGLE_TEXT_POINT_C_X__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_POINT_C_X__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_POINT_C_Y__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_POINT_C_Y__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C(i0) (0x00000800 + 0x4*(i0)) |
#define NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C__ESIZE 0x00000004 |
#define NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR1_C__LEN 0x00000080 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0 0x00000be4 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_L__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT0_T__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1 0x00000be8 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_R__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_E_POINT1_B__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_COLOR0_E 0x00000bec |
#define NV04_GDI_RECTANGLE_TEXT_COLOR1_E 0x00000bf0 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E 0x00000bf4 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_W__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_W__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_H__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_IN_E_H__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E 0x00000bf8 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_W__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_SIZE_OUT_E_H__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_POINT_E 0x00000bfc |
#define NV04_GDI_RECTANGLE_TEXT_POINT_E_X__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_POINT_E_X__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_POINT_E_Y__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_POINT_E_Y__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E(i0) (0x00000c00 + 0x4*(i0)) |
#define NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E__ESIZE 0x00000004 |
#define NV04_GDI_RECTANGLE_TEXT_MONOCHROME_COLOR01_E__LEN 0x00000080 |
#define NV04_GDI_RECTANGLE_TEXT_FONT_F 0x00000ff0 |
#define NV04_GDI_RECTANGLE_TEXT_FONT_F_OFFSET__MASK 0x0fffffff |
#define NV04_GDI_RECTANGLE_TEXT_FONT_F_OFFSET__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_FONT_F_PITCH__MASK 0xf0000000 |
#define NV04_GDI_RECTANGLE_TEXT_FONT_F_PITCH__SHIFT 28 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0 0x00000ff4 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_L__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_L__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_T__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT0_T__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1 0x00000ff8 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_R__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_R__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_B__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_F_POINT1_B__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_COLOR1_F 0x00000ffc |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F(i0) (0x00001000 + 0x4*(i0)) |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F__ESIZE 0x00000004 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F__LEN 0x00000100 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_INDEX__MASK 0x000000ff |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_INDEX__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_X__MASK 0x000fff00 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_X__SHIFT 8 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_Y__MASK 0xfff00000 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_F_Y__SHIFT 20 |
#define NV04_GDI_RECTANGLE_TEXT_FONT_G 0x000017f0 |
#define NV04_GDI_RECTANGLE_TEXT_FONT_G_OFFSET__MASK 0x0fffffff |
#define NV04_GDI_RECTANGLE_TEXT_FONT_G_OFFSET__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_FONT_G_PITCH__MASK 0xf0000000 |
#define NV04_GDI_RECTANGLE_TEXT_FONT_G_PITCH__SHIFT 28 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0 0x000017f4 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_L__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_L__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_T__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT0_T__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1 0x000017f8 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_R__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_R__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_B__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CLIP_G_POINT1_B__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_COLOR1_G 0x000017fc |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT(i0) (0x00001800 + 0x8*(i0)) |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT__ESIZE 0x00000008 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT__LEN 0x00000100 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_X__MASK 0x0000ffff |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_X__SHIFT 0 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_Y__MASK 0xffff0000 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_POINT_Y__SHIFT 16 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_INDEX(i0) (0x00001804 + 0x8*(i0)) |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_INDEX__ESIZE 0x00000008 |
#define NV04_GDI_RECTANGLE_TEXT_CHARACTER_COLOR1_G_INDEX__LEN 0x00000100 |
#define NV10_TEXTURE_FROM_CPU_WAIT_FOR_IDLE 0x00000108 |
#define NV10_TEXTURE_FROM_CPU_DMA_NOTIFY 0x00000180 |
#define NV10_TEXTURE_FROM_CPU_SURFACE 0x00000184 |
#define NV10_TEXTURE_FROM_CPU_COLOR_FORMAT 0x00000300 |
#define NV10_TEXTURE_FROM_CPU_POINT 0x00000304 |
#define NV10_TEXTURE_FROM_CPU_POINT_X__MASK 0x0000ffff |
#define NV10_TEXTURE_FROM_CPU_POINT_X__SHIFT 0 |
#define NV10_TEXTURE_FROM_CPU_POINT_Y__MASK 0xffff0000 |
#define NV10_TEXTURE_FROM_CPU_POINT_Y__SHIFT 16 |
#define NV10_TEXTURE_FROM_CPU_SIZE 0x00000308 |
#define NV10_TEXTURE_FROM_CPU_SIZE_W__MASK 0x0000ffff |
#define NV10_TEXTURE_FROM_CPU_SIZE_W__SHIFT 0 |
#define NV10_TEXTURE_FROM_CPU_SIZE_H__MASK 0xffff0000 |
#define NV10_TEXTURE_FROM_CPU_SIZE_H__SHIFT 16 |
#define NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL 0x0000030c |
#define NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_X__MASK 0x0000ffff |
#define NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_X__SHIFT 0 |
#define NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_W__MASK 0xffff0000 |
#define NV10_TEXTURE_FROM_CPU_CLIP_HORIZONTAL_W__SHIFT 16 |
#define NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL 0x00000310 |
#define NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_Y__MASK 0x0000ffff |
#define NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_Y__SHIFT 0 |
#define NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_H__MASK 0xffff0000 |
#define NV10_TEXTURE_FROM_CPU_CLIP_VERTICAL_H__SHIFT 16 |
#define NV10_TEXTURE_FROM_CPU_COLOR(i0) (0x00000400 + 0x4*(i0)) |
#define NV10_TEXTURE_FROM_CPU_COLOR__ESIZE 0x00000004 |
#define NV10_TEXTURE_FROM_CPU_COLOR__LEN 0x00000700 |
#endif /* NV01_2D_XML */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv04_3d.xml.h |
---|
0,0 → 1,738 |
#ifndef NV04_3D_XML |
#define NV04_3D_XML |
/* Autogenerated file, DO NOT EDIT manually! |
This file was generated by the rules-ng-ng headergen tool in this git repository: |
http://0x04.net/cgit/index.cgi/rules-ng-ng |
git clone git://0x04.net/rules-ng-ng |
The rules-ng-ng source files this header was generated from are: |
- nv04_3d.xml ( 17839 bytes, from 2010-11-15 02:23:48) |
- copyright.xml ( 6452 bytes, from 2010-11-15 15:10:58) |
- nv_object.xml ( 11547 bytes, from 2010-11-13 23:32:57) |
- nvchipsets.xml ( 3074 bytes, from 2010-11-13 23:32:57) |
- nv_defs.xml ( 4437 bytes, from 2010-11-01 00:28:46) |
- nv_3ddefs.xml ( 16394 bytes, from 2010-11-01 00:28:46) |
Copyright (C) 2006-2010 by the following authors: |
- Artur Huillet <arthur.huillet@free.fr> (ahuillet) |
- Ben Skeggs (darktama, darktama_) |
- B. R. <koala_br@users.sourceforge.net> (koala_br) |
- Carlos Martin <carlosmn@users.sf.net> (carlosmn) |
- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr) |
- Dawid Gajownik <gajownik@users.sf.net> (gajownik) |
- Dmitry Baryshkov |
- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag) |
- EdB <edb_@users.sf.net> (edb_) |
- Erik Waling <erikwailing@users.sf.net> (erikwaling) |
- Francisco Jerez <currojerez@riseup.net> (curro) |
- imirkin <imirkin@users.sf.net> (imirkin) |
- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome) |
- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy) |
- Laurent Carlier <lordheavym@gmail.com> (lordheavy) |
- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1) |
- Maarten Maathuis <madman2003@gmail.com> (stillunknown) |
- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin) |
- Mark Carey <mark.carey@gmail.com> (careym) |
- Matthieu Castet <matthieu.castet@parrot.com> (mat-c) |
- nvidiaman <nvidiaman@users.sf.net> (nvidiaman) |
- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata) |
- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen) |
- Peter Popov <ironpeter@users.sf.net> (ironpeter) |
- Richard Hughes <hughsient@users.sf.net> (hughsient) |
- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar) |
- Serge Martin |
- Simon Raffeiner |
- Stephane Loeuillet <leroutier@users.sf.net> (leroutier) |
- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu) |
- sturmflut <sturmflut@users.sf.net> (sturmflut) |
- Sylvain Munaut <tnt@246tNt.com> |
- Victor Stinner <victor.stinner@haypocalc.com> (haypo) |
- Wladmir van der Laan <laanwj@gmail.com> (miathan6) |
- Younes Manton <younes.m@gmail.com> (ymanton) |
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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
*/ |
#define NV04_CONTEXT_SURFACES_3D_DMA_NOTIFY 0x00000180 |
#define NV04_CONTEXT_SURFACES_3D_DMA_COLOR 0x00000184 |
#define NV04_CONTEXT_SURFACES_3D_DMA_ZETA 0x00000188 |
#define NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL 0x000002f8 |
#define NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_X__MASK 0x0000ffff |
#define NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_X__SHIFT 0 |
#define NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_W__MASK 0xffff0000 |
#define NV04_CONTEXT_SURFACES_3D_CLIP_HORIZONTAL_W__SHIFT 16 |
#define NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL 0x000002fc |
#define NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_Y__MASK 0x0000ffff |
#define NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_Y__SHIFT 0 |
#define NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_H__MASK 0xffff0000 |
#define NV04_CONTEXT_SURFACES_3D_CLIP_VERTICAL_H__SHIFT 16 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT 0x00000300 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR__MASK 0x000000ff |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR__SHIFT 0 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1R5G5B5_Z1R5G5B5 0x00000001 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1R5G5B5_X1R5G5B5 0x00000002 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_R5G6B5 0x00000003 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X8R8G8B8_Z8R8G8B8 0x00000004 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X8R8G8B8_X8R8G8B8 0x00000005 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1A7R8G8B8_Z1A7R8G8B8 0x00000006 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X1A7R8G8B8_X1A7R8G8B8 0x00000007 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_A8R8G8B8 0x00000008 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE__MASK 0x0000ff00 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE__SHIFT 8 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_PITCH 0x00000100 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_SWIZZLE 0x00000200 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_U__MASK 0x00ff0000 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_U__SHIFT 16 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_V__MASK 0xff000000 |
#define NV04_CONTEXT_SURFACES_3D_FORMAT_BASE_SIZE_V__SHIFT 24 |
#define NV04_CONTEXT_SURFACES_3D_CLIP_SIZE 0x00000304 |
#define NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_W__MASK 0x0000ffff |
#define NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_W__SHIFT 0 |
#define NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_H__MASK 0xffff0000 |
#define NV04_CONTEXT_SURFACES_3D_CLIP_SIZE_H__SHIFT 16 |
#define NV04_CONTEXT_SURFACES_3D_PITCH 0x00000308 |
#define NV04_CONTEXT_SURFACES_3D_PITCH_COLOR__MASK 0x0000ffff |
#define NV04_CONTEXT_SURFACES_3D_PITCH_COLOR__SHIFT 0 |
#define NV04_CONTEXT_SURFACES_3D_PITCH_ZETA__MASK 0xffff0000 |
#define NV04_CONTEXT_SURFACES_3D_PITCH_ZETA__SHIFT 16 |
#define NV04_CONTEXT_SURFACES_3D_OFFSET_COLOR 0x0000030c |
#define NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA 0x00000310 |
#define NV04_TEXTURED_TRIANGLE_DMA_NOTIFY 0x00000180 |
#define NV04_TEXTURED_TRIANGLE_DMA_A 0x00000184 |
#define NV04_TEXTURED_TRIANGLE_DMA_B 0x00000188 |
#define NV04_TEXTURED_TRIANGLE_SURFACES 0x0000018c |
#define NV04_TEXTURED_TRIANGLE_COLORKEY 0x00000300 |
#define NV04_TEXTURED_TRIANGLE_OFFSET 0x00000304 |
#define NV04_TEXTURED_TRIANGLE_FORMAT 0x00000308 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_DMA_A 0x00000001 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_DMA_B 0x00000002 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_KEY_ENABLE 0x00000004 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH__MASK 0x00000030 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH__SHIFT 4 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_CENTER 0x00000010 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_CORNER 0x00000020 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH__MASK 0x000000c0 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH__SHIFT 6 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_CENTER 0x00000040 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_CORNER 0x00000080 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_COLOR__MASK 0x00000f00 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_COLOR__SHIFT 8 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_Y8 0x00000100 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A1R5G5B5 0x00000200 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_X1R5G5B5 0x00000300 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A4R4G4B4 0x00000400 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_R5G6B5 0x00000500 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A8R8G8B8 0x00000600 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_X8R8G8B8 0x00000700 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_MIPMAP_LEVELS__MASK 0x0000f000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_MIPMAP_LEVELS__SHIFT 12 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_U__MASK 0x000f0000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_U__SHIFT 16 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_V__MASK 0x00f00000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_V__SHIFT 20 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU__MASK 0x07000000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU__SHIFT 24 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_REPEAT 0x01000000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_MIRRORED_REPEAT 0x02000000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE 0x03000000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_BORDER 0x04000000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_WRAPU 0x08000000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSV__MASK 0x70000000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSV__SHIFT 28 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_REPEAT 0x10000000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_MIRRORED_REPEAT 0x20000000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_EDGE 0x30000000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_BORDER 0x40000000 |
#define NV04_TEXTURED_TRIANGLE_FORMAT_WRAPV 0x80000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER 0x0000030c |
#define NV04_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_X__MASK 0x000000ff |
#define NV04_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_X__SHIFT 0 |
#define NV04_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_Y__MASK 0x00007f00 |
#define NV04_TEXTURED_TRIANGLE_FILTER_KERNEL_SIZE_Y__SHIFT 8 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MIPMAP_DITHER_ENABLE 0x00008000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MIPMAP_LODBIAS__MASK 0x00ff0000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MIPMAP_LODBIAS__SHIFT 16 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MINIFY__MASK 0x07000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MINIFY__SHIFT 24 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST 0x01000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR 0x02000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST 0x03000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST 0x04000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR 0x05000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR 0x06000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MINIFY_ENABLE 0x08000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MAGNIFY__MASK 0x70000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MAGNIFY__SHIFT 28 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MAGNIFY_NEAREST 0x10000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_MAGNIFY_LINEAR 0x20000000 |
#define NV04_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MAGNIFY_ENABLE 0x80000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND 0x00000310 |
#define NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP__MASK 0x0000000f |
#define NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP__SHIFT 0 |
#define NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_DECAL 0x00000001 |
#define NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_MODULATE 0x00000002 |
#define NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_DECALALPHA 0x00000003 |
#define NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_MODULATEALPHA 0x00000004 |
#define NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_DECALMASK 0x00000005 |
#define NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_MODULATEMASK 0x00000006 |
#define NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_COPY 0x00000007 |
#define NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP_ADD 0x00000008 |
#define NV04_TEXTURED_TRIANGLE_BLEND_MASK_BIT__MASK 0x00000030 |
#define NV04_TEXTURED_TRIANGLE_BLEND_MASK_BIT__SHIFT 4 |
#define NV04_TEXTURED_TRIANGLE_BLEND_MASK_BIT_LSB 0x00000010 |
#define NV04_TEXTURED_TRIANGLE_BLEND_MASK_BIT_MSB 0x00000020 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE__MASK 0x000000c0 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE__SHIFT 6 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT 0x00000040 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD 0x00000080 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_PHONG 0x000000c0 |
#define NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE 0x00000100 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE 0x00001000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE 0x00010000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_BLEND_ENABLE 0x00100000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC__MASK 0x0f000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC__SHIFT 24 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC_ZERO 0x01000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC_ONE 0x02000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC_SRC_COLOR 0x03000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC_ONE_MINUS_SRC_COLOR 0x04000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC_SRC_ALPHA 0x05000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC_ONE_MINUS_SRC_ALPHA 0x06000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC_DST_ALPHA 0x07000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC_ONE_MINUS_DST_ALPHA 0x08000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC_DST_COLOR 0x09000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC_ONE_MINUS_DST_COLOR 0x0a000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_SRC_SRC_ALPHA_SATURATE 0x0b000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST__MASK 0xf0000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST__SHIFT 28 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST_ZERO 0x10000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST_ONE 0x20000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST_SRC_COLOR 0x30000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST_ONE_MINUS_SRC_COLOR 0x40000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST_SRC_ALPHA 0x50000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST_ONE_MINUS_SRC_ALPHA 0x60000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST_DST_ALPHA 0x70000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST_ONE_MINUS_DST_ALPHA 0x80000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST_DST_COLOR 0x90000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST_ONE_MINUS_DST_COLOR 0xa0000000 |
#define NV04_TEXTURED_TRIANGLE_BLEND_DST_SRC_ALPHA_SATURATE 0xb0000000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL 0x00000314 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_REF__MASK 0x000000ff |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_REF__SHIFT 0 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC__MASK 0x00000f00 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC__SHIFT 8 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_NEVER 0x00000100 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_LESS 0x00000200 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_EQUAL 0x00000300 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_LEQUAL 0x00000400 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_GREATER 0x00000500 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_NOTEQUAL 0x00000600 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_GEQUAL 0x00000700 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_ALWAYS 0x00000800 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_ENABLE 0x00001000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN__MASK 0x00002000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN__SHIFT 13 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN_CENTER 0x00000000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN_CORNER 0x00002000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE 0x00004000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FUNC__MASK 0x000f0000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FUNC__SHIFT 16 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_NEVER 0x00010000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_LESS 0x00020000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_EQUAL 0x00030000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_LEQUAL 0x00040000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_GREATER 0x00050000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_NOTEQUAL 0x00060000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_GEQUAL 0x00070000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_ALWAYS 0x00080000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE__MASK 0x00300000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE__SHIFT 20 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_BOTH 0x00000000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_NONE 0x00100000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CW 0x00200000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CCW 0x00300000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE 0x00400000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_PERSPECTIVE_ENABLE 0x00800000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_WRITE 0x01000000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT__MASK 0xc0000000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT__SHIFT 30 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_FIXED 0x40000000 |
#define NV04_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_FLOAT 0x80000000 |
#define NV04_TEXTURED_TRIANGLE_FOGCOLOR 0x00000318 |
#define NV04_TEXTURED_TRIANGLE_FOGCOLOR_B__MASK 0x000000ff |
#define NV04_TEXTURED_TRIANGLE_FOGCOLOR_B__SHIFT 0 |
#define NV04_TEXTURED_TRIANGLE_FOGCOLOR_G__MASK 0x0000ff00 |
#define NV04_TEXTURED_TRIANGLE_FOGCOLOR_G__SHIFT 8 |
#define NV04_TEXTURED_TRIANGLE_FOGCOLOR_R__MASK 0x00ff0000 |
#define NV04_TEXTURED_TRIANGLE_FOGCOLOR_R__SHIFT 16 |
#define NV04_TEXTURED_TRIANGLE_FOGCOLOR_A__MASK 0xff000000 |
#define NV04_TEXTURED_TRIANGLE_FOGCOLOR_A__SHIFT 24 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX(i0) (0x00000400 + 0x20*(i0)) |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX__ESIZE 0x00000020 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX__LEN 0x00000010 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SX(i0) (0x00000400 + 0x20*(i0)) |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SY(i0) (0x00000404 + 0x20*(i0)) |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SZ(i0) (0x00000408 + 0x20*(i0)) |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_RHW(i0) (0x0000040c + 0x20*(i0)) |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_COLOR(i0) (0x00000410 + 0x20*(i0)) |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_COLOR_B__MASK 0x000000ff |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_COLOR_B__SHIFT 0 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_COLOR_G__MASK 0x0000ff00 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_COLOR_G__SHIFT 8 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_COLOR_R__MASK 0x00ff0000 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_COLOR_R__SHIFT 16 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_COLOR_A__MASK 0xff000000 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_COLOR_A__SHIFT 24 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR(i0) (0x00000414 + 0x20*(i0)) |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_B__MASK 0x000000ff |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_B__SHIFT 0 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_G__MASK 0x0000ff00 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_G__SHIFT 8 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_R__MASK 0x00ff0000 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_R__SHIFT 16 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_FOG__MASK 0xff000000 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_SPECULAR_FOG__SHIFT 24 |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_TU(i0) (0x00000418 + 0x20*(i0)) |
#define NV04_TEXTURED_TRIANGLE_TLVERTEX_TV(i0) (0x0000041c + 0x20*(i0)) |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE(i0) (0x00000600 + 0x4*(i0)) |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE__ESIZE 0x00000004 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE__LEN 0x00000040 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I0__MASK 0x0000000f |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I0__SHIFT 0 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I1__MASK 0x000000f0 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I1__SHIFT 4 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I2__MASK 0x00000f00 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I2__SHIFT 8 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I3__MASK 0x0000f000 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I3__SHIFT 12 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I4__MASK 0x000f0000 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I4__SHIFT 16 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I5__MASK 0x00f00000 |
#define NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE_I5__SHIFT 20 |
#define NV04_MULTITEX_TRIANGLE_DMA_NOTIFY 0x00000180 |
#define NV04_MULTITEX_TRIANGLE_DMA_A 0x00000184 |
#define NV04_MULTITEX_TRIANGLE_DMA_B 0x00000188 |
#define NV04_MULTITEX_TRIANGLE_SURFACES 0x0000018c |
#define NV04_MULTITEX_TRIANGLE_OFFSET(i0) (0x00000308 + 0x4*(i0)) |
#define NV04_MULTITEX_TRIANGLE_OFFSET__ESIZE 0x00000004 |
#define NV04_MULTITEX_TRIANGLE_OFFSET__LEN 0x00000002 |
#define NV04_MULTITEX_TRIANGLE_FORMAT(i0) (0x00000310 + 0x4*(i0)) |
#define NV04_MULTITEX_TRIANGLE_FORMAT__ESIZE 0x00000004 |
#define NV04_MULTITEX_TRIANGLE_FORMAT__LEN 0x00000002 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_DMA_A 0x00000001 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_DMA_B 0x00000002 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ORIGIN_ZOH__MASK 0x00000030 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ORIGIN_ZOH__SHIFT 4 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ORIGIN_ZOH_CENTER 0x00000010 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ORIGIN_ZOH_CORNER 0x00000020 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ORIGIN_FOH__MASK 0x000000c0 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ORIGIN_FOH__SHIFT 6 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ORIGIN_FOH_CENTER 0x00000040 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ORIGIN_FOH_CORNER 0x00000080 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_COLOR__MASK 0x00000f00 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_COLOR__SHIFT 8 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_COLOR_Y8 0x00000100 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_COLOR_A1R5G5B5 0x00000200 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_COLOR_X1R5G5B5 0x00000300 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_COLOR_A4R4G4B4 0x00000400 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_COLOR_R5G6B5 0x00000500 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_COLOR_A8R8G8B8 0x00000600 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_COLOR_X8R8G8B8 0x00000700 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_MIPMAP_LEVELS__MASK 0x0000f000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_MIPMAP_LEVELS__SHIFT 12 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_U__MASK 0x000f0000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_U__SHIFT 16 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_V__MASK 0x00f00000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_BASE_SIZE_V__SHIFT 20 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSU__MASK 0x07000000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSU__SHIFT 24 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSU_REPEAT 0x01000000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSU_MIRRORED_REPEAT 0x02000000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE 0x03000000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_BORDER 0x04000000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_WRAPU 0x08000000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSV__MASK 0x70000000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSV__SHIFT 28 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSV_REPEAT 0x10000000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSV_MIRRORED_REPEAT 0x20000000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_EDGE 0x30000000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_BORDER 0x40000000 |
#define NV04_MULTITEX_TRIANGLE_FORMAT_WRAPV 0x80000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER(i0) (0x00000318 + 0x4*(i0)) |
#define NV04_MULTITEX_TRIANGLE_FILTER__ESIZE 0x00000004 |
#define NV04_MULTITEX_TRIANGLE_FILTER__LEN 0x00000002 |
#define NV04_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_X__MASK 0x000000ff |
#define NV04_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_X__SHIFT 0 |
#define NV04_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_Y__MASK 0x00007f00 |
#define NV04_MULTITEX_TRIANGLE_FILTER_KERNEL_SIZE_Y__SHIFT 8 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MIPMAP_DITHER_ENABLE 0x00008000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MIPMAP_LODBIAS__MASK 0x00ff0000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MIPMAP_LODBIAS__SHIFT 16 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MINIFY__MASK 0x07000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MINIFY__SHIFT 24 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MINIFY_NEAREST 0x01000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MINIFY_LINEAR 0x02000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST 0x03000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST 0x04000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR 0x05000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR 0x06000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_ANISOTROPIC_MINIFY_ENABLE 0x08000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MAGNIFY__MASK 0x70000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MAGNIFY__SHIFT 28 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MAGNIFY_NEAREST 0x10000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_MAGNIFY_LINEAR 0x20000000 |
#define NV04_MULTITEX_TRIANGLE_FILTER_ANISOTROPIC_MAGNIFY_ENABLE 0x80000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA(i0) (0x00000320 + 0xc*(i0)) |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA__ESIZE 0x0000000c |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA__LEN 0x00000002 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_INVERSE0 0x00000001 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT0__MASK 0x000000fc |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT0__SHIFT 2 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT0_ZERO 0x00000004 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT0_CONSTANT 0x00000008 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT0_PRIMARY_COLOR 0x0000000c |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT0_PREVIOUS 0x00000010 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT0_TEXTURE0 0x00000014 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT0_TEXTURE1 0x00000018 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT0_TEXTURELOD 0x0000001c |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_INVERSE1 0x00000100 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT1__MASK 0x0000fc00 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT1__SHIFT 10 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT1_ZERO 0x00000400 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT1_CONSTANT 0x00000800 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT1_PRIMARY_COLOR 0x00000c00 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT1_PREVIOUS 0x00001000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT1_TEXTURE0 0x00001400 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT1_TEXTURE1 0x00001800 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT1_TEXTURELOD 0x00001c00 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_INVERSE2 0x00010000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT2__MASK 0x00fc0000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT2__SHIFT 18 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT2_ZERO 0x00040000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT2_CONSTANT 0x00080000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT2_PRIMARY_COLOR 0x000c0000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT2_PREVIOUS 0x00100000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT2_TEXTURE0 0x00140000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT2_TEXTURE1 0x00180000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT2_TEXTURELOD 0x001c0000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_INVERSE3 0x01000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT3__MASK 0x1c000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT3__SHIFT 26 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT3_ZERO 0x04000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT3_CONSTANT 0x08000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT3_PRIMARY_COLOR 0x0c000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT3_PREVIOUS 0x10000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT3_TEXTURE0 0x14000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT3_TEXTURE1 0x18000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_ARGUMENT3_TEXTURELOD 0x1c000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_MAP__MASK 0xe0000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_MAP__SHIFT 29 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_MAP_IDENTITY 0x20000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_MAP_SCALE2 0x40000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_MAP_SCALE4 0x60000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_MAP_BIAS 0x80000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_ALPHA_MAP_BIAS_SCALE2 0xe0000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR(i0) (0x00000324 + 0xc*(i0)) |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR__ESIZE 0x0000000c |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR__LEN 0x00000002 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_INVERSE0 0x00000001 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ALPHA0 0x00000002 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0__MASK 0x000000fc |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0__SHIFT 2 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0_ZERO 0x00000004 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0_CONSTANT 0x00000008 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0_PRIMARY_COLOR 0x0000000c |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0_PREVIOUS 0x00000010 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0_TEXTURE0 0x00000014 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0_TEXTURE1 0x00000018 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0_TEXTURELOD 0x0000001c |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_INVERSE1 0x00000100 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ALPHA1 0x00000200 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT1__MASK 0x0000fc00 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT1__SHIFT 10 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT1_ZERO 0x00000400 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT1_CONSTANT 0x00000800 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT1_PRIMARY_COLOR 0x00000c00 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT1_PREVIOUS 0x00001000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT1_TEXTURE0 0x00001400 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT1_TEXTURE1 0x00001800 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT1_TEXTURELOD 0x00001c00 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_INVERSE2 0x00010000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ALPHA2 0x00020000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT2__MASK 0x00fc0000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT2__SHIFT 18 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT2_ZERO 0x00040000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT2_CONSTANT 0x00080000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT2_PRIMARY_COLOR 0x000c0000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT2_PREVIOUS 0x00100000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT2_TEXTURE0 0x00140000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT2_TEXTURE1 0x00180000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT2_TEXTURELOD 0x001c0000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_INVERSE3 0x01000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ALPHA3 0x02000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT3__MASK 0x1c000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT3__SHIFT 26 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT3_ZERO 0x04000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT3_CONSTANT 0x08000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT3_PRIMARY_COLOR 0x0c000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT3_PREVIOUS 0x10000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT3_TEXTURE0 0x14000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT3_TEXTURE1 0x18000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT3_TEXTURELOD 0x1c000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP__MASK 0xe0000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP__SHIFT 29 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_IDENTITY 0x20000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_SCALE2 0x40000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_SCALE4 0x60000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_BIAS 0x80000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_BIAS_SCALE2 0xe0000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_FACTOR 0x00000334 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_FACTOR_B__MASK 0x000000ff |
#define NV04_MULTITEX_TRIANGLE_COMBINE_FACTOR_B__SHIFT 0 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_FACTOR_G__MASK 0x0000ff00 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_FACTOR_G__SHIFT 8 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_FACTOR_R__MASK 0x00ff0000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_FACTOR_R__SHIFT 16 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_FACTOR_A__MASK 0xff000000 |
#define NV04_MULTITEX_TRIANGLE_COMBINE_FACTOR_A__SHIFT 24 |
#define NV04_MULTITEX_TRIANGLE_BLEND 0x00000338 |
#define NV04_MULTITEX_TRIANGLE_BLEND_MASK_BIT__MASK 0x00000030 |
#define NV04_MULTITEX_TRIANGLE_BLEND_MASK_BIT__SHIFT 4 |
#define NV04_MULTITEX_TRIANGLE_BLEND_MASK_BIT_LSB 0x00000010 |
#define NV04_MULTITEX_TRIANGLE_BLEND_MASK_BIT_MSB 0x00000020 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE__MASK 0x000000c0 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE__SHIFT 6 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_FLAT 0x00000040 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_GOURAUD 0x00000080 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_PHONG 0x000000c0 |
#define NV04_MULTITEX_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE 0x00000100 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SPECULAR_ENABLE 0x00001000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_FOG_ENABLE 0x00010000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_BLEND_ENABLE 0x00100000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC__MASK 0x0f000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC__SHIFT 24 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC_ZERO 0x01000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC_ONE 0x02000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC_SRC_COLOR 0x03000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC_ONE_MINUS_SRC_COLOR 0x04000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC_SRC_ALPHA 0x05000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC_ONE_MINUS_SRC_ALPHA 0x06000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC_DST_ALPHA 0x07000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC_ONE_MINUS_DST_ALPHA 0x08000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC_DST_COLOR 0x09000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC_ONE_MINUS_DST_COLOR 0x0a000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_SRC_SRC_ALPHA_SATURATE 0x0b000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST__MASK 0xf0000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST__SHIFT 28 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST_ZERO 0x10000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST_ONE 0x20000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST_SRC_COLOR 0x30000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST_ONE_MINUS_SRC_COLOR 0x40000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST_SRC_ALPHA 0x50000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST_ONE_MINUS_SRC_ALPHA 0x60000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST_DST_ALPHA 0x70000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST_ONE_MINUS_DST_ALPHA 0x80000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST_DST_COLOR 0x90000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST_ONE_MINUS_DST_COLOR 0xa0000000 |
#define NV04_MULTITEX_TRIANGLE_BLEND_DST_SRC_ALPHA_SATURATE 0xb0000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0 0x0000033c |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_REF__MASK 0x000000ff |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_REF__SHIFT 0 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC__MASK 0x00000f00 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC__SHIFT 8 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_NEVER 0x00000100 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_LESS 0x00000200 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_EQUAL 0x00000300 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_LEQUAL 0x00000400 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_GREATER 0x00000500 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_NOTEQUAL 0x00000600 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_GEQUAL 0x00000700 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_FUNC_ALWAYS 0x00000800 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_ENABLE 0x00001000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ORIGIN__MASK 0x00002000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ORIGIN__SHIFT 13 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ORIGIN_CENTER 0x00000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ORIGIN_CORNER 0x00002000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_ENABLE 0x00004000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC__MASK 0x000f0000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC__SHIFT 16 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_NEVER 0x00010000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_LESS 0x00020000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_EQUAL 0x00030000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_LEQUAL 0x00040000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_GREATER 0x00050000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_NOTEQUAL 0x00060000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_GEQUAL 0x00070000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FUNC_ALWAYS 0x00080000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE__MASK 0x00300000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE__SHIFT 20 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_BOTH 0x00000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_NONE 0x00100000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_CW 0x00200000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_CCW 0x00300000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_DITHER_ENABLE 0x00400000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_PERSPECTIVE_ENABLE 0x00800000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_WRITE 0x01000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_STENCIL_WRITE 0x02000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_WRITE 0x04000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_RED_WRITE 0x08000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_GREEN_WRITE 0x10000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_BLUE_WRITE 0x20000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FORMAT__MASK 0xc0000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FORMAT__SHIFT 30 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FORMAT_FIXED 0x40000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL0_Z_FORMAT_FLOAT 0x80000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL1 0x00000340 |
#define NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_ENABLE 0x00000001 |
#define NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_FUNC__MASK 0x000000f0 |
#define NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_FUNC__SHIFT 4 |
#define NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_REF__MASK 0x0000ff00 |
#define NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_REF__SHIFT 8 |
#define NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_READ__MASK 0x00ff0000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_READ__SHIFT 16 |
#define NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_WRITE__MASK 0xff000000 |
#define NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_MASK_WRITE__SHIFT 24 |
#define NV04_MULTITEX_TRIANGLE_CONTROL2 0x00000344 |
#define NV04_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_FAIL__MASK 0x0000000f |
#define NV04_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_FAIL__SHIFT 0 |
#define NV04_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZFAIL__MASK 0x000000f0 |
#define NV04_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZFAIL__SHIFT 4 |
#define NV04_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZPASS__MASK 0x00000f00 |
#define NV04_MULTITEX_TRIANGLE_CONTROL2_STENCIL_OP_ZPASS__SHIFT 8 |
#define NV04_MULTITEX_TRIANGLE_FOGCOLOR 0x00000348 |
#define NV04_MULTITEX_TRIANGLE_FOGCOLOR_B__MASK 0x000000ff |
#define NV04_MULTITEX_TRIANGLE_FOGCOLOR_B__SHIFT 0 |
#define NV04_MULTITEX_TRIANGLE_FOGCOLOR_G__MASK 0x0000ff00 |
#define NV04_MULTITEX_TRIANGLE_FOGCOLOR_G__SHIFT 8 |
#define NV04_MULTITEX_TRIANGLE_FOGCOLOR_R__MASK 0x00ff0000 |
#define NV04_MULTITEX_TRIANGLE_FOGCOLOR_R__SHIFT 16 |
#define NV04_MULTITEX_TRIANGLE_FOGCOLOR_A__MASK 0xff000000 |
#define NV04_MULTITEX_TRIANGLE_FOGCOLOR_A__SHIFT 24 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX(i0) (0x00000400 + 0x28*(i0)) |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX__ESIZE 0x00000028 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX__LEN 0x00000008 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SX(i0) (0x00000400 + 0x28*(i0)) |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SY(i0) (0x00000404 + 0x28*(i0)) |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SZ(i0) (0x00000408 + 0x28*(i0)) |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_RHW(i0) (0x0000040c + 0x28*(i0)) |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR(i0) (0x00000410 + 0x28*(i0)) |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_B__MASK 0x000000ff |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_B__SHIFT 0 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_G__MASK 0x0000ff00 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_G__SHIFT 8 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_R__MASK 0x00ff0000 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_R__SHIFT 16 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_A__MASK 0xff000000 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_COLOR_A__SHIFT 24 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR(i0) (0x00000414 + 0x28*(i0)) |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_B__MASK 0x000000ff |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_B__SHIFT 0 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_G__MASK 0x0000ff00 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_G__SHIFT 8 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_R__MASK 0x00ff0000 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_R__SHIFT 16 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_FOG__MASK 0xff000000 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_SPECULAR_FOG__SHIFT 24 |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_TU0(i0) (0x00000418 + 0x28*(i0)) |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_TV0(i0) (0x0000041c + 0x28*(i0)) |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_TU1(i0) (0x00000420 + 0x28*(i0)) |
#define NV04_MULTITEX_TRIANGLE_TLMTVERTEX_TV1(i0) (0x00000424 + 0x28*(i0)) |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE(i0) (0x00000540 + 0x4*(i0)) |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE__ESIZE 0x00000004 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE__LEN 0x00000030 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I0__MASK 0x0000000f |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I0__SHIFT 0 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I1__MASK 0x000000f0 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I1__SHIFT 4 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I2__MASK 0x00000f00 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I2__SHIFT 8 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I3__MASK 0x0000f000 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I3__SHIFT 12 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I4__MASK 0x000f0000 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I4__SHIFT 16 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I5__MASK 0x00f00000 |
#define NV04_MULTITEX_TRIANGLE_DRAWPRIMITIVE_I5__SHIFT 20 |
#endif /* NV04_3D_XML */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv04_context.c |
---|
0,0 → 1,282 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_fbo.h" |
#include "nouveau_util.h" |
#include "nv04_3d.xml.h" |
#include "nv04_driver.h" |
static GLboolean |
texunit_needs_combiners(struct gl_texture_unit *u) |
{ |
struct gl_texture_object *t = u->_Current; |
struct gl_texture_image *ti = t->Image[0][t->BaseLevel]; |
return ti->TexFormat == MESA_FORMAT_A8 || |
ti->TexFormat == MESA_FORMAT_L8 || |
u->EnvMode == GL_COMBINE || |
u->EnvMode == GL_COMBINE4_NV || |
u->EnvMode == GL_BLEND || |
u->EnvMode == GL_ADD; |
} |
struct nouveau_object * |
nv04_context_engine(struct gl_context *ctx) |
{ |
struct nv04_context *nctx = to_nv04_context(ctx); |
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_object *fahrenheit; |
if ((ctx->Texture.Unit[0]._ReallyEnabled && |
texunit_needs_combiners(&ctx->Texture.Unit[0])) || |
ctx->Texture.Unit[1]._ReallyEnabled || |
ctx->Stencil.Enabled || |
!(ctx->Color.ColorMask[0][RCOMP] && |
ctx->Color.ColorMask[0][GCOMP] && |
ctx->Color.ColorMask[0][BCOMP] && |
ctx->Color.ColorMask[0][ACOMP])) |
fahrenheit = hw->eng3dm; |
else |
fahrenheit = hw->eng3d; |
if (fahrenheit != nctx->eng3d) { |
BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1); |
PUSH_DATA (push, fahrenheit->handle); |
nctx->eng3d = fahrenheit; |
} |
return fahrenheit; |
} |
static void |
nv04_hwctx_init(struct gl_context *ctx) |
{ |
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nv04_fifo *fifo = hw->chan->data; |
BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1); |
PUSH_DATA (push, hw->surf3d->handle); |
BEGIN_NV04(push, NV04_SF3D(DMA_NOTIFY), 3); |
PUSH_DATA (push, hw->ntfy->handle); |
PUSH_DATA (push, fifo->vram); |
PUSH_DATA (push, fifo->vram); |
BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1); |
PUSH_DATA (push, hw->eng3d->handle); |
BEGIN_NV04(push, NV04_TTRI(DMA_NOTIFY), 4); |
PUSH_DATA (push, hw->ntfy->handle); |
PUSH_DATA (push, fifo->vram); |
PUSH_DATA (push, fifo->gart); |
PUSH_DATA (push, hw->surf3d->handle); |
BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1); |
PUSH_DATA (push, hw->eng3dm->handle); |
BEGIN_NV04(push, NV04_MTRI(DMA_NOTIFY), 4); |
PUSH_DATA (push, hw->ntfy->handle); |
PUSH_DATA (push, fifo->vram); |
PUSH_DATA (push, fifo->gart); |
PUSH_DATA (push, hw->surf3d->handle); |
PUSH_KICK (push); |
} |
static void |
init_dummy_texture(struct gl_context *ctx) |
{ |
struct nouveau_surface *s = &to_nv04_context(ctx)->dummy_texture; |
nouveau_surface_alloc(ctx, s, SWIZZLED, |
NOUVEAU_BO_MAP | NOUVEAU_BO_VRAM, |
MESA_FORMAT_ARGB8888, 1, 1); |
nouveau_bo_map(s->bo, NOUVEAU_BO_WR, context_client(ctx)); |
*(uint32_t *)s->bo->map = 0xffffffff; |
} |
static void |
nv04_context_destroy(struct gl_context *ctx) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
nv04_surface_takedown(ctx); |
nv04_render_destroy(ctx); |
nouveau_surface_ref(NULL, &to_nv04_context(ctx)->dummy_texture); |
nouveau_object_del(&nctx->hw.eng3d); |
nouveau_object_del(&nctx->hw.eng3dm); |
nouveau_object_del(&nctx->hw.surf3d); |
nouveau_context_deinit(ctx); |
free(ctx); |
} |
static struct gl_context * |
nv04_context_create(struct nouveau_screen *screen, const struct gl_config *visual, |
struct gl_context *share_ctx) |
{ |
struct nv04_context *nctx; |
struct nouveau_hw_state *hw; |
struct gl_context *ctx; |
int ret; |
nctx = CALLOC_STRUCT(nv04_context); |
if (!nctx) |
return NULL; |
ctx = &nctx->base.base; |
hw = &nctx->base.hw; |
if (!nouveau_context_init(ctx, screen, visual, share_ctx)) |
goto fail; |
/* GL constants. */ |
ctx->Const.MaxTextureLevels = 11; |
ctx->Const.MaxTextureCoordUnits = NV04_TEXTURE_UNITS; |
ctx->Const.FragmentProgram.MaxTextureImageUnits = NV04_TEXTURE_UNITS; |
ctx->Const.MaxTextureUnits = NV04_TEXTURE_UNITS; |
ctx->Const.MaxTextureMaxAnisotropy = 2; |
ctx->Const.MaxTextureLodBias = 15; |
/* 2D engine. */ |
ret = nv04_surface_init(ctx); |
if (!ret) |
goto fail; |
/* 3D engine. */ |
ret = nouveau_object_new(context_chan(ctx), 0xbeef0001, |
NV04_TEXTURED_TRIANGLE_CLASS, NULL, 0, |
&hw->eng3d); |
if (ret) |
goto fail; |
ret = nouveau_object_new(context_chan(ctx), 0xbeef0002, |
NV04_MULTITEX_TRIANGLE_CLASS, NULL, 0, |
&hw->eng3dm); |
if (ret) |
goto fail; |
ret = nouveau_object_new(context_chan(ctx), 0xbeef0003, |
NV04_SURFACE_3D_CLASS, NULL, 0, |
&hw->surf3d); |
if (ret) |
goto fail; |
init_dummy_texture(ctx); |
nv04_hwctx_init(ctx); |
nv04_render_init(ctx); |
return ctx; |
fail: |
nv04_context_destroy(ctx); |
return NULL; |
} |
const struct nouveau_driver nv04_driver = { |
.context_create = nv04_context_create, |
.context_destroy = nv04_context_destroy, |
.surface_copy = nv04_surface_copy, |
.surface_fill = nv04_surface_fill, |
.emit = (nouveau_state_func[]) { |
nv04_defer_control, |
nouveau_emit_nothing, |
nv04_defer_blend, |
nv04_defer_blend, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nv04_defer_control, |
nouveau_emit_nothing, |
nv04_defer_control, |
nouveau_emit_nothing, |
nv04_defer_control, |
nv04_defer_control, |
nouveau_emit_nothing, |
nv04_emit_framebuffer, |
nv04_defer_blend, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nv04_emit_scissor, |
nv04_defer_blend, |
nv04_defer_control, |
nv04_defer_control, |
nv04_defer_control, |
nv04_emit_tex_env, |
nv04_emit_tex_env, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nv04_emit_tex_obj, |
nv04_emit_tex_obj, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nv04_emit_blend, |
nv04_emit_control, |
}, |
.num_emit = NUM_NV04_STATE, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv04_context.h |
---|
0,0 → 1,59 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NV04_CONTEXT_H__ |
#define __NV04_CONTEXT_H__ |
#include "nouveau_context.h" |
#include "nv_object.xml.h" |
struct nv04_context { |
struct nouveau_context base; |
struct nouveau_object *eng3d; |
struct nouveau_surface dummy_texture; |
float viewport[16]; |
uint32_t colorkey; |
struct nouveau_surface *texture[2]; |
uint32_t format[2]; |
uint32_t filter[2]; |
uint32_t alpha[2]; |
uint32_t color[2]; |
uint32_t factor; |
uint32_t blend; |
uint32_t ctrl[3]; |
uint32_t fog; |
}; |
#define to_nv04_context(ctx) ((struct nv04_context *)(ctx)) |
#define nv04_mtex_engine(obj) ((obj)->oclass == NV04_MULTITEX_TRIANGLE_CLASS) |
struct nouveau_object * |
nv04_context_engine(struct gl_context *ctx); |
extern const struct nouveau_driver nv04_driver; |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv04_driver.h |
---|
0,0 → 1,93 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NV04_DRIVER_H__ |
#define __NV04_DRIVER_H__ |
#include "nv04_context.h" |
enum { |
NOUVEAU_STATE_BLEND = NUM_NOUVEAU_STATE, |
NOUVEAU_STATE_CONTROL, |
NUM_NV04_STATE |
}; |
#define NV04_TEXTURE_UNITS 2 |
/* nv04_render.c */ |
void |
nv04_render_init(struct gl_context *ctx); |
void |
nv04_render_destroy(struct gl_context *ctx); |
/* nv04_surface.c */ |
GLboolean |
nv04_surface_init(struct gl_context *ctx); |
void |
nv04_surface_takedown(struct gl_context *ctx); |
void |
nv04_surface_copy(struct gl_context *ctx, |
struct nouveau_surface *dst, struct nouveau_surface *src, |
int dx, int dy, int sx, int sy, int w, int h); |
void |
nv04_surface_fill(struct gl_context *ctx, |
struct nouveau_surface *dst, |
unsigned mask, unsigned value, |
int dx, int dy, int w, int h); |
/* nv04_state_fb.c */ |
void |
nv04_emit_framebuffer(struct gl_context *ctx, int emit); |
void |
nv04_emit_scissor(struct gl_context *ctx, int emit); |
/* nv04_state_raster.c */ |
void |
nv04_defer_control(struct gl_context *ctx, int emit); |
void |
nv04_emit_control(struct gl_context *ctx, int emit); |
void |
nv04_defer_blend(struct gl_context *ctx, int emit); |
void |
nv04_emit_blend(struct gl_context *ctx, int emit); |
/* nv04_state_frag.c */ |
void |
nv04_emit_tex_env(struct gl_context *ctx, int emit); |
/* nv04_state_tex.c */ |
void |
nv04_emit_tex_obj(struct gl_context *ctx, int emit); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv04_render.c |
---|
0,0 → 1,294 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_util.h" |
#include "nv04_3d.xml.h" |
#include "nv04_driver.h" |
#include "tnl/tnl.h" |
#include "tnl/t_pipeline.h" |
#include "tnl/t_vertex.h" |
#define NUM_VERTEX_ATTRS 6 |
static void |
swtnl_update_viewport(struct gl_context *ctx) |
{ |
float *viewport = to_nv04_context(ctx)->viewport; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
get_viewport_scale(ctx, viewport); |
get_viewport_translate(ctx, &viewport[MAT_TX]); |
/* It wants normalized Z coordinates. */ |
viewport[MAT_SZ] /= fb->_DepthMaxF; |
viewport[MAT_TZ] /= fb->_DepthMaxF; |
} |
static void |
swtnl_emit_attr(struct gl_context *ctx, struct tnl_attr_map *m, int attr, int emit) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
if (tnl->render_inputs_bitset & BITFIELD64_BIT(attr)) |
*m = (struct tnl_attr_map) { |
.attrib = attr, |
.format = emit, |
}; |
else |
*m = (struct tnl_attr_map) { |
.format = EMIT_PAD, |
.offset = _tnl_format_info[emit].attrsize, |
}; |
} |
static void |
swtnl_choose_attrs(struct gl_context *ctx) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct nouveau_object *fahrenheit = nv04_context_engine(ctx); |
struct nv04_context *nctx = to_nv04_context(ctx); |
static struct tnl_attr_map map[NUM_VERTEX_ATTRS]; |
int n = 0; |
tnl->vb.AttribPtr[VERT_ATTRIB_POS] = tnl->vb.NdcPtr; |
swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT); |
swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA); |
swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR); |
swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_FOG, EMIT_1UB_1F); |
swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_TEX0, EMIT_2F); |
if (nv04_mtex_engine(fahrenheit)) |
swtnl_emit_attr(ctx, &map[n++], _TNL_ATTRIB_TEX1, EMIT_2F); |
swtnl_update_viewport(ctx); |
_tnl_install_attrs(ctx, map, n, nctx->viewport, 0); |
} |
/* TnL renderer entry points */ |
static void |
swtnl_restart_ttri(struct nv04_context *nv04, struct nouveau_pushbuf *push) |
{ |
BEGIN_NV04(push, NV04_TTRI(COLORKEY), 7); |
PUSH_DATA (push, nv04->colorkey); |
PUSH_RELOC(push, nv04->texture[0]->bo, nv04->texture[0]->offset, |
NOUVEAU_BO_LOW, 0, 0); |
PUSH_RELOC(push, nv04->texture[0]->bo, nv04->format[0], NOUVEAU_BO_OR, |
NV04_TEXTURED_TRIANGLE_FORMAT_DMA_A, |
NV04_TEXTURED_TRIANGLE_FORMAT_DMA_B); |
PUSH_DATA (push, nv04->filter[0]); |
PUSH_DATA (push, nv04->blend); |
PUSH_DATA (push, nv04->ctrl[0] & ~0x3e000000); |
PUSH_DATA (push, nv04->fog); |
} |
static void |
swtnl_restart_mtri(struct nv04_context *nv04, struct nouveau_pushbuf *push) |
{ |
BEGIN_NV04(push, NV04_MTRI(OFFSET(0)), 8); |
PUSH_RELOC(push, nv04->texture[0]->bo, nv04->texture[0]->offset, |
NOUVEAU_BO_LOW, 0, 0); |
PUSH_RELOC(push, nv04->texture[1]->bo, nv04->texture[1]->offset, |
NOUVEAU_BO_LOW, 0, 0); |
PUSH_RELOC(push, nv04->texture[0]->bo, nv04->format[0], NOUVEAU_BO_OR, |
NV04_TEXTURED_TRIANGLE_FORMAT_DMA_A, |
NV04_TEXTURED_TRIANGLE_FORMAT_DMA_B); |
PUSH_RELOC(push, nv04->texture[1]->bo, nv04->format[1], NOUVEAU_BO_OR, |
NV04_TEXTURED_TRIANGLE_FORMAT_DMA_A, |
NV04_TEXTURED_TRIANGLE_FORMAT_DMA_B); |
PUSH_DATA (push, nv04->filter[0]); |
PUSH_DATA (push, nv04->filter[1]); |
PUSH_DATA (push, nv04->alpha[0]); |
PUSH_DATA (push, nv04->color[0]); |
BEGIN_NV04(push, NV04_MTRI(COMBINE_ALPHA(1)), 8); |
PUSH_DATA (push, nv04->alpha[1]); |
PUSH_DATA (push, nv04->color[1]); |
PUSH_DATA (push, nv04->factor); |
PUSH_DATA (push, nv04->blend & ~0x0000000f); |
PUSH_DATA (push, nv04->ctrl[0]); |
PUSH_DATA (push, nv04->ctrl[1]); |
PUSH_DATA (push, nv04->ctrl[2]); |
PUSH_DATA (push, nv04->fog); |
} |
static inline bool |
swtnl_restart(struct gl_context *ctx, int multi, unsigned vertex_size) |
{ |
const int tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; |
struct nv04_context *nv04 = to_nv04_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_pushbuf_refn refs[] = { |
{ nv04->texture[0]->bo, tex_flags }, |
{ nv04->texture[1]->bo, tex_flags }, |
}; |
/* wait for enough space for state, and at least one whole primitive */ |
if (nouveau_pushbuf_space(push, 32 + (4 * vertex_size), 4, 0) || |
nouveau_pushbuf_refn (push, refs, multi ? 2 : 1)) |
return false; |
/* emit engine state */ |
if (multi) |
swtnl_restart_mtri(nv04, push); |
else |
swtnl_restart_ttri(nv04, push); |
return true; |
} |
static void |
swtnl_start(struct gl_context *ctx) |
{ |
struct nouveau_object *eng3d = nv04_context_engine(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
unsigned vertex_size; |
nouveau_pushbuf_bufctx(push, push->user_priv); |
nouveau_pushbuf_validate(push); |
swtnl_choose_attrs(ctx); |
vertex_size = TNL_CONTEXT(ctx)->clipspace.vertex_size / 4; |
if (eng3d->oclass == NV04_MULTITEX_TRIANGLE_CLASS) |
swtnl_restart(ctx, 1, vertex_size); |
else |
swtnl_restart(ctx, 0, vertex_size); |
} |
static void |
swtnl_finish(struct gl_context *ctx) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
nouveau_pushbuf_bufctx(push, NULL); |
} |
static void |
swtnl_primitive(struct gl_context *ctx, GLenum mode) |
{ |
} |
static void |
swtnl_reset_stipple(struct gl_context *ctx) |
{ |
} |
/* Primitive rendering */ |
#define BEGIN_PRIMITIVE(n) \ |
struct nouveau_object *eng3d = to_nv04_context(ctx)->eng3d; \ |
struct nouveau_pushbuf *push = context_push(ctx); \ |
int vertex_size = TNL_CONTEXT(ctx)->clipspace.vertex_size / 4; \ |
int multi = (eng3d->oclass == NV04_MULTITEX_TRIANGLE_CLASS); \ |
\ |
if (PUSH_AVAIL(push) < 32 + (n * vertex_size)) { \ |
if (!swtnl_restart(ctx, multi, vertex_size)) \ |
return; \ |
} \ |
\ |
BEGIN_NV04(push, NV04_TTRI(TLVERTEX_SX(0)), n * vertex_size); |
#define OUT_VERTEX(i) \ |
PUSH_DATAp(push, _tnl_get_vertex(ctx, i), vertex_size); |
#define END_PRIMITIVE(draw) \ |
if (multi) { \ |
BEGIN_NV04(push, NV04_MTRI(DRAWPRIMITIVE(0)), 1); \ |
PUSH_DATA (push, draw); \ |
} else { \ |
BEGIN_NV04(push, NV04_TTRI(DRAWPRIMITIVE(0)), 1); \ |
PUSH_DATA (push, draw); \ |
} |
static void |
swtnl_points(struct gl_context *ctx, GLuint first, GLuint last) |
{ |
} |
static void |
swtnl_line(struct gl_context *ctx, GLuint v1, GLuint v2) |
{ |
} |
static void |
swtnl_triangle(struct gl_context *ctx, GLuint v1, GLuint v2, GLuint v3) |
{ |
BEGIN_PRIMITIVE(3); |
OUT_VERTEX(v1); |
OUT_VERTEX(v2); |
OUT_VERTEX(v3); |
END_PRIMITIVE(0x102); |
} |
static void |
swtnl_quad(struct gl_context *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4) |
{ |
BEGIN_PRIMITIVE(4); |
OUT_VERTEX(v1); |
OUT_VERTEX(v2); |
OUT_VERTEX(v3); |
OUT_VERTEX(v4); |
END_PRIMITIVE(0x213103); |
} |
/* TnL initialization. */ |
void |
nv04_render_init(struct gl_context *ctx) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
tnl->Driver.RunPipeline = _tnl_run_pipeline; |
tnl->Driver.Render.Interp = _tnl_interp; |
tnl->Driver.Render.CopyPV = _tnl_copy_pv; |
tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; |
tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; |
tnl->Driver.Render.BuildVertices = _tnl_build_vertices; |
tnl->Driver.Render.Start = swtnl_start; |
tnl->Driver.Render.Finish = swtnl_finish; |
tnl->Driver.Render.PrimitiveNotify = swtnl_primitive; |
tnl->Driver.Render.ResetLineStipple = swtnl_reset_stipple; |
tnl->Driver.Render.Points = swtnl_points; |
tnl->Driver.Render.Line = swtnl_line; |
tnl->Driver.Render.Triangle = swtnl_triangle; |
tnl->Driver.Render.Quad = swtnl_quad; |
_tnl_need_projected_coords(ctx, GL_TRUE); |
_tnl_init_vertices(ctx, tnl->vb.Size, |
NUM_VERTEX_ATTRS * 4 * sizeof(GLfloat)); |
_tnl_allow_pixel_fog(ctx, GL_FALSE); |
_tnl_wakeup(ctx); |
} |
void |
nv04_render_destroy(struct gl_context *ctx) |
{ |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv04_state_fb.c |
---|
0,0 → 1,109 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_fbo.h" |
#include "nouveau_util.h" |
#include "nv04_3d.xml.h" |
#include "nv04_driver.h" |
static inline unsigned |
get_rt_format(gl_format format) |
{ |
switch (format) { |
case MESA_FORMAT_XRGB8888: |
return NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_X8R8G8B8_X8R8G8B8; |
case MESA_FORMAT_ARGB8888: |
return NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_A8R8G8B8; |
case MESA_FORMAT_RGB565: |
return NV04_CONTEXT_SURFACES_3D_FORMAT_COLOR_R5G6B5; |
default: |
assert(0); |
} |
} |
void |
nv04_emit_framebuffer(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct nouveau_surface *s; |
uint32_t rt_format = NV04_CONTEXT_SURFACES_3D_FORMAT_TYPE_PITCH; |
uint32_t rt_pitch = 0, zeta_pitch = 0; |
unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR; |
if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) |
return; |
PUSH_RESET(push, BUFCTX_FB); |
/* Render target */ |
if (fb->_ColorDrawBuffers[0]) { |
s = &to_nouveau_renderbuffer( |
fb->_ColorDrawBuffers[0])->surface; |
rt_format |= get_rt_format(s->format); |
zeta_pitch = rt_pitch = s->pitch; |
BEGIN_NV04(push, NV04_SF3D(OFFSET_COLOR), 1); |
PUSH_MTHDl(push, NV04_SF3D(OFFSET_COLOR), BUFCTX_FB, |
s->bo, 0, bo_flags); |
} |
/* depth/stencil */ |
if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { |
s = &to_nouveau_renderbuffer( |
fb->Attachment[BUFFER_DEPTH].Renderbuffer)->surface; |
zeta_pitch = s->pitch; |
BEGIN_NV04(push, NV04_SF3D(OFFSET_ZETA), 1); |
PUSH_MTHDl(push, NV04_SF3D(OFFSET_ZETA), BUFCTX_FB, |
s->bo, 0, bo_flags); |
} |
BEGIN_NV04(push, NV04_SF3D(FORMAT), 1); |
PUSH_DATA (push, rt_format); |
BEGIN_NV04(push, NV04_SF3D(PITCH), 1); |
PUSH_DATA (push, zeta_pitch << 16 | rt_pitch); |
/* Recompute the scissor state. */ |
context_dirty(ctx, SCISSOR); |
} |
void |
nv04_emit_scissor(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
int x, y, w, h; |
get_scissors(ctx->DrawBuffer, &x, &y, &w, &h); |
BEGIN_NV04(push, NV04_SF3D(CLIP_HORIZONTAL), 2); |
PUSH_DATA (push, w << 16 | x); |
PUSH_DATA (push, h << 16 | y); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv04_state_frag.c |
---|
0,0 → 1,299 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_util.h" |
#include "nv_object.xml.h" |
#include "nv04_3d.xml.h" |
#include "nv04_driver.h" |
#define COMBINER_SHIFT(in) \ |
(NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT##in##__SHIFT \ |
- NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0__SHIFT) |
#define COMBINER_SOURCE(reg) \ |
NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ARGUMENT0_##reg |
#define COMBINER_INVERT \ |
NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_INVERSE0 |
#define COMBINER_ALPHA \ |
NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_ALPHA0 |
struct combiner_state { |
struct gl_context *ctx; |
int unit; |
GLboolean alpha; |
GLboolean premodulate; |
/* GL state */ |
GLenum mode; |
GLenum *source; |
GLenum *operand; |
GLuint logscale; |
/* Derived HW state */ |
uint32_t hw; |
}; |
#define __INIT_COMBINER_ALPHA_A GL_TRUE |
#define __INIT_COMBINER_ALPHA_RGB GL_FALSE |
/* Initialize a combiner_state struct from the texture unit |
* context. */ |
#define INIT_COMBINER(chan, ctx, rc, i) do { \ |
struct gl_tex_env_combine_state *c = \ |
ctx->Texture.Unit[i]._CurrentCombine; \ |
(rc)->ctx = ctx; \ |
(rc)->unit = i; \ |
(rc)->alpha = __INIT_COMBINER_ALPHA_##chan; \ |
(rc)->premodulate = c->_NumArgs##chan == 4; \ |
(rc)->mode = c->Mode##chan; \ |
(rc)->source = c->Source##chan; \ |
(rc)->operand = c->Operand##chan; \ |
(rc)->logscale = c->ScaleShift##chan; \ |
(rc)->hw = 0; \ |
} while (0) |
/* Get the combiner source for the specified EXT_texture_env_combine |
* source. */ |
static uint32_t |
get_input_source(struct combiner_state *rc, int source) |
{ |
switch (source) { |
case GL_ZERO: |
return COMBINER_SOURCE(ZERO); |
case GL_TEXTURE: |
return rc->unit ? COMBINER_SOURCE(TEXTURE1) : |
COMBINER_SOURCE(TEXTURE0); |
case GL_TEXTURE0: |
return COMBINER_SOURCE(TEXTURE0); |
case GL_TEXTURE1: |
return COMBINER_SOURCE(TEXTURE1); |
case GL_CONSTANT: |
return COMBINER_SOURCE(CONSTANT); |
case GL_PRIMARY_COLOR: |
return COMBINER_SOURCE(PRIMARY_COLOR); |
case GL_PREVIOUS: |
return rc->unit ? COMBINER_SOURCE(PREVIOUS) : |
COMBINER_SOURCE(PRIMARY_COLOR); |
default: |
assert(0); |
} |
} |
/* Get the (possibly inverted) combiner input mapping for the |
* specified EXT_texture_env_combine operand. */ |
#define INVERT 0x1 |
static uint32_t |
get_input_mapping(struct combiner_state *rc, int operand, int flags) |
{ |
int map = 0; |
if (!is_color_operand(operand) && !rc->alpha) |
map |= COMBINER_ALPHA; |
if (is_negative_operand(operand) == !(flags & INVERT)) |
map |= COMBINER_INVERT; |
return map; |
} |
static uint32_t |
get_input_arg(struct combiner_state *rc, int arg, int flags) |
{ |
int source = rc->source[arg]; |
int operand = rc->operand[arg]; |
/* Fake several unsupported texture formats. */ |
if (is_texture_source(source)) { |
int i = (source == GL_TEXTURE ? |
rc->unit : source - GL_TEXTURE0); |
struct gl_texture_object *t = rc->ctx->Texture.Unit[i]._Current; |
gl_format format = t->Image[0][t->BaseLevel]->TexFormat; |
if (format == MESA_FORMAT_A8) { |
/* Emulated using I8. */ |
if (is_color_operand(operand)) |
return COMBINER_SOURCE(ZERO) | |
get_input_mapping(rc, operand, flags); |
} else if (format == MESA_FORMAT_L8) { |
/* Emulated using I8. */ |
if (!is_color_operand(operand)) |
return COMBINER_SOURCE(ZERO) | |
get_input_mapping(rc, operand, |
flags ^ INVERT); |
} |
} |
return get_input_source(rc, source) | |
get_input_mapping(rc, operand, flags); |
} |
/* Bind the combiner input <in> to the combiner source <src>, |
* possibly inverted. */ |
#define INPUT_SRC(rc, in, src, flags) \ |
(rc)->hw |= ((flags & INVERT ? COMBINER_INVERT : 0) | \ |
COMBINER_SOURCE(src)) << COMBINER_SHIFT(in) |
/* Bind the combiner input <in> to the EXT_texture_env_combine |
* argument <arg>, possibly inverted. */ |
#define INPUT_ARG(rc, in, arg, flags) \ |
(rc)->hw |= get_input_arg(rc, arg, flags) << COMBINER_SHIFT(in) |
#define UNSIGNED_OP(rc) \ |
(rc)->hw |= ((rc)->logscale ? \ |
NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_SCALE2 : \ |
NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_IDENTITY) |
#define SIGNED_OP(rc) \ |
(rc)->hw |= ((rc)->logscale ? \ |
NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_BIAS_SCALE2 : \ |
NV04_MULTITEX_TRIANGLE_COMBINE_COLOR_MAP_BIAS) |
static void |
setup_combiner(struct combiner_state *rc) |
{ |
switch (rc->mode) { |
case GL_REPLACE: |
INPUT_ARG(rc, 0, 0, 0); |
INPUT_SRC(rc, 1, ZERO, INVERT); |
INPUT_SRC(rc, 2, ZERO, 0); |
INPUT_SRC(rc, 3, ZERO, 0); |
UNSIGNED_OP(rc); |
break; |
case GL_MODULATE: |
INPUT_ARG(rc, 0, 0, 0); |
INPUT_ARG(rc, 1, 1, 0); |
INPUT_SRC(rc, 2, ZERO, 0); |
INPUT_SRC(rc, 3, ZERO, 0); |
UNSIGNED_OP(rc); |
break; |
case GL_ADD: |
case GL_ADD_SIGNED: |
if (rc->premodulate) { |
INPUT_ARG(rc, 0, 0, 0); |
INPUT_ARG(rc, 1, 1, 0); |
INPUT_ARG(rc, 2, 2, 0); |
INPUT_ARG(rc, 3, 3, 0); |
} else { |
INPUT_ARG(rc, 0, 0, 0); |
INPUT_SRC(rc, 1, ZERO, INVERT); |
INPUT_ARG(rc, 2, 1, 0); |
INPUT_SRC(rc, 3, ZERO, INVERT); |
} |
if (rc->mode == GL_ADD_SIGNED) |
SIGNED_OP(rc); |
else |
UNSIGNED_OP(rc); |
break; |
case GL_INTERPOLATE: |
INPUT_ARG(rc, 0, 0, 0); |
INPUT_ARG(rc, 1, 2, 0); |
INPUT_ARG(rc, 2, 1, 0); |
INPUT_ARG(rc, 3, 2, INVERT); |
UNSIGNED_OP(rc); |
break; |
default: |
assert(0); |
} |
} |
static unsigned |
get_texenv_mode(unsigned mode) |
{ |
switch (mode) { |
case GL_REPLACE: |
return 0x1; |
case GL_DECAL: |
return 0x3; |
case GL_MODULATE: |
return 0x4; |
default: |
assert(0); |
} |
} |
void |
nv04_emit_tex_env(struct gl_context *ctx, int emit) |
{ |
struct nv04_context *nv04 = to_nv04_context(ctx); |
const int i = emit - NOUVEAU_STATE_TEX_ENV0; |
struct combiner_state rc_a = {}, rc_c = {}; |
/* Compute the new combiner state. */ |
if (ctx->Texture.Unit[i]._ReallyEnabled) { |
INIT_COMBINER(A, ctx, &rc_a, i); |
setup_combiner(&rc_a); |
INIT_COMBINER(RGB, ctx, &rc_c, i); |
setup_combiner(&rc_c); |
} else { |
if (i == 0) { |
INPUT_SRC(&rc_a, 0, PRIMARY_COLOR, 0); |
INPUT_SRC(&rc_c, 0, PRIMARY_COLOR, 0); |
} else { |
INPUT_SRC(&rc_a, 0, PREVIOUS, 0); |
INPUT_SRC(&rc_c, 0, PREVIOUS, 0); |
} |
INPUT_SRC(&rc_a, 1, ZERO, INVERT); |
INPUT_SRC(&rc_c, 1, ZERO, INVERT); |
INPUT_SRC(&rc_a, 2, ZERO, 0); |
INPUT_SRC(&rc_c, 2, ZERO, 0); |
INPUT_SRC(&rc_a, 3, ZERO, 0); |
INPUT_SRC(&rc_c, 3, ZERO, 0); |
UNSIGNED_OP(&rc_a); |
UNSIGNED_OP(&rc_c); |
} |
/* calculate non-multitex state */ |
nv04->blend &= ~NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP__MASK; |
if (ctx->Texture._EnabledUnits) |
nv04->blend |= get_texenv_mode(ctx->Texture.Unit[0].EnvMode); |
else |
nv04->blend |= get_texenv_mode(GL_MODULATE); |
/* update calculated multitex state */ |
nv04->alpha[i] = rc_a.hw; |
nv04->color[i] = rc_c.hw; |
nv04->factor = pack_rgba_f(MESA_FORMAT_ARGB8888, |
ctx->Texture.Unit[0].EnvColor); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv04_state_raster.c |
---|
0,0 → 1,227 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_util.h" |
#include "nv_object.xml.h" |
#include "nv04_3d.xml.h" |
#include "nv04_driver.h" |
#include "main/stencil.h" |
static unsigned |
get_comparison_op(unsigned op) |
{ |
switch (op) { |
case GL_NEVER: |
return 0x1; |
case GL_LESS: |
return 0x2; |
case GL_EQUAL: |
return 0x3; |
case GL_LEQUAL: |
return 0x4; |
case GL_GREATER: |
return 0x5; |
case GL_NOTEQUAL: |
return 0x6; |
case GL_GEQUAL: |
return 0x7; |
case GL_ALWAYS: |
return 0x8; |
default: |
assert(0); |
} |
} |
static unsigned |
get_stencil_op(unsigned op) |
{ |
switch (op) { |
case GL_KEEP: |
return 0x1; |
case GL_ZERO: |
return 0x2; |
case GL_REPLACE: |
return 0x3; |
case GL_INCR: |
return 0x4; |
case GL_DECR: |
return 0x5; |
case GL_INVERT: |
return 0x6; |
case GL_INCR_WRAP: |
return 0x7; |
case GL_DECR_WRAP: |
return 0x8; |
default: |
assert(0); |
} |
} |
static unsigned |
get_blend_func(unsigned func) |
{ |
switch (func) { |
case GL_ZERO: |
return 0x1; |
case GL_ONE: |
return 0x2; |
case GL_SRC_COLOR: |
return 0x3; |
case GL_ONE_MINUS_SRC_COLOR: |
return 0x4; |
case GL_SRC_ALPHA: |
return 0x5; |
case GL_ONE_MINUS_SRC_ALPHA: |
return 0x6; |
case GL_DST_ALPHA: |
return 0x7; |
case GL_ONE_MINUS_DST_ALPHA: |
return 0x8; |
case GL_DST_COLOR: |
return 0x9; |
case GL_ONE_MINUS_DST_COLOR: |
return 0xa; |
case GL_SRC_ALPHA_SATURATE: |
return 0xb; |
default: |
assert(0); |
} |
} |
void |
nv04_defer_control(struct gl_context *ctx, int emit) |
{ |
context_dirty(ctx, CONTROL); |
} |
void |
nv04_emit_control(struct gl_context *ctx, int emit) |
{ |
struct nv04_context *nv04 = to_nv04_context(ctx); |
int cull = ctx->Polygon.CullFaceMode; |
int front = ctx->Polygon.FrontFace; |
nv04->ctrl[0] = NV04_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_FIXED | |
NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN_CORNER; |
nv04->ctrl[1] = 0; |
nv04->ctrl[2] = 0; |
/* Dithering. */ |
if (ctx->Color.DitherFlag) |
nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE; |
/* Cull mode. */ |
if (!ctx->Polygon.CullFlag) |
nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_NONE; |
else if (cull == GL_FRONT_AND_BACK) |
nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_BOTH; |
else |
nv04->ctrl[0] |= (cull == GL_FRONT) ^ (front == GL_CCW) ? |
NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CW : |
NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CCW; |
/* Depth test. */ |
if (ctx->Depth.Test) |
nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE; |
if (ctx->Depth.Mask) |
nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_WRITE; |
nv04->ctrl[0] |= get_comparison_op(ctx->Depth.Func) << 16; |
/* Alpha test. */ |
if (ctx->Color.AlphaEnabled) |
nv04->ctrl[0] |= NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_ENABLE; |
nv04->ctrl[0] |= get_comparison_op(ctx->Color.AlphaFunc) << 8 | |
FLOAT_TO_UBYTE(ctx->Color.AlphaRef); |
/* Color mask. */ |
if (ctx->Color.ColorMask[0][RCOMP]) |
nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_RED_WRITE; |
if (ctx->Color.ColorMask[0][GCOMP]) |
nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_GREEN_WRITE; |
if (ctx->Color.ColorMask[0][BCOMP]) |
nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_BLUE_WRITE; |
if (ctx->Color.ColorMask[0][ACOMP]) |
nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_WRITE; |
/* Stencil test. */ |
if (ctx->Stencil.WriteMask[0]) |
nv04->ctrl[0] |= NV04_MULTITEX_TRIANGLE_CONTROL0_STENCIL_WRITE; |
if (ctx->Stencil.Enabled) |
nv04->ctrl[1] |= NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_ENABLE; |
nv04->ctrl[1] |= get_comparison_op(ctx->Stencil.Function[0]) << 4 | |
_mesa_get_stencil_ref(ctx, 0) << 8 | |
ctx->Stencil.ValueMask[0] << 16 | |
ctx->Stencil.WriteMask[0] << 24; |
nv04->ctrl[2] |= get_stencil_op(ctx->Stencil.ZPassFunc[0]) << 8 | |
get_stencil_op(ctx->Stencil.ZFailFunc[0]) << 4 | |
get_stencil_op(ctx->Stencil.FailFunc[0]); |
} |
void |
nv04_defer_blend(struct gl_context *ctx, int emit) |
{ |
context_dirty(ctx, BLEND); |
} |
void |
nv04_emit_blend(struct gl_context *ctx, int emit) |
{ |
struct nv04_context *nv04 = to_nv04_context(ctx); |
nv04->blend &= NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_MAP__MASK; |
nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_MASK_BIT_MSB | |
NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE; |
/* Alpha blending. */ |
nv04->blend |= get_blend_func(ctx->Color.Blend[0].DstRGB) << 28 | |
get_blend_func(ctx->Color.Blend[0].SrcRGB) << 24; |
if (ctx->Color.BlendEnabled) |
nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_BLEND_ENABLE; |
/* Shade model. */ |
if (ctx->Light.ShadeModel == GL_SMOOTH) |
nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD; |
else |
nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT; |
/* Secondary color */ |
if (_mesa_need_secondary_color(ctx)) |
nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE; |
/* Fog. */ |
if (ctx->Fog.Enabled) { |
nv04->blend |= NV04_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE; |
nv04->fog = pack_rgba_f(MESA_FORMAT_ARGB8888, ctx->Fog.Color); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv04_state_tex.c |
---|
0,0 → 1,116 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_texture.h" |
#include "nouveau_util.h" |
#include "nouveau_gldefs.h" |
#include "nv_object.xml.h" |
#include "nv04_3d.xml.h" |
#include "nv04_driver.h" |
#include "main/samplerobj.h" |
static uint32_t |
get_tex_format(struct gl_texture_image *ti) |
{ |
switch (ti->TexFormat) { |
case MESA_FORMAT_A8: |
case MESA_FORMAT_L8: |
case MESA_FORMAT_I8: |
return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_Y8; |
case MESA_FORMAT_ARGB1555: |
return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A1R5G5B5; |
case MESA_FORMAT_ARGB4444: |
return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A4R4G4B4; |
case MESA_FORMAT_RGB565: |
return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_R5G6B5; |
case MESA_FORMAT_ARGB8888: |
return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A8R8G8B8; |
case MESA_FORMAT_XRGB8888: |
return NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_X8R8G8B8; |
default: |
assert(0); |
} |
} |
void |
nv04_emit_tex_obj(struct gl_context *ctx, int emit) |
{ |
struct nv04_context *nv04 = to_nv04_context(ctx); |
const int i = emit - NOUVEAU_STATE_TEX_OBJ0; |
struct nouveau_surface *s; |
uint32_t format = 0xa0, filter = 0x1010; |
if (ctx->Texture.Unit[i]._ReallyEnabled) { |
struct gl_texture_object *t = ctx->Texture.Unit[i]._Current; |
struct gl_texture_image *ti = t->Image[0][t->BaseLevel]; |
const struct gl_sampler_object *sa = _mesa_get_samplerobj(ctx, i); |
int lod_max = 1, lod_bias = 0; |
if (!nouveau_texture_validate(ctx, t)) |
return; |
s = &to_nouveau_texture(t)->surfaces[t->BaseLevel]; |
if (sa->MinFilter != GL_NEAREST && |
sa->MinFilter != GL_LINEAR) { |
lod_max = CLAMP(MIN2(sa->MaxLod, t->_MaxLambda), |
0, 15) + 1; |
lod_bias = CLAMP(ctx->Texture.Unit[i].LodBias + |
sa->LodBias, -16, 15) * 8; |
} |
format |= nvgl_wrap_mode(sa->WrapT) << 28 | |
nvgl_wrap_mode(sa->WrapS) << 24 | |
ti->HeightLog2 << 20 | |
ti->WidthLog2 << 16 | |
lod_max << 12 | |
get_tex_format(ti); |
filter |= log2i(sa->MaxAnisotropy) << 31 | |
nvgl_filter_mode(sa->MagFilter) << 28 | |
log2i(sa->MaxAnisotropy) << 27 | |
nvgl_filter_mode(sa->MinFilter) << 24 | |
(lod_bias & 0xff) << 16; |
} else { |
s = &to_nv04_context(ctx)->dummy_texture; |
format |= NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_REPEAT | |
NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_REPEAT | |
1 << 12 | |
NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_A8R8G8B8; |
filter |= NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST | |
NV04_TEXTURED_TRIANGLE_FILTER_MAGNIFY_NEAREST; |
} |
nv04->texture[i] = s; |
nv04->format[i] = format; |
nv04->filter[i] = filter; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv04_surface.c |
---|
0,0 → 1,613 |
/* |
* Copyright (C) 2007-2010 The Nouveau Project. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nv_object.xml.h" |
#include "nv_m2mf.xml.h" |
#include "nv01_2d.xml.h" |
#include "nv04_3d.xml.h" |
#include "nouveau_context.h" |
#include "nouveau_util.h" |
#include "nv04_driver.h" |
static inline int |
swzsurf_format(gl_format format) |
{ |
switch (format) { |
case MESA_FORMAT_A8: |
case MESA_FORMAT_L8: |
case MESA_FORMAT_I8: |
case MESA_FORMAT_RGB332: |
return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8; |
case MESA_FORMAT_RGB565: |
case MESA_FORMAT_RGB565_REV: |
case MESA_FORMAT_ARGB4444: |
case MESA_FORMAT_ARGB4444_REV: |
case MESA_FORMAT_ARGB1555: |
case MESA_FORMAT_RGBA5551: |
case MESA_FORMAT_ARGB1555_REV: |
case MESA_FORMAT_AL88: |
case MESA_FORMAT_AL88_REV: |
case MESA_FORMAT_YCBCR: |
case MESA_FORMAT_YCBCR_REV: |
case MESA_FORMAT_Z16: |
return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5; |
case MESA_FORMAT_RGBA8888: |
case MESA_FORMAT_RGBA8888_REV: |
case MESA_FORMAT_XRGB8888: |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_ARGB8888_REV: |
case MESA_FORMAT_S8_Z24: |
case MESA_FORMAT_Z24_S8: |
case MESA_FORMAT_Z32: |
return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8; |
default: |
assert(0); |
} |
} |
static inline int |
surf2d_format(gl_format format) |
{ |
switch (format) { |
case MESA_FORMAT_A8: |
case MESA_FORMAT_L8: |
case MESA_FORMAT_I8: |
case MESA_FORMAT_RGB332: |
return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8; |
case MESA_FORMAT_RGB565: |
case MESA_FORMAT_RGB565_REV: |
case MESA_FORMAT_ARGB4444: |
case MESA_FORMAT_ARGB4444_REV: |
case MESA_FORMAT_ARGB1555: |
case MESA_FORMAT_RGBA5551: |
case MESA_FORMAT_ARGB1555_REV: |
case MESA_FORMAT_AL88: |
case MESA_FORMAT_AL88_REV: |
case MESA_FORMAT_YCBCR: |
case MESA_FORMAT_YCBCR_REV: |
case MESA_FORMAT_Z16: |
return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5; |
case MESA_FORMAT_RGBA8888: |
case MESA_FORMAT_RGBA8888_REV: |
case MESA_FORMAT_XRGB8888: |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_ARGB8888_REV: |
case MESA_FORMAT_S8_Z24: |
case MESA_FORMAT_Z24_S8: |
case MESA_FORMAT_Z32: |
return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32; |
default: |
assert(0); |
} |
} |
static inline int |
rect_format(gl_format format) |
{ |
switch (format) { |
case MESA_FORMAT_A8: |
case MESA_FORMAT_L8: |
case MESA_FORMAT_I8: |
case MESA_FORMAT_RGB332: |
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8; |
case MESA_FORMAT_RGB565: |
case MESA_FORMAT_RGB565_REV: |
case MESA_FORMAT_ARGB4444: |
case MESA_FORMAT_ARGB4444_REV: |
case MESA_FORMAT_ARGB1555: |
case MESA_FORMAT_RGBA5551: |
case MESA_FORMAT_ARGB1555_REV: |
case MESA_FORMAT_AL88: |
case MESA_FORMAT_AL88_REV: |
case MESA_FORMAT_YCBCR: |
case MESA_FORMAT_YCBCR_REV: |
case MESA_FORMAT_Z16: |
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5; |
case MESA_FORMAT_RGBA8888: |
case MESA_FORMAT_RGBA8888_REV: |
case MESA_FORMAT_XRGB8888: |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_ARGB8888_REV: |
case MESA_FORMAT_S8_Z24: |
case MESA_FORMAT_Z24_S8: |
case MESA_FORMAT_Z32: |
return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8; |
default: |
assert(0); |
} |
} |
static inline int |
sifm_format(gl_format format) |
{ |
switch (format) { |
case MESA_FORMAT_A8: |
case MESA_FORMAT_L8: |
case MESA_FORMAT_I8: |
case MESA_FORMAT_RGB332: |
return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8; |
case MESA_FORMAT_RGB565: |
case MESA_FORMAT_RGB565_REV: |
case MESA_FORMAT_ARGB4444: |
case MESA_FORMAT_ARGB4444_REV: |
case MESA_FORMAT_ARGB1555: |
case MESA_FORMAT_RGBA5551: |
case MESA_FORMAT_ARGB1555_REV: |
case MESA_FORMAT_AL88: |
case MESA_FORMAT_AL88_REV: |
case MESA_FORMAT_YCBCR: |
case MESA_FORMAT_YCBCR_REV: |
case MESA_FORMAT_Z16: |
return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5; |
case MESA_FORMAT_RGBA8888: |
case MESA_FORMAT_RGBA8888_REV: |
case MESA_FORMAT_XRGB8888: |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_ARGB8888_REV: |
case MESA_FORMAT_S8_Z24: |
case MESA_FORMAT_Z24_S8: |
case MESA_FORMAT_Z32: |
return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8; |
default: |
assert(0); |
} |
} |
static void |
nv04_surface_copy_swizzle(struct gl_context *ctx, |
struct nouveau_surface *dst, |
struct nouveau_surface *src, |
int dx, int dy, int sx, int sy, |
int w, int h) |
{ |
struct nouveau_pushbuf_refn refs[] = { |
{ src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART }, |
{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM }, |
}; |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; |
struct nouveau_object *swzsurf = hw->swzsurf; |
struct nv04_fifo *fifo = hw->chan->data; |
/* Max width & height may not be the same on all HW, but must be POT */ |
const unsigned max_w = 1024; |
const unsigned max_h = 1024; |
unsigned sub_w = w > max_w ? max_w : w; |
unsigned sub_h = h > max_h ? max_h : h; |
unsigned x, y; |
/* Swizzled surfaces must be POT */ |
assert(_mesa_is_pow_two(dst->width) && |
_mesa_is_pow_two(dst->height)); |
if (context_chipset(ctx) < 0x10) { |
BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1); |
PUSH_DATA (push, swzsurf->handle); |
} |
for (y = 0; y < h; y += sub_h) { |
sub_h = MIN2(sub_h, h - y); |
for (x = 0; x < w; x += sub_w) { |
sub_w = MIN2(sub_w, w - x); |
if (nouveau_pushbuf_space(push, 64, 4, 0) || |
nouveau_pushbuf_refn (push, refs, 2)) |
return; |
BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1); |
PUSH_DATA (push, fifo->vram); |
BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2); |
PUSH_DATA (push, swzsurf_format(dst->format) | |
log2i(dst->width) << 16 | |
log2i(dst->height) << 24); |
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); |
BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1); |
PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); |
BEGIN_NV04(push, NV05_SIFM(SURFACE), 1); |
PUSH_DATA (push, swzsurf->handle); |
BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8); |
PUSH_DATA (push, sifm_format(src->format)); |
PUSH_DATA (push, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY); |
PUSH_DATA (push, (y + dy) << 16 | (x + dx)); |
PUSH_DATA (push, sub_h << 16 | sub_w); |
PUSH_DATA (push, (y + dy) << 16 | (x + dx)); |
PUSH_DATA (push, sub_h << 16 | sub_w); |
PUSH_DATA (push, 1 << 20); |
PUSH_DATA (push, 1 << 20); |
BEGIN_NV04(push, NV03_SIFM(SIZE), 4); |
PUSH_DATA (push, align(sub_h, 2) << 16 | align(sub_w, 2)); |
PUSH_DATA (push, src->pitch | |
NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER | |
NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE); |
PUSH_RELOC(push, src->bo, src->offset + (y + sy) * src->pitch + |
(x + sx) * src->cpp, NOUVEAU_BO_LOW, 0, 0); |
PUSH_DATA (push, 0); |
} |
} |
if (context_chipset(ctx) < 0x10) { |
BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1); |
PUSH_DATA (push, hw->surf3d->handle); |
} |
} |
static void |
nv04_surface_copy_m2mf(struct gl_context *ctx, |
struct nouveau_surface *dst, |
struct nouveau_surface *src, |
int dx, int dy, int sx, int sy, |
int w, int h) |
{ |
struct nouveau_pushbuf_refn refs[] = { |
{ src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART }, |
{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART }, |
}; |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; |
struct nv04_fifo *fifo = hw->chan->data; |
unsigned dst_offset = dst->offset + dy * dst->pitch + dx * dst->cpp; |
unsigned src_offset = src->offset + sy * src->pitch + sx * src->cpp; |
while (h) { |
int count = (h > 2047) ? 2047 : h; |
if (nouveau_pushbuf_space(push, 16, 4, 0) || |
nouveau_pushbuf_refn (push, refs, 2)) |
return; |
BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2); |
PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); |
PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); |
BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8); |
PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0); |
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); |
PUSH_DATA (push, src->pitch); |
PUSH_DATA (push, dst->pitch); |
PUSH_DATA (push, w * src->cpp); |
PUSH_DATA (push, count); |
PUSH_DATA (push, 0x0101); |
PUSH_DATA (push, 0); |
src_offset += src->pitch * count; |
dst_offset += dst->pitch * count; |
h -= count; |
} |
} |
typedef unsigned (*get_offset_t)(struct nouveau_surface *s, |
unsigned x, unsigned y); |
static unsigned |
get_linear_offset(struct nouveau_surface *s, unsigned x, unsigned y) |
{ |
return x * s->cpp + y * s->pitch; |
} |
static unsigned |
get_swizzled_offset(struct nouveau_surface *s, unsigned x, unsigned y) |
{ |
unsigned k = log2i(MIN2(s->width, s->height)); |
unsigned u = (x & 0x001) << 0 | |
(x & 0x002) << 1 | |
(x & 0x004) << 2 | |
(x & 0x008) << 3 | |
(x & 0x010) << 4 | |
(x & 0x020) << 5 | |
(x & 0x040) << 6 | |
(x & 0x080) << 7 | |
(x & 0x100) << 8 | |
(x & 0x200) << 9 | |
(x & 0x400) << 10 | |
(x & 0x800) << 11; |
unsigned v = (y & 0x001) << 1 | |
(y & 0x002) << 2 | |
(y & 0x004) << 3 | |
(y & 0x008) << 4 | |
(y & 0x010) << 5 | |
(y & 0x020) << 6 | |
(y & 0x040) << 7 | |
(y & 0x080) << 8 | |
(y & 0x100) << 9 | |
(y & 0x200) << 10 | |
(y & 0x400) << 11 | |
(y & 0x800) << 12; |
return s->cpp * (((u | v) & ~(~0 << 2*k)) | |
(x & (~0 << k)) << k | |
(y & (~0 << k)) << k); |
} |
static void |
nv04_surface_copy_cpu(struct gl_context *ctx, |
struct nouveau_surface *dst, |
struct nouveau_surface *src, |
int dx, int dy, int sx, int sy, |
int w, int h) |
{ |
int x, y; |
get_offset_t get_dst = (dst->layout == SWIZZLED ? |
get_swizzled_offset : get_linear_offset); |
get_offset_t get_src = (src->layout == SWIZZLED ? |
get_swizzled_offset : get_linear_offset); |
void *dp, *sp; |
nouveau_bo_map(dst->bo, NOUVEAU_BO_WR, context_client(ctx)); |
nouveau_bo_map(src->bo, NOUVEAU_BO_RD, context_client(ctx)); |
dp = dst->bo->map + dst->offset; |
sp = src->bo->map + src->offset; |
for (y = 0; y < h; y++) { |
for (x = 0; x < w; x++) { |
memcpy(dp + get_dst(dst, dx + x, dy + y), |
sp + get_src(src, sx + x, sy + y), dst->cpp); |
} |
} |
} |
void |
nv04_surface_copy(struct gl_context *ctx, |
struct nouveau_surface *dst, |
struct nouveau_surface *src, |
int dx, int dy, int sx, int sy, |
int w, int h) |
{ |
if (_mesa_is_format_compressed(src->format)) { |
sx = get_format_blocksx(src->format, sx); |
sy = get_format_blocksy(src->format, sy); |
dx = get_format_blocksx(dst->format, dx); |
dy = get_format_blocksy(dst->format, dy); |
w = get_format_blocksx(src->format, w); |
h = get_format_blocksy(src->format, h); |
} |
/* Linear texture copy. */ |
if ((src->layout == LINEAR && dst->layout == LINEAR) || |
dst->width <= 2 || dst->height <= 1) { |
nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h); |
return; |
} |
/* Swizzle using sifm+swzsurf. */ |
if (src->layout == LINEAR && dst->layout == SWIZZLED && |
dst->cpp != 1 && !(dst->offset & 63)) { |
nv04_surface_copy_swizzle(ctx, dst, src, dx, dy, sx, sy, w, h); |
return; |
} |
/* Fallback to CPU copy. */ |
nv04_surface_copy_cpu(ctx, dst, src, dx, dy, sx, sy, w, h); |
} |
void |
nv04_surface_fill(struct gl_context *ctx, |
struct nouveau_surface *dst, |
unsigned mask, unsigned value, |
int dx, int dy, int w, int h) |
{ |
struct nouveau_pushbuf_refn refs[] = { |
{ dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART }, |
}; |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; |
struct nv04_fifo *fifo = hw->chan->data; |
if (nouveau_pushbuf_space(push, 64, 4, 0) || |
nouveau_pushbuf_refn (push, refs, 1)) |
return; |
BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2); |
PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); |
PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); |
BEGIN_NV04(push, NV04_SF2D(FORMAT), 4); |
PUSH_DATA (push, surf2d_format(dst->format)); |
PUSH_DATA (push, (dst->pitch << 16) | dst->pitch); |
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); |
PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); |
BEGIN_NV04(push, NV01_PATT(COLOR_FORMAT), 1); |
PUSH_DATA (push, rect_format(dst->format)); |
BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR1), 1); |
PUSH_DATA (push, mask | ~0ll << (8 * dst->cpp)); |
BEGIN_NV04(push, NV04_GDI(COLOR_FORMAT), 1); |
PUSH_DATA (push, rect_format(dst->format)); |
BEGIN_NV04(push, NV04_GDI(COLOR1_A), 1); |
PUSH_DATA (push, value); |
BEGIN_NV04(push, NV04_GDI(UNCLIPPED_RECTANGLE_POINT(0)), 2); |
PUSH_DATA (push, (dx << 16) | dy); |
PUSH_DATA (push, ( w << 16) | h); |
} |
void |
nv04_surface_takedown(struct gl_context *ctx) |
{ |
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; |
nouveau_object_del(&hw->swzsurf); |
nouveau_object_del(&hw->sifm); |
nouveau_object_del(&hw->rect); |
nouveau_object_del(&hw->rop); |
nouveau_object_del(&hw->patt); |
nouveau_object_del(&hw->surf2d); |
nouveau_object_del(&hw->m2mf); |
nouveau_object_del(&hw->ntfy); |
} |
GLboolean |
nv04_surface_init(struct gl_context *ctx) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; |
struct nouveau_object *chan = hw->chan; |
unsigned handle = 0x88000000, class; |
int ret; |
/* Notifier object. */ |
ret = nouveau_object_new(chan, handle++, NOUVEAU_NOTIFIER_CLASS, |
&(struct nv04_notify) { |
.length = 32, |
}, sizeof(struct nv04_notify), &hw->ntfy); |
if (ret) |
goto fail; |
/* Memory to memory format. */ |
ret = nouveau_object_new(chan, handle++, NV03_M2MF_CLASS, |
NULL, 0, &hw->m2mf); |
if (ret) |
goto fail; |
BEGIN_NV04(push, NV01_SUBC(M2MF, OBJECT), 1); |
PUSH_DATA (push, hw->m2mf->handle); |
BEGIN_NV04(push, NV03_M2MF(DMA_NOTIFY), 1); |
PUSH_DATA (push, hw->ntfy->handle); |
/* Context surfaces 2D. */ |
if (context_chipset(ctx) < 0x10) |
class = NV04_SURFACE_2D_CLASS; |
else |
class = NV10_SURFACE_2D_CLASS; |
ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->surf2d); |
if (ret) |
goto fail; |
BEGIN_NV04(push, NV01_SUBC(SF2D, OBJECT), 1); |
PUSH_DATA (push, hw->surf2d->handle); |
/* Raster op. */ |
ret = nouveau_object_new(chan, handle++, NV03_ROP_CLASS, |
NULL, 0, &hw->rop); |
if (ret) |
goto fail; |
BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1); |
PUSH_DATA (push, hw->rop->handle); |
BEGIN_NV04(push, NV01_ROP(DMA_NOTIFY), 1); |
PUSH_DATA (push, hw->ntfy->handle); |
BEGIN_NV04(push, NV01_ROP(ROP), 1); |
PUSH_DATA (push, 0xca); /* DPSDxax in the GDI speech. */ |
/* Image pattern. */ |
ret = nouveau_object_new(chan, handle++, NV04_PATTERN_CLASS, |
NULL, 0, &hw->patt); |
if (ret) |
goto fail; |
BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1); |
PUSH_DATA (push, hw->patt->handle); |
BEGIN_NV04(push, NV01_PATT(DMA_NOTIFY), 1); |
PUSH_DATA (push, hw->ntfy->handle); |
BEGIN_NV04(push, NV01_PATT(MONOCHROME_FORMAT), 3); |
PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE); |
PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8); |
PUSH_DATA (push, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO); |
BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR0), 4); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, ~0); |
PUSH_DATA (push, ~0); |
/* GDI rectangle text. */ |
ret = nouveau_object_new(chan, handle++, NV04_GDI_CLASS, |
NULL, 0, &hw->rect); |
if (ret) |
goto fail; |
BEGIN_NV04(push, NV01_SUBC(GDI, OBJECT), 1); |
PUSH_DATA (push, hw->rect->handle); |
BEGIN_NV04(push, NV04_GDI(DMA_NOTIFY), 1); |
PUSH_DATA (push, hw->ntfy->handle); |
BEGIN_NV04(push, NV04_GDI(SURFACE), 1); |
PUSH_DATA (push, hw->surf2d->handle); |
BEGIN_NV04(push, NV04_GDI(ROP), 1); |
PUSH_DATA (push, hw->rop->handle); |
BEGIN_NV04(push, NV04_GDI(PATTERN), 1); |
PUSH_DATA (push, hw->patt->handle); |
BEGIN_NV04(push, NV04_GDI(OPERATION), 1); |
PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND); |
BEGIN_NV04(push, NV04_GDI(MONOCHROME_FORMAT), 1); |
PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE); |
/* Swizzled surface. */ |
if (context_chipset(ctx) < 0x20) |
class = NV04_SURFACE_SWZ_CLASS; |
else |
class = NV20_SURFACE_SWZ_CLASS; |
ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->swzsurf); |
if (ret) |
goto fail; |
BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1); |
PUSH_DATA (push, hw->swzsurf->handle); |
/* Scaled image from memory. */ |
if (context_chipset(ctx) < 0x10) |
class = NV04_SIFM_CLASS; |
else |
class = NV10_SIFM_CLASS; |
ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->sifm); |
if (ret) |
goto fail; |
BEGIN_NV04(push, NV01_SUBC(SIFM, OBJECT), 1); |
PUSH_DATA (push, hw->sifm->handle); |
if (context_chipset(ctx) >= 0x10) { |
BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1); |
PUSH_DATA (push, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE); |
} |
return GL_TRUE; |
fail: |
nv04_surface_takedown(ctx); |
return GL_FALSE; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv10_3d.xml.h |
---|
0,0 → 1,1619 |
#ifndef NV10_3D_XML |
#define NV10_3D_XML |
/* Autogenerated file, DO NOT EDIT manually! |
This file was generated by the rules-ng-ng headergen tool in this git repository: |
http://0x04.net/cgit/index.cgi/rules-ng-ng |
git clone git://0x04.net/rules-ng-ng |
The rules-ng-ng source files this header was generated from are: |
- nv10_3d.xml ( 18437 bytes, from 2010-11-15 15:30:21) |
- copyright.xml ( 6452 bytes, from 2010-11-15 15:10:58) |
- nv_defs.xml ( 4437 bytes, from 2010-11-01 00:28:46) |
- nv_3ddefs.xml ( 16394 bytes, from 2010-11-01 00:28:46) |
- nv_object.xml ( 11547 bytes, from 2010-11-13 23:32:57) |
- nvchipsets.xml ( 3074 bytes, from 2010-11-13 23:32:57) |
Copyright (C) 2006-2010 by the following authors: |
- Artur Huillet <arthur.huillet@free.fr> (ahuillet) |
- Ben Skeggs (darktama, darktama_) |
- B. R. <koala_br@users.sourceforge.net> (koala_br) |
- Carlos Martin <carlosmn@users.sf.net> (carlosmn) |
- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr) |
- Dawid Gajownik <gajownik@users.sf.net> (gajownik) |
- Dmitry Baryshkov |
- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag) |
- EdB <edb_@users.sf.net> (edb_) |
- Erik Waling <erikwailing@users.sf.net> (erikwaling) |
- Francisco Jerez <currojerez@riseup.net> (curro) |
- imirkin <imirkin@users.sf.net> (imirkin) |
- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome) |
- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy) |
- Laurent Carlier <lordheavym@gmail.com> (lordheavy) |
- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1) |
- Maarten Maathuis <madman2003@gmail.com> (stillunknown) |
- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin) |
- Mark Carey <mark.carey@gmail.com> (careym) |
- Matthieu Castet <matthieu.castet@parrot.com> (mat-c) |
- nvidiaman <nvidiaman@users.sf.net> (nvidiaman) |
- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata) |
- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen) |
- Peter Popov <ironpeter@users.sf.net> (ironpeter) |
- Richard Hughes <hughsient@users.sf.net> (hughsient) |
- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar) |
- Serge Martin |
- Simon Raffeiner |
- Stephane Loeuillet <leroutier@users.sf.net> (leroutier) |
- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu) |
- sturmflut <sturmflut@users.sf.net> (sturmflut) |
- Sylvain Munaut <tnt@246tNt.com> |
- Victor Stinner <victor.stinner@haypocalc.com> (haypo) |
- Wladmir van der Laan <laanwj@gmail.com> (miathan6) |
- Younes Manton <younes.m@gmail.com> (ymanton) |
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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
*/ |
#define NV10_VERTEX_ATTR_POS 0x00000000 |
#define NV10_VERTEX_ATTR_COLOR0 0x00000001 |
#define NV10_VERTEX_ATTR_COLOR1 0x00000002 |
#define NV10_VERTEX_ATTR_TEX0 0x00000003 |
#define NV10_VERTEX_ATTR_TEX1 0x00000004 |
#define NV10_VERTEX_ATTR_NORMAL 0x00000005 |
#define NV10_VERTEX_ATTR_WEIGHT 0x00000006 |
#define NV10_VERTEX_ATTR_FOG 0x00000007 |
#define NV11_3D_FLIP_SET_READ 0x00000120 |
#define NV11_3D_FLIP_SET_WRITE 0x00000124 |
#define NV11_3D_FLIP_MAX 0x00000128 |
#define NV11_3D_FLIP_INCR_WRITE 0x0000012c |
#define NV11_3D_FLIP_WAIT 0x00000130 |
#define NV10_3D_DMA_NOTIFY 0x00000180 |
#define NV10_3D_DMA_TEXTURE0 0x00000184 |
#define NV10_3D_DMA_TEXTURE1 0x00000188 |
#define NV10_3D_DMA_COLOR 0x00000194 |
#define NV10_3D_DMA_ZETA 0x00000198 |
#define NV10_3D_RT_HORIZ 0x00000200 |
#define NV10_3D_RT_HORIZ_X__MASK 0x0000ffff |
#define NV10_3D_RT_HORIZ_X__SHIFT 0 |
#define NV10_3D_RT_HORIZ_W__MASK 0xffff0000 |
#define NV10_3D_RT_HORIZ_W__SHIFT 16 |
#define NV10_3D_RT_VERT 0x00000204 |
#define NV10_3D_RT_VERT_Y__MASK 0x0000ffff |
#define NV10_3D_RT_VERT_Y__SHIFT 0 |
#define NV10_3D_RT_VERT_H__MASK 0xffff0000 |
#define NV10_3D_RT_VERT_H__SHIFT 16 |
#define NV10_3D_RT_FORMAT 0x00000208 |
#define NV10_3D_RT_FORMAT_TYPE__MASK 0x00000f00 |
#define NV10_3D_RT_FORMAT_TYPE__SHIFT 8 |
#define NV10_3D_RT_FORMAT_TYPE_LINEAR 0x00000100 |
#define NV10_3D_RT_FORMAT_TYPE_SWIZZLED 0x00000200 |
#define NV10_3D_RT_FORMAT_DEPTH__MASK 0x00000030 |
#define NV10_3D_RT_FORMAT_DEPTH__SHIFT 4 |
#define NV10_3D_RT_FORMAT_DEPTH_Z24S8 0x00000000 |
#define NV10_3D_RT_FORMAT_DEPTH_Z16 0x00000010 |
#define NV10_3D_RT_FORMAT_COLOR__MASK 0x0000000f |
#define NV10_3D_RT_FORMAT_COLOR__SHIFT 0 |
#define NV10_3D_RT_FORMAT_COLOR_R5G6B5 0x00000003 |
#define NV10_3D_RT_FORMAT_COLOR_X8R8G8B8 0x00000005 |
#define NV10_3D_RT_FORMAT_COLOR_A8R8G8B8 0x00000008 |
#define NV10_3D_RT_FORMAT_COLOR_B8 0x00000009 |
#define NV10_3D_RT_PITCH 0x0000020c |
#define NV10_3D_RT_PITCH_COLOR_PITCH__MASK 0x0000ffff |
#define NV10_3D_RT_PITCH_COLOR_PITCH__SHIFT 0 |
#define NV10_3D_RT_PITCH_ZETA_PITCH__MASK 0xffff0000 |
#define NV10_3D_RT_PITCH_ZETA_PITCH__SHIFT 16 |
#define NV10_3D_COLOR_OFFSET 0x00000210 |
#define NV10_3D_ZETA_OFFSET 0x00000214 |
#define NV10_3D_UNK0290 0x00000290 |
#define NV10_3D_VIEWPORT_CLIP_MODE 0x000002b4 |
#define NV10_3D_VIEWPORT_CLIP_HORIZ(i0) (0x000002c0 + 0x4*(i0)) |
#define NV10_3D_VIEWPORT_CLIP_HORIZ__ESIZE 0x00000004 |
#define NV10_3D_VIEWPORT_CLIP_HORIZ__LEN 0x00000008 |
#define NV10_3D_VIEWPORT_CLIP_HORIZ_CLIP_L__MASK 0x000007ff |
#define NV10_3D_VIEWPORT_CLIP_HORIZ_CLIP_L__SHIFT 0 |
#define NV10_3D_VIEWPORT_CLIP_HORIZ_CLIP_LEFT_ENABLE 0x00000800 |
#define NV10_3D_VIEWPORT_CLIP_HORIZ_CLIP_R__MASK 0x07ff0000 |
#define NV10_3D_VIEWPORT_CLIP_HORIZ_CLIP_R__SHIFT 16 |
#define NV10_3D_VIEWPORT_CLIP_HORIZ_CLIP_RIGHT_ENABLE 0x08000000 |
#define NV10_3D_VIEWPORT_CLIP_VERT(i0) (0x000002e0 + 0x4*(i0)) |
#define NV10_3D_VIEWPORT_CLIP_VERT__ESIZE 0x00000004 |
#define NV10_3D_VIEWPORT_CLIP_VERT__LEN 0x00000008 |
#define NV10_3D_VIEWPORT_CLIP_VERT_CLIP_T__MASK 0x000007ff |
#define NV10_3D_VIEWPORT_CLIP_VERT_CLIP_T__SHIFT 0 |
#define NV10_3D_VIEWPORT_CLIP_VERT_CLIP_TOP_ENABLE 0x00000800 |
#define NV10_3D_VIEWPORT_CLIP_VERT_CLIP_B__MASK 0x07ff0000 |
#define NV10_3D_VIEWPORT_CLIP_VERT_CLIP_B__SHIFT 16 |
#define NV10_3D_VIEWPORT_CLIP_VERT_CLIP_BOTTOM_ENABLE 0x08000000 |
#define NV10_3D_ALPHA_FUNC_ENABLE 0x00000300 |
#define NV10_3D_BLEND_FUNC_ENABLE 0x00000304 |
#define NV10_3D_CULL_FACE_ENABLE 0x00000308 |
#define NV10_3D_DEPTH_TEST_ENABLE 0x0000030c |
#define NV10_3D_DITHER_ENABLE 0x00000310 |
#define NV10_3D_LIGHTING_ENABLE 0x00000314 |
#define NV10_3D_POINT_PARAMETERS_ENABLE 0x00000318 |
#define NV10_3D_POINT_SMOOTH_ENABLE 0x0000031c |
#define NV10_3D_LINE_SMOOTH_ENABLE 0x00000320 |
#define NV10_3D_POLYGON_SMOOTH_ENABLE 0x00000324 |
#define NV10_3D_STENCIL_ENABLE 0x0000032c |
#define NV10_3D_POLYGON_OFFSET_POINT_ENABLE 0x00000330 |
#define NV10_3D_POLYGON_OFFSET_LINE_ENABLE 0x00000334 |
#define NV10_3D_POLYGON_OFFSET_FILL_ENABLE 0x00000338 |
#define NV10_3D_ALPHA_FUNC_FUNC 0x0000033c |
#define NV10_3D_ALPHA_FUNC_FUNC_NEVER 0x00000200 |
#define NV10_3D_ALPHA_FUNC_FUNC_LESS 0x00000201 |
#define NV10_3D_ALPHA_FUNC_FUNC_EQUAL 0x00000202 |
#define NV10_3D_ALPHA_FUNC_FUNC_LEQUAL 0x00000203 |
#define NV10_3D_ALPHA_FUNC_FUNC_GREATER 0x00000204 |
#define NV10_3D_ALPHA_FUNC_FUNC_NOTEQUAL 0x00000205 |
#define NV10_3D_ALPHA_FUNC_FUNC_GEQUAL 0x00000206 |
#define NV10_3D_ALPHA_FUNC_FUNC_ALWAYS 0x00000207 |
#define NV10_3D_ALPHA_FUNC_REF 0x00000340 |
#define NV10_3D_BLEND_FUNC_SRC 0x00000344 |
#define NV10_3D_BLEND_FUNC_SRC_ZERO 0x00000000 |
#define NV10_3D_BLEND_FUNC_SRC_ONE 0x00000001 |
#define NV10_3D_BLEND_FUNC_SRC_SRC_COLOR 0x00000300 |
#define NV10_3D_BLEND_FUNC_SRC_ONE_MINUS_SRC_COLOR 0x00000301 |
#define NV10_3D_BLEND_FUNC_SRC_SRC_ALPHA 0x00000302 |
#define NV10_3D_BLEND_FUNC_SRC_ONE_MINUS_SRC_ALPHA 0x00000303 |
#define NV10_3D_BLEND_FUNC_SRC_DST_ALPHA 0x00000304 |
#define NV10_3D_BLEND_FUNC_SRC_ONE_MINUS_DST_ALPHA 0x00000305 |
#define NV10_3D_BLEND_FUNC_SRC_DST_COLOR 0x00000306 |
#define NV10_3D_BLEND_FUNC_SRC_ONE_MINUS_DST_COLOR 0x00000307 |
#define NV10_3D_BLEND_FUNC_SRC_SRC_ALPHA_SATURATE 0x00000308 |
#define NV10_3D_BLEND_FUNC_SRC_CONSTANT_COLOR 0x00008001 |
#define NV10_3D_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_COLOR 0x00008002 |
#define NV10_3D_BLEND_FUNC_SRC_CONSTANT_ALPHA 0x00008003 |
#define NV10_3D_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_ALPHA 0x00008004 |
#define NV10_3D_BLEND_FUNC_DST 0x00000348 |
#define NV10_3D_BLEND_FUNC_DST_ZERO 0x00000000 |
#define NV10_3D_BLEND_FUNC_DST_ONE 0x00000001 |
#define NV10_3D_BLEND_FUNC_DST_SRC_COLOR 0x00000300 |
#define NV10_3D_BLEND_FUNC_DST_ONE_MINUS_SRC_COLOR 0x00000301 |
#define NV10_3D_BLEND_FUNC_DST_SRC_ALPHA 0x00000302 |
#define NV10_3D_BLEND_FUNC_DST_ONE_MINUS_SRC_ALPHA 0x00000303 |
#define NV10_3D_BLEND_FUNC_DST_DST_ALPHA 0x00000304 |
#define NV10_3D_BLEND_FUNC_DST_ONE_MINUS_DST_ALPHA 0x00000305 |
#define NV10_3D_BLEND_FUNC_DST_DST_COLOR 0x00000306 |
#define NV10_3D_BLEND_FUNC_DST_ONE_MINUS_DST_COLOR 0x00000307 |
#define NV10_3D_BLEND_FUNC_DST_SRC_ALPHA_SATURATE 0x00000308 |
#define NV10_3D_BLEND_FUNC_DST_CONSTANT_COLOR 0x00008001 |
#define NV10_3D_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_COLOR 0x00008002 |
#define NV10_3D_BLEND_FUNC_DST_CONSTANT_ALPHA 0x00008003 |
#define NV10_3D_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_ALPHA 0x00008004 |
#define NV10_3D_BLEND_COLOR 0x0000034c |
#define NV10_3D_BLEND_COLOR_B__MASK 0x000000ff |
#define NV10_3D_BLEND_COLOR_B__SHIFT 0 |
#define NV10_3D_BLEND_COLOR_G__MASK 0x0000ff00 |
#define NV10_3D_BLEND_COLOR_G__SHIFT 8 |
#define NV10_3D_BLEND_COLOR_R__MASK 0x00ff0000 |
#define NV10_3D_BLEND_COLOR_R__SHIFT 16 |
#define NV10_3D_BLEND_COLOR_A__MASK 0xff000000 |
#define NV10_3D_BLEND_COLOR_A__SHIFT 24 |
#define NV10_3D_BLEND_EQUATION 0x00000350 |
#define NV10_3D_BLEND_EQUATION_FUNC_ADD 0x00008006 |
#define NV10_3D_BLEND_EQUATION_MIN 0x00008007 |
#define NV10_3D_BLEND_EQUATION_MAX 0x00008008 |
#define NV10_3D_BLEND_EQUATION_FUNC_SUBTRACT 0x0000800a |
#define NV10_3D_BLEND_EQUATION_FUNC_REVERSE_SUBTRACT 0x0000800b |
#define NV10_3D_DEPTH_FUNC 0x00000354 |
#define NV10_3D_DEPTH_FUNC_NEVER 0x00000200 |
#define NV10_3D_DEPTH_FUNC_LESS 0x00000201 |
#define NV10_3D_DEPTH_FUNC_EQUAL 0x00000202 |
#define NV10_3D_DEPTH_FUNC_LEQUAL 0x00000203 |
#define NV10_3D_DEPTH_FUNC_GREATER 0x00000204 |
#define NV10_3D_DEPTH_FUNC_NOTEQUAL 0x00000205 |
#define NV10_3D_DEPTH_FUNC_GEQUAL 0x00000206 |
#define NV10_3D_DEPTH_FUNC_ALWAYS 0x00000207 |
#define NV10_3D_COLOR_MASK 0x00000358 |
#define NV10_3D_COLOR_MASK_B 0x00000001 |
#define NV10_3D_COLOR_MASK_G 0x00000100 |
#define NV10_3D_COLOR_MASK_R 0x00010000 |
#define NV10_3D_COLOR_MASK_A 0x01000000 |
#define NV10_3D_DEPTH_WRITE_ENABLE 0x0000035c |
#define NV10_3D_STENCIL_MASK 0x00000360 |
#define NV10_3D_STENCIL_FUNC_FUNC 0x00000364 |
#define NV10_3D_STENCIL_FUNC_FUNC_NEVER 0x00000200 |
#define NV10_3D_STENCIL_FUNC_FUNC_LESS 0x00000201 |
#define NV10_3D_STENCIL_FUNC_FUNC_EQUAL 0x00000202 |
#define NV10_3D_STENCIL_FUNC_FUNC_LEQUAL 0x00000203 |
#define NV10_3D_STENCIL_FUNC_FUNC_GREATER 0x00000204 |
#define NV10_3D_STENCIL_FUNC_FUNC_NOTEQUAL 0x00000205 |
#define NV10_3D_STENCIL_FUNC_FUNC_GEQUAL 0x00000206 |
#define NV10_3D_STENCIL_FUNC_FUNC_ALWAYS 0x00000207 |
#define NV10_3D_STENCIL_FUNC_REF 0x00000368 |
#define NV10_3D_STENCIL_FUNC_MASK 0x0000036c |
#define NV10_3D_STENCIL_OP_FAIL 0x00000370 |
#define NV10_3D_STENCIL_OP_FAIL_ZERO 0x00000000 |
#define NV10_3D_STENCIL_OP_FAIL_INVERT 0x0000150a |
#define NV10_3D_STENCIL_OP_FAIL_KEEP 0x00001e00 |
#define NV10_3D_STENCIL_OP_FAIL_REPLACE 0x00001e01 |
#define NV10_3D_STENCIL_OP_FAIL_INCR 0x00001e02 |
#define NV10_3D_STENCIL_OP_FAIL_DECR 0x00001e03 |
#define NV10_3D_STENCIL_OP_FAIL_INCR_WRAP 0x00008507 |
#define NV10_3D_STENCIL_OP_FAIL_DECR_WRAP 0x00008508 |
#define NV10_3D_STENCIL_OP_ZFAIL 0x00000374 |
#define NV10_3D_STENCIL_OP_ZFAIL_ZERO 0x00000000 |
#define NV10_3D_STENCIL_OP_ZFAIL_INVERT 0x0000150a |
#define NV10_3D_STENCIL_OP_ZFAIL_KEEP 0x00001e00 |
#define NV10_3D_STENCIL_OP_ZFAIL_REPLACE 0x00001e01 |
#define NV10_3D_STENCIL_OP_ZFAIL_INCR 0x00001e02 |
#define NV10_3D_STENCIL_OP_ZFAIL_DECR 0x00001e03 |
#define NV10_3D_STENCIL_OP_ZFAIL_INCR_WRAP 0x00008507 |
#define NV10_3D_STENCIL_OP_ZFAIL_DECR_WRAP 0x00008508 |
#define NV10_3D_STENCIL_OP_ZPASS 0x00000378 |
#define NV10_3D_STENCIL_OP_ZPASS_ZERO 0x00000000 |
#define NV10_3D_STENCIL_OP_ZPASS_INVERT 0x0000150a |
#define NV10_3D_STENCIL_OP_ZPASS_KEEP 0x00001e00 |
#define NV10_3D_STENCIL_OP_ZPASS_REPLACE 0x00001e01 |
#define NV10_3D_STENCIL_OP_ZPASS_INCR 0x00001e02 |
#define NV10_3D_STENCIL_OP_ZPASS_DECR 0x00001e03 |
#define NV10_3D_STENCIL_OP_ZPASS_INCR_WRAP 0x00008507 |
#define NV10_3D_STENCIL_OP_ZPASS_DECR_WRAP 0x00008508 |
#define NV10_3D_SHADE_MODEL 0x0000037c |
#define NV10_3D_SHADE_MODEL_FLAT 0x00001d00 |
#define NV10_3D_SHADE_MODEL_SMOOTH 0x00001d01 |
#define NV10_3D_LINE_WIDTH 0x00000380 |
#define NV10_3D_POLYGON_OFFSET_FACTOR 0x00000384 |
#define NV10_3D_POLYGON_OFFSET_UNITS 0x00000388 |
#define NV10_3D_POLYGON_MODE_FRONT 0x0000038c |
#define NV10_3D_POLYGON_MODE_FRONT_POINT 0x00001b00 |
#define NV10_3D_POLYGON_MODE_FRONT_LINE 0x00001b01 |
#define NV10_3D_POLYGON_MODE_FRONT_FILL 0x00001b02 |
#define NV10_3D_POLYGON_MODE_BACK 0x00000390 |
#define NV10_3D_POLYGON_MODE_BACK_POINT 0x00001b00 |
#define NV10_3D_POLYGON_MODE_BACK_LINE 0x00001b01 |
#define NV10_3D_POLYGON_MODE_BACK_FILL 0x00001b02 |
#define NV10_3D_DEPTH_RANGE_NEAR 0x00000394 |
#define NV10_3D_DEPTH_RANGE_FAR 0x00000398 |
#define NV10_3D_CULL_FACE 0x0000039c |
#define NV10_3D_CULL_FACE_FRONT 0x00000404 |
#define NV10_3D_CULL_FACE_BACK 0x00000405 |
#define NV10_3D_CULL_FACE_FRONT_AND_BACK 0x00000408 |
#define NV10_3D_FRONT_FACE 0x000003a0 |
#define NV10_3D_FRONT_FACE_CW 0x00000900 |
#define NV10_3D_FRONT_FACE_CCW 0x00000901 |
#define NV10_3D_VERTEX_POS_3F 0x00000c00 |
#define NV10_3D_VERTEX_POS_3F_X 0x00000c00 |
#define NV10_3D_VERTEX_POS_3F_Y 0x00000c04 |
#define NV10_3D_VERTEX_POS_3F_Z 0x00000c08 |
#define NV10_3D_VERTEX_POS_4F 0x00000c18 |
#define NV10_3D_VERTEX_POS_4F_X 0x00000c18 |
#define NV10_3D_VERTEX_POS_4F_Y 0x00000c1c |
#define NV10_3D_VERTEX_POS_4F_Z 0x00000c20 |
#define NV10_3D_VERTEX_POS_4F_W 0x00000c24 |
#define NV10_3D_VERTEX_NOR_3F 0x00000c30 |
#define NV10_3D_VERTEX_NOR_3F_X 0x00000c30 |
#define NV10_3D_VERTEX_NOR_3F_Y 0x00000c34 |
#define NV10_3D_VERTEX_NOR_3F_Z 0x00000c38 |
#define NV10_3D_VERTEX_NOR_3I 0x00000c30 |
#define NV10_3D_VERTEX_NOR_3I_XY 0x00000c30 |
#define NV10_3D_VERTEX_NOR_3I_XY_X__MASK 0x0000ffff |
#define NV10_3D_VERTEX_NOR_3I_XY_X__SHIFT 0 |
#define NV10_3D_VERTEX_NOR_3I_XY_Y__MASK 0xffff0000 |
#define NV10_3D_VERTEX_NOR_3I_XY_Y__SHIFT 16 |
#define NV10_3D_VERTEX_NOR_3I_Z 0x00000c34 |
#define NV10_3D_VERTEX_NOR_3I_Z_Z__MASK 0x0000ffff |
#define NV10_3D_VERTEX_NOR_3I_Z_Z__SHIFT 0 |
#define NV10_3D_VERTEX_COL_4F 0x00000c50 |
#define NV10_3D_VERTEX_COL_4F_R 0x00000c50 |
#define NV10_3D_VERTEX_COL_4F_G 0x00000c54 |
#define NV10_3D_VERTEX_COL_4F_B 0x00000c58 |
#define NV10_3D_VERTEX_COL_4F_A 0x00000c5c |
#define NV10_3D_VERTEX_COL_3F 0x00000c60 |
#define NV10_3D_VERTEX_COL_3F_R 0x00000c60 |
#define NV10_3D_VERTEX_COL_3F_G 0x00000c64 |
#define NV10_3D_VERTEX_COL_3F_B 0x00000c68 |
#define NV10_3D_VERTEX_COL_4I 0x00000c6c |
#define NV10_3D_VERTEX_COL_4I_R__MASK 0x000000ff |
#define NV10_3D_VERTEX_COL_4I_R__SHIFT 0 |
#define NV10_3D_VERTEX_COL_4I_G__MASK 0x0000ff00 |
#define NV10_3D_VERTEX_COL_4I_G__SHIFT 8 |
#define NV10_3D_VERTEX_COL_4I_B__MASK 0x00ff0000 |
#define NV10_3D_VERTEX_COL_4I_B__SHIFT 16 |
#define NV10_3D_VERTEX_COL_4I_A__MASK 0xff000000 |
#define NV10_3D_VERTEX_COL_4I_A__SHIFT 24 |
#define NV10_3D_VERTEX_COL2_3F 0x00000c80 |
#define NV10_3D_VERTEX_COL2_3F_R 0x00000c80 |
#define NV10_3D_VERTEX_COL2_3F_G 0x00000c84 |
#define NV10_3D_VERTEX_COL2_3F_B 0x00000c88 |
#define NV10_3D_VERTEX_COL2_3I 0x00000c8c |
#define NV10_3D_VERTEX_COL2_3I_R__MASK 0x000000ff |
#define NV10_3D_VERTEX_COL2_3I_R__SHIFT 0 |
#define NV10_3D_VERTEX_COL2_3I_G__MASK 0x0000ff00 |
#define NV10_3D_VERTEX_COL2_3I_G__SHIFT 8 |
#define NV10_3D_VERTEX_COL2_3I_B__MASK 0x00ff0000 |
#define NV10_3D_VERTEX_COL2_3I_B__SHIFT 16 |
#define NV10_3D_VERTEX_TX0_2F 0x00000c90 |
#define NV10_3D_VERTEX_TX0_2F_S 0x00000c90 |
#define NV10_3D_VERTEX_TX0_2F_T 0x00000c94 |
#define NV10_3D_VERTEX_TX0_2I 0x00000c98 |
#define NV10_3D_VERTEX_TX0_2I_S__MASK 0x0000ffff |
#define NV10_3D_VERTEX_TX0_2I_S__SHIFT 0 |
#define NV10_3D_VERTEX_TX0_2I_T__MASK 0xffff0000 |
#define NV10_3D_VERTEX_TX0_2I_T__SHIFT 16 |
#define NV10_3D_VERTEX_TX0_4F 0x00000ca0 |
#define NV10_3D_VERTEX_TX0_4F_S 0x00000ca0 |
#define NV10_3D_VERTEX_TX0_4F_T 0x00000ca4 |
#define NV10_3D_VERTEX_TX0_4F_R 0x00000ca8 |
#define NV10_3D_VERTEX_TX0_4F_Q 0x00000cac |
#define NV10_3D_VERTEX_TX0_4I 0x00000cb0 |
#define NV10_3D_VERTEX_TX0_4I_ST 0x00000cb0 |
#define NV10_3D_VERTEX_TX0_4I_ST_S__MASK 0x0000ffff |
#define NV10_3D_VERTEX_TX0_4I_ST_S__SHIFT 0 |
#define NV10_3D_VERTEX_TX0_4I_ST_T__MASK 0xffff0000 |
#define NV10_3D_VERTEX_TX0_4I_ST_T__SHIFT 16 |
#define NV10_3D_VERTEX_TX0_4I_RQ 0x00000cb4 |
#define NV10_3D_VERTEX_TX0_4I_RQ_R__MASK 0x0000ffff |
#define NV10_3D_VERTEX_TX0_4I_RQ_R__SHIFT 0 |
#define NV10_3D_VERTEX_TX0_4I_RQ_Q__MASK 0xffff0000 |
#define NV10_3D_VERTEX_TX0_4I_RQ_Q__SHIFT 16 |
#define NV10_3D_VERTEX_TX1_2F 0x00000cb8 |
#define NV10_3D_VERTEX_TX1_2F_S 0x00000cb8 |
#define NV10_3D_VERTEX_TX1_2F_T 0x00000cbc |
#define NV10_3D_VERTEX_TX1_2I 0x00000cc0 |
#define NV10_3D_VERTEX_TX1_2I_S__MASK 0x0000ffff |
#define NV10_3D_VERTEX_TX1_2I_S__SHIFT 0 |
#define NV10_3D_VERTEX_TX1_2I_T__MASK 0xffff0000 |
#define NV10_3D_VERTEX_TX1_2I_T__SHIFT 16 |
#define NV10_3D_VERTEX_TX1_4F 0x00000cc8 |
#define NV10_3D_VERTEX_TX1_4F_S 0x00000cc8 |
#define NV10_3D_VERTEX_TX1_4F_T 0x00000ccc |
#define NV10_3D_VERTEX_TX1_4F_R 0x00000cd0 |
#define NV10_3D_VERTEX_TX1_4F_Q 0x00000cd4 |
#define NV10_3D_VERTEX_TX1_4I 0x00000cd8 |
#define NV10_3D_VERTEX_TX1_4I_ST 0x00000cd8 |
#define NV10_3D_VERTEX_TX1_4I_ST_S__MASK 0x0000ffff |
#define NV10_3D_VERTEX_TX1_4I_ST_S__SHIFT 0 |
#define NV10_3D_VERTEX_TX1_4I_ST_T__MASK 0xffff0000 |
#define NV10_3D_VERTEX_TX1_4I_ST_T__SHIFT 16 |
#define NV10_3D_VERTEX_TX1_4I_RQ 0x00000cdc |
#define NV10_3D_VERTEX_TX1_4I_RQ_R__MASK 0x0000ffff |
#define NV10_3D_VERTEX_TX1_4I_RQ_R__SHIFT 0 |
#define NV10_3D_VERTEX_TX1_4I_RQ_Q__MASK 0xffff0000 |
#define NV10_3D_VERTEX_TX1_4I_RQ_Q__SHIFT 16 |
#define NV10_3D_VERTEX_FOG_1F 0x00000ce0 |
#define NV10_3D_VERTEX_WGH_1F 0x00000ce4 |
#define NV10_3D_EDGEFLAG_ENABLE 0x00000cec |
#define NV10_3D_DMA_VTXBUF 0x0000018c |
#define NV10_3D_VTXBUF_VALIDATE 0x00000cf0 |
#define NV10_3D_VTXBUF_OFFSET(i0) (0x00000d00 + 0x8*(i0)) |
#define NV10_3D_VTXBUF_FMT(i0) (0x00000d04 + 0x8*(i0)) |
#define NV10_3D_VTXBUF_FMT_TYPE__MASK 0x0000000f |
#define NV10_3D_VTXBUF_FMT_TYPE__SHIFT 0 |
#define NV10_3D_VTXBUF_FMT_TYPE_B8G8R8A8_UNORM 0x00000000 |
#define NV10_3D_VTXBUF_FMT_TYPE_V16_SNORM 0x00000001 |
#define NV10_3D_VTXBUF_FMT_TYPE_V32_FLOAT 0x00000002 |
#define NV10_3D_VTXBUF_FMT_TYPE_U8_UNORM 0x00000004 |
#define NV10_3D_VTXBUF_FMT_FIELDS__MASK 0x000000f0 |
#define NV10_3D_VTXBUF_FMT_FIELDS__SHIFT 4 |
#define NV10_3D_VTXBUF_FMT_STRIDE__MASK 0x0000ff00 |
#define NV10_3D_VTXBUF_FMT_STRIDE__SHIFT 8 |
#define NV10_3D_VTXBUF_FMT_HOMOGENEOUS 0x01000000 |
#define NV10_3D_VERTEX_BEGIN_END 0x00000dfc |
#define NV10_3D_VERTEX_BEGIN_END_STOP 0x00000000 |
#define NV10_3D_VERTEX_BEGIN_END_POINTS 0x00000001 |
#define NV10_3D_VERTEX_BEGIN_END_LINES 0x00000002 |
#define NV10_3D_VERTEX_BEGIN_END_LINE_LOOP 0x00000003 |
#define NV10_3D_VERTEX_BEGIN_END_LINE_STRIP 0x00000004 |
#define NV10_3D_VERTEX_BEGIN_END_TRIANGLES 0x00000005 |
#define NV10_3D_VERTEX_BEGIN_END_TRIANGLE_STRIP 0x00000006 |
#define NV10_3D_VERTEX_BEGIN_END_TRIANGLE_FAN 0x00000007 |
#define NV10_3D_VERTEX_BEGIN_END_QUADS 0x00000008 |
#define NV10_3D_VERTEX_BEGIN_END_QUAD_STRIP 0x00000009 |
#define NV10_3D_VERTEX_BEGIN_END_POLYGON 0x0000000a |
#define NV10_3D_VTXBUF_ELEMENT_U16 0x00000e00 |
#define NV10_3D_VTXBUF_ELEMENT_U16_I0__MASK 0x0000ffff |
#define NV10_3D_VTXBUF_ELEMENT_U16_I0__SHIFT 0 |
#define NV10_3D_VTXBUF_ELEMENT_U16_I1__MASK 0xffff0000 |
#define NV10_3D_VTXBUF_ELEMENT_U16_I1__SHIFT 16 |
#define NV10_3D_VTXBUF_ELEMENT_U32 0x00001100 |
#define NV10_3D_VTXBUF_BEGIN_END 0x000013fc |
#define NV10_3D_VTXBUF_BEGIN_END_STOP 0x00000000 |
#define NV10_3D_VTXBUF_BEGIN_END_POINTS 0x00000001 |
#define NV10_3D_VTXBUF_BEGIN_END_LINES 0x00000002 |
#define NV10_3D_VTXBUF_BEGIN_END_LINE_LOOP 0x00000003 |
#define NV10_3D_VTXBUF_BEGIN_END_LINE_STRIP 0x00000004 |
#define NV10_3D_VTXBUF_BEGIN_END_TRIANGLES 0x00000005 |
#define NV10_3D_VTXBUF_BEGIN_END_TRIANGLE_STRIP 0x00000006 |
#define NV10_3D_VTXBUF_BEGIN_END_TRIANGLE_FAN 0x00000007 |
#define NV10_3D_VTXBUF_BEGIN_END_QUADS 0x00000008 |
#define NV10_3D_VTXBUF_BEGIN_END_QUAD_STRIP 0x00000009 |
#define NV10_3D_VTXBUF_BEGIN_END_POLYGON 0x0000000a |
#define NV10_3D_VTXBUF_BATCH 0x00001400 |
#define NV10_3D_VTXBUF_BATCH_FIRST__MASK 0x0000ffff |
#define NV10_3D_VTXBUF_BATCH_FIRST__SHIFT 0 |
#define NV10_3D_VTXBUF_BATCH_LAST__MASK 0xff000000 |
#define NV10_3D_VTXBUF_BATCH_LAST__SHIFT 24 |
#define NV10_3D_VTXBUF_DATA 0x00001800 |
#define NV10_3D_VERTEX_WEIGHT_ENABLE 0x00000328 |
#define NV10_3D_VIEW_MATRIX_ENABLE 0x000003e8 |
#define NV10_3D_VIEW_MATRIX_ENABLE_MODELVIEW1 0x00000001 |
#define NV10_3D_VIEW_MATRIX_ENABLE_MODELVIEW0 0x00000002 |
#define NV10_3D_VIEW_MATRIX_ENABLE_PROJECTION 0x00000004 |
#define NV10_3D_MODELVIEW_MATRIX(i0, i1) (0x00000400 + 0x40*(i0) + 0x4*(i1)) |
#define NV10_3D_MODELVIEW_MATRIX__ESIZE 0x00000004 |
#define NV10_3D_MODELVIEW_MATRIX__LEN 0x00000010 |
#define NV10_3D_INVERSE_MODELVIEW_MATRIX(i0, i1) (0x00000480 + 0x40*(i0) + 0x4*(i1)) |
#define NV10_3D_INVERSE_MODELVIEW_MATRIX__ESIZE 0x00000004 |
#define NV10_3D_INVERSE_MODELVIEW_MATRIX__LEN 0x0000000c |
#define NV10_3D_PROJECTION_MATRIX(i0) (0x00000500 + 0x4*(i0)) |
#define NV10_3D_PROJECTION_MATRIX__ESIZE 0x00000004 |
#define NV10_3D_PROJECTION_MATRIX__LEN 0x00000010 |
#define NV10_3D_VIEWPORT_TRANSLATE 0x000006e8 |
#define NV10_3D_VIEWPORT_TRANSLATE_X 0x000006e8 |
#define NV10_3D_VIEWPORT_TRANSLATE_Y 0x000006ec |
#define NV10_3D_VIEWPORT_TRANSLATE_Z 0x000006f0 |
#define NV10_3D_VIEWPORT_TRANSLATE_W 0x000006f4 |
#define NV10_3D_LIGHT_MODEL 0x00000294 |
#define NV10_3D_LIGHT_MODEL_VERTEX_SPECULAR 0x00000001 |
#define NV10_3D_LIGHT_MODEL_SEPARATE_SPECULAR 0x00000002 |
#define NV10_3D_LIGHT_MODEL_LOCAL_VIEWER 0x00010000 |
#define NV10_3D_COLOR_MATERIAL 0x00000298 |
#define NV10_3D_COLOR_MATERIAL_EMISSION 0x00000001 |
#define NV10_3D_COLOR_MATERIAL_AMBIENT 0x00000002 |
#define NV10_3D_COLOR_MATERIAL_DIFFUSE 0x00000004 |
#define NV10_3D_COLOR_MATERIAL_SPECULAR 0x00000008 |
#define NV10_3D_MATERIAL_FACTOR 0x000003a8 |
#define NV10_3D_MATERIAL_FACTOR_R 0x000003a8 |
#define NV10_3D_MATERIAL_FACTOR_G 0x000003ac |
#define NV10_3D_MATERIAL_FACTOR_B 0x000003b0 |
#define NV10_3D_MATERIAL_FACTOR_A 0x000003b4 |
#define NV10_3D_NORMALIZE_ENABLE 0x000003a4 |
#define NV10_3D_SEPARATE_SPECULAR_ENABLE 0x000003b8 |
#define NV10_3D_ENABLED_LIGHTS 0x000003bc |
#define NV10_3D_ENABLED_LIGHTS_0__MASK 0x00000003 |
#define NV10_3D_ENABLED_LIGHTS_0__SHIFT 0 |
#define NV10_3D_ENABLED_LIGHTS_0_DISABLED 0x00000000 |
#define NV10_3D_ENABLED_LIGHTS_0_NONPOSITIONAL 0x00000001 |
#define NV10_3D_ENABLED_LIGHTS_0_POSITIONAL 0x00000002 |
#define NV10_3D_ENABLED_LIGHTS_0_DIRECTIONAL 0x00000003 |
#define NV10_3D_ENABLED_LIGHTS_1__MASK 0x0000000c |
#define NV10_3D_ENABLED_LIGHTS_1__SHIFT 2 |
#define NV10_3D_ENABLED_LIGHTS_1_DISABLED 0x00000000 |
#define NV10_3D_ENABLED_LIGHTS_1_NONPOSITIONAL 0x00000004 |
#define NV10_3D_ENABLED_LIGHTS_1_POSITIONAL 0x00000008 |
#define NV10_3D_ENABLED_LIGHTS_1_DIRECTIONAL 0x0000000c |
#define NV10_3D_ENABLED_LIGHTS_2__MASK 0x00000030 |
#define NV10_3D_ENABLED_LIGHTS_2__SHIFT 4 |
#define NV10_3D_ENABLED_LIGHTS_2_DISABLED 0x00000000 |
#define NV10_3D_ENABLED_LIGHTS_2_NONPOSITIONAL 0x00000010 |
#define NV10_3D_ENABLED_LIGHTS_2_POSITIONAL 0x00000020 |
#define NV10_3D_ENABLED_LIGHTS_2_DIRECTIONAL 0x00000030 |
#define NV10_3D_ENABLED_LIGHTS_3__MASK 0x000000c0 |
#define NV10_3D_ENABLED_LIGHTS_3__SHIFT 6 |
#define NV10_3D_ENABLED_LIGHTS_3_DISABLED 0x00000000 |
#define NV10_3D_ENABLED_LIGHTS_3_NONPOSITIONAL 0x00000040 |
#define NV10_3D_ENABLED_LIGHTS_3_POSITIONAL 0x00000080 |
#define NV10_3D_ENABLED_LIGHTS_3_DIRECTIONAL 0x000000c0 |
#define NV10_3D_ENABLED_LIGHTS_4__MASK 0x00000300 |
#define NV10_3D_ENABLED_LIGHTS_4__SHIFT 8 |
#define NV10_3D_ENABLED_LIGHTS_4_DISABLED 0x00000000 |
#define NV10_3D_ENABLED_LIGHTS_4_NONPOSITIONAL 0x00000100 |
#define NV10_3D_ENABLED_LIGHTS_4_POSITIONAL 0x00000200 |
#define NV10_3D_ENABLED_LIGHTS_4_DIRECTIONAL 0x00000300 |
#define NV10_3D_ENABLED_LIGHTS_5__MASK 0x00000c00 |
#define NV10_3D_ENABLED_LIGHTS_5__SHIFT 10 |
#define NV10_3D_ENABLED_LIGHTS_5_DISABLED 0x00000000 |
#define NV10_3D_ENABLED_LIGHTS_5_NONPOSITIONAL 0x00000400 |
#define NV10_3D_ENABLED_LIGHTS_5_POSITIONAL 0x00000800 |
#define NV10_3D_ENABLED_LIGHTS_5_DIRECTIONAL 0x00000c00 |
#define NV10_3D_ENABLED_LIGHTS_6__MASK 0x00003000 |
#define NV10_3D_ENABLED_LIGHTS_6__SHIFT 12 |
#define NV10_3D_ENABLED_LIGHTS_6_DISABLED 0x00000000 |
#define NV10_3D_ENABLED_LIGHTS_6_NONPOSITIONAL 0x00001000 |
#define NV10_3D_ENABLED_LIGHTS_6_POSITIONAL 0x00002000 |
#define NV10_3D_ENABLED_LIGHTS_6_DIRECTIONAL 0x00003000 |
#define NV10_3D_ENABLED_LIGHTS_7__MASK 0x0000c000 |
#define NV10_3D_ENABLED_LIGHTS_7__SHIFT 14 |
#define NV10_3D_ENABLED_LIGHTS_7_DISABLED 0x00000000 |
#define NV10_3D_ENABLED_LIGHTS_7_NONPOSITIONAL 0x00004000 |
#define NV10_3D_ENABLED_LIGHTS_7_POSITIONAL 0x00008000 |
#define NV10_3D_ENABLED_LIGHTS_7_DIRECTIONAL 0x0000c000 |
#define NV10_3D_MATERIAL_SHININESS(i0) (0x000006a0 + 0x4*(i0)) |
#define NV10_3D_MATERIAL_SHININESS__ESIZE 0x00000004 |
#define NV10_3D_MATERIAL_SHININESS__LEN 0x00000006 |
#define NV10_3D_LIGHT_MODEL_AMBIENT 0x000006c4 |
#define NV10_3D_LIGHT_MODEL_AMBIENT_R 0x000006c4 |
#define NV10_3D_LIGHT_MODEL_AMBIENT_G 0x000006c8 |
#define NV10_3D_LIGHT_MODEL_AMBIENT_B 0x000006cc |
#define NV10_3D_LIGHT(i0) (0x00000800 + 0x80*(i0)) |
#define NV10_3D_LIGHT__ESIZE 0x00000080 |
#define NV10_3D_LIGHT__LEN 0x00000008 |
#define NV10_3D_LIGHT_AMBIENT(i0) (0x00000800 + 0x80*(i0)) |
#define NV10_3D_LIGHT_AMBIENT_R(i0) (0x00000800 + 0x80*(i0)) |
#define NV10_3D_LIGHT_AMBIENT_G(i0) (0x00000804 + 0x80*(i0)) |
#define NV10_3D_LIGHT_AMBIENT_B(i0) (0x00000808 + 0x80*(i0)) |
#define NV10_3D_LIGHT_DIFFUSE(i0) (0x0000080c + 0x80*(i0)) |
#define NV10_3D_LIGHT_DIFFUSE_R(i0) (0x0000080c + 0x80*(i0)) |
#define NV10_3D_LIGHT_DIFFUSE_G(i0) (0x00000810 + 0x80*(i0)) |
#define NV10_3D_LIGHT_DIFFUSE_B(i0) (0x00000814 + 0x80*(i0)) |
#define NV10_3D_LIGHT_SPECULAR(i0) (0x00000818 + 0x80*(i0)) |
#define NV10_3D_LIGHT_SPECULAR_R(i0) (0x00000818 + 0x80*(i0)) |
#define NV10_3D_LIGHT_SPECULAR_G(i0) (0x0000081c + 0x80*(i0)) |
#define NV10_3D_LIGHT_SPECULAR_B(i0) (0x00000820 + 0x80*(i0)) |
#define NV10_3D_LIGHT_HALF_VECTOR(i0) (0x00000828 + 0x80*(i0)) |
#define NV10_3D_LIGHT_HALF_VECTOR_X(i0) (0x00000828 + 0x80*(i0)) |
#define NV10_3D_LIGHT_HALF_VECTOR_Y(i0) (0x0000082c + 0x80*(i0)) |
#define NV10_3D_LIGHT_HALF_VECTOR_Z(i0) (0x00000830 + 0x80*(i0)) |
#define NV10_3D_LIGHT_DIRECTION(i0) (0x00000834 + 0x80*(i0)) |
#define NV10_3D_LIGHT_DIRECTION_X(i0) (0x00000834 + 0x80*(i0)) |
#define NV10_3D_LIGHT_DIRECTION_Y(i0) (0x00000838 + 0x80*(i0)) |
#define NV10_3D_LIGHT_DIRECTION_Z(i0) (0x0000083c + 0x80*(i0)) |
#define NV10_3D_LIGHT_SPOT_CUTOFF(i0, i1) (0x00000840 + 0x80*(i0) + 0x4*(i1)) |
#define NV10_3D_LIGHT_SPOT_CUTOFF__ESIZE 0x00000004 |
#define NV10_3D_LIGHT_SPOT_CUTOFF__LEN 0x00000007 |
#define NV10_3D_LIGHT_POSITION(i0) (0x0000085c + 0x80*(i0)) |
#define NV10_3D_LIGHT_POSITION_X(i0) (0x0000085c + 0x80*(i0)) |
#define NV10_3D_LIGHT_POSITION_Y(i0) (0x00000860 + 0x80*(i0)) |
#define NV10_3D_LIGHT_POSITION_Z(i0) (0x00000864 + 0x80*(i0)) |
#define NV10_3D_LIGHT_ATTENUATION(i0) (0x00000868 + 0x80*(i0)) |
#define NV10_3D_LIGHT_ATTENUATION_CONSTANT(i0) (0x00000868 + 0x80*(i0)) |
#define NV10_3D_LIGHT_ATTENUATION_LINEAR(i0) (0x0000086c + 0x80*(i0)) |
#define NV10_3D_LIGHT_ATTENUATION_QUADRATIC(i0) (0x00000870 + 0x80*(i0)) |
#define NV10_3D_FOG_MODE 0x0000029c |
#define NV10_3D_FOG_MODE_LINEAR 0x00002601 |
#define NV10_3D_FOG_MODE_EXP 0x00000800 |
#define NV10_3D_FOG_MODE_EXP_ABS 0x00000802 |
#define NV10_3D_FOG_MODE_EXP2 0x00000803 |
#define NV10_3D_FOG_COORD 0x000002a0 |
#define NV10_3D_FOG_COORD_FOG 0x00000000 |
#define NV10_3D_FOG_COORD_DIST_RADIAL 0x00000001 |
#define NV10_3D_FOG_COORD_DIST_ORTHOGONAL 0x00000002 |
#define NV10_3D_FOG_COORD_DIST_ORTHOGONAL_ABS 0x00000003 |
#define NV10_3D_FOG_ENABLE 0x000002a4 |
#define NV10_3D_FOG_COLOR 0x000002a8 |
#define NV10_3D_FOG_COLOR_R__MASK 0x000000ff |
#define NV10_3D_FOG_COLOR_R__SHIFT 0 |
#define NV10_3D_FOG_COLOR_G__MASK 0x0000ff00 |
#define NV10_3D_FOG_COLOR_G__SHIFT 8 |
#define NV10_3D_FOG_COLOR_B__MASK 0x00ff0000 |
#define NV10_3D_FOG_COLOR_B__SHIFT 16 |
#define NV10_3D_FOG_COLOR_A__MASK 0xff000000 |
#define NV10_3D_FOG_COLOR_A__SHIFT 24 |
#define NV10_3D_FOG_COEFF(i0) (0x00000680 + 0x4*(i0)) |
#define NV10_3D_FOG_COEFF__ESIZE 0x00000004 |
#define NV10_3D_FOG_COEFF__LEN 0x00000003 |
#define NV10_3D_TEX_GEN_MODE(i0, i1) (0x000003c0 + 0x10*(i0) + 0x4*(i1)) |
#define NV10_3D_TEX_GEN_MODE__ESIZE 0x00000004 |
#define NV10_3D_TEX_GEN_MODE__LEN 0x00000004 |
#define NV10_3D_TEX_GEN_MODE_FALSE 0x00000000 |
#define NV10_3D_TEX_GEN_MODE_EYE_LINEAR 0x00002400 |
#define NV10_3D_TEX_GEN_MODE_OBJECT_LINEAR 0x00002401 |
#define NV10_3D_TEX_GEN_MODE_SPHERE_MAP 0x00002402 |
#define NV10_3D_TEX_GEN_MODE_NORMAL_MAP 0x00008511 |
#define NV10_3D_TEX_GEN_MODE_REFLECTION_MAP 0x00008512 |
#define NV10_3D_TEX_GEN_COEFF(i0, i1) (0x00000600 + 0x40*(i0) + 0x10*(i1)) |
#define NV10_3D_TEX_GEN_COEFF__ESIZE 0x00000010 |
#define NV10_3D_TEX_GEN_COEFF__LEN 0x00000004 |
#define NV10_3D_TEX_GEN_COEFF_A(i0, i1) (0x00000600 + 0x40*(i0) + 0x10*(i1)) |
#define NV10_3D_TEX_GEN_COEFF_B(i0, i1) (0x00000604 + 0x40*(i0) + 0x10*(i1)) |
#define NV10_3D_TEX_GEN_COEFF_C(i0, i1) (0x00000608 + 0x40*(i0) + 0x10*(i1)) |
#define NV10_3D_TEX_GEN_COEFF_D(i0, i1) (0x0000060c + 0x40*(i0) + 0x10*(i1)) |
#define NV10_3D_TEX_MATRIX_ENABLE(i0) (0x000003e0 + 0x4*(i0)) |
#define NV10_3D_TEX_MATRIX_ENABLE__ESIZE 0x00000004 |
#define NV10_3D_TEX_MATRIX_ENABLE__LEN 0x00000002 |
#define NV10_3D_TEX_MATRIX(i0, i1) (0x00000540 + 0x40*(i0) + 0x4*(i1)) |
#define NV10_3D_TEX_MATRIX__ESIZE 0x00000004 |
#define NV10_3D_TEX_MATRIX__LEN 0x00000010 |
#define NV10_3D_TEX(i0) (0x00000000 + 0x4*(i0)) |
#define NV10_3D_TEX__ESIZE 0x00000004 |
#define NV10_3D_TEX__LEN 0x00000002 |
#define NV10_3D_TEX_OFFSET(i0) (0x00000218 + 0x4*(i0)) |
#define NV10_3D_TEX_FORMAT(i0) (0x00000220 + 0x4*(i0)) |
#define NV10_3D_TEX_FORMAT_DMA0 0x00000001 |
#define NV10_3D_TEX_FORMAT_DMA1 0x00000002 |
#define NV10_3D_TEX_FORMAT_CUBE_MAP 0x00000004 |
#define NV10_3D_TEX_FORMAT_FORMAT__MASK 0x00000f80 |
#define NV10_3D_TEX_FORMAT_FORMAT__SHIFT 7 |
#define NV10_3D_TEX_FORMAT_FORMAT_L8 0x00000000 |
#define NV10_3D_TEX_FORMAT_FORMAT_I8 0x00000080 |
#define NV10_3D_TEX_FORMAT_FORMAT_A1R5G5B5 0x00000100 |
#define NV10_3D_TEX_FORMAT_FORMAT_A4R4G4B4 0x00000200 |
#define NV10_3D_TEX_FORMAT_FORMAT_R5G6B5 0x00000280 |
#define NV10_3D_TEX_FORMAT_FORMAT_A8R8G8B8 0x00000300 |
#define NV10_3D_TEX_FORMAT_FORMAT_X8R8G8B8 0x00000380 |
#define NV10_3D_TEX_FORMAT_FORMAT_INDEX8 0x00000580 |
#define NV10_3D_TEX_FORMAT_FORMAT_DXT1 0x00000600 |
#define NV10_3D_TEX_FORMAT_FORMAT_DXT3 0x00000700 |
#define NV10_3D_TEX_FORMAT_FORMAT_DXT5 0x00000780 |
#define NV10_3D_TEX_FORMAT_FORMAT_A1R5G5B5_RECT 0x00000800 |
#define NV10_3D_TEX_FORMAT_FORMAT_R5G6B5_RECT 0x00000880 |
#define NV10_3D_TEX_FORMAT_FORMAT_A8R8G8B8_RECT 0x00000900 |
#define NV10_3D_TEX_FORMAT_FORMAT_I8_RECT 0x00000980 |
#define NV10_3D_TEX_FORMAT_MIPMAP 0x00008000 |
#define NV10_3D_TEX_FORMAT_BASE_SIZE_U__MASK 0x000f0000 |
#define NV10_3D_TEX_FORMAT_BASE_SIZE_U__SHIFT 16 |
#define NV10_3D_TEX_FORMAT_BASE_SIZE_V__MASK 0x00f00000 |
#define NV10_3D_TEX_FORMAT_BASE_SIZE_V__SHIFT 20 |
#define NV10_3D_TEX_FORMAT_WRAP_S__MASK 0x0f000000 |
#define NV10_3D_TEX_FORMAT_WRAP_S__SHIFT 24 |
#define NV10_3D_TEX_FORMAT_WRAP_S_REPEAT 0x01000000 |
#define NV10_3D_TEX_FORMAT_WRAP_S_MIRRORED_REPEAT 0x02000000 |
#define NV10_3D_TEX_FORMAT_WRAP_S_CLAMP_TO_EDGE 0x03000000 |
#define NV10_3D_TEX_FORMAT_WRAP_S_CLAMP_TO_BORDER 0x04000000 |
#define NV10_3D_TEX_FORMAT_WRAP_S_CLAMP 0x05000000 |
#define NV10_3D_TEX_FORMAT_WRAP_T__MASK 0xf0000000 |
#define NV10_3D_TEX_FORMAT_WRAP_T__SHIFT 28 |
#define NV10_3D_TEX_FORMAT_WRAP_T_REPEAT 0x10000000 |
#define NV10_3D_TEX_FORMAT_WRAP_T_MIRRORED_REPEAT 0x20000000 |
#define NV10_3D_TEX_FORMAT_WRAP_T_CLAMP_TO_EDGE 0x30000000 |
#define NV10_3D_TEX_FORMAT_WRAP_T_CLAMP_TO_BORDER 0x40000000 |
#define NV10_3D_TEX_FORMAT_WRAP_T_CLAMP 0x50000000 |
#define NV10_3D_TEX_ENABLE(i0) (0x00000228 + 0x4*(i0)) |
#define NV10_3D_TEX_ENABLE_CULL__MASK 0x0000000f |
#define NV10_3D_TEX_ENABLE_CULL__SHIFT 0 |
#define NV10_3D_TEX_ENABLE_CULL_DISABLED 0x00000000 |
#define NV10_3D_TEX_ENABLE_CULL_TEST_ALL 0x00000003 |
#define NV10_3D_TEX_ENABLE_CULL_TEST_ALPHA 0x00000004 |
#define NV10_3D_TEX_ENABLE_ANISOTROPY__MASK 0x00000030 |
#define NV10_3D_TEX_ENABLE_ANISOTROPY__SHIFT 4 |
#define NV10_3D_TEX_ENABLE_MIPMAP_MAX_LOD__MASK 0x0003c000 |
#define NV10_3D_TEX_ENABLE_MIPMAP_MAX_LOD__SHIFT 14 |
#define NV10_3D_TEX_ENABLE_MIPMAP_MIN_LOD__MASK 0x3c000000 |
#define NV10_3D_TEX_ENABLE_MIPMAP_MIN_LOD__SHIFT 26 |
#define NV10_3D_TEX_ENABLE_ENABLE 0x40000000 |
#define NV10_3D_TEX_NPOT_PITCH(i0) (0x00000230 + 0x4*(i0)) |
#define NV10_3D_TEX_NPOT_PITCH_PITCH__MASK 0xffff0000 |
#define NV10_3D_TEX_NPOT_PITCH_PITCH__SHIFT 16 |
#define NV10_3D_TEX_NPOT_SIZE(i0) (0x00000240 + 0x4*(i0)) |
#define NV10_3D_TEX_NPOT_SIZE_H__MASK 0x0000ffff |
#define NV10_3D_TEX_NPOT_SIZE_H__SHIFT 0 |
#define NV10_3D_TEX_NPOT_SIZE_W__MASK 0xffff0000 |
#define NV10_3D_TEX_NPOT_SIZE_W__SHIFT 16 |
#define NV10_3D_TEX_FILTER(i0) (0x00000248 + 0x4*(i0)) |
#define NV10_3D_TEX_FILTER_LOD_BIAS__MASK 0x00000f00 |
#define NV10_3D_TEX_FILTER_LOD_BIAS__SHIFT 8 |
#define NV10_3D_TEX_FILTER_MINIFY__MASK 0x0f000000 |
#define NV10_3D_TEX_FILTER_MINIFY__SHIFT 24 |
#define NV10_3D_TEX_FILTER_MINIFY_NEAREST 0x01000000 |
#define NV10_3D_TEX_FILTER_MINIFY_LINEAR 0x02000000 |
#define NV10_3D_TEX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST 0x03000000 |
#define NV10_3D_TEX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST 0x04000000 |
#define NV10_3D_TEX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR 0x05000000 |
#define NV10_3D_TEX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR 0x06000000 |
#define NV10_3D_TEX_FILTER_MAGNIFY__MASK 0xf0000000 |
#define NV10_3D_TEX_FILTER_MAGNIFY__SHIFT 28 |
#define NV10_3D_TEX_FILTER_MAGNIFY_NEAREST 0x10000000 |
#define NV10_3D_TEX_FILTER_MAGNIFY_LINEAR 0x20000000 |
#define NV10_3D_TEX_PALETTE_OFFSET(i0) (0x00000250 + 0x4*(i0)) |
#define NV10_3D_RC_IN_ALPHA(i0) (0x00000260 + 0x4*(i0)) |
#define NV10_3D_RC_IN_ALPHA_D_INPUT__MASK 0x0000000f |
#define NV10_3D_RC_IN_ALPHA_D_INPUT__SHIFT 0 |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_CONSTANT_COLOR0 0x00000001 |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_CONSTANT_COLOR1 0x00000002 |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_FOG 0x00000003 |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_PRIMARY_COLOR 0x00000004 |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_SECONDARY_COLOR 0x00000005 |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_TEXTURE0 0x00000008 |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_TEXTURE1 0x00000009 |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_TEXTURE2 0x0000000a |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_TEXTURE3 0x0000000b |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_SPARE0 0x0000000c |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_SPARE1 0x0000000d |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e |
#define NV10_3D_RC_IN_ALPHA_D_INPUT_E_TIMES_F 0x0000000f |
#define NV10_3D_RC_IN_ALPHA_D_COMPONENT_USAGE__MASK 0x00000010 |
#define NV10_3D_RC_IN_ALPHA_D_COMPONENT_USAGE__SHIFT 4 |
#define NV10_3D_RC_IN_ALPHA_D_COMPONENT_USAGE_BLUE 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_D_COMPONENT_USAGE_ALPHA 0x00000010 |
#define NV10_3D_RC_IN_ALPHA_D_MAPPING__MASK 0x000000e0 |
#define NV10_3D_RC_IN_ALPHA_D_MAPPING__SHIFT 5 |
#define NV10_3D_RC_IN_ALPHA_D_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_D_MAPPING_UNSIGNED_INVERT 0x00000020 |
#define NV10_3D_RC_IN_ALPHA_D_MAPPING_EXPAND_NORMAL 0x00000040 |
#define NV10_3D_RC_IN_ALPHA_D_MAPPING_EXPAND_NEGATE 0x00000060 |
#define NV10_3D_RC_IN_ALPHA_D_MAPPING_HALF_BIAS_NORMAL 0x00000080 |
#define NV10_3D_RC_IN_ALPHA_D_MAPPING_HALF_BIAS_NEGATE 0x000000a0 |
#define NV10_3D_RC_IN_ALPHA_D_MAPPING_SIGNED_IDENTITY 0x000000c0 |
#define NV10_3D_RC_IN_ALPHA_D_MAPPING_SIGNED_NEGATE 0x000000e0 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT__MASK 0x00000f00 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT__SHIFT 8 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_CONSTANT_COLOR0 0x00000100 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_CONSTANT_COLOR1 0x00000200 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_FOG 0x00000300 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_PRIMARY_COLOR 0x00000400 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_SECONDARY_COLOR 0x00000500 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_TEXTURE0 0x00000800 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_TEXTURE1 0x00000900 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_TEXTURE2 0x00000a00 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_TEXTURE3 0x00000b00 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_SPARE0 0x00000c00 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_SPARE1 0x00000d00 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV10_3D_RC_IN_ALPHA_C_INPUT_E_TIMES_F 0x00000f00 |
#define NV10_3D_RC_IN_ALPHA_C_COMPONENT_USAGE__MASK 0x00001000 |
#define NV10_3D_RC_IN_ALPHA_C_COMPONENT_USAGE__SHIFT 12 |
#define NV10_3D_RC_IN_ALPHA_C_COMPONENT_USAGE_BLUE 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_C_COMPONENT_USAGE_ALPHA 0x00001000 |
#define NV10_3D_RC_IN_ALPHA_C_MAPPING__MASK 0x0000e000 |
#define NV10_3D_RC_IN_ALPHA_C_MAPPING__SHIFT 13 |
#define NV10_3D_RC_IN_ALPHA_C_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_C_MAPPING_UNSIGNED_INVERT 0x00002000 |
#define NV10_3D_RC_IN_ALPHA_C_MAPPING_EXPAND_NORMAL 0x00004000 |
#define NV10_3D_RC_IN_ALPHA_C_MAPPING_EXPAND_NEGATE 0x00006000 |
#define NV10_3D_RC_IN_ALPHA_C_MAPPING_HALF_BIAS_NORMAL 0x00008000 |
#define NV10_3D_RC_IN_ALPHA_C_MAPPING_HALF_BIAS_NEGATE 0x0000a000 |
#define NV10_3D_RC_IN_ALPHA_C_MAPPING_SIGNED_IDENTITY 0x0000c000 |
#define NV10_3D_RC_IN_ALPHA_C_MAPPING_SIGNED_NEGATE 0x0000e000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT__MASK 0x000f0000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT__SHIFT 16 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_CONSTANT_COLOR0 0x00010000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_CONSTANT_COLOR1 0x00020000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_FOG 0x00030000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_PRIMARY_COLOR 0x00040000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_SECONDARY_COLOR 0x00050000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_TEXTURE0 0x00080000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_TEXTURE1 0x00090000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_TEXTURE2 0x000a0000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_TEXTURE3 0x000b0000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_SPARE0 0x000c0000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_SPARE1 0x000d0000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000 |
#define NV10_3D_RC_IN_ALPHA_B_INPUT_E_TIMES_F 0x000f0000 |
#define NV10_3D_RC_IN_ALPHA_B_COMPONENT_USAGE__MASK 0x00100000 |
#define NV10_3D_RC_IN_ALPHA_B_COMPONENT_USAGE__SHIFT 20 |
#define NV10_3D_RC_IN_ALPHA_B_COMPONENT_USAGE_BLUE 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_B_COMPONENT_USAGE_ALPHA 0x00100000 |
#define NV10_3D_RC_IN_ALPHA_B_MAPPING__MASK 0x00e00000 |
#define NV10_3D_RC_IN_ALPHA_B_MAPPING__SHIFT 21 |
#define NV10_3D_RC_IN_ALPHA_B_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_B_MAPPING_UNSIGNED_INVERT 0x00200000 |
#define NV10_3D_RC_IN_ALPHA_B_MAPPING_EXPAND_NORMAL 0x00400000 |
#define NV10_3D_RC_IN_ALPHA_B_MAPPING_EXPAND_NEGATE 0x00600000 |
#define NV10_3D_RC_IN_ALPHA_B_MAPPING_HALF_BIAS_NORMAL 0x00800000 |
#define NV10_3D_RC_IN_ALPHA_B_MAPPING_HALF_BIAS_NEGATE 0x00a00000 |
#define NV10_3D_RC_IN_ALPHA_B_MAPPING_SIGNED_IDENTITY 0x00c00000 |
#define NV10_3D_RC_IN_ALPHA_B_MAPPING_SIGNED_NEGATE 0x00e00000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT__MASK 0x0f000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT__SHIFT 24 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_CONSTANT_COLOR0 0x01000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_CONSTANT_COLOR1 0x02000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_FOG 0x03000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_PRIMARY_COLOR 0x04000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_SECONDARY_COLOR 0x05000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_TEXTURE0 0x08000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_TEXTURE1 0x09000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_TEXTURE2 0x0a000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_TEXTURE3 0x0b000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_SPARE0 0x0c000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_SPARE1 0x0d000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000 |
#define NV10_3D_RC_IN_ALPHA_A_INPUT_E_TIMES_F 0x0f000000 |
#define NV10_3D_RC_IN_ALPHA_A_COMPONENT_USAGE__MASK 0x10000000 |
#define NV10_3D_RC_IN_ALPHA_A_COMPONENT_USAGE__SHIFT 28 |
#define NV10_3D_RC_IN_ALPHA_A_COMPONENT_USAGE_BLUE 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_A_COMPONENT_USAGE_ALPHA 0x10000000 |
#define NV10_3D_RC_IN_ALPHA_A_MAPPING__MASK 0xe0000000 |
#define NV10_3D_RC_IN_ALPHA_A_MAPPING__SHIFT 29 |
#define NV10_3D_RC_IN_ALPHA_A_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_IN_ALPHA_A_MAPPING_UNSIGNED_INVERT 0x20000000 |
#define NV10_3D_RC_IN_ALPHA_A_MAPPING_EXPAND_NORMAL 0x40000000 |
#define NV10_3D_RC_IN_ALPHA_A_MAPPING_EXPAND_NEGATE 0x60000000 |
#define NV10_3D_RC_IN_ALPHA_A_MAPPING_HALF_BIAS_NORMAL 0x80000000 |
#define NV10_3D_RC_IN_ALPHA_A_MAPPING_HALF_BIAS_NEGATE 0xa0000000 |
#define NV10_3D_RC_IN_ALPHA_A_MAPPING_SIGNED_IDENTITY 0xc0000000 |
#define NV10_3D_RC_IN_ALPHA_A_MAPPING_SIGNED_NEGATE 0xe0000000 |
#define NV10_3D_RC_IN_RGB(i0) (0x00000268 + 0x4*(i0)) |
#define NV10_3D_RC_IN_RGB_D_INPUT__MASK 0x0000000f |
#define NV10_3D_RC_IN_RGB_D_INPUT__SHIFT 0 |
#define NV10_3D_RC_IN_RGB_D_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_IN_RGB_D_INPUT_CONSTANT_COLOR0 0x00000001 |
#define NV10_3D_RC_IN_RGB_D_INPUT_CONSTANT_COLOR1 0x00000002 |
#define NV10_3D_RC_IN_RGB_D_INPUT_FOG 0x00000003 |
#define NV10_3D_RC_IN_RGB_D_INPUT_PRIMARY_COLOR 0x00000004 |
#define NV10_3D_RC_IN_RGB_D_INPUT_SECONDARY_COLOR 0x00000005 |
#define NV10_3D_RC_IN_RGB_D_INPUT_TEXTURE0 0x00000008 |
#define NV10_3D_RC_IN_RGB_D_INPUT_TEXTURE1 0x00000009 |
#define NV10_3D_RC_IN_RGB_D_INPUT_TEXTURE2 0x0000000a |
#define NV10_3D_RC_IN_RGB_D_INPUT_TEXTURE3 0x0000000b |
#define NV10_3D_RC_IN_RGB_D_INPUT_SPARE0 0x0000000c |
#define NV10_3D_RC_IN_RGB_D_INPUT_SPARE1 0x0000000d |
#define NV10_3D_RC_IN_RGB_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e |
#define NV10_3D_RC_IN_RGB_D_INPUT_E_TIMES_F 0x0000000f |
#define NV10_3D_RC_IN_RGB_D_COMPONENT_USAGE__MASK 0x00000010 |
#define NV10_3D_RC_IN_RGB_D_COMPONENT_USAGE__SHIFT 4 |
#define NV10_3D_RC_IN_RGB_D_COMPONENT_USAGE_RGB 0x00000000 |
#define NV10_3D_RC_IN_RGB_D_COMPONENT_USAGE_ALPHA 0x00000010 |
#define NV10_3D_RC_IN_RGB_D_MAPPING__MASK 0x000000e0 |
#define NV10_3D_RC_IN_RGB_D_MAPPING__SHIFT 5 |
#define NV10_3D_RC_IN_RGB_D_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_IN_RGB_D_MAPPING_UNSIGNED_INVERT 0x00000020 |
#define NV10_3D_RC_IN_RGB_D_MAPPING_EXPAND_NORMAL 0x00000040 |
#define NV10_3D_RC_IN_RGB_D_MAPPING_EXPAND_NEGATE 0x00000060 |
#define NV10_3D_RC_IN_RGB_D_MAPPING_HALF_BIAS_NORMAL 0x00000080 |
#define NV10_3D_RC_IN_RGB_D_MAPPING_HALF_BIAS_NEGATE 0x000000a0 |
#define NV10_3D_RC_IN_RGB_D_MAPPING_SIGNED_IDENTITY 0x000000c0 |
#define NV10_3D_RC_IN_RGB_D_MAPPING_SIGNED_NEGATE 0x000000e0 |
#define NV10_3D_RC_IN_RGB_C_INPUT__MASK 0x00000f00 |
#define NV10_3D_RC_IN_RGB_C_INPUT__SHIFT 8 |
#define NV10_3D_RC_IN_RGB_C_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_IN_RGB_C_INPUT_CONSTANT_COLOR0 0x00000100 |
#define NV10_3D_RC_IN_RGB_C_INPUT_CONSTANT_COLOR1 0x00000200 |
#define NV10_3D_RC_IN_RGB_C_INPUT_FOG 0x00000300 |
#define NV10_3D_RC_IN_RGB_C_INPUT_PRIMARY_COLOR 0x00000400 |
#define NV10_3D_RC_IN_RGB_C_INPUT_SECONDARY_COLOR 0x00000500 |
#define NV10_3D_RC_IN_RGB_C_INPUT_TEXTURE0 0x00000800 |
#define NV10_3D_RC_IN_RGB_C_INPUT_TEXTURE1 0x00000900 |
#define NV10_3D_RC_IN_RGB_C_INPUT_TEXTURE2 0x00000a00 |
#define NV10_3D_RC_IN_RGB_C_INPUT_TEXTURE3 0x00000b00 |
#define NV10_3D_RC_IN_RGB_C_INPUT_SPARE0 0x00000c00 |
#define NV10_3D_RC_IN_RGB_C_INPUT_SPARE1 0x00000d00 |
#define NV10_3D_RC_IN_RGB_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV10_3D_RC_IN_RGB_C_INPUT_E_TIMES_F 0x00000f00 |
#define NV10_3D_RC_IN_RGB_C_COMPONENT_USAGE__MASK 0x00001000 |
#define NV10_3D_RC_IN_RGB_C_COMPONENT_USAGE__SHIFT 12 |
#define NV10_3D_RC_IN_RGB_C_COMPONENT_USAGE_RGB 0x00000000 |
#define NV10_3D_RC_IN_RGB_C_COMPONENT_USAGE_ALPHA 0x00001000 |
#define NV10_3D_RC_IN_RGB_C_MAPPING__MASK 0x0000e000 |
#define NV10_3D_RC_IN_RGB_C_MAPPING__SHIFT 13 |
#define NV10_3D_RC_IN_RGB_C_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_IN_RGB_C_MAPPING_UNSIGNED_INVERT 0x00002000 |
#define NV10_3D_RC_IN_RGB_C_MAPPING_EXPAND_NORMAL 0x00004000 |
#define NV10_3D_RC_IN_RGB_C_MAPPING_EXPAND_NEGATE 0x00006000 |
#define NV10_3D_RC_IN_RGB_C_MAPPING_HALF_BIAS_NORMAL 0x00008000 |
#define NV10_3D_RC_IN_RGB_C_MAPPING_HALF_BIAS_NEGATE 0x0000a000 |
#define NV10_3D_RC_IN_RGB_C_MAPPING_SIGNED_IDENTITY 0x0000c000 |
#define NV10_3D_RC_IN_RGB_C_MAPPING_SIGNED_NEGATE 0x0000e000 |
#define NV10_3D_RC_IN_RGB_B_INPUT__MASK 0x000f0000 |
#define NV10_3D_RC_IN_RGB_B_INPUT__SHIFT 16 |
#define NV10_3D_RC_IN_RGB_B_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_CONSTANT_COLOR0 0x00010000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_CONSTANT_COLOR1 0x00020000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_FOG 0x00030000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_PRIMARY_COLOR 0x00040000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_SECONDARY_COLOR 0x00050000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_TEXTURE0 0x00080000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_TEXTURE1 0x00090000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_TEXTURE2 0x000a0000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_TEXTURE3 0x000b0000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_SPARE0 0x000c0000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_SPARE1 0x000d0000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000 |
#define NV10_3D_RC_IN_RGB_B_INPUT_E_TIMES_F 0x000f0000 |
#define NV10_3D_RC_IN_RGB_B_COMPONENT_USAGE__MASK 0x00100000 |
#define NV10_3D_RC_IN_RGB_B_COMPONENT_USAGE__SHIFT 20 |
#define NV10_3D_RC_IN_RGB_B_COMPONENT_USAGE_RGB 0x00000000 |
#define NV10_3D_RC_IN_RGB_B_COMPONENT_USAGE_ALPHA 0x00100000 |
#define NV10_3D_RC_IN_RGB_B_MAPPING__MASK 0x00e00000 |
#define NV10_3D_RC_IN_RGB_B_MAPPING__SHIFT 21 |
#define NV10_3D_RC_IN_RGB_B_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_IN_RGB_B_MAPPING_UNSIGNED_INVERT 0x00200000 |
#define NV10_3D_RC_IN_RGB_B_MAPPING_EXPAND_NORMAL 0x00400000 |
#define NV10_3D_RC_IN_RGB_B_MAPPING_EXPAND_NEGATE 0x00600000 |
#define NV10_3D_RC_IN_RGB_B_MAPPING_HALF_BIAS_NORMAL 0x00800000 |
#define NV10_3D_RC_IN_RGB_B_MAPPING_HALF_BIAS_NEGATE 0x00a00000 |
#define NV10_3D_RC_IN_RGB_B_MAPPING_SIGNED_IDENTITY 0x00c00000 |
#define NV10_3D_RC_IN_RGB_B_MAPPING_SIGNED_NEGATE 0x00e00000 |
#define NV10_3D_RC_IN_RGB_A_INPUT__MASK 0x0f000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT__SHIFT 24 |
#define NV10_3D_RC_IN_RGB_A_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_CONSTANT_COLOR0 0x01000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_CONSTANT_COLOR1 0x02000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_FOG 0x03000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_PRIMARY_COLOR 0x04000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_SECONDARY_COLOR 0x05000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_TEXTURE0 0x08000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_TEXTURE1 0x09000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_TEXTURE2 0x0a000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_TEXTURE3 0x0b000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_SPARE0 0x0c000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_SPARE1 0x0d000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000 |
#define NV10_3D_RC_IN_RGB_A_INPUT_E_TIMES_F 0x0f000000 |
#define NV10_3D_RC_IN_RGB_A_COMPONENT_USAGE__MASK 0x10000000 |
#define NV10_3D_RC_IN_RGB_A_COMPONENT_USAGE__SHIFT 28 |
#define NV10_3D_RC_IN_RGB_A_COMPONENT_USAGE_RGB 0x00000000 |
#define NV10_3D_RC_IN_RGB_A_COMPONENT_USAGE_ALPHA 0x10000000 |
#define NV10_3D_RC_IN_RGB_A_MAPPING__MASK 0xe0000000 |
#define NV10_3D_RC_IN_RGB_A_MAPPING__SHIFT 29 |
#define NV10_3D_RC_IN_RGB_A_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_IN_RGB_A_MAPPING_UNSIGNED_INVERT 0x20000000 |
#define NV10_3D_RC_IN_RGB_A_MAPPING_EXPAND_NORMAL 0x40000000 |
#define NV10_3D_RC_IN_RGB_A_MAPPING_EXPAND_NEGATE 0x60000000 |
#define NV10_3D_RC_IN_RGB_A_MAPPING_HALF_BIAS_NORMAL 0x80000000 |
#define NV10_3D_RC_IN_RGB_A_MAPPING_HALF_BIAS_NEGATE 0xa0000000 |
#define NV10_3D_RC_IN_RGB_A_MAPPING_SIGNED_IDENTITY 0xc0000000 |
#define NV10_3D_RC_IN_RGB_A_MAPPING_SIGNED_NEGATE 0xe0000000 |
#define NV10_3D_RC_COLOR(i0) (0x00000270 + 0x4*(i0)) |
#define NV10_3D_RC_COLOR_B__MASK 0x000000ff |
#define NV10_3D_RC_COLOR_B__SHIFT 0 |
#define NV10_3D_RC_COLOR_G__MASK 0x0000ff00 |
#define NV10_3D_RC_COLOR_G__SHIFT 8 |
#define NV10_3D_RC_COLOR_R__MASK 0x00ff0000 |
#define NV10_3D_RC_COLOR_R__SHIFT 16 |
#define NV10_3D_RC_COLOR_A__MASK 0xff000000 |
#define NV10_3D_RC_COLOR_A__SHIFT 24 |
#define NV10_3D_RC_OUT_ALPHA(i0) (0x00000278 + 0x4*(i0)) |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT__MASK 0x0000000f |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT__SHIFT 0 |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_ZERO 0x00000000 |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_CONSTANT_COLOR0 0x00000001 |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_CONSTANT_COLOR1 0x00000002 |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_FOG 0x00000003 |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_PRIMARY_COLOR 0x00000004 |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_SECONDARY_COLOR 0x00000005 |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE0 0x00000008 |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE1 0x00000009 |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE2 0x0000000a |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE3 0x0000000b |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_SPARE0 0x0000000c |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_SPARE1 0x0000000d |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e |
#define NV10_3D_RC_OUT_ALPHA_CD_OUTPUT_E_TIMES_F 0x0000000f |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT__MASK 0x000000f0 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT__SHIFT 4 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_ZERO 0x00000000 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_CONSTANT_COLOR0 0x00000010 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_CONSTANT_COLOR1 0x00000020 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_FOG 0x00000030 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_PRIMARY_COLOR 0x00000040 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_SECONDARY_COLOR 0x00000050 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE0 0x00000080 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE1 0x00000090 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE2 0x000000a0 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE3 0x000000b0 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_SPARE0 0x000000c0 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_SPARE1 0x000000d0 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000000e0 |
#define NV10_3D_RC_OUT_ALPHA_AB_OUTPUT_E_TIMES_F 0x000000f0 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT__MASK 0x00000f00 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT__SHIFT 8 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_ZERO 0x00000000 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_CONSTANT_COLOR0 0x00000100 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_CONSTANT_COLOR1 0x00000200 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_FOG 0x00000300 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_PRIMARY_COLOR 0x00000400 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_SECONDARY_COLOR 0x00000500 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE0 0x00000800 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE1 0x00000900 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE2 0x00000a00 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE3 0x00000b00 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_SPARE0 0x00000c00 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_SPARE1 0x00000d00 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV10_3D_RC_OUT_ALPHA_SUM_OUTPUT_E_TIMES_F 0x00000f00 |
#define NV10_3D_RC_OUT_ALPHA_CD_DOT_PRODUCT 0x00001000 |
#define NV10_3D_RC_OUT_ALPHA_AB_DOT_PRODUCT 0x00002000 |
#define NV10_3D_RC_OUT_ALPHA_MUX_SUM 0x00004000 |
#define NV10_3D_RC_OUT_ALPHA_BIAS__MASK 0x00008000 |
#define NV10_3D_RC_OUT_ALPHA_BIAS__SHIFT 15 |
#define NV10_3D_RC_OUT_ALPHA_BIAS_NONE 0x00000000 |
#define NV10_3D_RC_OUT_ALPHA_BIAS_BIAS_BY_NEGATIVE_ONE_HALF 0x00008000 |
#define NV10_3D_RC_OUT_ALPHA_SCALE__MASK 0x00030000 |
#define NV10_3D_RC_OUT_ALPHA_SCALE__SHIFT 16 |
#define NV10_3D_RC_OUT_ALPHA_SCALE_NONE 0x00000000 |
#define NV10_3D_RC_OUT_ALPHA_SCALE_SCALE_BY_TWO 0x00010000 |
#define NV10_3D_RC_OUT_ALPHA_SCALE_SCALE_BY_FOUR 0x00020000 |
#define NV10_3D_RC_OUT_ALPHA_SCALE_SCALE_BY_ONE_HALF 0x00030000 |
#define NV10_3D_RC_OUT_RGB(i0) (0x00000280 + 0x4*(i0)) |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT__MASK 0x0000000f |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT__SHIFT 0 |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_ZERO 0x00000000 |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_CONSTANT_COLOR0 0x00000001 |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_CONSTANT_COLOR1 0x00000002 |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_FOG 0x00000003 |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_PRIMARY_COLOR 0x00000004 |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_SECONDARY_COLOR 0x00000005 |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE0 0x00000008 |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE1 0x00000009 |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE2 0x0000000a |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE3 0x0000000b |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_SPARE0 0x0000000c |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_SPARE1 0x0000000d |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e |
#define NV10_3D_RC_OUT_RGB_CD_OUTPUT_E_TIMES_F 0x0000000f |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT__MASK 0x000000f0 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT__SHIFT 4 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_ZERO 0x00000000 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_CONSTANT_COLOR0 0x00000010 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_CONSTANT_COLOR1 0x00000020 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_FOG 0x00000030 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_PRIMARY_COLOR 0x00000040 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_SECONDARY_COLOR 0x00000050 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE0 0x00000080 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE1 0x00000090 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE2 0x000000a0 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE3 0x000000b0 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_SPARE0 0x000000c0 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_SPARE1 0x000000d0 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000000e0 |
#define NV10_3D_RC_OUT_RGB_AB_OUTPUT_E_TIMES_F 0x000000f0 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT__MASK 0x00000f00 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT__SHIFT 8 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_ZERO 0x00000000 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_CONSTANT_COLOR0 0x00000100 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_CONSTANT_COLOR1 0x00000200 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_FOG 0x00000300 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_PRIMARY_COLOR 0x00000400 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_SECONDARY_COLOR 0x00000500 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE0 0x00000800 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE1 0x00000900 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE2 0x00000a00 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE3 0x00000b00 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_SPARE0 0x00000c00 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_SPARE1 0x00000d00 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV10_3D_RC_OUT_RGB_SUM_OUTPUT_E_TIMES_F 0x00000f00 |
#define NV10_3D_RC_OUT_RGB_CD_DOT_PRODUCT 0x00001000 |
#define NV10_3D_RC_OUT_RGB_AB_DOT_PRODUCT 0x00002000 |
#define NV10_3D_RC_OUT_RGB_MUX_SUM 0x00004000 |
#define NV10_3D_RC_OUT_RGB_BIAS__MASK 0x00008000 |
#define NV10_3D_RC_OUT_RGB_BIAS__SHIFT 15 |
#define NV10_3D_RC_OUT_RGB_BIAS_NONE 0x00000000 |
#define NV10_3D_RC_OUT_RGB_BIAS_BIAS_BY_NEGATIVE_ONE_HALF 0x00008000 |
#define NV10_3D_RC_OUT_RGB_SCALE__MASK 0x00030000 |
#define NV10_3D_RC_OUT_RGB_SCALE__SHIFT 16 |
#define NV10_3D_RC_OUT_RGB_SCALE_NONE 0x00000000 |
#define NV10_3D_RC_OUT_RGB_SCALE_SCALE_BY_TWO 0x00010000 |
#define NV10_3D_RC_OUT_RGB_SCALE_SCALE_BY_FOUR 0x00020000 |
#define NV10_3D_RC_OUT_RGB_SCALE_SCALE_BY_ONE_HALF 0x00030000 |
#define NV10_3D_RC_OUT_RGB_OPERATION__MASK 0x38000000 |
#define NV10_3D_RC_OUT_RGB_OPERATION__SHIFT 27 |
#define NV10_3D_RC_FINAL0 0x00000288 |
#define NV10_3D_RC_FINAL0_D_INPUT__MASK 0x0000000f |
#define NV10_3D_RC_FINAL0_D_INPUT__SHIFT 0 |
#define NV10_3D_RC_FINAL0_D_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_FINAL0_D_INPUT_CONSTANT_COLOR0 0x00000001 |
#define NV10_3D_RC_FINAL0_D_INPUT_CONSTANT_COLOR1 0x00000002 |
#define NV10_3D_RC_FINAL0_D_INPUT_FOG 0x00000003 |
#define NV10_3D_RC_FINAL0_D_INPUT_PRIMARY_COLOR 0x00000004 |
#define NV10_3D_RC_FINAL0_D_INPUT_SECONDARY_COLOR 0x00000005 |
#define NV10_3D_RC_FINAL0_D_INPUT_TEXTURE0 0x00000008 |
#define NV10_3D_RC_FINAL0_D_INPUT_TEXTURE1 0x00000009 |
#define NV10_3D_RC_FINAL0_D_INPUT_TEXTURE2 0x0000000a |
#define NV10_3D_RC_FINAL0_D_INPUT_TEXTURE3 0x0000000b |
#define NV10_3D_RC_FINAL0_D_INPUT_SPARE0 0x0000000c |
#define NV10_3D_RC_FINAL0_D_INPUT_SPARE1 0x0000000d |
#define NV10_3D_RC_FINAL0_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e |
#define NV10_3D_RC_FINAL0_D_INPUT_E_TIMES_F 0x0000000f |
#define NV10_3D_RC_FINAL0_D_COMPONENT_USAGE__MASK 0x00000010 |
#define NV10_3D_RC_FINAL0_D_COMPONENT_USAGE__SHIFT 4 |
#define NV10_3D_RC_FINAL0_D_COMPONENT_USAGE_RGB 0x00000000 |
#define NV10_3D_RC_FINAL0_D_COMPONENT_USAGE_ALPHA 0x00000010 |
#define NV10_3D_RC_FINAL0_D_MAPPING__MASK 0x000000e0 |
#define NV10_3D_RC_FINAL0_D_MAPPING__SHIFT 5 |
#define NV10_3D_RC_FINAL0_D_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_FINAL0_D_MAPPING_UNSIGNED_INVERT 0x00000020 |
#define NV10_3D_RC_FINAL0_D_MAPPING_EXPAND_NORMAL 0x00000040 |
#define NV10_3D_RC_FINAL0_D_MAPPING_EXPAND_NEGATE 0x00000060 |
#define NV10_3D_RC_FINAL0_D_MAPPING_HALF_BIAS_NORMAL 0x00000080 |
#define NV10_3D_RC_FINAL0_D_MAPPING_HALF_BIAS_NEGATE 0x000000a0 |
#define NV10_3D_RC_FINAL0_D_MAPPING_SIGNED_IDENTITY 0x000000c0 |
#define NV10_3D_RC_FINAL0_D_MAPPING_SIGNED_NEGATE 0x000000e0 |
#define NV10_3D_RC_FINAL0_C_INPUT__MASK 0x00000f00 |
#define NV10_3D_RC_FINAL0_C_INPUT__SHIFT 8 |
#define NV10_3D_RC_FINAL0_C_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_FINAL0_C_INPUT_CONSTANT_COLOR0 0x00000100 |
#define NV10_3D_RC_FINAL0_C_INPUT_CONSTANT_COLOR1 0x00000200 |
#define NV10_3D_RC_FINAL0_C_INPUT_FOG 0x00000300 |
#define NV10_3D_RC_FINAL0_C_INPUT_PRIMARY_COLOR 0x00000400 |
#define NV10_3D_RC_FINAL0_C_INPUT_SECONDARY_COLOR 0x00000500 |
#define NV10_3D_RC_FINAL0_C_INPUT_TEXTURE0 0x00000800 |
#define NV10_3D_RC_FINAL0_C_INPUT_TEXTURE1 0x00000900 |
#define NV10_3D_RC_FINAL0_C_INPUT_TEXTURE2 0x00000a00 |
#define NV10_3D_RC_FINAL0_C_INPUT_TEXTURE3 0x00000b00 |
#define NV10_3D_RC_FINAL0_C_INPUT_SPARE0 0x00000c00 |
#define NV10_3D_RC_FINAL0_C_INPUT_SPARE1 0x00000d00 |
#define NV10_3D_RC_FINAL0_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV10_3D_RC_FINAL0_C_INPUT_E_TIMES_F 0x00000f00 |
#define NV10_3D_RC_FINAL0_C_COMPONENT_USAGE__MASK 0x00001000 |
#define NV10_3D_RC_FINAL0_C_COMPONENT_USAGE__SHIFT 12 |
#define NV10_3D_RC_FINAL0_C_COMPONENT_USAGE_RGB 0x00000000 |
#define NV10_3D_RC_FINAL0_C_COMPONENT_USAGE_ALPHA 0x00001000 |
#define NV10_3D_RC_FINAL0_C_MAPPING__MASK 0x0000e000 |
#define NV10_3D_RC_FINAL0_C_MAPPING__SHIFT 13 |
#define NV10_3D_RC_FINAL0_C_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_FINAL0_C_MAPPING_UNSIGNED_INVERT 0x00002000 |
#define NV10_3D_RC_FINAL0_C_MAPPING_EXPAND_NORMAL 0x00004000 |
#define NV10_3D_RC_FINAL0_C_MAPPING_EXPAND_NEGATE 0x00006000 |
#define NV10_3D_RC_FINAL0_C_MAPPING_HALF_BIAS_NORMAL 0x00008000 |
#define NV10_3D_RC_FINAL0_C_MAPPING_HALF_BIAS_NEGATE 0x0000a000 |
#define NV10_3D_RC_FINAL0_C_MAPPING_SIGNED_IDENTITY 0x0000c000 |
#define NV10_3D_RC_FINAL0_C_MAPPING_SIGNED_NEGATE 0x0000e000 |
#define NV10_3D_RC_FINAL0_B_INPUT__MASK 0x000f0000 |
#define NV10_3D_RC_FINAL0_B_INPUT__SHIFT 16 |
#define NV10_3D_RC_FINAL0_B_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_FINAL0_B_INPUT_CONSTANT_COLOR0 0x00010000 |
#define NV10_3D_RC_FINAL0_B_INPUT_CONSTANT_COLOR1 0x00020000 |
#define NV10_3D_RC_FINAL0_B_INPUT_FOG 0x00030000 |
#define NV10_3D_RC_FINAL0_B_INPUT_PRIMARY_COLOR 0x00040000 |
#define NV10_3D_RC_FINAL0_B_INPUT_SECONDARY_COLOR 0x00050000 |
#define NV10_3D_RC_FINAL0_B_INPUT_TEXTURE0 0x00080000 |
#define NV10_3D_RC_FINAL0_B_INPUT_TEXTURE1 0x00090000 |
#define NV10_3D_RC_FINAL0_B_INPUT_TEXTURE2 0x000a0000 |
#define NV10_3D_RC_FINAL0_B_INPUT_TEXTURE3 0x000b0000 |
#define NV10_3D_RC_FINAL0_B_INPUT_SPARE0 0x000c0000 |
#define NV10_3D_RC_FINAL0_B_INPUT_SPARE1 0x000d0000 |
#define NV10_3D_RC_FINAL0_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000 |
#define NV10_3D_RC_FINAL0_B_INPUT_E_TIMES_F 0x000f0000 |
#define NV10_3D_RC_FINAL0_B_COMPONENT_USAGE__MASK 0x00100000 |
#define NV10_3D_RC_FINAL0_B_COMPONENT_USAGE__SHIFT 20 |
#define NV10_3D_RC_FINAL0_B_COMPONENT_USAGE_RGB 0x00000000 |
#define NV10_3D_RC_FINAL0_B_COMPONENT_USAGE_ALPHA 0x00100000 |
#define NV10_3D_RC_FINAL0_B_MAPPING__MASK 0x00e00000 |
#define NV10_3D_RC_FINAL0_B_MAPPING__SHIFT 21 |
#define NV10_3D_RC_FINAL0_B_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_FINAL0_B_MAPPING_UNSIGNED_INVERT 0x00200000 |
#define NV10_3D_RC_FINAL0_B_MAPPING_EXPAND_NORMAL 0x00400000 |
#define NV10_3D_RC_FINAL0_B_MAPPING_EXPAND_NEGATE 0x00600000 |
#define NV10_3D_RC_FINAL0_B_MAPPING_HALF_BIAS_NORMAL 0x00800000 |
#define NV10_3D_RC_FINAL0_B_MAPPING_HALF_BIAS_NEGATE 0x00a00000 |
#define NV10_3D_RC_FINAL0_B_MAPPING_SIGNED_IDENTITY 0x00c00000 |
#define NV10_3D_RC_FINAL0_B_MAPPING_SIGNED_NEGATE 0x00e00000 |
#define NV10_3D_RC_FINAL0_A_INPUT__MASK 0x0f000000 |
#define NV10_3D_RC_FINAL0_A_INPUT__SHIFT 24 |
#define NV10_3D_RC_FINAL0_A_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_CONSTANT_COLOR0 0x01000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_CONSTANT_COLOR1 0x02000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_FOG 0x03000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_PRIMARY_COLOR 0x04000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_SECONDARY_COLOR 0x05000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_TEXTURE0 0x08000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_TEXTURE1 0x09000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_TEXTURE2 0x0a000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_TEXTURE3 0x0b000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_SPARE0 0x0c000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_SPARE1 0x0d000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000 |
#define NV10_3D_RC_FINAL0_A_INPUT_E_TIMES_F 0x0f000000 |
#define NV10_3D_RC_FINAL0_A_COMPONENT_USAGE__MASK 0x10000000 |
#define NV10_3D_RC_FINAL0_A_COMPONENT_USAGE__SHIFT 28 |
#define NV10_3D_RC_FINAL0_A_COMPONENT_USAGE_RGB 0x00000000 |
#define NV10_3D_RC_FINAL0_A_COMPONENT_USAGE_ALPHA 0x10000000 |
#define NV10_3D_RC_FINAL0_A_MAPPING__MASK 0xe0000000 |
#define NV10_3D_RC_FINAL0_A_MAPPING__SHIFT 29 |
#define NV10_3D_RC_FINAL0_A_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_FINAL0_A_MAPPING_UNSIGNED_INVERT 0x20000000 |
#define NV10_3D_RC_FINAL0_A_MAPPING_EXPAND_NORMAL 0x40000000 |
#define NV10_3D_RC_FINAL0_A_MAPPING_EXPAND_NEGATE 0x60000000 |
#define NV10_3D_RC_FINAL0_A_MAPPING_HALF_BIAS_NORMAL 0x80000000 |
#define NV10_3D_RC_FINAL0_A_MAPPING_HALF_BIAS_NEGATE 0xa0000000 |
#define NV10_3D_RC_FINAL0_A_MAPPING_SIGNED_IDENTITY 0xc0000000 |
#define NV10_3D_RC_FINAL0_A_MAPPING_SIGNED_NEGATE 0xe0000000 |
#define NV10_3D_RC_FINAL1 0x0000028c |
#define NV10_3D_RC_FINAL1_COLOR_SUM_CLAMP 0x00000080 |
#define NV10_3D_RC_FINAL1_G_INPUT__MASK 0x00000f00 |
#define NV10_3D_RC_FINAL1_G_INPUT__SHIFT 8 |
#define NV10_3D_RC_FINAL1_G_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_FINAL1_G_INPUT_CONSTANT_COLOR0 0x00000100 |
#define NV10_3D_RC_FINAL1_G_INPUT_CONSTANT_COLOR1 0x00000200 |
#define NV10_3D_RC_FINAL1_G_INPUT_FOG 0x00000300 |
#define NV10_3D_RC_FINAL1_G_INPUT_PRIMARY_COLOR 0x00000400 |
#define NV10_3D_RC_FINAL1_G_INPUT_SECONDARY_COLOR 0x00000500 |
#define NV10_3D_RC_FINAL1_G_INPUT_TEXTURE0 0x00000800 |
#define NV10_3D_RC_FINAL1_G_INPUT_TEXTURE1 0x00000900 |
#define NV10_3D_RC_FINAL1_G_INPUT_TEXTURE2 0x00000a00 |
#define NV10_3D_RC_FINAL1_G_INPUT_TEXTURE3 0x00000b00 |
#define NV10_3D_RC_FINAL1_G_INPUT_SPARE0 0x00000c00 |
#define NV10_3D_RC_FINAL1_G_INPUT_SPARE1 0x00000d00 |
#define NV10_3D_RC_FINAL1_G_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV10_3D_RC_FINAL1_G_INPUT_E_TIMES_F 0x00000f00 |
#define NV10_3D_RC_FINAL1_G_COMPONENT_USAGE__MASK 0x00001000 |
#define NV10_3D_RC_FINAL1_G_COMPONENT_USAGE__SHIFT 12 |
#define NV10_3D_RC_FINAL1_G_COMPONENT_USAGE_RGB 0x00000000 |
#define NV10_3D_RC_FINAL1_G_COMPONENT_USAGE_ALPHA 0x00001000 |
#define NV10_3D_RC_FINAL1_G_MAPPING__MASK 0x0000e000 |
#define NV10_3D_RC_FINAL1_G_MAPPING__SHIFT 13 |
#define NV10_3D_RC_FINAL1_G_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_FINAL1_G_MAPPING_UNSIGNED_INVERT 0x00002000 |
#define NV10_3D_RC_FINAL1_G_MAPPING_EXPAND_NORMAL 0x00004000 |
#define NV10_3D_RC_FINAL1_G_MAPPING_EXPAND_NEGATE 0x00006000 |
#define NV10_3D_RC_FINAL1_G_MAPPING_HALF_BIAS_NORMAL 0x00008000 |
#define NV10_3D_RC_FINAL1_G_MAPPING_HALF_BIAS_NEGATE 0x0000a000 |
#define NV10_3D_RC_FINAL1_G_MAPPING_SIGNED_IDENTITY 0x0000c000 |
#define NV10_3D_RC_FINAL1_G_MAPPING_SIGNED_NEGATE 0x0000e000 |
#define NV10_3D_RC_FINAL1_F_INPUT__MASK 0x000f0000 |
#define NV10_3D_RC_FINAL1_F_INPUT__SHIFT 16 |
#define NV10_3D_RC_FINAL1_F_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_FINAL1_F_INPUT_CONSTANT_COLOR0 0x00010000 |
#define NV10_3D_RC_FINAL1_F_INPUT_CONSTANT_COLOR1 0x00020000 |
#define NV10_3D_RC_FINAL1_F_INPUT_FOG 0x00030000 |
#define NV10_3D_RC_FINAL1_F_INPUT_PRIMARY_COLOR 0x00040000 |
#define NV10_3D_RC_FINAL1_F_INPUT_SECONDARY_COLOR 0x00050000 |
#define NV10_3D_RC_FINAL1_F_INPUT_TEXTURE0 0x00080000 |
#define NV10_3D_RC_FINAL1_F_INPUT_TEXTURE1 0x00090000 |
#define NV10_3D_RC_FINAL1_F_INPUT_TEXTURE2 0x000a0000 |
#define NV10_3D_RC_FINAL1_F_INPUT_TEXTURE3 0x000b0000 |
#define NV10_3D_RC_FINAL1_F_INPUT_SPARE0 0x000c0000 |
#define NV10_3D_RC_FINAL1_F_INPUT_SPARE1 0x000d0000 |
#define NV10_3D_RC_FINAL1_F_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000 |
#define NV10_3D_RC_FINAL1_F_INPUT_E_TIMES_F 0x000f0000 |
#define NV10_3D_RC_FINAL1_F_COMPONENT_USAGE__MASK 0x00100000 |
#define NV10_3D_RC_FINAL1_F_COMPONENT_USAGE__SHIFT 20 |
#define NV10_3D_RC_FINAL1_F_COMPONENT_USAGE_RGB 0x00000000 |
#define NV10_3D_RC_FINAL1_F_COMPONENT_USAGE_ALPHA 0x00100000 |
#define NV10_3D_RC_FINAL1_F_MAPPING__MASK 0x00e00000 |
#define NV10_3D_RC_FINAL1_F_MAPPING__SHIFT 21 |
#define NV10_3D_RC_FINAL1_F_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_FINAL1_F_MAPPING_UNSIGNED_INVERT 0x00200000 |
#define NV10_3D_RC_FINAL1_F_MAPPING_EXPAND_NORMAL 0x00400000 |
#define NV10_3D_RC_FINAL1_F_MAPPING_EXPAND_NEGATE 0x00600000 |
#define NV10_3D_RC_FINAL1_F_MAPPING_HALF_BIAS_NORMAL 0x00800000 |
#define NV10_3D_RC_FINAL1_F_MAPPING_HALF_BIAS_NEGATE 0x00a00000 |
#define NV10_3D_RC_FINAL1_F_MAPPING_SIGNED_IDENTITY 0x00c00000 |
#define NV10_3D_RC_FINAL1_F_MAPPING_SIGNED_NEGATE 0x00e00000 |
#define NV10_3D_RC_FINAL1_E_INPUT__MASK 0x0f000000 |
#define NV10_3D_RC_FINAL1_E_INPUT__SHIFT 24 |
#define NV10_3D_RC_FINAL1_E_INPUT_ZERO 0x00000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_CONSTANT_COLOR0 0x01000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_CONSTANT_COLOR1 0x02000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_FOG 0x03000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_PRIMARY_COLOR 0x04000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_SECONDARY_COLOR 0x05000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_TEXTURE0 0x08000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_TEXTURE1 0x09000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_TEXTURE2 0x0a000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_TEXTURE3 0x0b000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_SPARE0 0x0c000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_SPARE1 0x0d000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000 |
#define NV10_3D_RC_FINAL1_E_INPUT_E_TIMES_F 0x0f000000 |
#define NV10_3D_RC_FINAL1_E_COMPONENT_USAGE__MASK 0x10000000 |
#define NV10_3D_RC_FINAL1_E_COMPONENT_USAGE__SHIFT 28 |
#define NV10_3D_RC_FINAL1_E_COMPONENT_USAGE_RGB 0x00000000 |
#define NV10_3D_RC_FINAL1_E_COMPONENT_USAGE_ALPHA 0x10000000 |
#define NV10_3D_RC_FINAL1_E_MAPPING__MASK 0xe0000000 |
#define NV10_3D_RC_FINAL1_E_MAPPING__SHIFT 29 |
#define NV10_3D_RC_FINAL1_E_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV10_3D_RC_FINAL1_E_MAPPING_UNSIGNED_INVERT 0x20000000 |
#define NV10_3D_RC_FINAL1_E_MAPPING_EXPAND_NORMAL 0x40000000 |
#define NV10_3D_RC_FINAL1_E_MAPPING_EXPAND_NEGATE 0x60000000 |
#define NV10_3D_RC_FINAL1_E_MAPPING_HALF_BIAS_NORMAL 0x80000000 |
#define NV10_3D_RC_FINAL1_E_MAPPING_HALF_BIAS_NEGATE 0xa0000000 |
#define NV10_3D_RC_FINAL1_E_MAPPING_SIGNED_IDENTITY 0xc0000000 |
#define NV10_3D_RC_FINAL1_E_MAPPING_SIGNED_NEGATE 0xe0000000 |
#define NV17_3D_DMA_HIERZ 0x000001b0 |
#define NV17_3D_HIERZ_PITCH 0x00000d5c |
#define NV17_3D_HIERZ_OFFSET 0x00000d60 |
#define NV17_3D_HIERZ_FILL_VALUE 0x00000d68 |
#define NV17_3D_HIERZ_BUFFER_CLEAR 0x00000d6c |
#define NV17_3D_UNK0D74 0x00000d74 |
#define NV17_3D_UNK0D84 0x00000d84 |
#define NV17_3D_HIERZ_WINDOW 0x00001638 |
#define NV17_3D_HIERZ_WINDOW_X 0x00001638 |
#define NV17_3D_HIERZ_WINDOW_Y 0x0000163c |
#define NV17_3D_HIERZ_WINDOW_Z 0x00001640 |
#define NV17_3D_HIERZ_WINDOW_W 0x00001644 |
#define NV17_3D_HIERZ_ENABLE 0x00001658 |
#define NV17_3D_UNK01AC 0x000001ac |
#define NV17_3D_UNK0258 0x00000258 |
#define NV17_3D_UNK025C 0x0000025c |
#define NV10_3D_UNK0290 0x00000290 |
#define NV17_3D_COLOR_MASK_ENABLE 0x000002bc |
#define NV10_3D_UNK03F0 0x000003f0 |
#define NV10_3D_UNK03F4 0x000003f4 |
#define NV17_3D_ZCLEAR_ENABLE 0x000003f8 |
#define NV17_3D_ZCLEAR_VALUE 0x000003fc |
#define NV17_3D_ZCLEAR_VALUE_DEPTH__MASK 0xffffff00 |
#define NV17_3D_ZCLEAR_VALUE_DEPTH__SHIFT 8 |
#define NV17_3D_ZCLEAR_VALUE_SEQUENCE__MASK 0x000000ff |
#define NV17_3D_ZCLEAR_VALUE_SEQUENCE__SHIFT 0 |
#define NV10_3D_POINT_SIZE 0x000003ec |
#define NV10_3D_POINT_PARAMETER(i0) (0x000006f8 + 0x4*(i0)) |
#define NV10_3D_POINT_PARAMETER__ESIZE 0x00000004 |
#define NV10_3D_POINT_PARAMETER__LEN 0x00000008 |
#define NV11_3D_COLOR_LOGIC_OP 0x00000d40 |
#define NV11_3D_COLOR_LOGIC_OP_ENABLE 0x00000d40 |
#define NV11_3D_COLOR_LOGIC_OP_OP 0x00000d44 |
#define NV11_3D_COLOR_LOGIC_OP_OP_CLEAR 0x00001500 |
#define NV11_3D_COLOR_LOGIC_OP_OP_AND 0x00001501 |
#define NV11_3D_COLOR_LOGIC_OP_OP_AND_REVERSE 0x00001502 |
#define NV11_3D_COLOR_LOGIC_OP_OP_COPY 0x00001503 |
#define NV11_3D_COLOR_LOGIC_OP_OP_AND_INVERTED 0x00001504 |
#define NV11_3D_COLOR_LOGIC_OP_OP_NOOP 0x00001505 |
#define NV11_3D_COLOR_LOGIC_OP_OP_XOR 0x00001506 |
#define NV11_3D_COLOR_LOGIC_OP_OP_OR 0x00001507 |
#define NV11_3D_COLOR_LOGIC_OP_OP_NOR 0x00001508 |
#define NV11_3D_COLOR_LOGIC_OP_OP_EQUIV 0x00001509 |
#define NV11_3D_COLOR_LOGIC_OP_OP_INVERT 0x0000150a |
#define NV11_3D_COLOR_LOGIC_OP_OP_OR_REVERSE 0x0000150b |
#define NV11_3D_COLOR_LOGIC_OP_OP_COPY_INVERTED 0x0000150c |
#define NV11_3D_COLOR_LOGIC_OP_OP_OR_INVERTED 0x0000150d |
#define NV11_3D_COLOR_LOGIC_OP_OP_NAND 0x0000150e |
#define NV11_3D_COLOR_LOGIC_OP_OP_SET 0x0000150f |
#endif /* NV10_3D_XML */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv10_context.c |
---|
0,0 → 1,574 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 <stdbool.h> |
#include "main/state.h" |
#include "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_fbo.h" |
#include "nouveau_util.h" |
#include "nv_object.xml.h" |
#include "nv10_3d.xml.h" |
#include "nv04_driver.h" |
#include "nv10_driver.h" |
static GLboolean |
use_fast_zclear(struct gl_context *ctx, GLbitfield buffers) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
if (buffers & BUFFER_BIT_STENCIL) { |
/* |
* The stencil test is bypassed when fast Z clears are |
* enabled. |
*/ |
nctx->hierz.clear_blocked = GL_TRUE; |
context_dirty(ctx, ZCLEAR); |
return GL_FALSE; |
} |
return !nctx->hierz.clear_blocked && |
fb->_Xmax == fb->Width && fb->_Xmin == 0 && |
fb->_Ymax == fb->Height && fb->_Ymin == 0; |
} |
GLboolean |
nv10_use_viewport_zclear(struct gl_context *ctx) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; |
return context_chipset(ctx) < 0x17 && |
!nctx->hierz.clear_blocked && depthRb && |
(_mesa_get_format_bits(depthRb->Format, |
GL_DEPTH_BITS) >= 24); |
} |
float |
nv10_transform_depth(struct gl_context *ctx, float z) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
if (nv10_use_viewport_zclear(ctx)) |
return 2097152.0 * (z + (nctx->hierz.clear_seq & 7)); |
else |
return ctx->DrawBuffer->_DepthMaxF * z; |
} |
static void |
nv10_zclear(struct gl_context *ctx, GLbitfield *buffers) |
{ |
/* |
* Pre-nv17 cards don't have native support for fast Z clears, |
* but in some cases we can still "clear" the Z buffer without |
* actually blitting to it if we're willing to sacrifice a few |
* bits of depth precision. |
* |
* Each time a clear is requested we modify the viewport |
* transform in such a way that the old contents of the depth |
* buffer are clamped to the requested clear value when |
* they're read by the GPU. |
*/ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb); |
struct nouveau_surface *s = &to_nouveau_renderbuffer( |
fb->Attachment[BUFFER_DEPTH].Renderbuffer)->surface; |
if (nv10_use_viewport_zclear(ctx)) { |
int x, y, w, h; |
float z = ctx->Depth.Clear; |
uint32_t value = pack_zs_f(s->format, z, 0); |
get_scissors(fb, &x, &y, &w, &h); |
*buffers &= ~BUFFER_BIT_DEPTH; |
if (use_fast_zclear(ctx, *buffers)) { |
if (nfb->hierz.clear_value != value) { |
/* Don't fast clear if we're changing |
* the depth value. */ |
nfb->hierz.clear_value = value; |
} else if (z == 0.0) { |
nctx->hierz.clear_seq++; |
context_dirty(ctx, ZCLEAR); |
if ((nctx->hierz.clear_seq & 7) != 0 && |
nctx->hierz.clear_seq != 1) |
/* We didn't wrap around -- no need to |
* clear the depth buffer for real. */ |
return; |
} else if (z == 1.0) { |
nctx->hierz.clear_seq--; |
context_dirty(ctx, ZCLEAR); |
if ((nctx->hierz.clear_seq & 7) != 7) |
/* No wrap around */ |
return; |
} |
} |
value = pack_zs_f(s->format, |
(z + (nctx->hierz.clear_seq & 7)) / 8, 0); |
context_drv(ctx)->surface_fill(ctx, s, ~0, value, x, y, w, h); |
} |
} |
static void |
nv17_zclear(struct gl_context *ctx, GLbitfield *buffers) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_framebuffer *nfb = to_nouveau_framebuffer( |
ctx->DrawBuffer); |
struct nouveau_surface *s = &to_nouveau_renderbuffer( |
nfb->base.Attachment[BUFFER_DEPTH].Renderbuffer)->surface; |
/* Clear the hierarchical depth buffer */ |
BEGIN_NV04(push, NV17_3D(HIERZ_FILL_VALUE), 1); |
PUSH_DATA (push, pack_zs_f(s->format, ctx->Depth.Clear, 0)); |
BEGIN_NV04(push, NV17_3D(HIERZ_BUFFER_CLEAR), 1); |
PUSH_DATA (push, 1); |
/* Mark the depth buffer as cleared */ |
if (use_fast_zclear(ctx, *buffers)) { |
if (nctx->hierz.clear_seq) |
*buffers &= ~BUFFER_BIT_DEPTH; |
nfb->hierz.clear_value = |
pack_zs_f(s->format, ctx->Depth.Clear, 0); |
nctx->hierz.clear_seq++; |
context_dirty(ctx, ZCLEAR); |
} |
} |
static void |
nv10_clear(struct gl_context *ctx, GLbitfield buffers) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
nouveau_validate_framebuffer(ctx); |
nouveau_pushbuf_bufctx(push, nctx->hw.bufctx); |
if (nouveau_pushbuf_validate(push)) { |
nouveau_pushbuf_bufctx(push, NULL); |
return; |
} |
if ((buffers & BUFFER_BIT_DEPTH) && ctx->Depth.Mask) { |
if (context_chipset(ctx) >= 0x17) |
nv17_zclear(ctx, &buffers); |
else |
nv10_zclear(ctx, &buffers); |
/* Emit the zclear state if it's dirty */ |
_mesa_update_state(ctx); |
} |
nouveau_pushbuf_bufctx(push, NULL); |
nouveau_clear(ctx, buffers); |
} |
static void |
nv10_hwctx_init(struct gl_context *ctx) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; |
struct nv04_fifo *fifo = hw->chan->data; |
int i; |
BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1); |
PUSH_DATA (push, hw->eng3d->handle); |
BEGIN_NV04(push, NV10_3D(DMA_NOTIFY), 1); |
PUSH_DATA (push, hw->ntfy->handle); |
BEGIN_NV04(push, NV10_3D(DMA_TEXTURE0), 3); |
PUSH_DATA (push, fifo->vram); |
PUSH_DATA (push, fifo->gart); |
PUSH_DATA (push, fifo->gart); |
BEGIN_NV04(push, NV10_3D(DMA_COLOR), 2); |
PUSH_DATA (push, fifo->vram); |
PUSH_DATA (push, fifo->vram); |
BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(RT_HORIZ), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_HORIZ(0)), 1); |
PUSH_DATA (push, 0x7ff << 16 | 0x800); |
BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_VERT(0)), 1); |
PUSH_DATA (push, 0x7ff << 16 | 0x800); |
for (i = 1; i < 8; i++) { |
BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_HORIZ(i)), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_VERT(i)), 1); |
PUSH_DATA (push, 0); |
} |
BEGIN_NV04(push, SUBC_3D(0x290), 1); |
PUSH_DATA (push, 0x10 << 16 | 1); |
BEGIN_NV04(push, SUBC_3D(0x3f4), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1); |
PUSH_DATA (push, 0); |
if (context_chipset(ctx) >= 0x17) { |
BEGIN_NV04(push, NV17_3D(UNK01AC), 2); |
PUSH_DATA (push, fifo->vram); |
PUSH_DATA (push, fifo->vram); |
BEGIN_NV04(push, SUBC_3D(0xd84), 1); |
PUSH_DATA (push, 0x3); |
BEGIN_NV04(push, NV17_3D(COLOR_MASK_ENABLE), 1); |
PUSH_DATA (push, 1); |
} |
if (context_chipset(ctx) >= 0x11) { |
BEGIN_NV04(push, SUBC_3D(0x120), 3); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 1); |
PUSH_DATA (push, 2); |
BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1); |
PUSH_DATA (push, 0); |
} |
BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1); |
PUSH_DATA (push, 0); |
/* Set state */ |
BEGIN_NV04(push, NV10_3D(FOG_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(ALPHA_FUNC_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(ALPHA_FUNC_FUNC), 2); |
PUSH_DATA (push, 0x207); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(TEX_ENABLE(0)), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(BLEND_FUNC_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(DITHER_ENABLE), 2); |
PUSH_DATA (push, 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(LINE_SMOOTH_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(VERTEX_WEIGHT_ENABLE), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(BLEND_FUNC_SRC), 4); |
PUSH_DATA (push, 1); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0x8006); |
BEGIN_NV04(push, NV10_3D(STENCIL_MASK), 8); |
PUSH_DATA (push, 0xff); |
PUSH_DATA (push, 0x207); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0xff); |
PUSH_DATA (push, 0x1e00); |
PUSH_DATA (push, 0x1e00); |
PUSH_DATA (push, 0x1e00); |
PUSH_DATA (push, 0x1d01); |
BEGIN_NV04(push, NV10_3D(NORMALIZE_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(FOG_ENABLE), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(LIGHT_MODEL), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(SEPARATE_SPECULAR_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(ENABLED_LIGHTS), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(POLYGON_OFFSET_POINT_ENABLE), 3); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(DEPTH_FUNC), 1); |
PUSH_DATA (push, 0x201); |
BEGIN_NV04(push, NV10_3D(DEPTH_WRITE_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(DEPTH_TEST_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(POLYGON_OFFSET_FACTOR), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(POINT_SIZE), 1); |
PUSH_DATA (push, 8); |
BEGIN_NV04(push, NV10_3D(POINT_PARAMETERS_ENABLE), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(LINE_WIDTH), 1); |
PUSH_DATA (push, 8); |
BEGIN_NV04(push, NV10_3D(LINE_SMOOTH_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(POLYGON_MODE_FRONT), 2); |
PUSH_DATA (push, 0x1b02); |
PUSH_DATA (push, 0x1b02); |
BEGIN_NV04(push, NV10_3D(CULL_FACE), 2); |
PUSH_DATA (push, 0x405); |
PUSH_DATA (push, 0x901); |
BEGIN_NV04(push, NV10_3D(POLYGON_SMOOTH_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(CULL_FACE_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(TEX_GEN_MODE(0, 0)), 8); |
for (i = 0; i < 8; i++) |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(0)), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(FOG_COEFF(0)), 3); |
PUSH_DATA (push, 0x3fc00000); /* -1.50 */ |
PUSH_DATA (push, 0xbdb8aa0a); /* -0.09 */ |
PUSH_DATA (push, 0); /* 0.00 */ |
BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(FOG_MODE), 2); |
PUSH_DATA (push, 0x802); |
PUSH_DATA (push, 2); |
/* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when |
* using texturing, except when using the texture matrix |
*/ |
BEGIN_NV04(push, NV10_3D(VIEW_MATRIX_ENABLE), 1); |
PUSH_DATA (push, 6); |
BEGIN_NV04(push, NV10_3D(COLOR_MASK), 1); |
PUSH_DATA (push, 0x01010101); |
/* Set vertex component */ |
BEGIN_NV04(push, NV10_3D(VERTEX_COL_4F_R), 4); |
PUSH_DATAf(push, 1.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 1.0); |
BEGIN_NV04(push, NV10_3D(VERTEX_COL2_3F_R), 3); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV10_3D(VERTEX_NOR_3F_X), 3); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
PUSH_DATAf(push, 1.0); |
BEGIN_NV04(push, NV10_3D(VERTEX_TX0_4F_S), 4); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 1.0); |
BEGIN_NV04(push, NV10_3D(VERTEX_TX1_4F_S), 4); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 1.0); |
BEGIN_NV04(push, NV10_3D(VERTEX_FOG_1F), 1); |
PUSH_DATAf(push, 0.0); |
BEGIN_NV04(push, NV10_3D(EDGEFLAG_ENABLE), 1); |
PUSH_DATA (push, 1); |
BEGIN_NV04(push, NV10_3D(DEPTH_RANGE_NEAR), 2); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 16777216.0); |
PUSH_KICK (push); |
} |
static void |
nv10_context_destroy(struct gl_context *ctx) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
nv04_surface_takedown(ctx); |
nv10_swtnl_destroy(ctx); |
nv10_vbo_destroy(ctx); |
nouveau_object_del(&nctx->hw.eng3d); |
nouveau_context_deinit(ctx); |
free(ctx); |
} |
static struct gl_context * |
nv10_context_create(struct nouveau_screen *screen, const struct gl_config *visual, |
struct gl_context *share_ctx) |
{ |
struct nouveau_context *nctx; |
struct gl_context *ctx; |
unsigned celsius_class; |
int ret; |
nctx = CALLOC_STRUCT(nouveau_context); |
if (!nctx) |
return NULL; |
ctx = &nctx->base; |
if (!nouveau_context_init(ctx, screen, visual, share_ctx)) |
goto fail; |
ctx->Extensions.ARB_texture_env_crossbar = true; |
ctx->Extensions.ARB_texture_env_combine = true; |
ctx->Extensions.ARB_texture_env_dot3 = true; |
ctx->Extensions.NV_fog_distance = true; |
ctx->Extensions.NV_texture_rectangle = true; |
if (ctx->Mesa_DXTn) { |
ctx->Extensions.EXT_texture_compression_s3tc = true; |
ctx->Extensions.ANGLE_texture_compression_dxt = true; |
} |
/* GL constants. */ |
ctx->Const.MaxTextureLevels = 12; |
ctx->Const.MaxTextureCoordUnits = NV10_TEXTURE_UNITS; |
ctx->Const.FragmentProgram.MaxTextureImageUnits = NV10_TEXTURE_UNITS; |
ctx->Const.MaxTextureUnits = NV10_TEXTURE_UNITS; |
ctx->Const.MaxTextureMaxAnisotropy = 2; |
ctx->Const.MaxTextureLodBias = 15; |
ctx->Driver.Clear = nv10_clear; |
/* 2D engine. */ |
ret = nv04_surface_init(ctx); |
if (!ret) |
goto fail; |
/* 3D engine. */ |
if (context_chipset(ctx) >= 0x17 && context_chipset(ctx) != 0x1a) |
celsius_class = NV17_3D_CLASS; |
else if (context_chipset(ctx) >= 0x11) |
celsius_class = NV15_3D_CLASS; |
else |
celsius_class = NV10_3D_CLASS; |
ret = nouveau_object_new(context_chan(ctx), 0xbeef0001, celsius_class, |
NULL, 0, &nctx->hw.eng3d); |
if (ret) |
goto fail; |
nv10_hwctx_init(ctx); |
nv10_vbo_init(ctx); |
nv10_swtnl_init(ctx); |
return ctx; |
fail: |
nv10_context_destroy(ctx); |
return NULL; |
} |
const struct nouveau_driver nv10_driver = { |
.context_create = nv10_context_create, |
.context_destroy = nv10_context_destroy, |
.surface_copy = nv04_surface_copy, |
.surface_fill = nv04_surface_fill, |
.emit = (nouveau_state_func[]) { |
nv10_emit_alpha_func, |
nv10_emit_blend_color, |
nv10_emit_blend_equation, |
nv10_emit_blend_func, |
nv10_emit_clip_plane, |
nv10_emit_clip_plane, |
nv10_emit_clip_plane, |
nv10_emit_clip_plane, |
nv10_emit_clip_plane, |
nv10_emit_clip_plane, |
nv10_emit_color_mask, |
nv10_emit_color_material, |
nv10_emit_cull_face, |
nv10_emit_front_face, |
nv10_emit_depth, |
nv10_emit_dither, |
nv10_emit_frag, |
nv10_emit_framebuffer, |
nv10_emit_fog, |
nv10_emit_light_enable, |
nv10_emit_light_model, |
nv10_emit_light_source, |
nv10_emit_light_source, |
nv10_emit_light_source, |
nv10_emit_light_source, |
nv10_emit_light_source, |
nv10_emit_light_source, |
nv10_emit_light_source, |
nv10_emit_light_source, |
nv10_emit_line_stipple, |
nv10_emit_line_mode, |
nv10_emit_logic_opcode, |
nv10_emit_material_ambient, |
nouveau_emit_nothing, |
nv10_emit_material_diffuse, |
nouveau_emit_nothing, |
nv10_emit_material_specular, |
nouveau_emit_nothing, |
nv10_emit_material_shininess, |
nouveau_emit_nothing, |
nv10_emit_modelview, |
nv10_emit_point_mode, |
nv10_emit_point_parameter, |
nv10_emit_polygon_mode, |
nv10_emit_polygon_offset, |
nv10_emit_polygon_stipple, |
nv10_emit_projection, |
nv10_emit_render_mode, |
nv10_emit_scissor, |
nv10_emit_shade_model, |
nv10_emit_stencil_func, |
nv10_emit_stencil_mask, |
nv10_emit_stencil_op, |
nv10_emit_tex_env, |
nv10_emit_tex_env, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nv10_emit_tex_gen, |
nv10_emit_tex_gen, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nv10_emit_tex_mat, |
nv10_emit_tex_mat, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nv10_emit_tex_obj, |
nv10_emit_tex_obj, |
nouveau_emit_nothing, |
nouveau_emit_nothing, |
nv10_emit_viewport, |
nv10_emit_zclear |
}, |
.num_emit = NUM_NV10_STATE, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv10_driver.h |
---|
0,0 → 1,211 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NV10_DRIVER_H__ |
#define __NV10_DRIVER_H__ |
enum { |
NOUVEAU_STATE_ZCLEAR = NUM_NOUVEAU_STATE, |
NUM_NV10_STATE |
}; |
#define NV10_TEXTURE_UNITS 2 |
/* nv10_context.c */ |
extern const struct nouveau_driver nv10_driver; |
GLboolean |
nv10_use_viewport_zclear(struct gl_context *ctx); |
float |
nv10_transform_depth(struct gl_context *ctx, float z); |
/* nv10_render.c */ |
void |
nv10_vbo_init(struct gl_context *ctx); |
void |
nv10_vbo_destroy(struct gl_context *ctx); |
void |
nv10_swtnl_init(struct gl_context *ctx); |
void |
nv10_swtnl_destroy(struct gl_context *ctx); |
/* nv10_state_fb.c */ |
void |
nv10_emit_framebuffer(struct gl_context *ctx, int emit); |
void |
nv10_emit_render_mode(struct gl_context *ctx, int emit); |
void |
nv10_emit_scissor(struct gl_context *ctx, int emit); |
void |
nv10_emit_viewport(struct gl_context *ctx, int emit); |
void |
nv10_emit_zclear(struct gl_context *ctx, int emit); |
/* nv10_state_polygon.c */ |
void |
nv10_emit_cull_face(struct gl_context *ctx, int emit); |
void |
nv10_emit_front_face(struct gl_context *ctx, int emit); |
void |
nv10_emit_line_mode(struct gl_context *ctx, int emit); |
void |
nv10_emit_line_stipple(struct gl_context *ctx, int emit); |
void |
nv10_emit_point_mode(struct gl_context *ctx, int emit); |
void |
nv10_emit_polygon_mode(struct gl_context *ctx, int emit); |
void |
nv10_emit_polygon_offset(struct gl_context *ctx, int emit); |
void |
nv10_emit_polygon_stipple(struct gl_context *ctx, int emit); |
/* nv10_state_raster.c */ |
void |
nv10_emit_alpha_func(struct gl_context *ctx, int emit); |
void |
nv10_emit_blend_color(struct gl_context *ctx, int emit); |
void |
nv10_emit_blend_equation(struct gl_context *ctx, int emit); |
void |
nv10_emit_blend_func(struct gl_context *ctx, int emit); |
void |
nv10_emit_color_mask(struct gl_context *ctx, int emit); |
void |
nv10_emit_depth(struct gl_context *ctx, int emit); |
void |
nv10_emit_dither(struct gl_context *ctx, int emit); |
void |
nv10_emit_logic_opcode(struct gl_context *ctx, int emit); |
void |
nv10_emit_shade_model(struct gl_context *ctx, int emit); |
void |
nv10_emit_stencil_func(struct gl_context *ctx, int emit); |
void |
nv10_emit_stencil_mask(struct gl_context *ctx, int emit); |
void |
nv10_emit_stencil_op(struct gl_context *ctx, int emit); |
/* nv10_state_frag.c */ |
void |
nv10_get_general_combiner(struct gl_context *ctx, int i, |
uint32_t *a_in, uint32_t *a_out, |
uint32_t *c_in, uint32_t *c_out, uint32_t *k); |
void |
nv10_get_final_combiner(struct gl_context *ctx, uint64_t *in, int *n); |
void |
nv10_emit_tex_env(struct gl_context *ctx, int emit); |
void |
nv10_emit_frag(struct gl_context *ctx, int emit); |
/* nv10_state_tex.c */ |
void |
nv10_emit_tex_gen(struct gl_context *ctx, int emit); |
void |
nv10_emit_tex_mat(struct gl_context *ctx, int emit); |
void |
nv10_emit_tex_obj(struct gl_context *ctx, int emit); |
/* nv10_state_tnl.c */ |
void |
nv10_get_fog_coeff(struct gl_context *ctx, float k[3]); |
void |
nv10_get_spot_coeff(struct gl_light *l, float k[7]); |
void |
nv10_get_shininess_coeff(float s, float k[6]); |
void |
nv10_emit_clip_plane(struct gl_context *ctx, int emit); |
void |
nv10_emit_color_material(struct gl_context *ctx, int emit); |
void |
nv10_emit_fog(struct gl_context *ctx, int emit); |
void |
nv10_emit_light_enable(struct gl_context *ctx, int emit); |
void |
nv10_emit_light_model(struct gl_context *ctx, int emit); |
void |
nv10_emit_light_source(struct gl_context *ctx, int emit); |
void |
nv10_emit_material_ambient(struct gl_context *ctx, int emit); |
void |
nv10_emit_material_diffuse(struct gl_context *ctx, int emit); |
void |
nv10_emit_material_specular(struct gl_context *ctx, int emit); |
void |
nv10_emit_material_shininess(struct gl_context *ctx, int emit); |
void |
nv10_emit_modelview(struct gl_context *ctx, int emit); |
void |
nv10_emit_point_parameter(struct gl_context *ctx, int emit); |
void |
nv10_emit_projection(struct gl_context *ctx, int emit); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv10_render.c |
---|
0,0 → 1,200 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nv10_3d.xml.h" |
#include "nv10_driver.h" |
#define NUM_VERTEX_ATTRS 8 |
static void |
nv10_emit_material(struct gl_context *ctx, struct nouveau_array *a, |
const void *v); |
/* Vertex attribute format. */ |
static struct nouveau_attr_info nv10_vertex_attrs[VERT_ATTRIB_MAX] = { |
[VERT_ATTRIB_POS] = { |
.vbo_index = 0, |
.imm_method = NV10_3D_VERTEX_POS_4F_X, |
.imm_fields = 4, |
}, |
[VERT_ATTRIB_COLOR0] = { |
.vbo_index = 1, |
.imm_method = NV10_3D_VERTEX_COL_4F_R, |
.imm_fields = 4, |
}, |
[VERT_ATTRIB_COLOR1] = { |
.vbo_index = 2, |
.imm_method = NV10_3D_VERTEX_COL2_3F_R, |
.imm_fields = 3, |
}, |
[VERT_ATTRIB_TEX0] = { |
.vbo_index = 3, |
.imm_method = NV10_3D_VERTEX_TX0_4F_S, |
.imm_fields = 4, |
}, |
[VERT_ATTRIB_TEX1] = { |
.vbo_index = 4, |
.imm_method = NV10_3D_VERTEX_TX1_4F_S, |
.imm_fields = 4, |
}, |
[VERT_ATTRIB_NORMAL] = { |
.vbo_index = 5, |
.imm_method = NV10_3D_VERTEX_NOR_3F_X, |
.imm_fields = 3, |
}, |
[VERT_ATTRIB_FOG] = { |
.vbo_index = 7, |
.imm_method = NV10_3D_VERTEX_FOG_1F, |
.imm_fields = 1, |
}, |
[VERT_ATTRIB_GENERIC0] = { |
.emit = nv10_emit_material, |
}, |
[VERT_ATTRIB_GENERIC2] = { |
.emit = nv10_emit_material, |
}, |
[VERT_ATTRIB_GENERIC4] = { |
.emit = nv10_emit_material, |
}, |
[VERT_ATTRIB_GENERIC6] = { |
.emit = nv10_emit_material, |
}, |
[VERT_ATTRIB_GENERIC8] = { |
.emit = nv10_emit_material, |
}, |
}; |
static int |
get_hw_format(int type) |
{ |
switch (type) { |
case GL_FLOAT: |
return NV10_3D_VTXBUF_FMT_TYPE_V32_FLOAT; |
case GL_SHORT: |
case GL_UNSIGNED_SHORT: |
return NV10_3D_VTXBUF_FMT_TYPE_V16_SNORM; |
case GL_UNSIGNED_BYTE: |
return NV10_3D_VTXBUF_FMT_TYPE_U8_UNORM; |
default: |
assert(0); |
} |
} |
static void |
nv10_render_set_format(struct gl_context *ctx) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
int i, attr, hw_format; |
FOR_EACH_ATTR(render, i, attr) { |
if (attr >= 0) { |
struct nouveau_array *a = &render->attrs[attr]; |
hw_format = a->stride << 8 | |
a->fields << 4 | |
get_hw_format(a->type); |
if (attr == VERT_ATTRIB_POS && a->fields == 4) |
hw_format |= NV10_3D_VTXBUF_FMT_HOMOGENEOUS; |
} else { |
/* Unused attribute. */ |
hw_format = NV10_3D_VTXBUF_FMT_TYPE_V32_FLOAT; |
} |
BEGIN_NV04(push, NV10_3D(VTXBUF_FMT(i)), 1); |
PUSH_DATA (push, hw_format); |
} |
} |
static void |
nv10_render_bind_vertices(struct gl_context *ctx) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
int i, attr; |
FOR_EACH_BOUND_ATTR(render, i, attr) { |
struct nouveau_array *a = &render->attrs[attr]; |
BEGIN_NV04(push, NV10_3D(VTXBUF_OFFSET(i)), 1); |
PUSH_MTHDl(push, NV10_3D(VTXBUF_OFFSET(i)), BUFCTX_VTX, |
a->bo, a->offset, NOUVEAU_BO_GART | |
NOUVEAU_BO_RD); |
} |
} |
static void |
nv10_render_release_vertices(struct gl_context *ctx) |
{ |
PUSH_RESET(context_push(ctx), BUFCTX_VTX); |
} |
/* Vertex array rendering defs. */ |
#define RENDER_LOCALS(ctx) |
#define BATCH_VALIDATE() \ |
BEGIN_NV04(push, NV10_3D(VTXBUF_VALIDATE), 1); \ |
PUSH_DATA (push, 0) |
#define BATCH_BEGIN(prim) \ |
BEGIN_NV04(push, NV10_3D(VTXBUF_BEGIN_END), 1); \ |
PUSH_DATA (push, prim) |
#define BATCH_END() \ |
BEGIN_NV04(push, NV10_3D(VTXBUF_BEGIN_END), 1); \ |
PUSH_DATA (push, 0) |
#define MAX_PACKET 0x400 |
#define MAX_OUT_L 0x100 |
#define BATCH_PACKET_L(n) \ |
BEGIN_NI04(push, NV10_3D(VTXBUF_BATCH), n) |
#define BATCH_OUT_L(i, n) \ |
PUSH_DATA (push, ((n) - 1) << 24 | (i)) |
#define MAX_OUT_I16 0x2 |
#define BATCH_PACKET_I16(n) \ |
BEGIN_NI04(push, NV10_3D(VTXBUF_ELEMENT_U16), n) |
#define BATCH_OUT_I16(i0, i1) \ |
PUSH_DATA (push, (i1) << 16 | (i0)) |
#define MAX_OUT_I32 0x1 |
#define BATCH_PACKET_I32(n) \ |
BEGIN_NI04(push, NV10_3D(VTXBUF_ELEMENT_U32), n) |
#define BATCH_OUT_I32(i) \ |
PUSH_DATA (push, i) |
#define IMM_PACKET(m, n) \ |
BEGIN_NV04(push, SUBC_3D(m), n) |
#define IMM_OUT(x) \ |
PUSH_DATAf(push, x) |
#define TAG(x) nv10_##x |
#include "nouveau_render_t.c" |
#include "nouveau_vbo_t.c" |
#include "nouveau_swtnl_t.c" |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv10_state_fb.c |
---|
0,0 → 1,219 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_fbo.h" |
#include "nouveau_util.h" |
#include "nv_object.xml.h" |
#include "nv10_3d.xml.h" |
#include "nv10_driver.h" |
static inline unsigned |
get_rt_format(gl_format format) |
{ |
switch (format) { |
case MESA_FORMAT_XRGB8888: |
return NV10_3D_RT_FORMAT_COLOR_X8R8G8B8; |
case MESA_FORMAT_ARGB8888: |
return NV10_3D_RT_FORMAT_COLOR_A8R8G8B8; |
case MESA_FORMAT_RGB565: |
return NV10_3D_RT_FORMAT_COLOR_R5G6B5; |
case MESA_FORMAT_Z16: |
return NV10_3D_RT_FORMAT_DEPTH_Z16; |
case MESA_FORMAT_Z24_S8: |
return NV10_3D_RT_FORMAT_DEPTH_Z24S8; |
default: |
assert(0); |
} |
} |
static void |
setup_hierz_buffer(struct gl_context *ctx) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb); |
unsigned pitch = align(fb->Width, 128), |
height = align(fb->Height, 2), |
size = pitch * height; |
if (!nfb->hierz.bo || nfb->hierz.bo->size != size) { |
union nouveau_bo_config config = { |
.nv04.surf_flags = NV04_BO_ZETA, |
.nv04.surf_pitch = 0 |
}; |
nouveau_bo_ref(NULL, &nfb->hierz.bo); |
nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_VRAM, 0, size, |
&config, &nfb->hierz.bo); |
} |
PUSH_SPACE(push, 11); |
BEGIN_NV04(push, NV17_3D(HIERZ_OFFSET), 1); |
PUSH_MTHDl(push, NV17_3D(HIERZ_OFFSET), BUFCTX_FB, |
nfb->hierz.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); |
BEGIN_NV04(push, NV17_3D(HIERZ_WINDOW_X), 4); |
PUSH_DATAf(push, - 1792); |
PUSH_DATAf(push, - 2304 + fb->Height); |
PUSH_DATAf(push, fb->_DepthMaxF / 2); |
PUSH_DATAf(push, 0); |
BEGIN_NV04(push, NV17_3D(HIERZ_PITCH), 1); |
PUSH_DATA (push, pitch); |
BEGIN_NV04(push, NV17_3D(HIERZ_ENABLE), 1); |
PUSH_DATA (push, 1); |
} |
void |
nv10_emit_framebuffer(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct nouveau_surface *s; |
unsigned rt_format = NV10_3D_RT_FORMAT_TYPE_LINEAR; |
unsigned rt_pitch = 0, zeta_pitch = 0; |
unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR; |
if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) |
return; |
PUSH_RESET(push, BUFCTX_FB); |
/* At least nv11 seems to get sad if we don't do this before |
* swapping RTs.*/ |
if (context_chipset(ctx) < 0x17) { |
int i; |
for (i = 0; i < 6; i++) { |
BEGIN_NV04(push, NV04_GRAPH(3D, NOP), 1); |
PUSH_DATA (push, 0); |
} |
} |
/* Render target */ |
if (fb->_ColorDrawBuffers[0]) { |
s = &to_nouveau_renderbuffer( |
fb->_ColorDrawBuffers[0])->surface; |
rt_format |= get_rt_format(s->format); |
zeta_pitch = rt_pitch = s->pitch; |
BEGIN_NV04(push, NV10_3D(COLOR_OFFSET), 1); |
PUSH_MTHDl(push, NV10_3D(COLOR_OFFSET), BUFCTX_FB, |
s->bo, 0, bo_flags); |
} |
/* depth/stencil */ |
if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { |
s = &to_nouveau_renderbuffer( |
fb->Attachment[BUFFER_DEPTH].Renderbuffer)->surface; |
rt_format |= get_rt_format(s->format); |
zeta_pitch = s->pitch; |
BEGIN_NV04(push, NV10_3D(ZETA_OFFSET), 1); |
PUSH_MTHDl(push, NV10_3D(ZETA_OFFSET), BUFCTX_FB, |
s->bo, 0, bo_flags); |
if (context_chipset(ctx) >= 0x17) { |
setup_hierz_buffer(ctx); |
context_dirty(ctx, ZCLEAR); |
} |
} |
BEGIN_NV04(push, NV10_3D(RT_FORMAT), 2); |
PUSH_DATA (push, rt_format); |
PUSH_DATA (push, zeta_pitch << 16 | rt_pitch); |
context_dirty(ctx, VIEWPORT); |
context_dirty(ctx, SCISSOR); |
} |
void |
nv10_emit_render_mode(struct gl_context *ctx, int emit) |
{ |
} |
void |
nv10_emit_scissor(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
int x, y, w, h; |
get_scissors(ctx->DrawBuffer, &x, &y, &w, &h); |
BEGIN_NV04(push, NV10_3D(RT_HORIZ), 2); |
PUSH_DATA (push, w << 16 | x); |
PUSH_DATA (push, h << 16 | y); |
} |
void |
nv10_emit_viewport(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_viewport_attrib *vp = &ctx->Viewport; |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
float a[4] = {}; |
get_viewport_translate(ctx, a); |
a[0] -= 2048; |
a[1] -= 2048; |
if (nv10_use_viewport_zclear(ctx)) |
a[2] = nv10_transform_depth(ctx, (vp->Far + vp->Near) / 2); |
BEGIN_NV04(push, NV10_3D(VIEWPORT_TRANSLATE_X), 4); |
PUSH_DATAp(push, a, 4); |
BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_HORIZ(0)), 1); |
PUSH_DATA (push, (fb->Width - 1) << 16 | 0x08000800); |
BEGIN_NV04(push, NV10_3D(VIEWPORT_CLIP_VERT(0)), 1); |
PUSH_DATA (push, (fb->Height - 1) << 16 | 0x08000800); |
context_dirty(ctx, PROJECTION); |
} |
void |
nv10_emit_zclear(struct gl_context *ctx, int emit) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_framebuffer *nfb = |
to_nouveau_framebuffer(ctx->DrawBuffer); |
if (nfb->hierz.bo) { |
BEGIN_NV04(push, NV17_3D(ZCLEAR_ENABLE), 2); |
PUSH_DATAb(push, !nctx->hierz.clear_blocked); |
PUSH_DATA (push, nfb->hierz.clear_value | |
(nctx->hierz.clear_seq & 0xff)); |
} else { |
BEGIN_NV04(push, NV10_3D(DEPTH_RANGE_NEAR), 2); |
PUSH_DATAf(push, nv10_transform_depth(ctx, 0)); |
PUSH_DATAf(push, nv10_transform_depth(ctx, 1)); |
context_dirty(ctx, VIEWPORT); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv10_state_frag.c |
---|
0,0 → 1,411 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_gldefs.h" |
#include "nv10_3d.xml.h" |
#include "nouveau_util.h" |
#include "nv10_driver.h" |
#include "nv20_driver.h" |
#define RC_IN_SHIFT_A 24 |
#define RC_IN_SHIFT_B 16 |
#define RC_IN_SHIFT_C 8 |
#define RC_IN_SHIFT_D 0 |
#define RC_IN_SHIFT_E 56 |
#define RC_IN_SHIFT_F 48 |
#define RC_IN_SHIFT_G 40 |
#define RC_IN_SOURCE(source) \ |
((uint64_t)NV10_3D_RC_IN_RGB_D_INPUT_##source) |
#define RC_IN_USAGE(usage) \ |
((uint64_t)NV10_3D_RC_IN_RGB_D_COMPONENT_USAGE_##usage) |
#define RC_IN_MAPPING(mapping) \ |
((uint64_t)NV10_3D_RC_IN_RGB_D_MAPPING_##mapping) |
#define RC_OUT_BIAS NV10_3D_RC_OUT_RGB_BIAS_BIAS_BY_NEGATIVE_ONE_HALF |
#define RC_OUT_SCALE_1 NV10_3D_RC_OUT_RGB_SCALE_NONE |
#define RC_OUT_SCALE_2 NV10_3D_RC_OUT_RGB_SCALE_SCALE_BY_TWO |
#define RC_OUT_SCALE_4 NV10_3D_RC_OUT_RGB_SCALE_SCALE_BY_FOUR |
/* Make the combiner do: spare0_i = A_i * B_i */ |
#define RC_OUT_AB NV10_3D_RC_OUT_RGB_AB_OUTPUT_SPARE0 |
/* spare0_i = dot3(A, B) */ |
#define RC_OUT_DOT_AB (NV10_3D_RC_OUT_RGB_AB_OUTPUT_SPARE0 | \ |
NV10_3D_RC_OUT_RGB_AB_DOT_PRODUCT) |
/* spare0_i = A_i * B_i + C_i * D_i */ |
#define RC_OUT_SUM NV10_3D_RC_OUT_RGB_SUM_OUTPUT_SPARE0 |
struct combiner_state { |
struct gl_context *ctx; |
int unit; |
GLboolean premodulate; |
/* GL state */ |
GLenum mode; |
GLenum *source; |
GLenum *operand; |
GLuint logscale; |
/* Derived HW state */ |
uint64_t in; |
uint32_t out; |
}; |
/* Initialize a combiner_state struct from the texture unit |
* context. */ |
#define INIT_COMBINER(chan, ctx, rc, i) do { \ |
struct gl_tex_env_combine_state *c = \ |
ctx->Texture.Unit[i]._CurrentCombine; \ |
(rc)->ctx = ctx; \ |
(rc)->unit = i; \ |
(rc)->premodulate = c->_NumArgs##chan == 4; \ |
(rc)->mode = c->Mode##chan; \ |
(rc)->source = c->Source##chan; \ |
(rc)->operand = c->Operand##chan; \ |
(rc)->logscale = c->ScaleShift##chan; \ |
(rc)->in = (rc)->out = 0; \ |
} while (0) |
/* Get the RC input source for the specified EXT_texture_env_combine |
* source. */ |
static uint32_t |
get_input_source(struct combiner_state *rc, int source) |
{ |
switch (source) { |
case GL_ZERO: |
return RC_IN_SOURCE(ZERO); |
case GL_TEXTURE: |
return RC_IN_SOURCE(TEXTURE0) + rc->unit; |
case GL_TEXTURE0: |
return RC_IN_SOURCE(TEXTURE0); |
case GL_TEXTURE1: |
return RC_IN_SOURCE(TEXTURE1); |
case GL_TEXTURE2: |
return RC_IN_SOURCE(TEXTURE2); |
case GL_TEXTURE3: |
return RC_IN_SOURCE(TEXTURE3); |
case GL_CONSTANT: |
return context_chipset(rc->ctx) >= 0x20 ? |
RC_IN_SOURCE(CONSTANT_COLOR0) : |
RC_IN_SOURCE(CONSTANT_COLOR0) + rc->unit; |
case GL_PRIMARY_COLOR: |
return RC_IN_SOURCE(PRIMARY_COLOR); |
case GL_PREVIOUS: |
return rc->unit ? RC_IN_SOURCE(SPARE0) |
: RC_IN_SOURCE(PRIMARY_COLOR); |
default: |
assert(0); |
} |
} |
/* Get the RC input mapping for the specified texture_env_combine |
* operand, possibly inverted or biased. */ |
#define INVERT 0x1 |
#define HALF_BIAS 0x2 |
static uint32_t |
get_input_mapping(struct combiner_state *rc, int operand, int flags) |
{ |
int map = 0; |
if (is_color_operand(operand)) |
map |= RC_IN_USAGE(RGB); |
else |
map |= RC_IN_USAGE(ALPHA); |
if (is_negative_operand(operand) == !(flags & INVERT)) |
map |= flags & HALF_BIAS ? |
RC_IN_MAPPING(HALF_BIAS_NEGATE) : |
RC_IN_MAPPING(UNSIGNED_INVERT); |
else |
map |= flags & HALF_BIAS ? |
RC_IN_MAPPING(HALF_BIAS_NORMAL) : |
RC_IN_MAPPING(UNSIGNED_IDENTITY); |
return map; |
} |
static uint32_t |
get_input_arg(struct combiner_state *rc, int arg, int flags) |
{ |
int source = rc->source[arg]; |
int operand = rc->operand[arg]; |
/* Fake several unsupported texture formats. */ |
if (is_texture_source(source)) { |
int i = (source == GL_TEXTURE ? |
rc->unit : source - GL_TEXTURE0); |
struct gl_texture_object *t = rc->ctx->Texture.Unit[i]._Current; |
gl_format format = t->Image[0][t->BaseLevel]->TexFormat; |
if (format == MESA_FORMAT_A8) { |
/* Emulated using I8. */ |
if (is_color_operand(operand)) |
return RC_IN_SOURCE(ZERO) | |
get_input_mapping(rc, operand, flags); |
} else if (format == MESA_FORMAT_L8) { |
/* Sometimes emulated using I8. */ |
if (!is_color_operand(operand)) |
return RC_IN_SOURCE(ZERO) | |
get_input_mapping(rc, operand, |
flags ^ INVERT); |
} else if (format == MESA_FORMAT_XRGB8888) { |
/* Sometimes emulated using ARGB8888. */ |
if (!is_color_operand(operand)) |
return RC_IN_SOURCE(ZERO) | |
get_input_mapping(rc, operand, |
flags ^ INVERT); |
} |
} |
return get_input_source(rc, source) | |
get_input_mapping(rc, operand, flags); |
} |
/* Bind the RC input variable <var> to the EXT_texture_env_combine |
* argument <arg>, possibly inverted or biased. */ |
#define INPUT_ARG(rc, var, arg, flags) \ |
(rc)->in |= get_input_arg(rc, arg, flags) << RC_IN_SHIFT_##var |
/* Bind the RC input variable <var> to the RC source <src>. */ |
#define INPUT_SRC(rc, var, src, chan) \ |
(rc)->in |= (RC_IN_SOURCE(src) | \ |
RC_IN_USAGE(chan)) << RC_IN_SHIFT_##var |
/* Bind the RC input variable <var> to a constant +/-1 */ |
#define INPUT_ONE(rc, var, flags) \ |
(rc)->in |= (RC_IN_SOURCE(ZERO) | \ |
(flags & INVERT ? RC_IN_MAPPING(EXPAND_NORMAL) : \ |
RC_IN_MAPPING(UNSIGNED_INVERT))) << RC_IN_SHIFT_##var |
static void |
setup_combiner(struct combiner_state *rc) |
{ |
switch (rc->mode) { |
case GL_REPLACE: |
INPUT_ARG(rc, A, 0, 0); |
INPUT_ONE(rc, B, 0); |
rc->out = RC_OUT_AB; |
break; |
case GL_MODULATE: |
INPUT_ARG(rc, A, 0, 0); |
INPUT_ARG(rc, B, 1, 0); |
rc->out = RC_OUT_AB; |
break; |
case GL_ADD: |
case GL_ADD_SIGNED: |
if (rc->premodulate) { |
INPUT_ARG(rc, A, 0, 0); |
INPUT_ARG(rc, B, 1, 0); |
INPUT_ARG(rc, C, 2, 0); |
INPUT_ARG(rc, D, 3, 0); |
} else { |
INPUT_ARG(rc, A, 0, 0); |
INPUT_ONE(rc, B, 0); |
INPUT_ARG(rc, C, 1, 0); |
INPUT_ONE(rc, D, 0); |
} |
rc->out = RC_OUT_SUM | |
(rc->mode == GL_ADD_SIGNED ? RC_OUT_BIAS : 0); |
break; |
case GL_INTERPOLATE: |
INPUT_ARG(rc, A, 0, 0); |
INPUT_ARG(rc, B, 2, 0); |
INPUT_ARG(rc, C, 1, 0); |
INPUT_ARG(rc, D, 2, INVERT); |
rc->out = RC_OUT_SUM; |
break; |
case GL_SUBTRACT: |
INPUT_ARG(rc, A, 0, 0); |
INPUT_ONE(rc, B, 0); |
INPUT_ARG(rc, C, 1, 0); |
INPUT_ONE(rc, D, INVERT); |
rc->out = RC_OUT_SUM; |
break; |
case GL_DOT3_RGB: |
case GL_DOT3_RGBA: |
INPUT_ARG(rc, A, 0, HALF_BIAS); |
INPUT_ARG(rc, B, 1, HALF_BIAS); |
rc->out = RC_OUT_DOT_AB | RC_OUT_SCALE_4; |
assert(!rc->logscale); |
break; |
default: |
assert(0); |
} |
switch (rc->logscale) { |
case 0: |
rc->out |= RC_OUT_SCALE_1; |
break; |
case 1: |
rc->out |= RC_OUT_SCALE_2; |
break; |
case 2: |
rc->out |= RC_OUT_SCALE_4; |
break; |
default: |
assert(0); |
} |
} |
void |
nv10_get_general_combiner(struct gl_context *ctx, int i, |
uint32_t *a_in, uint32_t *a_out, |
uint32_t *c_in, uint32_t *c_out, uint32_t *k) |
{ |
struct combiner_state rc_a, rc_c; |
if (ctx->Texture.Unit[i]._ReallyEnabled) { |
INIT_COMBINER(RGB, ctx, &rc_c, i); |
if (rc_c.mode == GL_DOT3_RGBA) |
rc_a = rc_c; |
else |
INIT_COMBINER(A, ctx, &rc_a, i); |
setup_combiner(&rc_c); |
setup_combiner(&rc_a); |
} else { |
rc_a.in = rc_a.out = rc_c.in = rc_c.out = 0; |
} |
*k = pack_rgba_f(MESA_FORMAT_ARGB8888, |
ctx->Texture.Unit[i].EnvColor); |
*a_in = rc_a.in; |
*a_out = rc_a.out; |
*c_in = rc_c.in; |
*c_out = rc_c.out; |
} |
void |
nv10_get_final_combiner(struct gl_context *ctx, uint64_t *in, int *n) |
{ |
struct combiner_state rc = {}; |
/* |
* The final fragment value equation is something like: |
* x_i = A_i * B_i + (1 - A_i) * C_i + D_i |
* x_alpha = G_alpha |
* where D_i = E_i * F_i, i one of {red, green, blue}. |
*/ |
if (ctx->Fog.ColorSumEnabled || ctx->Light.Enabled) { |
INPUT_SRC(&rc, D, E_TIMES_F, RGB); |
INPUT_SRC(&rc, F, SECONDARY_COLOR, RGB); |
} |
if (ctx->Fog.Enabled) { |
INPUT_SRC(&rc, A, FOG, ALPHA); |
INPUT_SRC(&rc, C, FOG, RGB); |
INPUT_SRC(&rc, E, FOG, ALPHA); |
} else { |
INPUT_ONE(&rc, A, 0); |
INPUT_ONE(&rc, C, 0); |
INPUT_ONE(&rc, E, 0); |
} |
if (ctx->Texture._EnabledUnits) { |
INPUT_SRC(&rc, B, SPARE0, RGB); |
INPUT_SRC(&rc, G, SPARE0, ALPHA); |
} else { |
INPUT_SRC(&rc, B, PRIMARY_COLOR, RGB); |
INPUT_SRC(&rc, G, PRIMARY_COLOR, ALPHA); |
} |
*in = rc.in; |
*n = log2i(ctx->Texture._EnabledUnits) + 1; |
} |
void |
nv10_emit_tex_env(struct gl_context *ctx, int emit) |
{ |
const int i = emit - NOUVEAU_STATE_TEX_ENV0; |
struct nouveau_pushbuf *push = context_push(ctx); |
uint32_t a_in, a_out, c_in, c_out, k; |
nv10_get_general_combiner(ctx, i, &a_in, &a_out, &c_in, &c_out, &k); |
/* Enable the combiners we're going to need. */ |
if (i == 1) { |
if (c_out || a_out) |
c_out |= 0x5 << 27; |
else |
c_out |= 0x3 << 27; |
} |
BEGIN_NV04(push, NV10_3D(RC_IN_ALPHA(i)), 1); |
PUSH_DATA (push, a_in); |
BEGIN_NV04(push, NV10_3D(RC_IN_RGB(i)), 1); |
PUSH_DATA (push, c_in); |
BEGIN_NV04(push, NV10_3D(RC_COLOR(i)), 1); |
PUSH_DATA (push, k); |
BEGIN_NV04(push, NV10_3D(RC_OUT_ALPHA(i)), 1); |
PUSH_DATA (push, a_out); |
BEGIN_NV04(push, NV10_3D(RC_OUT_RGB(i)), 1); |
PUSH_DATA (push, c_out); |
context_dirty(ctx, FRAG); |
} |
void |
nv10_emit_frag(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
uint64_t in; |
int n; |
nv10_get_final_combiner(ctx, &in, &n); |
BEGIN_NV04(push, NV10_3D(RC_FINAL0), 2); |
PUSH_DATA (push, in); |
PUSH_DATA (push, in >> 32); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv10_state_polygon.c |
---|
0,0 → 1,121 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_gldefs.h" |
#include "nouveau_util.h" |
#include "nv10_3d.xml.h" |
#include "nv10_driver.h" |
void |
nv10_emit_cull_face(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
GLenum mode = ctx->Polygon.CullFaceMode; |
BEGIN_NV04(push, NV10_3D(CULL_FACE_ENABLE), 1); |
PUSH_DATAb(push, ctx->Polygon.CullFlag); |
BEGIN_NV04(push, NV10_3D(CULL_FACE), 1); |
PUSH_DATA (push, (mode == GL_FRONT ? NV10_3D_CULL_FACE_FRONT : |
mode == GL_BACK ? NV10_3D_CULL_FACE_BACK : |
NV10_3D_CULL_FACE_FRONT_AND_BACK)); |
} |
void |
nv10_emit_front_face(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(FRONT_FACE), 1); |
PUSH_DATA (push, ctx->Polygon.FrontFace == GL_CW ? |
NV10_3D_FRONT_FACE_CW : NV10_3D_FRONT_FACE_CCW); |
} |
void |
nv10_emit_line_mode(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
GLboolean smooth = ctx->Line.SmoothFlag && |
ctx->Hint.LineSmooth == GL_NICEST; |
BEGIN_NV04(push, NV10_3D(LINE_WIDTH), 1); |
PUSH_DATA (push, MAX2(smooth ? 0 : 1, |
ctx->Line.Width) * 8); |
BEGIN_NV04(push, NV10_3D(LINE_SMOOTH_ENABLE), 1); |
PUSH_DATAb(push, smooth); |
} |
void |
nv10_emit_line_stipple(struct gl_context *ctx, int emit) |
{ |
} |
void |
nv10_emit_point_mode(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(POINT_SIZE), 1); |
PUSH_DATA (push, (uint32_t)(ctx->Point.Size * 8)); |
BEGIN_NV04(push, NV10_3D(POINT_SMOOTH_ENABLE), 1); |
PUSH_DATAb(push, ctx->Point.SmoothFlag); |
} |
void |
nv10_emit_polygon_mode(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(POLYGON_MODE_FRONT), 2); |
PUSH_DATA (push, nvgl_polygon_mode(ctx->Polygon.FrontMode)); |
PUSH_DATA (push, nvgl_polygon_mode(ctx->Polygon.BackMode)); |
BEGIN_NV04(push, NV10_3D(POLYGON_SMOOTH_ENABLE), 1); |
PUSH_DATAb(push, ctx->Polygon.SmoothFlag); |
} |
void |
nv10_emit_polygon_offset(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(POLYGON_OFFSET_POINT_ENABLE), 3); |
PUSH_DATAb(push, ctx->Polygon.OffsetPoint); |
PUSH_DATAb(push, ctx->Polygon.OffsetLine); |
PUSH_DATAb(push, ctx->Polygon.OffsetFill); |
BEGIN_NV04(push, NV10_3D(POLYGON_OFFSET_FACTOR), 2); |
PUSH_DATAf(push, ctx->Polygon.OffsetFactor); |
PUSH_DATAf(push, ctx->Polygon.OffsetUnits); |
} |
void |
nv10_emit_polygon_stipple(struct gl_context *ctx, int emit) |
{ |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv10_state_raster.c |
---|
0,0 → 1,172 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_gldefs.h" |
#include "nouveau_util.h" |
#include "nv10_3d.xml.h" |
#include "nv10_driver.h" |
#include "main/stencil.h" |
void |
nv10_emit_alpha_func(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(ALPHA_FUNC_ENABLE), 1); |
PUSH_DATAb(push, ctx->Color.AlphaEnabled); |
BEGIN_NV04(push, NV10_3D(ALPHA_FUNC_FUNC), 2); |
PUSH_DATA (push, nvgl_comparison_op(ctx->Color.AlphaFunc)); |
PUSH_DATA (push, FLOAT_TO_UBYTE(ctx->Color.AlphaRef)); |
} |
void |
nv10_emit_blend_color(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(BLEND_COLOR), 1); |
PUSH_DATA (push, FLOAT_TO_UBYTE(ctx->Color.BlendColor[3]) << 24 | |
FLOAT_TO_UBYTE(ctx->Color.BlendColor[0]) << 16 | |
FLOAT_TO_UBYTE(ctx->Color.BlendColor[1]) << 8 | |
FLOAT_TO_UBYTE(ctx->Color.BlendColor[2]) << 0); |
} |
void |
nv10_emit_blend_equation(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(BLEND_FUNC_ENABLE), 1); |
PUSH_DATAb(push, ctx->Color.BlendEnabled); |
BEGIN_NV04(push, NV10_3D(BLEND_EQUATION), 1); |
PUSH_DATA (push, nvgl_blend_eqn(ctx->Color.Blend[0].EquationRGB)); |
} |
void |
nv10_emit_blend_func(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(BLEND_FUNC_SRC), 2); |
PUSH_DATA (push, nvgl_blend_func(ctx->Color.Blend[0].SrcRGB)); |
PUSH_DATA (push, nvgl_blend_func(ctx->Color.Blend[0].DstRGB)); |
} |
void |
nv10_emit_color_mask(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(COLOR_MASK), 1); |
PUSH_DATA (push, ((ctx->Color.ColorMask[0][3] ? 1 << 24 : 0) | |
(ctx->Color.ColorMask[0][0] ? 1 << 16 : 0) | |
(ctx->Color.ColorMask[0][1] ? 1 << 8 : 0) | |
(ctx->Color.ColorMask[0][2] ? 1 << 0 : 0))); |
} |
void |
nv10_emit_depth(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(DEPTH_TEST_ENABLE), 1); |
PUSH_DATAb(push, ctx->Depth.Test); |
BEGIN_NV04(push, NV10_3D(DEPTH_WRITE_ENABLE), 1); |
PUSH_DATAb(push, ctx->Depth.Mask); |
BEGIN_NV04(push, NV10_3D(DEPTH_FUNC), 1); |
PUSH_DATA (push, nvgl_comparison_op(ctx->Depth.Func)); |
} |
void |
nv10_emit_dither(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(DITHER_ENABLE), 1); |
PUSH_DATAb(push, ctx->Color.DitherFlag); |
} |
void |
nv10_emit_logic_opcode(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
assert(!ctx->Color.ColorLogicOpEnabled |
|| context_chipset(ctx) >= 0x11); |
BEGIN_NV04(push, NV11_3D(COLOR_LOGIC_OP_ENABLE), 2); |
PUSH_DATAb(push, ctx->Color.ColorLogicOpEnabled); |
PUSH_DATA (push, nvgl_logicop_func(ctx->Color.LogicOp)); |
} |
void |
nv10_emit_shade_model(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(SHADE_MODEL), 1); |
PUSH_DATA (push, ctx->Light.ShadeModel == GL_SMOOTH ? |
NV10_3D_SHADE_MODEL_SMOOTH : NV10_3D_SHADE_MODEL_FLAT); |
} |
void |
nv10_emit_stencil_func(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(STENCIL_ENABLE), 1); |
PUSH_DATAb(push, ctx->Stencil.Enabled); |
BEGIN_NV04(push, NV10_3D(STENCIL_FUNC_FUNC), 3); |
PUSH_DATA (push, nvgl_comparison_op(ctx->Stencil.Function[0])); |
PUSH_DATA (push, _mesa_get_stencil_ref(ctx, 0)); |
PUSH_DATA (push, ctx->Stencil.ValueMask[0]); |
} |
void |
nv10_emit_stencil_mask(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(STENCIL_MASK), 1); |
PUSH_DATA (push, ctx->Stencil.WriteMask[0]); |
} |
void |
nv10_emit_stencil_op(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV10_3D(STENCIL_OP_FAIL), 3); |
PUSH_DATA (push, nvgl_stencil_op(ctx->Stencil.FailFunc[0])); |
PUSH_DATA (push, nvgl_stencil_op(ctx->Stencil.ZFailFunc[0])); |
PUSH_DATA (push, nvgl_stencil_op(ctx->Stencil.ZPassFunc[0])); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv10_state_tex.c |
---|
0,0 → 1,240 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_gldefs.h" |
#include "nouveau_texture.h" |
#include "nv10_3d.xml.h" |
#include "nouveau_util.h" |
#include "nv10_driver.h" |
#include "main/samplerobj.h" |
void |
nv10_emit_tex_gen(struct gl_context *ctx, int emit) |
{ |
const int i = emit - NOUVEAU_STATE_TEX_GEN0; |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_texture_unit *unit = &ctx->Texture.Unit[i]; |
int j; |
for (j = 0; j < 4; j++) { |
if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) { |
struct gl_texgen *coord = get_texgen_coord(unit, j); |
float *k = get_texgen_coeff(coord); |
if (k) { |
BEGIN_NV04(push, NV10_3D(TEX_GEN_COEFF(i, j)), 4); |
PUSH_DATAp(push, k, 4); |
} |
BEGIN_NV04(push, NV10_3D(TEX_GEN_MODE(i,j)), 1); |
PUSH_DATA (push, nvgl_texgen_mode(coord->Mode)); |
} else { |
BEGIN_NV04(push, NV10_3D(TEX_GEN_MODE(i,j)), 1); |
PUSH_DATA (push, 0); |
} |
} |
context_dirty_i(ctx, TEX_MAT, i); |
} |
void |
nv10_emit_tex_mat(struct gl_context *ctx, int emit) |
{ |
const int i = emit - NOUVEAU_STATE_TEX_MAT0; |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
if (nctx->fallback == HWTNL && |
((ctx->Texture._TexMatEnabled & 1 << i) || |
ctx->Texture.Unit[i]._GenFlags)) { |
BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(i)), 1); |
PUSH_DATA (push, 1); |
BEGIN_NV04(push, NV10_3D(TEX_MATRIX(i, 0)), 16); |
PUSH_DATAm(push, ctx->TextureMatrixStack[i].Top->m); |
} else { |
BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(i)), 1); |
PUSH_DATA (push, 0); |
} |
} |
static uint32_t |
get_tex_format_pot(struct gl_texture_image *ti) |
{ |
switch (ti->TexFormat) { |
case MESA_FORMAT_ARGB8888: |
return NV10_3D_TEX_FORMAT_FORMAT_A8R8G8B8; |
case MESA_FORMAT_XRGB8888: |
return NV10_3D_TEX_FORMAT_FORMAT_X8R8G8B8; |
case MESA_FORMAT_ARGB1555: |
return NV10_3D_TEX_FORMAT_FORMAT_A1R5G5B5; |
case MESA_FORMAT_ARGB4444: |
return NV10_3D_TEX_FORMAT_FORMAT_A4R4G4B4; |
case MESA_FORMAT_RGB565: |
return NV10_3D_TEX_FORMAT_FORMAT_R5G6B5; |
case MESA_FORMAT_A8: |
case MESA_FORMAT_I8: |
return NV10_3D_TEX_FORMAT_FORMAT_I8; |
case MESA_FORMAT_L8: |
return NV10_3D_TEX_FORMAT_FORMAT_L8; |
case MESA_FORMAT_RGB_DXT1: |
case MESA_FORMAT_RGBA_DXT1: |
return NV10_3D_TEX_FORMAT_FORMAT_DXT1; |
case MESA_FORMAT_RGBA_DXT3: |
return NV10_3D_TEX_FORMAT_FORMAT_DXT3; |
case MESA_FORMAT_RGBA_DXT5: |
return NV10_3D_TEX_FORMAT_FORMAT_DXT5; |
default: |
assert(0); |
} |
} |
static uint32_t |
get_tex_format_rect(struct gl_texture_image *ti) |
{ |
switch (ti->TexFormat) { |
case MESA_FORMAT_ARGB1555: |
return NV10_3D_TEX_FORMAT_FORMAT_A1R5G5B5_RECT; |
case MESA_FORMAT_RGB565: |
return NV10_3D_TEX_FORMAT_FORMAT_R5G6B5_RECT; |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_XRGB8888: |
return NV10_3D_TEX_FORMAT_FORMAT_A8R8G8B8_RECT; |
case MESA_FORMAT_A8: |
case MESA_FORMAT_L8: |
case MESA_FORMAT_I8: |
return NV10_3D_TEX_FORMAT_FORMAT_I8_RECT; |
default: |
assert(0); |
} |
} |
void |
nv10_emit_tex_obj(struct gl_context *ctx, int emit) |
{ |
const int i = emit - NOUVEAU_STATE_TEX_OBJ0; |
struct nouveau_pushbuf *push = context_push(ctx); |
const int bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART | NOUVEAU_BO_VRAM; |
struct gl_texture_object *t; |
struct nouveau_surface *s; |
struct gl_texture_image *ti; |
const struct gl_sampler_object *sa; |
uint32_t tx_format, tx_filter, tx_enable; |
PUSH_RESET(push, BUFCTX_TEX(i)); |
if (!ctx->Texture.Unit[i]._ReallyEnabled) { |
BEGIN_NV04(push, NV10_3D(TEX_ENABLE(i)), 1); |
PUSH_DATA (push, 0); |
return; |
} |
t = ctx->Texture.Unit[i]._Current; |
s = &to_nouveau_texture(t)->surfaces[t->BaseLevel]; |
ti = t->Image[0][t->BaseLevel]; |
sa = _mesa_get_samplerobj(ctx, i); |
if (!nouveau_texture_validate(ctx, t)) |
return; |
/* Recompute the texturing registers. */ |
tx_format = nvgl_wrap_mode(sa->WrapT) << 28 |
| nvgl_wrap_mode(sa->WrapS) << 24 |
| ti->HeightLog2 << 20 |
| ti->WidthLog2 << 16 |
| 5 << 4 | 1 << 12; |
tx_filter = nvgl_filter_mode(sa->MagFilter) << 28 |
| nvgl_filter_mode(sa->MinFilter) << 24; |
tx_enable = NV10_3D_TEX_ENABLE_ENABLE |
| log2i(sa->MaxAnisotropy) << 4; |
if (t->Target == GL_TEXTURE_RECTANGLE) { |
BEGIN_NV04(push, NV10_3D(TEX_NPOT_PITCH(i)), 1); |
PUSH_DATA (push, s->pitch << 16); |
BEGIN_NV04(push, NV10_3D(TEX_NPOT_SIZE(i)), 1); |
PUSH_DATA (push, align(s->width, 2) << 16 | s->height); |
tx_format |= get_tex_format_rect(ti); |
} else { |
tx_format |= get_tex_format_pot(ti); |
} |
if (sa->MinFilter != GL_NEAREST && |
sa->MinFilter != GL_LINEAR) { |
int lod_min = sa->MinLod; |
int lod_max = MIN2(sa->MaxLod, t->_MaxLambda); |
int lod_bias = sa->LodBias |
+ ctx->Texture.Unit[i].LodBias; |
lod_max = CLAMP(lod_max, 0, 15); |
lod_min = CLAMP(lod_min, 0, 15); |
lod_bias = CLAMP(lod_bias, 0, 15); |
tx_format |= NV10_3D_TEX_FORMAT_MIPMAP; |
tx_filter |= lod_bias << 8; |
tx_enable |= lod_min << 26 |
| lod_max << 14; |
} |
/* Write it to the hardware. */ |
BEGIN_NV04(push, NV10_3D(TEX_FORMAT(i)), 1); |
PUSH_MTHD (push, NV10_3D(TEX_FORMAT(i)), BUFCTX_TEX(i), |
s->bo, tx_format, bo_flags | NOUVEAU_BO_OR, |
NV10_3D_TEX_FORMAT_DMA0, |
NV10_3D_TEX_FORMAT_DMA1); |
BEGIN_NV04(push, NV10_3D(TEX_OFFSET(i)), 1); |
PUSH_MTHDl(push, NV10_3D(TEX_OFFSET(i)), BUFCTX_TEX(i), |
s->bo, s->offset, bo_flags); |
BEGIN_NV04(push, NV10_3D(TEX_FILTER(i)), 1); |
PUSH_DATA (push, tx_filter); |
BEGIN_NV04(push, NV10_3D(TEX_ENABLE(i)), 1); |
PUSH_DATA (push, tx_enable); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv10_state_tnl.c |
---|
0,0 → 1,488 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_gldefs.h" |
#include "nouveau_util.h" |
#include "nv10_3d.xml.h" |
#include "nv10_driver.h" |
void |
nv10_emit_clip_plane(struct gl_context *ctx, int emit) |
{ |
} |
static inline unsigned |
get_material_bitmask(unsigned m) |
{ |
unsigned ret = 0; |
if (m & MAT_BIT_FRONT_EMISSION) |
ret |= NV10_3D_COLOR_MATERIAL_EMISSION; |
if (m & MAT_BIT_FRONT_AMBIENT) |
ret |= NV10_3D_COLOR_MATERIAL_AMBIENT; |
if (m & MAT_BIT_FRONT_DIFFUSE) |
ret |= NV10_3D_COLOR_MATERIAL_DIFFUSE; |
if (m & MAT_BIT_FRONT_SPECULAR) |
ret |= NV10_3D_COLOR_MATERIAL_SPECULAR; |
return ret; |
} |
void |
nv10_emit_color_material(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
unsigned mask = get_material_bitmask(ctx->Light._ColorMaterialBitmask); |
BEGIN_NV04(push, NV10_3D(COLOR_MATERIAL), 1); |
PUSH_DATA (push, ctx->Light.ColorMaterialEnabled ? mask : 0); |
} |
static unsigned |
get_fog_mode(unsigned mode) |
{ |
switch (mode) { |
case GL_LINEAR: |
return NV10_3D_FOG_MODE_LINEAR; |
case GL_EXP: |
return NV10_3D_FOG_MODE_EXP; |
case GL_EXP2: |
return NV10_3D_FOG_MODE_EXP2; |
default: |
assert(0); |
} |
} |
static unsigned |
get_fog_source(unsigned source, unsigned distance_mode) |
{ |
switch (source) { |
case GL_FOG_COORDINATE_EXT: |
return NV10_3D_FOG_COORD_FOG; |
case GL_FRAGMENT_DEPTH_EXT: |
switch (distance_mode) { |
case GL_EYE_PLANE_ABSOLUTE_NV: |
return NV10_3D_FOG_COORD_DIST_ORTHOGONAL_ABS; |
case GL_EYE_PLANE: |
return NV10_3D_FOG_COORD_DIST_ORTHOGONAL; |
case GL_EYE_RADIAL_NV: |
return NV10_3D_FOG_COORD_DIST_RADIAL; |
default: |
assert(0); |
} |
default: |
assert(0); |
} |
} |
void |
nv10_get_fog_coeff(struct gl_context *ctx, float k[3]) |
{ |
struct gl_fog_attrib *f = &ctx->Fog; |
switch (f->Mode) { |
case GL_LINEAR: |
k[0] = 2 + f->Start / (f->End - f->Start); |
k[1] = -1 / (f->End - f->Start); |
break; |
case GL_EXP: |
k[0] = 1.5; |
k[1] = -0.09 * f->Density; |
break; |
case GL_EXP2: |
k[0] = 1.5; |
k[1] = -0.21 * f->Density; |
break; |
default: |
assert(0); |
} |
k[2] = 0; |
} |
void |
nv10_emit_fog(struct gl_context *ctx, int emit) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_fog_attrib *f = &ctx->Fog; |
unsigned source = nctx->fallback == HWTNL ? |
f->FogCoordinateSource : GL_FOG_COORDINATE_EXT; |
float k[3]; |
nv10_get_fog_coeff(ctx, k); |
BEGIN_NV04(push, NV10_3D(FOG_MODE), 4); |
PUSH_DATA (push, get_fog_mode(f->Mode)); |
PUSH_DATA (push, get_fog_source(source, f->FogDistanceMode)); |
PUSH_DATAb(push, f->Enabled); |
PUSH_DATA (push, pack_rgba_f(MESA_FORMAT_RGBA8888_REV, f->Color)); |
BEGIN_NV04(push, NV10_3D(FOG_COEFF(0)), 3); |
PUSH_DATAp(push, k, 3); |
context_dirty(ctx, FRAG); |
} |
static inline unsigned |
get_light_mode(struct gl_light *l) |
{ |
if (l->Enabled) { |
if (l->_Flags & LIGHT_SPOT) |
return NV10_3D_ENABLED_LIGHTS_0_DIRECTIONAL; |
else if (l->_Flags & LIGHT_POSITIONAL) |
return NV10_3D_ENABLED_LIGHTS_0_POSITIONAL; |
else |
return NV10_3D_ENABLED_LIGHTS_0_NONPOSITIONAL; |
} else { |
return NV10_3D_ENABLED_LIGHTS_0_DISABLED; |
} |
} |
void |
nv10_emit_light_enable(struct gl_context *ctx, int emit) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
uint32_t en_lights = 0; |
int i; |
if (nctx->fallback != HWTNL) { |
BEGIN_NV04(push, NV10_3D(LIGHTING_ENABLE), 1); |
PUSH_DATA (push, 0); |
return; |
} |
for (i = 0; i < MAX_LIGHTS; i++) |
en_lights |= get_light_mode(&ctx->Light.Light[i]) << 2 * i; |
BEGIN_NV04(push, NV10_3D(ENABLED_LIGHTS), 1); |
PUSH_DATA (push, en_lights); |
BEGIN_NV04(push, NV10_3D(LIGHTING_ENABLE), 1); |
PUSH_DATAb(push, ctx->Light.Enabled); |
BEGIN_NV04(push, NV10_3D(NORMALIZE_ENABLE), 1); |
PUSH_DATAb(push, ctx->Transform.Normalize); |
} |
void |
nv10_emit_light_model(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_lightmodel *m = &ctx->Light.Model; |
BEGIN_NV04(push, NV10_3D(SEPARATE_SPECULAR_ENABLE), 1); |
PUSH_DATAb(push, m->ColorControl == GL_SEPARATE_SPECULAR_COLOR); |
BEGIN_NV04(push, NV10_3D(LIGHT_MODEL), 1); |
PUSH_DATA (push, ((m->LocalViewer ? |
NV10_3D_LIGHT_MODEL_LOCAL_VIEWER : 0) | |
(_mesa_need_secondary_color(ctx) ? |
NV10_3D_LIGHT_MODEL_SEPARATE_SPECULAR : 0) | |
(!ctx->Light.Enabled && ctx->Fog.ColorSumEnabled ? |
NV10_3D_LIGHT_MODEL_VERTEX_SPECULAR : 0))); |
} |
static float |
get_shine(const float p[], float x) |
{ |
const int n = 15; |
const float *y = &p[1]; |
float f = (n - 1) * (1 - 1 / (1 + p[0] * x)) |
/ (1 - 1 / (1 + p[0] * 1024)); |
int i = f; |
/* Linear interpolation in f-space (Faster and somewhat more |
* accurate than x-space). */ |
if (x == 0) |
return y[0]; |
else if (i > n - 2) |
return y[n - 1]; |
else |
return y[i] + (y[i + 1] - y[i]) * (f - i); |
} |
static const float nv10_spot_params[2][16] = { |
{ 0.02, -3.80e-05, -1.77, -2.41, -2.71, -2.88, -2.98, -3.06, |
-3.11, -3.17, -3.23, -3.28, -3.37, -3.47, -3.83, -5.11 }, |
{ 0.02, -0.01, 1.77, 2.39, 2.70, 2.87, 2.98, 3.06, |
3.10, 3.16, 3.23, 3.27, 3.37, 3.47, 3.83, 5.11 }, |
}; |
void |
nv10_get_spot_coeff(struct gl_light *l, float k[7]) |
{ |
float e = l->SpotExponent; |
float a0, b0, a1, a2, b2, a3; |
if (e > 0) |
a0 = -1 - 5.36e-3 / sqrt(e); |
else |
a0 = -1; |
b0 = 1 / (1 + 0.273 * e); |
a1 = get_shine(nv10_spot_params[0], e); |
a2 = get_shine(nv10_spot_params[1], e); |
b2 = 1 / (1 + 0.273 * e); |
a3 = 0.9 + 0.278 * e; |
if (l->SpotCutoff > 0) { |
float cutoff = MAX2(a3, 1 / (1 - l->_CosCutoff)); |
k[0] = MAX2(0, a0 + b0 * cutoff); |
k[1] = a1; |
k[2] = a2 + b2 * cutoff; |
k[3] = - cutoff * l->_NormSpotDirection[0]; |
k[4] = - cutoff * l->_NormSpotDirection[1]; |
k[5] = - cutoff * l->_NormSpotDirection[2]; |
k[6] = 1 - cutoff; |
} else { |
k[0] = b0; |
k[1] = a1; |
k[2] = a2 + b2; |
k[3] = - l->_NormSpotDirection[0]; |
k[4] = - l->_NormSpotDirection[1]; |
k[5] = - l->_NormSpotDirection[2]; |
k[6] = -1; |
} |
} |
void |
nv10_emit_light_source(struct gl_context *ctx, int emit) |
{ |
const int i = emit - NOUVEAU_STATE_LIGHT_SOURCE0; |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_light *l = &ctx->Light.Light[i]; |
if (l->_Flags & LIGHT_POSITIONAL) { |
BEGIN_NV04(push, NV10_3D(LIGHT_POSITION_X(i)), 3); |
PUSH_DATAp(push, l->_Position, 3); |
BEGIN_NV04(push, NV10_3D(LIGHT_ATTENUATION_CONSTANT(i)), 3); |
PUSH_DATAf(push, l->ConstantAttenuation); |
PUSH_DATAf(push, l->LinearAttenuation); |
PUSH_DATAf(push, l->QuadraticAttenuation); |
} else { |
BEGIN_NV04(push, NV10_3D(LIGHT_DIRECTION_X(i)), 3); |
PUSH_DATAp(push, l->_VP_inf_norm, 3); |
BEGIN_NV04(push, NV10_3D(LIGHT_HALF_VECTOR_X(i)), 3); |
PUSH_DATAp(push, l->_h_inf_norm, 3); |
} |
if (l->_Flags & LIGHT_SPOT) { |
float k[7]; |
nv10_get_spot_coeff(l, k); |
BEGIN_NV04(push, NV10_3D(LIGHT_SPOT_CUTOFF(i, 0)), 7); |
PUSH_DATAp(push, k, 7); |
} |
} |
#define USE_COLOR_MATERIAL(attr) \ |
(ctx->Light.ColorMaterialEnabled && \ |
ctx->Light._ColorMaterialBitmask & (1 << MAT_ATTRIB_FRONT_##attr)) |
void |
nv10_emit_material_ambient(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
float (*mat)[4] = ctx->Light.Material.Attrib; |
float c_scene[3], c_factor[3]; |
struct gl_light *l; |
if (USE_COLOR_MATERIAL(AMBIENT)) { |
COPY_3V(c_scene, ctx->Light.Model.Ambient); |
COPY_3V(c_factor, mat[MAT_ATTRIB_FRONT_EMISSION]); |
} else if (USE_COLOR_MATERIAL(EMISSION)) { |
SCALE_3V(c_scene, mat[MAT_ATTRIB_FRONT_AMBIENT], |
ctx->Light.Model.Ambient); |
ZERO_3V(c_factor); |
} else { |
COPY_3V(c_scene, ctx->Light._BaseColor[0]); |
ZERO_3V(c_factor); |
} |
BEGIN_NV04(push, NV10_3D(LIGHT_MODEL_AMBIENT_R), 3); |
PUSH_DATAp(push, c_scene, 3); |
if (ctx->Light.ColorMaterialEnabled) { |
BEGIN_NV04(push, NV10_3D(MATERIAL_FACTOR_R), 3); |
PUSH_DATAp(push, c_factor, 3); |
} |
foreach(l, &ctx->Light.EnabledList) { |
const int i = l - ctx->Light.Light; |
float *c_light = (USE_COLOR_MATERIAL(AMBIENT) ? |
l->Ambient : |
l->_MatAmbient[0]); |
BEGIN_NV04(push, NV10_3D(LIGHT_AMBIENT_R(i)), 3); |
PUSH_DATAp(push, c_light, 3); |
} |
} |
void |
nv10_emit_material_diffuse(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
GLfloat (*mat)[4] = ctx->Light.Material.Attrib; |
struct gl_light *l; |
BEGIN_NV04(push, NV10_3D(MATERIAL_FACTOR_A), 1); |
PUSH_DATAf(push, mat[MAT_ATTRIB_FRONT_DIFFUSE][3]); |
foreach(l, &ctx->Light.EnabledList) { |
const int i = l - ctx->Light.Light; |
float *c_light = (USE_COLOR_MATERIAL(DIFFUSE) ? |
l->Diffuse : |
l->_MatDiffuse[0]); |
BEGIN_NV04(push, NV10_3D(LIGHT_DIFFUSE_R(i)), 3); |
PUSH_DATAp(push, c_light, 3); |
} |
} |
void |
nv10_emit_material_specular(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_light *l; |
foreach(l, &ctx->Light.EnabledList) { |
const int i = l - ctx->Light.Light; |
float *c_light = (USE_COLOR_MATERIAL(SPECULAR) ? |
l->Specular : |
l->_MatSpecular[0]); |
BEGIN_NV04(push, NV10_3D(LIGHT_SPECULAR_R(i)), 3); |
PUSH_DATAp(push, c_light, 3); |
} |
} |
static const float nv10_shininess_param[6][16] = { |
{ 0.70, 0.00, 0.06, 0.06, 0.05, 0.04, 0.02, 0.00, |
-0.06, -0.13, -0.24, -0.36, -0.51, -0.66, -0.82, -1.00 }, |
{ 0.01, 1.00, -2.29, -2.77, -2.96, -3.06, -3.12, -3.18, |
-3.24, -3.29, -3.36, -3.43, -3.51, -3.75, -4.33, -5.11 }, |
{ 0.02, 0.00, 2.28, 2.75, 2.94, 3.04, 3.1, 3.15, |
3.18, 3.22, 3.27, 3.32, 3.39, 3.48, 3.84, 5.11 }, |
{ 0.70, 0.00, 0.05, 0.06, 0.06, 0.06, 0.05, 0.04, |
0.02, 0.01, -0.03, -0.12, -0.25, -0.43, -0.68, -0.99 }, |
{ 0.01, 1.00, -1.61, -2.35, -2.67, -2.84, -2.96, -3.05, |
-3.08, -3.14, -3.2, -3.26, -3.32, -3.42, -3.54, -4.21 }, |
{ 0.01, 0.00, 2.25, 2.73, 2.92, 3.03, 3.09, 3.15, |
3.16, 3.21, 3.25, 3.29, 3.35, 3.43, 3.56, 4.22 }, |
}; |
void |
nv10_get_shininess_coeff(float s, float k[6]) |
{ |
int i; |
for (i = 0; i < 6; i++) |
k[i] = get_shine(nv10_shininess_param[i], s); |
} |
void |
nv10_emit_material_shininess(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
float (*mat)[4] = ctx->Light.Material.Attrib; |
float k[6]; |
nv10_get_shininess_coeff( |
CLAMP(mat[MAT_ATTRIB_FRONT_SHININESS][0], 0, 1024), |
k); |
BEGIN_NV04(push, NV10_3D(MATERIAL_SHININESS(0)), 6); |
PUSH_DATAp(push, k, 6); |
} |
void |
nv10_emit_modelview(struct gl_context *ctx, int emit) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
GLmatrix *m = ctx->ModelviewMatrixStack.Top; |
if (nctx->fallback != HWTNL) |
return; |
if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled || |
(ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { |
BEGIN_NV04(push, NV10_3D(MODELVIEW_MATRIX(0, 0)), 16); |
PUSH_DATAm(push, m->m); |
} |
if (ctx->Light.Enabled || |
(ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { |
int i, j; |
BEGIN_NV04(push, NV10_3D(INVERSE_MODELVIEW_MATRIX(0, 0)), 12); |
for (i = 0; i < 3; i++) |
for (j = 0; j < 4; j++) |
PUSH_DATAf(push, m->inv[4*i + j]); |
} |
} |
void |
nv10_emit_point_parameter(struct gl_context *ctx, int emit) |
{ |
} |
void |
nv10_emit_projection(struct gl_context *ctx, int emit) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
GLmatrix m; |
_math_matrix_ctr(&m); |
get_viewport_scale(ctx, m.m); |
if (nv10_use_viewport_zclear(ctx)) |
m.m[MAT_SZ] /= 8; |
if (nctx->fallback == HWTNL) |
_math_matrix_mul_matrix(&m, &m, &ctx->_ModelProjectMatrix); |
BEGIN_NV04(push, NV10_3D(PROJECTION_MATRIX(0)), 16); |
PUSH_DATAm(push, m.m); |
_math_matrix_dtr(&m); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv20_3d.xml.h |
---|
0,0 → 1,2076 |
#ifndef NV20_3D_XML |
#define NV20_3D_XML |
/* Autogenerated file, DO NOT EDIT manually! |
This file was generated by the rules-ng-ng headergen tool in this git repository: |
http://0x04.net/cgit/index.cgi/rules-ng-ng |
git clone git://0x04.net/rules-ng-ng |
The rules-ng-ng source files this header was generated from are: |
- nv20_3d.xml ( 21073 bytes, from 2010-11-15 02:24:38) |
- copyright.xml ( 6452 bytes, from 2010-11-15 15:10:58) |
- nv10_3d.xml ( 18449 bytes, from 2010-11-15 02:24:38) |
- nv_defs.xml ( 4437 bytes, from 2010-11-01 00:28:46) |
- nv_3ddefs.xml ( 16394 bytes, from 2010-11-01 00:28:46) |
- nv_object.xml ( 11547 bytes, from 2010-11-13 23:32:57) |
- nvchipsets.xml ( 3074 bytes, from 2010-11-13 23:32:57) |
Copyright (C) 2006-2010 by the following authors: |
- Artur Huillet <arthur.huillet@free.fr> (ahuillet) |
- Ben Skeggs (darktama, darktama_) |
- B. R. <koala_br@users.sourceforge.net> (koala_br) |
- Carlos Martin <carlosmn@users.sf.net> (carlosmn) |
- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr) |
- Dawid Gajownik <gajownik@users.sf.net> (gajownik) |
- Dmitry Baryshkov |
- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag) |
- EdB <edb_@users.sf.net> (edb_) |
- Erik Waling <erikwailing@users.sf.net> (erikwaling) |
- Francisco Jerez <currojerez@riseup.net> (curro) |
- imirkin <imirkin@users.sf.net> (imirkin) |
- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome) |
- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy) |
- Laurent Carlier <lordheavym@gmail.com> (lordheavy) |
- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1) |
- Maarten Maathuis <madman2003@gmail.com> (stillunknown) |
- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin) |
- Mark Carey <mark.carey@gmail.com> (careym) |
- Matthieu Castet <matthieu.castet@parrot.com> (mat-c) |
- nvidiaman <nvidiaman@users.sf.net> (nvidiaman) |
- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata) |
- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen) |
- Peter Popov <ironpeter@users.sf.net> (ironpeter) |
- Richard Hughes <hughsient@users.sf.net> (hughsient) |
- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar) |
- Serge Martin |
- Simon Raffeiner |
- Stephane Loeuillet <leroutier@users.sf.net> (leroutier) |
- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu) |
- sturmflut <sturmflut@users.sf.net> (sturmflut) |
- Sylvain Munaut <tnt@246tNt.com> |
- Victor Stinner <victor.stinner@haypocalc.com> (haypo) |
- Wladmir van der Laan <laanwj@gmail.com> (miathan6) |
- Younes Manton <younes.m@gmail.com> (ymanton) |
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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
*/ |
#define NV20_VERTEX_ATTR_POS 0x00000000 |
#define NV20_VERTEX_ATTR_NORMAL 0x00000002 |
#define NV20_VERTEX_ATTR_COLOR0 0x00000003 |
#define NV20_VERTEX_ATTR_COLOR1 0x00000004 |
#define NV20_VERTEX_ATTR_FOG 0x00000005 |
#define NV20_VERTEX_ATTR_TEX0 0x00000009 |
#define NV20_VERTEX_ATTR_TEX1 0x0000000a |
#define NV20_VERTEX_ATTR_TEX2 0x0000000b |
#define NV20_VERTEX_ATTR_TEX3 0x0000000c |
#define NV20_3D_FLIP_SET_READ 0x00000120 |
#define NV20_3D_FLIP_SET_WRITE 0x00000124 |
#define NV20_3D_FLIP_MAX 0x00000128 |
#define NV20_3D_FLIP_INCR_WRITE 0x0000012c |
#define NV20_3D_FLIP_WAIT 0x00000130 |
#define NV20_3D_DMA_NOTIFY 0x00000180 |
#define NV20_3D_DMA_TEXTURE0 0x00000184 |
#define NV20_3D_DMA_TEXTURE1 0x00000188 |
#define NV20_3D_DMA_COLOR 0x00000194 |
#define NV20_3D_DMA_ZETA 0x00000198 |
#define NV20_3D_RT_HORIZ 0x00000200 |
#define NV20_3D_RT_HORIZ_X__MASK 0x0000ffff |
#define NV20_3D_RT_HORIZ_X__SHIFT 0 |
#define NV20_3D_RT_HORIZ_W__MASK 0xffff0000 |
#define NV20_3D_RT_HORIZ_W__SHIFT 16 |
#define NV20_3D_RT_VERT 0x00000204 |
#define NV20_3D_RT_VERT_Y__MASK 0x0000ffff |
#define NV20_3D_RT_VERT_Y__SHIFT 0 |
#define NV20_3D_RT_VERT_H__MASK 0xffff0000 |
#define NV20_3D_RT_VERT_H__SHIFT 16 |
#define NV20_3D_RT_FORMAT 0x00000208 |
#define NV20_3D_RT_FORMAT_TYPE__MASK 0x00000f00 |
#define NV20_3D_RT_FORMAT_TYPE__SHIFT 8 |
#define NV20_3D_RT_FORMAT_TYPE_LINEAR 0x00000100 |
#define NV20_3D_RT_FORMAT_TYPE_SWIZZLED 0x00000200 |
#define NV20_3D_RT_FORMAT_DEPTH__MASK 0x00000030 |
#define NV20_3D_RT_FORMAT_DEPTH__SHIFT 4 |
#define NV20_3D_RT_FORMAT_DEPTH_Z16 0x00000010 |
#define NV20_3D_RT_FORMAT_DEPTH_Z24S8 0x00000020 |
#define NV20_3D_RT_FORMAT_COLOR__MASK 0x0000000f |
#define NV20_3D_RT_FORMAT_COLOR__SHIFT 0 |
#define NV20_3D_RT_FORMAT_COLOR_R5G6B5 0x00000003 |
#define NV20_3D_RT_FORMAT_COLOR_X8R8G8B8 0x00000005 |
#define NV20_3D_RT_FORMAT_COLOR_A8R8G8B8 0x00000008 |
#define NV20_3D_RT_FORMAT_COLOR_B8 0x00000009 |
#define NV20_3D_RT_PITCH 0x0000020c |
#define NV20_3D_RT_PITCH_COLOR_PITCH__MASK 0x0000ffff |
#define NV20_3D_RT_PITCH_COLOR_PITCH__SHIFT 0 |
#define NV20_3D_RT_PITCH_ZETA_PITCH__MASK 0xffff0000 |
#define NV20_3D_RT_PITCH_ZETA_PITCH__SHIFT 16 |
#define NV20_3D_COLOR_OFFSET 0x00000210 |
#define NV20_3D_ZETA_OFFSET 0x00000214 |
#define NV20_3D_UNK0290 0x00000290 |
#define NV20_3D_VIEWPORT_CLIP_MODE 0x000002b4 |
#define NV20_3D_VIEWPORT_CLIP_HORIZ(i0) (0x000002c0 + 0x4*(i0)) |
#define NV20_3D_VIEWPORT_CLIP_HORIZ__ESIZE 0x00000004 |
#define NV20_3D_VIEWPORT_CLIP_HORIZ__LEN 0x00000008 |
#define NV20_3D_VIEWPORT_CLIP_HORIZ_CLIP_L__MASK 0x000007ff |
#define NV20_3D_VIEWPORT_CLIP_HORIZ_CLIP_L__SHIFT 0 |
#define NV20_3D_VIEWPORT_CLIP_HORIZ_CLIP_R__MASK 0x07ff0000 |
#define NV20_3D_VIEWPORT_CLIP_HORIZ_CLIP_R__SHIFT 16 |
#define NV20_3D_VIEWPORT_CLIP_VERT(i0) (0x000002e0 + 0x4*(i0)) |
#define NV20_3D_VIEWPORT_CLIP_VERT__ESIZE 0x00000004 |
#define NV20_3D_VIEWPORT_CLIP_VERT__LEN 0x00000008 |
#define NV20_3D_VIEWPORT_CLIP_VERT_CLIP_T__MASK 0x000007ff |
#define NV20_3D_VIEWPORT_CLIP_VERT_CLIP_T__SHIFT 0 |
#define NV20_3D_VIEWPORT_CLIP_VERT_CLIP_B__MASK 0x07ff0000 |
#define NV20_3D_VIEWPORT_CLIP_VERT_CLIP_B__SHIFT 16 |
#define NV20_3D_ALPHA_FUNC_ENABLE 0x00000300 |
#define NV20_3D_BLEND_FUNC_ENABLE 0x00000304 |
#define NV20_3D_CULL_FACE_ENABLE 0x00000308 |
#define NV20_3D_DEPTH_TEST_ENABLE 0x0000030c |
#define NV20_3D_DITHER_ENABLE 0x00000310 |
#define NV20_3D_LIGHTING_ENABLE 0x00000314 |
#define NV20_3D_POINT_PARAMETERS_ENABLE 0x00000318 |
#define NV20_3D_POINT_SMOOTH_ENABLE 0x0000031c |
#define NV20_3D_LINE_SMOOTH_ENABLE 0x00000320 |
#define NV20_3D_POLYGON_SMOOTH_ENABLE 0x00000324 |
#define NV20_3D_STENCIL_ENABLE 0x0000032c |
#define NV20_3D_POLYGON_OFFSET_POINT_ENABLE 0x00000330 |
#define NV20_3D_POLYGON_OFFSET_LINE_ENABLE 0x00000334 |
#define NV20_3D_POLYGON_OFFSET_FILL_ENABLE 0x00000338 |
#define NV20_3D_ALPHA_FUNC_FUNC 0x0000033c |
#define NV20_3D_ALPHA_FUNC_FUNC_NEVER 0x00000200 |
#define NV20_3D_ALPHA_FUNC_FUNC_LESS 0x00000201 |
#define NV20_3D_ALPHA_FUNC_FUNC_EQUAL 0x00000202 |
#define NV20_3D_ALPHA_FUNC_FUNC_LEQUAL 0x00000203 |
#define NV20_3D_ALPHA_FUNC_FUNC_GREATER 0x00000204 |
#define NV20_3D_ALPHA_FUNC_FUNC_NOTEQUAL 0x00000205 |
#define NV20_3D_ALPHA_FUNC_FUNC_GEQUAL 0x00000206 |
#define NV20_3D_ALPHA_FUNC_FUNC_ALWAYS 0x00000207 |
#define NV20_3D_ALPHA_FUNC_REF 0x00000340 |
#define NV20_3D_BLEND_FUNC_SRC 0x00000344 |
#define NV20_3D_BLEND_FUNC_SRC_ZERO 0x00000000 |
#define NV20_3D_BLEND_FUNC_SRC_ONE 0x00000001 |
#define NV20_3D_BLEND_FUNC_SRC_SRC_COLOR 0x00000300 |
#define NV20_3D_BLEND_FUNC_SRC_ONE_MINUS_SRC_COLOR 0x00000301 |
#define NV20_3D_BLEND_FUNC_SRC_SRC_ALPHA 0x00000302 |
#define NV20_3D_BLEND_FUNC_SRC_ONE_MINUS_SRC_ALPHA 0x00000303 |
#define NV20_3D_BLEND_FUNC_SRC_DST_ALPHA 0x00000304 |
#define NV20_3D_BLEND_FUNC_SRC_ONE_MINUS_DST_ALPHA 0x00000305 |
#define NV20_3D_BLEND_FUNC_SRC_DST_COLOR 0x00000306 |
#define NV20_3D_BLEND_FUNC_SRC_ONE_MINUS_DST_COLOR 0x00000307 |
#define NV20_3D_BLEND_FUNC_SRC_SRC_ALPHA_SATURATE 0x00000308 |
#define NV20_3D_BLEND_FUNC_SRC_CONSTANT_COLOR 0x00008001 |
#define NV20_3D_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_COLOR 0x00008002 |
#define NV20_3D_BLEND_FUNC_SRC_CONSTANT_ALPHA 0x00008003 |
#define NV20_3D_BLEND_FUNC_SRC_ONE_MINUS_CONSTANT_ALPHA 0x00008004 |
#define NV20_3D_BLEND_FUNC_DST 0x00000348 |
#define NV20_3D_BLEND_FUNC_DST_ZERO 0x00000000 |
#define NV20_3D_BLEND_FUNC_DST_ONE 0x00000001 |
#define NV20_3D_BLEND_FUNC_DST_SRC_COLOR 0x00000300 |
#define NV20_3D_BLEND_FUNC_DST_ONE_MINUS_SRC_COLOR 0x00000301 |
#define NV20_3D_BLEND_FUNC_DST_SRC_ALPHA 0x00000302 |
#define NV20_3D_BLEND_FUNC_DST_ONE_MINUS_SRC_ALPHA 0x00000303 |
#define NV20_3D_BLEND_FUNC_DST_DST_ALPHA 0x00000304 |
#define NV20_3D_BLEND_FUNC_DST_ONE_MINUS_DST_ALPHA 0x00000305 |
#define NV20_3D_BLEND_FUNC_DST_DST_COLOR 0x00000306 |
#define NV20_3D_BLEND_FUNC_DST_ONE_MINUS_DST_COLOR 0x00000307 |
#define NV20_3D_BLEND_FUNC_DST_SRC_ALPHA_SATURATE 0x00000308 |
#define NV20_3D_BLEND_FUNC_DST_CONSTANT_COLOR 0x00008001 |
#define NV20_3D_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_COLOR 0x00008002 |
#define NV20_3D_BLEND_FUNC_DST_CONSTANT_ALPHA 0x00008003 |
#define NV20_3D_BLEND_FUNC_DST_ONE_MINUS_CONSTANT_ALPHA 0x00008004 |
#define NV20_3D_BLEND_COLOR 0x0000034c |
#define NV20_3D_BLEND_COLOR_B__MASK 0x000000ff |
#define NV20_3D_BLEND_COLOR_B__SHIFT 0 |
#define NV20_3D_BLEND_COLOR_G__MASK 0x0000ff00 |
#define NV20_3D_BLEND_COLOR_G__SHIFT 8 |
#define NV20_3D_BLEND_COLOR_R__MASK 0x00ff0000 |
#define NV20_3D_BLEND_COLOR_R__SHIFT 16 |
#define NV20_3D_BLEND_COLOR_A__MASK 0xff000000 |
#define NV20_3D_BLEND_COLOR_A__SHIFT 24 |
#define NV20_3D_BLEND_EQUATION 0x00000350 |
#define NV20_3D_BLEND_EQUATION_FUNC_ADD 0x00008006 |
#define NV20_3D_BLEND_EQUATION_MIN 0x00008007 |
#define NV20_3D_BLEND_EQUATION_MAX 0x00008008 |
#define NV20_3D_BLEND_EQUATION_FUNC_SUBTRACT 0x0000800a |
#define NV20_3D_BLEND_EQUATION_FUNC_REVERSE_SUBTRACT 0x0000800b |
#define NV20_3D_DEPTH_FUNC 0x00000354 |
#define NV20_3D_DEPTH_FUNC_NEVER 0x00000200 |
#define NV20_3D_DEPTH_FUNC_LESS 0x00000201 |
#define NV20_3D_DEPTH_FUNC_EQUAL 0x00000202 |
#define NV20_3D_DEPTH_FUNC_LEQUAL 0x00000203 |
#define NV20_3D_DEPTH_FUNC_GREATER 0x00000204 |
#define NV20_3D_DEPTH_FUNC_NOTEQUAL 0x00000205 |
#define NV20_3D_DEPTH_FUNC_GEQUAL 0x00000206 |
#define NV20_3D_DEPTH_FUNC_ALWAYS 0x00000207 |
#define NV20_3D_COLOR_MASK 0x00000358 |
#define NV20_3D_COLOR_MASK_B 0x00000001 |
#define NV20_3D_COLOR_MASK_G 0x00000100 |
#define NV20_3D_COLOR_MASK_R 0x00010000 |
#define NV20_3D_COLOR_MASK_A 0x01000000 |
#define NV20_3D_DEPTH_WRITE_ENABLE 0x0000035c |
#define NV20_3D_STENCIL_MASK 0x00000360 |
#define NV20_3D_STENCIL_FUNC_FUNC 0x00000364 |
#define NV20_3D_STENCIL_FUNC_FUNC_NEVER 0x00000200 |
#define NV20_3D_STENCIL_FUNC_FUNC_LESS 0x00000201 |
#define NV20_3D_STENCIL_FUNC_FUNC_EQUAL 0x00000202 |
#define NV20_3D_STENCIL_FUNC_FUNC_LEQUAL 0x00000203 |
#define NV20_3D_STENCIL_FUNC_FUNC_GREATER 0x00000204 |
#define NV20_3D_STENCIL_FUNC_FUNC_NOTEQUAL 0x00000205 |
#define NV20_3D_STENCIL_FUNC_FUNC_GEQUAL 0x00000206 |
#define NV20_3D_STENCIL_FUNC_FUNC_ALWAYS 0x00000207 |
#define NV20_3D_STENCIL_FUNC_REF 0x00000368 |
#define NV20_3D_STENCIL_FUNC_MASK 0x0000036c |
#define NV20_3D_STENCIL_OP_FAIL 0x00000370 |
#define NV20_3D_STENCIL_OP_FAIL_ZERO 0x00000000 |
#define NV20_3D_STENCIL_OP_FAIL_INVERT 0x0000150a |
#define NV20_3D_STENCIL_OP_FAIL_KEEP 0x00001e00 |
#define NV20_3D_STENCIL_OP_FAIL_REPLACE 0x00001e01 |
#define NV20_3D_STENCIL_OP_FAIL_INCR 0x00001e02 |
#define NV20_3D_STENCIL_OP_FAIL_DECR 0x00001e03 |
#define NV20_3D_STENCIL_OP_FAIL_INCR_WRAP 0x00008507 |
#define NV20_3D_STENCIL_OP_FAIL_DECR_WRAP 0x00008508 |
#define NV20_3D_STENCIL_OP_ZFAIL 0x00000374 |
#define NV20_3D_STENCIL_OP_ZFAIL_ZERO 0x00000000 |
#define NV20_3D_STENCIL_OP_ZFAIL_INVERT 0x0000150a |
#define NV20_3D_STENCIL_OP_ZFAIL_KEEP 0x00001e00 |
#define NV20_3D_STENCIL_OP_ZFAIL_REPLACE 0x00001e01 |
#define NV20_3D_STENCIL_OP_ZFAIL_INCR 0x00001e02 |
#define NV20_3D_STENCIL_OP_ZFAIL_DECR 0x00001e03 |
#define NV20_3D_STENCIL_OP_ZFAIL_INCR_WRAP 0x00008507 |
#define NV20_3D_STENCIL_OP_ZFAIL_DECR_WRAP 0x00008508 |
#define NV20_3D_STENCIL_OP_ZPASS 0x00000378 |
#define NV20_3D_STENCIL_OP_ZPASS_ZERO 0x00000000 |
#define NV20_3D_STENCIL_OP_ZPASS_INVERT 0x0000150a |
#define NV20_3D_STENCIL_OP_ZPASS_KEEP 0x00001e00 |
#define NV20_3D_STENCIL_OP_ZPASS_REPLACE 0x00001e01 |
#define NV20_3D_STENCIL_OP_ZPASS_INCR 0x00001e02 |
#define NV20_3D_STENCIL_OP_ZPASS_DECR 0x00001e03 |
#define NV20_3D_STENCIL_OP_ZPASS_INCR_WRAP 0x00008507 |
#define NV20_3D_STENCIL_OP_ZPASS_DECR_WRAP 0x00008508 |
#define NV20_3D_SHADE_MODEL 0x0000037c |
#define NV20_3D_SHADE_MODEL_FLAT 0x00001d00 |
#define NV20_3D_SHADE_MODEL_SMOOTH 0x00001d01 |
#define NV20_3D_LINE_WIDTH 0x00000380 |
#define NV20_3D_POLYGON_OFFSET_FACTOR 0x00000384 |
#define NV20_3D_POLYGON_OFFSET_UNITS 0x00000388 |
#define NV20_3D_POLYGON_MODE_FRONT 0x0000038c |
#define NV20_3D_POLYGON_MODE_FRONT_POINT 0x00001b00 |
#define NV20_3D_POLYGON_MODE_FRONT_LINE 0x00001b01 |
#define NV20_3D_POLYGON_MODE_FRONT_FILL 0x00001b02 |
#define NV20_3D_POLYGON_MODE_BACK 0x00000390 |
#define NV20_3D_POLYGON_MODE_BACK_POINT 0x00001b00 |
#define NV20_3D_POLYGON_MODE_BACK_LINE 0x00001b01 |
#define NV20_3D_POLYGON_MODE_BACK_FILL 0x00001b02 |
#define NV20_3D_DEPTH_RANGE_NEAR 0x00000394 |
#define NV20_3D_DEPTH_RANGE_FAR 0x00000398 |
#define NV20_3D_CULL_FACE 0x0000039c |
#define NV20_3D_CULL_FACE_FRONT 0x00000404 |
#define NV20_3D_CULL_FACE_BACK 0x00000405 |
#define NV20_3D_CULL_FACE_FRONT_AND_BACK 0x00000408 |
#define NV20_3D_FRONT_FACE 0x000003a0 |
#define NV20_3D_FRONT_FACE_CW 0x00000900 |
#define NV20_3D_FRONT_FACE_CCW 0x00000901 |
#define NV20_3D_DMA_FENCE 0x000001a4 |
#define NV20_3D_DMA_QUERY 0x000001a8 |
#define NV20_3D_VERTEX_POS_3F 0x00001500 |
#define NV20_3D_VERTEX_POS_3F_X 0x00001500 |
#define NV20_3D_VERTEX_POS_3F_Y 0x00001504 |
#define NV20_3D_VERTEX_POS_3F_Z 0x00001508 |
#define NV20_3D_VERTEX_POS_4F 0x00001518 |
#define NV20_3D_VERTEX_POS_4F_X 0x00001518 |
#define NV20_3D_VERTEX_POS_4F_Y 0x0000151c |
#define NV20_3D_VERTEX_POS_4F_Z 0x00001520 |
#define NV20_3D_VERTEX_POS_4F_W 0x00001524 |
#define NV20_3D_VERTEX_POS_3I 0x00001528 |
#define NV20_3D_VERTEX_POS_3I_XY 0x00001528 |
#define NV20_3D_VERTEX_POS_3I_XY_X__MASK 0x0000ffff |
#define NV20_3D_VERTEX_POS_3I_XY_X__SHIFT 0 |
#define NV20_3D_VERTEX_POS_3I_XY_Y__MASK 0xffff0000 |
#define NV20_3D_VERTEX_POS_3I_XY_Y__SHIFT 16 |
#define NV20_3D_VERTEX_POS_3I_Z 0x0000152c |
#define NV20_3D_VERTEX_POS_3I_Z_Z__MASK 0x0000ffff |
#define NV20_3D_VERTEX_POS_3I_Z_Z__SHIFT 0 |
#define NV20_3D_VERTEX_NOR_3F 0x00001530 |
#define NV20_3D_VERTEX_NOR_3F_X 0x00001530 |
#define NV20_3D_VERTEX_NOR_3F_Y 0x00001534 |
#define NV20_3D_VERTEX_NOR_3F_Z 0x00001538 |
#define NV20_3D_VERTEX_NOR_3I 0x00001540 |
#define NV20_3D_VERTEX_NOR_3I_XY 0x00001540 |
#define NV20_3D_VERTEX_NOR_3I_XY_X__MASK 0x0000ffff |
#define NV20_3D_VERTEX_NOR_3I_XY_X__SHIFT 0 |
#define NV20_3D_VERTEX_NOR_3I_XY_Y__MASK 0xffff0000 |
#define NV20_3D_VERTEX_NOR_3I_XY_Y__SHIFT 16 |
#define NV20_3D_VERTEX_NOR_3I_Z 0x00001544 |
#define NV20_3D_VERTEX_NOR_3I_Z_Z__MASK 0x0000ffff |
#define NV20_3D_VERTEX_NOR_3I_Z_Z__SHIFT 0 |
#define NV20_3D_VERTEX_COL_4F 0x00001550 |
#define NV20_3D_VERTEX_COL_4F_R 0x00001550 |
#define NV20_3D_VERTEX_COL_4F_G 0x00001554 |
#define NV20_3D_VERTEX_COL_4F_B 0x00001558 |
#define NV20_3D_VERTEX_COL_4F_A 0x0000155c |
#define NV20_3D_VERTEX_COL_3F 0x00001560 |
#define NV20_3D_VERTEX_COL_3F_R 0x00001560 |
#define NV20_3D_VERTEX_COL_3F_G 0x00001564 |
#define NV20_3D_VERTEX_COL_3F_B 0x00001568 |
#define NV20_3D_VERTEX_COL_4I 0x0000156c |
#define NV20_3D_VERTEX_COL_4I_R__MASK 0x000000ff |
#define NV20_3D_VERTEX_COL_4I_R__SHIFT 0 |
#define NV20_3D_VERTEX_COL_4I_G__MASK 0x0000ff00 |
#define NV20_3D_VERTEX_COL_4I_G__SHIFT 8 |
#define NV20_3D_VERTEX_COL_4I_B__MASK 0x00ff0000 |
#define NV20_3D_VERTEX_COL_4I_B__SHIFT 16 |
#define NV20_3D_VERTEX_COL_4I_A__MASK 0xff000000 |
#define NV20_3D_VERTEX_COL_4I_A__SHIFT 24 |
#define NV20_3D_VERTEX_COL2_3F 0x00001580 |
#define NV20_3D_VERTEX_COL2_3F_R 0x00001580 |
#define NV20_3D_VERTEX_COL2_3F_G 0x00001584 |
#define NV20_3D_VERTEX_COL2_3F_B 0x00001588 |
#define NV20_3D_VERTEX_COL2_3I 0x0000158c |
#define NV20_3D_VERTEX_COL2_3I_R__MASK 0x000000ff |
#define NV20_3D_VERTEX_COL2_3I_R__SHIFT 0 |
#define NV20_3D_VERTEX_COL2_3I_G__MASK 0x0000ff00 |
#define NV20_3D_VERTEX_COL2_3I_G__SHIFT 8 |
#define NV20_3D_VERTEX_COL2_3I_B__MASK 0x00ff0000 |
#define NV20_3D_VERTEX_COL2_3I_B__SHIFT 16 |
#define NV20_3D_VERTEX_TX0_2F 0x00001590 |
#define NV20_3D_VERTEX_TX0_2F_S 0x00001590 |
#define NV20_3D_VERTEX_TX0_2F_T 0x00001594 |
#define NV20_3D_VERTEX_TX0_2I 0x00001598 |
#define NV20_3D_VERTEX_TX0_2I_S__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX0_2I_S__SHIFT 0 |
#define NV20_3D_VERTEX_TX0_2I_T__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX0_2I_T__SHIFT 16 |
#define NV20_3D_VERTEX_TX0_4F 0x000015a0 |
#define NV20_3D_VERTEX_TX0_4F_S 0x000015a0 |
#define NV20_3D_VERTEX_TX0_4F_T 0x000015a4 |
#define NV20_3D_VERTEX_TX0_4F_R 0x000015a8 |
#define NV20_3D_VERTEX_TX0_4F_Q 0x000015ac |
#define NV20_3D_VERTEX_TX0_4I 0x000015b0 |
#define NV20_3D_VERTEX_TX0_4I_ST 0x000015b0 |
#define NV20_3D_VERTEX_TX0_4I_ST_S__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX0_4I_ST_S__SHIFT 0 |
#define NV20_3D_VERTEX_TX0_4I_ST_T__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX0_4I_ST_T__SHIFT 16 |
#define NV20_3D_VERTEX_TX0_4I_RQ 0x000015b4 |
#define NV20_3D_VERTEX_TX0_4I_RQ_R__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX0_4I_RQ_R__SHIFT 0 |
#define NV20_3D_VERTEX_TX0_4I_RQ_Q__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX0_4I_RQ_Q__SHIFT 16 |
#define NV20_3D_VERTEX_TX1_2F 0x000015b8 |
#define NV20_3D_VERTEX_TX1_2F_S 0x000015b8 |
#define NV20_3D_VERTEX_TX1_2F_T 0x000015bc |
#define NV20_3D_VERTEX_TX1_2I 0x000015c0 |
#define NV20_3D_VERTEX_TX1_2I_S__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX1_2I_S__SHIFT 0 |
#define NV20_3D_VERTEX_TX1_2I_T__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX1_2I_T__SHIFT 16 |
#define NV20_3D_VERTEX_TX1_4F 0x000015c8 |
#define NV20_3D_VERTEX_TX1_4F_S 0x000015c8 |
#define NV20_3D_VERTEX_TX1_4F_T 0x000015cc |
#define NV20_3D_VERTEX_TX1_4F_R 0x000015d0 |
#define NV20_3D_VERTEX_TX1_4F_Q 0x000015d4 |
#define NV20_3D_VERTEX_TX1_4I 0x000015d8 |
#define NV20_3D_VERTEX_TX1_4I_ST 0x000015d8 |
#define NV20_3D_VERTEX_TX1_4I_ST_S__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX1_4I_ST_S__SHIFT 0 |
#define NV20_3D_VERTEX_TX1_4I_ST_T__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX1_4I_ST_T__SHIFT 16 |
#define NV20_3D_VERTEX_TX1_4I_RQ 0x000015dc |
#define NV20_3D_VERTEX_TX1_4I_RQ_R__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX1_4I_RQ_R__SHIFT 0 |
#define NV20_3D_VERTEX_TX1_4I_RQ_Q__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX1_4I_RQ_Q__SHIFT 16 |
#define NV20_3D_VERTEX_TX2_2F 0x000015e0 |
#define NV20_3D_VERTEX_TX2_2F_S 0x000015e0 |
#define NV20_3D_VERTEX_TX2_2F_T 0x000015e4 |
#define NV20_3D_VERTEX_TX2_2I 0x000015e8 |
#define NV20_3D_VERTEX_TX2_2I_S__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX2_2I_S__SHIFT 0 |
#define NV20_3D_VERTEX_TX2_2I_T__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX2_2I_T__SHIFT 16 |
#define NV20_3D_VERTEX_TX2_4F 0x000015f0 |
#define NV20_3D_VERTEX_TX2_4F_S 0x000015f0 |
#define NV20_3D_VERTEX_TX2_4F_T 0x000015f4 |
#define NV20_3D_VERTEX_TX2_4F_R 0x000015f8 |
#define NV20_3D_VERTEX_TX2_4F_Q 0x000015fc |
#define NV20_3D_VERTEX_TX2_4I 0x00001600 |
#define NV20_3D_VERTEX_TX2_4I_ST 0x00001600 |
#define NV20_3D_VERTEX_TX2_4I_ST_S__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX2_4I_ST_S__SHIFT 0 |
#define NV20_3D_VERTEX_TX2_4I_ST_T__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX2_4I_ST_T__SHIFT 16 |
#define NV20_3D_VERTEX_TX2_4I_RQ 0x00001604 |
#define NV20_3D_VERTEX_TX2_4I_RQ_R__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX2_4I_RQ_R__SHIFT 0 |
#define NV20_3D_VERTEX_TX2_4I_RQ_Q__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX2_4I_RQ_Q__SHIFT 16 |
#define NV20_3D_VERTEX_TX3_2F 0x00001608 |
#define NV20_3D_VERTEX_TX3_2F_S 0x00001608 |
#define NV20_3D_VERTEX_TX3_2F_T 0x0000160c |
#define NV20_3D_VERTEX_TX3_2I 0x00001610 |
#define NV20_3D_VERTEX_TX3_2I_S__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX3_2I_S__SHIFT 0 |
#define NV20_3D_VERTEX_TX3_2I_T__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX3_2I_T__SHIFT 16 |
#define NV20_3D_VERTEX_TX3_4F 0x00001620 |
#define NV20_3D_VERTEX_TX3_4F_S 0x00001620 |
#define NV20_3D_VERTEX_TX3_4F_T 0x00001624 |
#define NV20_3D_VERTEX_TX3_4F_R 0x00001628 |
#define NV20_3D_VERTEX_TX3_4F_Q 0x0000162c |
#define NV20_3D_VERTEX_TX3_4I 0x00001630 |
#define NV20_3D_VERTEX_TX3_4I_ST 0x00001630 |
#define NV20_3D_VERTEX_TX3_4I_ST_S__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX3_4I_ST_S__SHIFT 0 |
#define NV20_3D_VERTEX_TX3_4I_ST_T__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX3_4I_ST_T__SHIFT 16 |
#define NV20_3D_VERTEX_TX3_4I_RQ 0x00001634 |
#define NV20_3D_VERTEX_TX3_4I_RQ_R__MASK 0x0000ffff |
#define NV20_3D_VERTEX_TX3_4I_RQ_R__SHIFT 0 |
#define NV20_3D_VERTEX_TX3_4I_RQ_Q__MASK 0xffff0000 |
#define NV20_3D_VERTEX_TX3_4I_RQ_Q__SHIFT 16 |
#define NV20_3D_VERTEX_FOG_1F 0x00001698 |
#define NV20_3D_EDGEFLAG_ENABLE 0x000016bc |
#define NV20_3D_VERTEX_ATTR_4F(i0) (0x00001a00 + 0x10*(i0)) |
#define NV20_3D_VERTEX_ATTR_4F__ESIZE 0x00000010 |
#define NV20_3D_VERTEX_ATTR_4F__LEN 0x00000010 |
#define NV20_3D_VERTEX_ATTR_4F_X(i0) (0x00001a00 + 0x10*(i0)) |
#define NV20_3D_VERTEX_ATTR_4F_Y(i0) (0x00001a04 + 0x10*(i0)) |
#define NV20_3D_VERTEX_ATTR_4F_Z(i0) (0x00001a08 + 0x10*(i0)) |
#define NV20_3D_VERTEX_ATTR_4F_W(i0) (0x00001a0c + 0x10*(i0)) |
#define NV20_3D_DMA_VTXBUF0 0x0000019c |
#define NV20_3D_DMA_VTXBUF1 0x000001a0 |
#define NV20_3D_VTXBUF_VALIDATE 0x00001710 |
#define NV20_3D_VTXBUF_OFFSET(i0) (0x00001720 + 0x4*(i0)) |
#define NV20_3D_VTXBUF_OFFSET_DMA1 0x80000000 |
#define NV20_3D_VTXBUF_OFFSET_OFFSET__MASK 0x0fffffff |
#define NV20_3D_VTXBUF_OFFSET_OFFSET__SHIFT 0 |
#define NV20_3D_VTXBUF_FMT(i0) (0x00001760 + 0x4*(i0)) |
#define NV20_3D_VTXBUF_FMT_TYPE__MASK 0x0000000f |
#define NV20_3D_VTXBUF_FMT_TYPE__SHIFT 0 |
#define NV20_3D_VTXBUF_FMT_TYPE_FLOAT 0x00000002 |
#define NV20_3D_VTXBUF_FMT_TYPE_UBYTE 0x00000004 |
#define NV20_3D_VTXBUF_FMT_TYPE_USHORT 0x00000005 |
#define NV20_3D_VTXBUF_FMT_SIZE__MASK 0x000000f0 |
#define NV20_3D_VTXBUF_FMT_SIZE__SHIFT 4 |
#define NV20_3D_VTXBUF_FMT_STRIDE__MASK 0x0000ff00 |
#define NV20_3D_VTXBUF_FMT_STRIDE__SHIFT 8 |
#define NV20_3D_VERTEX_BEGIN_END 0x000017fc |
#define NV20_3D_VERTEX_BEGIN_END_STOP 0x00000000 |
#define NV20_3D_VERTEX_BEGIN_END_POINTS 0x00000001 |
#define NV20_3D_VERTEX_BEGIN_END_LINES 0x00000002 |
#define NV20_3D_VERTEX_BEGIN_END_LINE_LOOP 0x00000003 |
#define NV20_3D_VERTEX_BEGIN_END_LINE_STRIP 0x00000004 |
#define NV20_3D_VERTEX_BEGIN_END_TRIANGLES 0x00000005 |
#define NV20_3D_VERTEX_BEGIN_END_TRIANGLE_STRIP 0x00000006 |
#define NV20_3D_VERTEX_BEGIN_END_TRIANGLE_FAN 0x00000007 |
#define NV20_3D_VERTEX_BEGIN_END_QUADS 0x00000008 |
#define NV20_3D_VERTEX_BEGIN_END_QUAD_STRIP 0x00000009 |
#define NV20_3D_VERTEX_BEGIN_END_POLYGON 0x0000000a |
#define NV20_3D_VTXBUF_ELEMENT_U16 0x00001800 |
#define NV20_3D_VTXBUF_ELEMENT_U16_I0__MASK 0x0000ffff |
#define NV20_3D_VTXBUF_ELEMENT_U16_I0__SHIFT 0 |
#define NV20_3D_VTXBUF_ELEMENT_U16_I1__MASK 0xffff0000 |
#define NV20_3D_VTXBUF_ELEMENT_U16_I1__SHIFT 16 |
#define NV20_3D_VTXBUF_ELEMENT_U32 0x00001808 |
#define NV20_3D_VTXBUF_BATCH 0x00001810 |
#define NV20_3D_VTXBUF_BATCH_OFFSET__MASK 0x00ffffff |
#define NV20_3D_VTXBUF_BATCH_OFFSET__SHIFT 0 |
#define NV20_3D_VTXBUF_BATCH_COUNT__MASK 0xff000000 |
#define NV20_3D_VTXBUF_BATCH_COUNT__SHIFT 24 |
#define NV20_3D_VTXBUF_DATA 0x00001818 |
#define NV20_3D_ENGINE 0x00001e94 |
#define NV20_3D_ENGINE_VP 0x00000002 |
#define NV20_3D_ENGINE_FIXED 0x00000004 |
#define NV20_3D_VP_UPLOAD_INST(i0) (0x00000b00 + 0x4*(i0)) |
#define NV20_3D_VP_UPLOAD_INST__ESIZE 0x00000004 |
#define NV20_3D_VP_UPLOAD_INST__LEN 0x00000004 |
#define NV20_3D_VP_UPLOAD_CONST(i0) (0x00000b80 + 0x4*(i0)) |
#define NV20_3D_VP_UPLOAD_CONST__ESIZE 0x00000004 |
#define NV20_3D_VP_UPLOAD_CONST__LEN 0x00000004 |
#define NV20_3D_VP_UPLOAD_FROM_ID 0x00001e9c |
#define NV20_3D_VP_START_FROM_ID 0x00001ea0 |
#define NV20_3D_VP_UPLOAD_CONST_ID 0x00001ea4 |
#define NV20_3D_MODELVIEW_MATRIX(i0, i1) (0x00000480 + 0x40*(i0) + 0x4*(i1)) |
#define NV20_3D_MODELVIEW_MATRIX__ESIZE 0x00000004 |
#define NV20_3D_MODELVIEW_MATRIX__LEN 0x00000010 |
#define NV20_3D_INVERSE_MODELVIEW_MATRIX(i0, i1) (0x00000580 + 0x40*(i0) + 0x4*(i1)) |
#define NV20_3D_INVERSE_MODELVIEW_MATRIX__ESIZE 0x00000004 |
#define NV20_3D_INVERSE_MODELVIEW_MATRIX__LEN 0x00000010 |
#define NV20_3D_PROJECTION_MATRIX(i0) (0x00000680 + 0x4*(i0)) |
#define NV20_3D_PROJECTION_MATRIX__ESIZE 0x00000004 |
#define NV20_3D_PROJECTION_MATRIX__LEN 0x00000010 |
#define NV20_3D_VIEWPORT_TRANSLATE 0x00000a20 |
#define NV20_3D_VIEWPORT_TRANSLATE_X 0x00000a20 |
#define NV20_3D_VIEWPORT_TRANSLATE_Y 0x00000a24 |
#define NV20_3D_VIEWPORT_TRANSLATE_Z 0x00000a28 |
#define NV20_3D_VIEWPORT_TRANSLATE_W 0x00000a2c |
#define NV20_3D_VIEWPORT_SCALE 0x00000af0 |
#define NV20_3D_VIEWPORT_SCALE_X 0x00000af0 |
#define NV20_3D_VIEWPORT_SCALE_Y 0x00000af4 |
#define NV20_3D_VIEWPORT_SCALE_Z 0x00000af8 |
#define NV20_3D_VIEWPORT_SCALE_W 0x00000afc |
#define NV20_3D_NORMALIZE_ENABLE 0x000003a4 |
#define NV20_3D_SEPARATE_SPECULAR_ENABLE 0x000003b8 |
#define NV20_3D_LIGHT_MODEL_TWO_SIDE_ENABLE 0x000017c4 |
#define NV20_3D_LIGHT_MODEL 0x00000294 |
#define NV20_3D_LIGHT_MODEL_VIEWER__MASK 0x00030000 |
#define NV20_3D_LIGHT_MODEL_VIEWER__SHIFT 16 |
#define NV20_3D_LIGHT_MODEL_VIEWER_NONLOCAL 0x00020000 |
#define NV20_3D_LIGHT_MODEL_VIEWER_LOCAL 0x00030000 |
#define NV20_3D_LIGHT_MODEL_SEPARATE_SPECULAR 0x00000001 |
#define NV20_3D_ENABLED_LIGHTS 0x000003bc |
#define NV20_3D_ENABLED_LIGHTS_0__MASK 0x00000003 |
#define NV20_3D_ENABLED_LIGHTS_0__SHIFT 0 |
#define NV20_3D_ENABLED_LIGHTS_0_DISABLED 0x00000000 |
#define NV20_3D_ENABLED_LIGHTS_0_NONPOSITIONAL 0x00000001 |
#define NV20_3D_ENABLED_LIGHTS_0_POSITIONAL 0x00000002 |
#define NV20_3D_ENABLED_LIGHTS_0_DIRECTIONAL 0x00000003 |
#define NV20_3D_ENABLED_LIGHTS_1__MASK 0x0000000c |
#define NV20_3D_ENABLED_LIGHTS_1__SHIFT 2 |
#define NV20_3D_ENABLED_LIGHTS_1_DISABLED 0x00000000 |
#define NV20_3D_ENABLED_LIGHTS_1_NONPOSITIONAL 0x00000004 |
#define NV20_3D_ENABLED_LIGHTS_1_POSITIONAL 0x00000008 |
#define NV20_3D_ENABLED_LIGHTS_1_DIRECTIONAL 0x0000000c |
#define NV20_3D_ENABLED_LIGHTS_2__MASK 0x00000030 |
#define NV20_3D_ENABLED_LIGHTS_2__SHIFT 4 |
#define NV20_3D_ENABLED_LIGHTS_2_DISABLED 0x00000000 |
#define NV20_3D_ENABLED_LIGHTS_2_NONPOSITIONAL 0x00000010 |
#define NV20_3D_ENABLED_LIGHTS_2_POSITIONAL 0x00000020 |
#define NV20_3D_ENABLED_LIGHTS_2_DIRECTIONAL 0x00000030 |
#define NV20_3D_ENABLED_LIGHTS_3__MASK 0x000000c0 |
#define NV20_3D_ENABLED_LIGHTS_3__SHIFT 6 |
#define NV20_3D_ENABLED_LIGHTS_3_DISABLED 0x00000000 |
#define NV20_3D_ENABLED_LIGHTS_3_NONPOSITIONAL 0x00000040 |
#define NV20_3D_ENABLED_LIGHTS_3_POSITIONAL 0x00000080 |
#define NV20_3D_ENABLED_LIGHTS_3_DIRECTIONAL 0x000000c0 |
#define NV20_3D_ENABLED_LIGHTS_4__MASK 0x00000300 |
#define NV20_3D_ENABLED_LIGHTS_4__SHIFT 8 |
#define NV20_3D_ENABLED_LIGHTS_4_DISABLED 0x00000000 |
#define NV20_3D_ENABLED_LIGHTS_4_NONPOSITIONAL 0x00000100 |
#define NV20_3D_ENABLED_LIGHTS_4_POSITIONAL 0x00000200 |
#define NV20_3D_ENABLED_LIGHTS_4_DIRECTIONAL 0x00000300 |
#define NV20_3D_ENABLED_LIGHTS_5__MASK 0x00000c00 |
#define NV20_3D_ENABLED_LIGHTS_5__SHIFT 10 |
#define NV20_3D_ENABLED_LIGHTS_5_DISABLED 0x00000000 |
#define NV20_3D_ENABLED_LIGHTS_5_NONPOSITIONAL 0x00000400 |
#define NV20_3D_ENABLED_LIGHTS_5_POSITIONAL 0x00000800 |
#define NV20_3D_ENABLED_LIGHTS_5_DIRECTIONAL 0x00000c00 |
#define NV20_3D_ENABLED_LIGHTS_6__MASK 0x00003000 |
#define NV20_3D_ENABLED_LIGHTS_6__SHIFT 12 |
#define NV20_3D_ENABLED_LIGHTS_6_DISABLED 0x00000000 |
#define NV20_3D_ENABLED_LIGHTS_6_NONPOSITIONAL 0x00001000 |
#define NV20_3D_ENABLED_LIGHTS_6_POSITIONAL 0x00002000 |
#define NV20_3D_ENABLED_LIGHTS_6_DIRECTIONAL 0x00003000 |
#define NV20_3D_ENABLED_LIGHTS_7__MASK 0x0000c000 |
#define NV20_3D_ENABLED_LIGHTS_7__SHIFT 14 |
#define NV20_3D_ENABLED_LIGHTS_7_DISABLED 0x00000000 |
#define NV20_3D_ENABLED_LIGHTS_7_NONPOSITIONAL 0x00004000 |
#define NV20_3D_ENABLED_LIGHTS_7_POSITIONAL 0x00008000 |
#define NV20_3D_ENABLED_LIGHTS_7_DIRECTIONAL 0x0000c000 |
#define NV20_3D_COLOR_MATERIAL 0x00000298 |
#define NV20_3D_COLOR_MATERIAL_FRONT_EMISSION__MASK 0x00000003 |
#define NV20_3D_COLOR_MATERIAL_FRONT_EMISSION__SHIFT 0 |
#define NV20_3D_COLOR_MATERIAL_FRONT_EMISSION_OFF 0x00000000 |
#define NV20_3D_COLOR_MATERIAL_FRONT_EMISSION_COL1 0x00000001 |
#define NV20_3D_COLOR_MATERIAL_FRONT_EMISSION_COL2 0x00000002 |
#define NV20_3D_COLOR_MATERIAL_FRONT_AMBIENT__MASK 0x0000000c |
#define NV20_3D_COLOR_MATERIAL_FRONT_AMBIENT__SHIFT 2 |
#define NV20_3D_COLOR_MATERIAL_FRONT_AMBIENT_OFF 0x00000000 |
#define NV20_3D_COLOR_MATERIAL_FRONT_AMBIENT_COL1 0x00000004 |
#define NV20_3D_COLOR_MATERIAL_FRONT_AMBIENT_COL2 0x00000008 |
#define NV20_3D_COLOR_MATERIAL_FRONT_DIFFUSE__MASK 0x00000030 |
#define NV20_3D_COLOR_MATERIAL_FRONT_DIFFUSE__SHIFT 4 |
#define NV20_3D_COLOR_MATERIAL_FRONT_DIFFUSE_OFF 0x00000000 |
#define NV20_3D_COLOR_MATERIAL_FRONT_DIFFUSE_COL1 0x00000010 |
#define NV20_3D_COLOR_MATERIAL_FRONT_DIFFUSE_COL2 0x00000020 |
#define NV20_3D_COLOR_MATERIAL_FRONT_SPECULAR__MASK 0x000000c0 |
#define NV20_3D_COLOR_MATERIAL_FRONT_SPECULAR__SHIFT 6 |
#define NV20_3D_COLOR_MATERIAL_FRONT_SPECULAR_OFF 0x00000000 |
#define NV20_3D_COLOR_MATERIAL_FRONT_SPECULAR_COL1 0x00000040 |
#define NV20_3D_COLOR_MATERIAL_FRONT_SPECULAR_COL2 0x00000080 |
#define NV20_3D_COLOR_MATERIAL_BACK_EMISSION__MASK 0x00000300 |
#define NV20_3D_COLOR_MATERIAL_BACK_EMISSION__SHIFT 8 |
#define NV20_3D_COLOR_MATERIAL_BACK_EMISSION_OFF 0x00000000 |
#define NV20_3D_COLOR_MATERIAL_BACK_EMISSION_COL1 0x00000100 |
#define NV20_3D_COLOR_MATERIAL_BACK_EMISSION_COL2 0x00000200 |
#define NV20_3D_COLOR_MATERIAL_BACK_AMBIENT__MASK 0x00000c00 |
#define NV20_3D_COLOR_MATERIAL_BACK_AMBIENT__SHIFT 10 |
#define NV20_3D_COLOR_MATERIAL_BACK_AMBIENT_OFF 0x00000000 |
#define NV20_3D_COLOR_MATERIAL_BACK_AMBIENT_COL1 0x00000400 |
#define NV20_3D_COLOR_MATERIAL_BACK_AMBIENT_COL2 0x00000800 |
#define NV20_3D_COLOR_MATERIAL_BACK_DIFFUSE__MASK 0x00003000 |
#define NV20_3D_COLOR_MATERIAL_BACK_DIFFUSE__SHIFT 12 |
#define NV20_3D_COLOR_MATERIAL_BACK_DIFFUSE_OFF 0x00000000 |
#define NV20_3D_COLOR_MATERIAL_BACK_DIFFUSE_COL1 0x00001000 |
#define NV20_3D_COLOR_MATERIAL_BACK_DIFFUSE_COL2 0x00002000 |
#define NV20_3D_COLOR_MATERIAL_BACK_SPECULAR__MASK 0x0000c000 |
#define NV20_3D_COLOR_MATERIAL_BACK_SPECULAR__SHIFT 14 |
#define NV20_3D_COLOR_MATERIAL_BACK_SPECULAR_OFF 0x00000000 |
#define NV20_3D_COLOR_MATERIAL_BACK_SPECULAR_COL1 0x00004000 |
#define NV20_3D_COLOR_MATERIAL_BACK_SPECULAR_COL2 0x00008000 |
#define NV20_3D_MATERIAL_FACTOR_FRONT 0x000003a8 |
#define NV20_3D_MATERIAL_FACTOR_FRONT_R 0x000003a8 |
#define NV20_3D_MATERIAL_FACTOR_FRONT_G 0x000003ac |
#define NV20_3D_MATERIAL_FACTOR_FRONT_B 0x000003b0 |
#define NV20_3D_MATERIAL_FACTOR_BACK 0x000017b0 |
#define NV20_3D_MATERIAL_FACTOR_BACK_R 0x000017b0 |
#define NV20_3D_MATERIAL_FACTOR_BACK_G 0x000017b4 |
#define NV20_3D_MATERIAL_FACTOR_BACK_B 0x000017b8 |
#define NV20_3D_MATERIAL_FACTOR_FRONT_A 0x000003b4 |
#define NV20_3D_MATERIAL_FACTOR_BACK_A 0x000017ac |
#define NV20_3D_LIGHT_MODEL_FRONT_AMBIENT 0x00000a10 |
#define NV20_3D_LIGHT_MODEL_FRONT_AMBIENT_R 0x00000a10 |
#define NV20_3D_LIGHT_MODEL_FRONT_AMBIENT_G 0x00000a14 |
#define NV20_3D_LIGHT_MODEL_FRONT_AMBIENT_B 0x00000a18 |
#define NV20_3D_LIGHT_MODEL_BACK_AMBIENT 0x000017a0 |
#define NV20_3D_LIGHT_MODEL_BACK_AMBIENT_R 0x000017a0 |
#define NV20_3D_LIGHT_MODEL_BACK_AMBIENT_G 0x000017a4 |
#define NV20_3D_LIGHT_MODEL_BACK_AMBIENT_B 0x000017a8 |
#define NV20_3D_FRONT_MATERIAL_SHININESS(i0) (0x000009e0 + 0x4*(i0)) |
#define NV20_3D_FRONT_MATERIAL_SHININESS__ESIZE 0x00000004 |
#define NV20_3D_FRONT_MATERIAL_SHININESS__LEN 0x00000006 |
#define NV20_3D_BACK_MATERIAL_SHININESS(i0) (0x00001e28 + 0x4*(i0)) |
#define NV20_3D_BACK_MATERIAL_SHININESS__ESIZE 0x00000004 |
#define NV20_3D_BACK_MATERIAL_SHININESS__LEN 0x00000006 |
#define NV20_3D_LIGHT_FRONT_AMBIENT(i0) (0x00001000 + 0x80*(i0)) |
#define NV20_3D_LIGHT_FRONT_AMBIENT_R(i0) (0x00001000 + 0x80*(i0)) |
#define NV20_3D_LIGHT_FRONT_AMBIENT_G(i0) (0x00001004 + 0x80*(i0)) |
#define NV20_3D_LIGHT_FRONT_AMBIENT_B(i0) (0x00001008 + 0x80*(i0)) |
#define NV20_3D_LIGHT_FRONT_DIFFUSE(i0) (0x0000100c + 0x80*(i0)) |
#define NV20_3D_LIGHT_FRONT_DIFFUSE_R(i0) (0x0000100c + 0x80*(i0)) |
#define NV20_3D_LIGHT_FRONT_DIFFUSE_G(i0) (0x00001010 + 0x80*(i0)) |
#define NV20_3D_LIGHT_FRONT_DIFFUSE_B(i0) (0x00001014 + 0x80*(i0)) |
#define NV20_3D_LIGHT_FRONT_SPECULAR(i0) (0x00001018 + 0x80*(i0)) |
#define NV20_3D_LIGHT_FRONT_SPECULAR_R(i0) (0x00001018 + 0x80*(i0)) |
#define NV20_3D_LIGHT_FRONT_SPECULAR_G(i0) (0x0000101c + 0x80*(i0)) |
#define NV20_3D_LIGHT_FRONT_SPECULAR_B(i0) (0x00001020 + 0x80*(i0)) |
#define NV20_3D_LIGHT_BACK_AMBIENT(i0) (0x00000c00 + 0x40*(i0)) |
#define NV20_3D_LIGHT_BACK_AMBIENT_R(i0) (0x00000c00 + 0x40*(i0)) |
#define NV20_3D_LIGHT_BACK_AMBIENT_G(i0) (0x00000c04 + 0x40*(i0)) |
#define NV20_3D_LIGHT_BACK_AMBIENT_B(i0) (0x00000c08 + 0x40*(i0)) |
#define NV20_3D_LIGHT_BACK_DIFFUSE(i0) (0x00000c0c + 0x40*(i0)) |
#define NV20_3D_LIGHT_BACK_DIFFUSE_R(i0) (0x00000c0c + 0x40*(i0)) |
#define NV20_3D_LIGHT_BACK_DIFFUSE_G(i0) (0x00000c10 + 0x40*(i0)) |
#define NV20_3D_LIGHT_BACK_DIFFUSE_B(i0) (0x00000c14 + 0x40*(i0)) |
#define NV20_3D_LIGHT_BACK_SPECULAR(i0) (0x00000c18 + 0x40*(i0)) |
#define NV20_3D_LIGHT_BACK_SPECULAR_R(i0) (0x00000c18 + 0x40*(i0)) |
#define NV20_3D_LIGHT_BACK_SPECULAR_G(i0) (0x00000c1c + 0x40*(i0)) |
#define NV20_3D_LIGHT_BACK_SPECULAR_B(i0) (0x00000c20 + 0x40*(i0)) |
#define NV20_3D_LIGHT_HALF_VECTOR(i0) (0x00001028 + 0x80*(i0)) |
#define NV20_3D_LIGHT_HALF_VECTOR_X(i0) (0x00001028 + 0x80*(i0)) |
#define NV20_3D_LIGHT_HALF_VECTOR_Y(i0) (0x0000102c + 0x80*(i0)) |
#define NV20_3D_LIGHT_HALF_VECTOR_Z(i0) (0x00001030 + 0x80*(i0)) |
#define NV20_3D_LIGHT_DIRECTION(i0) (0x00001034 + 0x80*(i0)) |
#define NV20_3D_LIGHT_DIRECTION_X(i0) (0x00001034 + 0x80*(i0)) |
#define NV20_3D_LIGHT_DIRECTION_Y(i0) (0x00001038 + 0x80*(i0)) |
#define NV20_3D_LIGHT_DIRECTION_Z(i0) (0x0000103c + 0x80*(i0)) |
#define NV20_3D_LIGHT_SPOT_CUTOFF(i0, i1) (0x00001040 + 0x80*(i0) + 0x4*(i1)) |
#define NV20_3D_LIGHT_SPOT_CUTOFF__ESIZE 0x00000004 |
#define NV20_3D_LIGHT_SPOT_CUTOFF__LEN 0x00000007 |
#define NV20_3D_LIGHT_POSITION(i0) (0x0000105c + 0x80*(i0)) |
#define NV20_3D_LIGHT_POSITION_X(i0) (0x0000105c + 0x80*(i0)) |
#define NV20_3D_LIGHT_POSITION_Y(i0) (0x00001060 + 0x80*(i0)) |
#define NV20_3D_LIGHT_POSITION_Z(i0) (0x00001064 + 0x80*(i0)) |
#define NV20_3D_LIGHT_ATTENUATION(i0) (0x00001068 + 0x80*(i0)) |
#define NV20_3D_LIGHT_ATTENUATION_CONSTANT(i0) (0x00001068 + 0x80*(i0)) |
#define NV20_3D_LIGHT_ATTENUATION_LINEAR(i0) (0x0000106c + 0x80*(i0)) |
#define NV20_3D_LIGHT_ATTENUATION_QUADRATIC(i0) (0x00001070 + 0x80*(i0)) |
#define NV20_3D_FOG_MODE 0x0000029c |
#define NV20_3D_FOG_MODE_LINEAR_UNSIGNED 0x00000804 |
#define NV20_3D_FOG_MODE_LINEAR_SIGNED 0x00002601 |
#define NV20_3D_FOG_MODE_EXP_UNSIGNED 0x00000802 |
#define NV20_3D_FOG_MODE_EXP_SIGNED 0x00000800 |
#define NV20_3D_FOG_MODE_EXP2_UNSIGNED 0x00000803 |
#define NV20_3D_FOG_MODE_EXP2_SIGNED 0x00000801 |
#define NV20_3D_FOG_COORD 0x000002a0 |
#define NV20_3D_FOG_COORD_DIST_RADIAL 0x00000001 |
#define NV20_3D_FOG_COORD_DIST_ORTHOGONAL 0x00000002 |
#define NV20_3D_FOG_COORD_DIST_ORTHOGONAL_ABS 0x00000003 |
#define NV20_3D_FOG_COORD_FOG 0x00000006 |
#define NV20_3D_FOG_ENABLE 0x000002a4 |
#define NV20_3D_FOG_COLOR 0x000002a8 |
#define NV20_3D_FOG_COLOR_R__MASK 0x000000ff |
#define NV20_3D_FOG_COLOR_R__SHIFT 0 |
#define NV20_3D_FOG_COLOR_G__MASK 0x0000ff00 |
#define NV20_3D_FOG_COLOR_G__SHIFT 8 |
#define NV20_3D_FOG_COLOR_B__MASK 0x00ff0000 |
#define NV20_3D_FOG_COLOR_B__SHIFT 16 |
#define NV20_3D_FOG_COLOR_A__MASK 0xff000000 |
#define NV20_3D_FOG_COLOR_A__SHIFT 24 |
#define NV20_3D_FOG_COEFF(i0) (0x000009c0 + 0x4*(i0)) |
#define NV20_3D_FOG_COEFF__ESIZE 0x00000004 |
#define NV20_3D_FOG_COEFF__LEN 0x00000003 |
#define NV20_3D_TEX_GEN_MODE(i0, i1) (0x000003c0 + 0x10*(i0) + 0x4*(i1)) |
#define NV20_3D_TEX_GEN_MODE__ESIZE 0x00000004 |
#define NV20_3D_TEX_GEN_MODE__LEN 0x00000004 |
#define NV20_3D_TEX_GEN_MODE_FALSE 0x00000000 |
#define NV20_3D_TEX_GEN_MODE_EYE_LINEAR 0x00002400 |
#define NV20_3D_TEX_GEN_MODE_OBJECT_LINEAR 0x00002401 |
#define NV20_3D_TEX_GEN_MODE_SPHERE_MAP 0x00002402 |
#define NV20_3D_TEX_GEN_MODE_NORMAL_MAP 0x00008511 |
#define NV20_3D_TEX_GEN_MODE_REFLECTION_MAP 0x00008512 |
#define NV20_3D_TEX_GEN_COEFF(i0, i1) (0x00000840 + 0x40*(i0) + 0x10*(i1)) |
#define NV20_3D_TEX_GEN_COEFF__ESIZE 0x00000010 |
#define NV20_3D_TEX_GEN_COEFF__LEN 0x00000004 |
#define NV20_3D_TEX_GEN_COEFF_A(i0, i1) (0x00000840 + 0x40*(i0) + 0x10*(i1)) |
#define NV20_3D_TEX_GEN_COEFF_B(i0, i1) (0x00000844 + 0x40*(i0) + 0x10*(i1)) |
#define NV20_3D_TEX_GEN_COEFF_C(i0, i1) (0x00000848 + 0x40*(i0) + 0x10*(i1)) |
#define NV20_3D_TEX_GEN_COEFF_D(i0, i1) (0x0000084c + 0x40*(i0) + 0x10*(i1)) |
#define NV20_3D_TEX_MATRIX_ENABLE(i0) (0x00000420 + 0x4*(i0)) |
#define NV20_3D_TEX_MATRIX_ENABLE__ESIZE 0x00000004 |
#define NV20_3D_TEX_MATRIX_ENABLE__LEN 0x00000004 |
#define NV20_3D_TEX_MATRIX(i0, i1) (0x000006c0 + 0x40*(i0) + 0x4*(i1)) |
#define NV20_3D_TEX_MATRIX__ESIZE 0x00000004 |
#define NV20_3D_TEX_MATRIX__LEN 0x00000010 |
#define NV20_3D_TEX_SHADER_CULL_MODE 0x000017f8 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_S__MASK 0x00000001 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_S__SHIFT 0 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_S_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_S_LESS 0x00000001 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_T__MASK 0x00000002 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_T__SHIFT 1 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_T_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_T_LESS 0x00000002 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_R__MASK 0x00000004 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_R__SHIFT 2 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_R_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_R_LESS 0x00000004 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_Q__MASK 0x00000008 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_Q__SHIFT 3 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_Q_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX0_Q_LESS 0x00000008 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_S__MASK 0x00000010 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_S__SHIFT 4 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_S_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_S_LESS 0x00000010 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_T__MASK 0x00000020 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_T__SHIFT 5 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_T_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_T_LESS 0x00000020 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_R__MASK 0x00000040 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_R__SHIFT 6 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_R_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_R_LESS 0x00000040 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_Q__MASK 0x00000080 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_Q__SHIFT 7 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_Q_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX1_Q_LESS 0x00000080 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_S__MASK 0x00000100 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_S__SHIFT 8 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_S_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_S_LESS 0x00000100 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_T__MASK 0x00000200 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_T__SHIFT 9 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_T_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_T_LESS 0x00000200 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_R__MASK 0x00000400 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_R__SHIFT 10 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_R_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_R_LESS 0x00000400 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_Q__MASK 0x00000800 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_Q__SHIFT 11 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_Q_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX2_Q_LESS 0x00000800 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_S__MASK 0x00001000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_S__SHIFT 12 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_S_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_S_LESS 0x00001000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_T__MASK 0x00002000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_T__SHIFT 13 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_T_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_T_LESS 0x00002000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_R__MASK 0x00004000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_R__SHIFT 14 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_R_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_R_LESS 0x00004000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_Q__MASK 0x00008000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_Q__SHIFT 15 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_Q_GEQUAL 0x00000000 |
#define NV20_3D_TEX_SHADER_CULL_MODE_TX3_Q_LESS 0x00008000 |
#define NV20_3D_TEX_SHADER_CONST_EYE 0x0000181c |
#define NV20_3D_TEX_SHADER_CONST_EYE_X 0x0000181c |
#define NV20_3D_TEX_SHADER_CONST_EYE_Y 0x00001820 |
#define NV20_3D_TEX_SHADER_CONST_EYE_Z 0x00001824 |
#define NV20_3D_TEX_SHADER_OFFSET_MATRIX(i0, i1) (0x00001b28 + 0x40*(i0) + 0x4*(i1)) |
#define NV20_3D_TEX_SHADER_OFFSET_MATRIX__ESIZE 0x00000004 |
#define NV20_3D_TEX_SHADER_OFFSET_MATRIX__LEN 0x00000004 |
#define NV20_3D_TEX_RCOMP 0x00001e6c |
#define NV20_3D_TEX_RCOMP_NEVER 0x00000000 |
#define NV20_3D_TEX_RCOMP_GREATER 0x00000001 |
#define NV20_3D_TEX_RCOMP_EQUAL 0x00000002 |
#define NV20_3D_TEX_RCOMP_GEQUAL 0x00000003 |
#define NV20_3D_TEX_RCOMP_LESS 0x00000004 |
#define NV20_3D_TEX_RCOMP_NOTEQUAL 0x00000005 |
#define NV20_3D_TEX_RCOMP_LEQUAL 0x00000006 |
#define NV20_3D_TEX_RCOMP_ALWAYS 0x00000007 |
#define NV20_3D_TEX_SHADER_OP 0x00001e70 |
#define NV20_3D_TEX_SHADER_OP_TX0__MASK 0x0000001f |
#define NV20_3D_TEX_SHADER_OP_TX0__SHIFT 0 |
#define NV20_3D_TEX_SHADER_OP_TX0_NONE 0x00000000 |
#define NV20_3D_TEX_SHADER_OP_TX0_TEXTURE_2D 0x00000001 |
#define NV20_3D_TEX_SHADER_OP_TX0_PASS_THROUGH 0x00000004 |
#define NV20_3D_TEX_SHADER_OP_TX0_CULL_FRAGMENT 0x00000005 |
#define NV20_3D_TEX_SHADER_OP_TX0_OFFSET_TEXTURE_2D 0x00000006 |
#define NV20_3D_TEX_SHADER_OP_TX0_DOT_PRODUCT_TEXTURE_2D 0x00000009 |
#define NV20_3D_TEX_SHADER_OP_TX0_DOT_PRODUCT_DEPTH_REPLACE 0x0000000a |
#define NV20_3D_TEX_SHADER_OP_TX0_DEPENDANT_AR_TEXTURE_2D 0x0000000f |
#define NV20_3D_TEX_SHADER_OP_TX0_DEPENDANT_GB_TEXTURE_2D 0x00000010 |
#define NV20_3D_TEX_SHADER_OP_TX0_DOT_PRODUCT 0x00000011 |
#define NV20_3D_TEX_SHADER_OP_TX1__MASK 0x000003e0 |
#define NV20_3D_TEX_SHADER_OP_TX1__SHIFT 5 |
#define NV20_3D_TEX_SHADER_OP_TX1_NONE 0x00000000 |
#define NV20_3D_TEX_SHADER_OP_TX1_TEXTURE_2D 0x00000020 |
#define NV20_3D_TEX_SHADER_OP_TX1_PASS_THROUGH 0x00000080 |
#define NV20_3D_TEX_SHADER_OP_TX1_CULL_FRAGMENT 0x000000a0 |
#define NV20_3D_TEX_SHADER_OP_TX1_OFFSET_TEXTURE_2D 0x000000c0 |
#define NV20_3D_TEX_SHADER_OP_TX1_DOT_PRODUCT_TEXTURE_2D 0x00000120 |
#define NV20_3D_TEX_SHADER_OP_TX1_DOT_PRODUCT_DEPTH_REPLACE 0x00000140 |
#define NV20_3D_TEX_SHADER_OP_TX1_DEPENDANT_AR_TEXTURE_2D 0x000001e0 |
#define NV20_3D_TEX_SHADER_OP_TX1_DEPENDANT_GB_TEXTURE_2D 0x00000200 |
#define NV20_3D_TEX_SHADER_OP_TX1_DOT_PRODUCT 0x00000220 |
#define NV20_3D_TEX_SHADER_OP_TX2__MASK 0x00007c00 |
#define NV20_3D_TEX_SHADER_OP_TX2__SHIFT 10 |
#define NV20_3D_TEX_SHADER_OP_TX2_NONE 0x00000000 |
#define NV20_3D_TEX_SHADER_OP_TX2_TEXTURE_2D 0x00000400 |
#define NV20_3D_TEX_SHADER_OP_TX2_PASS_THROUGH 0x00001000 |
#define NV20_3D_TEX_SHADER_OP_TX2_CULL_FRAGMENT 0x00001400 |
#define NV20_3D_TEX_SHADER_OP_TX2_OFFSET_TEXTURE_2D 0x00001800 |
#define NV20_3D_TEX_SHADER_OP_TX2_DOT_PRODUCT_TEXTURE_2D 0x00002400 |
#define NV20_3D_TEX_SHADER_OP_TX2_DOT_PRODUCT_DEPTH_REPLACE 0x00002800 |
#define NV20_3D_TEX_SHADER_OP_TX2_DEPENDANT_AR_TEXTURE_2D 0x00003c00 |
#define NV20_3D_TEX_SHADER_OP_TX2_DEPENDANT_GB_TEXTURE_2D 0x00004000 |
#define NV20_3D_TEX_SHADER_OP_TX2_DOT_PRODUCT 0x00004400 |
#define NV20_3D_TEX_SHADER_OP_TX3__MASK 0x000f8000 |
#define NV20_3D_TEX_SHADER_OP_TX3__SHIFT 15 |
#define NV20_3D_TEX_SHADER_OP_TX3_NONE 0x00000000 |
#define NV20_3D_TEX_SHADER_OP_TX3_TEXTURE_2D 0x00008000 |
#define NV20_3D_TEX_SHADER_OP_TX3_PASS_THROUGH 0x00020000 |
#define NV20_3D_TEX_SHADER_OP_TX3_CULL_FRAGMENT 0x00028000 |
#define NV20_3D_TEX_SHADER_OP_TX3_OFFSET_TEXTURE_2D 0x00030000 |
#define NV20_3D_TEX_SHADER_OP_TX3_DOT_PRODUCT_TEXTURE_2D 0x00048000 |
#define NV20_3D_TEX_SHADER_OP_TX3_DOT_PRODUCT_DEPTH_REPLACE 0x00050000 |
#define NV20_3D_TEX_SHADER_OP_TX3_DEPENDANT_AR_TEXTURE_2D 0x00078000 |
#define NV20_3D_TEX_SHADER_OP_TX3_DEPENDANT_GB_TEXTURE_2D 0x00080000 |
#define NV20_3D_TEX_SHADER_OP_TX3_DOT_PRODUCT 0x00088000 |
#define NV20_3D_TEX_SHADER_DOTMAPPING 0x00001e74 |
#define NV20_3D_TEX_SHADER_DOTMAPPING_TX0__MASK 0x0000000f |
#define NV20_3D_TEX_SHADER_DOTMAPPING_TX0__SHIFT 0 |
#define NV20_3D_TEX_SHADER_DOTMAPPING_TX1__MASK 0x000000f0 |
#define NV20_3D_TEX_SHADER_DOTMAPPING_TX1__SHIFT 4 |
#define NV20_3D_TEX_SHADER_DOTMAPPING_TX2__MASK 0x00000f00 |
#define NV20_3D_TEX_SHADER_DOTMAPPING_TX2__SHIFT 8 |
#define NV20_3D_TEX_SHADER_DOTMAPPING_TX3__MASK 0x0000f000 |
#define NV20_3D_TEX_SHADER_DOTMAPPING_TX3__SHIFT 12 |
#define NV20_3D_TEX_SHADER_PREVIOUS 0x00001e78 |
#define NV20_3D_TEX_SHADER_PREVIOUS_TX0__MASK 0x00000f00 |
#define NV20_3D_TEX_SHADER_PREVIOUS_TX0__SHIFT 8 |
#define NV20_3D_TEX_SHADER_PREVIOUS_TX1__MASK 0x0000f000 |
#define NV20_3D_TEX_SHADER_PREVIOUS_TX1__SHIFT 12 |
#define NV20_3D_TEX_SHADER_PREVIOUS_TX2__MASK 0x00030000 |
#define NV20_3D_TEX_SHADER_PREVIOUS_TX2__SHIFT 16 |
#define NV20_3D_TEX_SHADER_PREVIOUS_TX3__MASK 0x00300000 |
#define NV20_3D_TEX_SHADER_PREVIOUS_TX3__SHIFT 20 |
#define NV20_3D_TEX(i0) (0x00000000 + 0x40*(i0)) |
#define NV20_3D_TEX__ESIZE 0x00000040 |
#define NV20_3D_TEX__LEN 0x00000004 |
#define NV20_3D_TEX_OFFSET(i0) (0x00001b00 + 0x40*(i0)) |
#define NV20_3D_TEX_FORMAT(i0) (0x00001b04 + 0x40*(i0)) |
#define NV20_3D_TEX_FORMAT_DMA0 0x00000001 |
#define NV20_3D_TEX_FORMAT_DMA1 0x00000002 |
#define NV20_3D_TEX_FORMAT_CUBIC 0x00000004 |
#define NV20_3D_TEX_FORMAT_NO_BORDER 0x00000008 |
#define NV20_3D_TEX_FORMAT_DIMS__MASK 0x000000f0 |
#define NV20_3D_TEX_FORMAT_DIMS__SHIFT 4 |
#define NV20_3D_TEX_FORMAT_DIMS_1D 0x00000010 |
#define NV20_3D_TEX_FORMAT_DIMS_2D 0x00000020 |
#define NV20_3D_TEX_FORMAT_DIMS_3D 0x00000030 |
#define NV20_3D_TEX_FORMAT_FORMAT__MASK 0x0000ff00 |
#define NV20_3D_TEX_FORMAT_FORMAT__SHIFT 8 |
#define NV20_3D_TEX_FORMAT_FORMAT_L8 0x00000000 |
#define NV20_3D_TEX_FORMAT_FORMAT_I8 0x00000100 |
#define NV20_3D_TEX_FORMAT_FORMAT_A1R5G5B5 0x00000200 |
#define NV20_3D_TEX_FORMAT_FORMAT_A4R4G4B4 0x00000400 |
#define NV20_3D_TEX_FORMAT_FORMAT_R5G6B5 0x00000500 |
#define NV20_3D_TEX_FORMAT_FORMAT_A8R8G8B8 0x00000600 |
#define NV20_3D_TEX_FORMAT_FORMAT_X8R8G8B8 0x00000700 |
#define NV20_3D_TEX_FORMAT_FORMAT_INDEX8 0x00000b00 |
#define NV20_3D_TEX_FORMAT_FORMAT_DXT1 0x00000c00 |
#define NV20_3D_TEX_FORMAT_FORMAT_DXT3 0x00000e00 |
#define NV20_3D_TEX_FORMAT_FORMAT_DXT5 0x00000f00 |
#define NV20_3D_TEX_FORMAT_FORMAT_A1R5G5B5_RECT 0x00001000 |
#define NV20_3D_TEX_FORMAT_FORMAT_R5G6B5_RECT 0x00001100 |
#define NV20_3D_TEX_FORMAT_FORMAT_A8R8G8B8_RECT 0x00001200 |
#define NV20_3D_TEX_FORMAT_FORMAT_L8_RECT 0x00001300 |
#define NV20_3D_TEX_FORMAT_FORMAT_DSDT8_RECT 0x00001700 |
#define NV20_3D_TEX_FORMAT_FORMAT_A8L8 0x00001a00 |
#define NV20_3D_TEX_FORMAT_FORMAT_I8_RECT 0x00001b00 |
#define NV20_3D_TEX_FORMAT_FORMAT_A4R4G4B4_RECT 0x00001d00 |
#define NV20_3D_TEX_FORMAT_FORMAT_R8G8B8_RECT 0x00001e00 |
#define NV20_3D_TEX_FORMAT_FORMAT_A8L8_RECT 0x00002000 |
#define NV20_3D_TEX_FORMAT_FORMAT_Z24 0x00002a00 |
#define NV20_3D_TEX_FORMAT_FORMAT_Z24_RECT 0x00002b00 |
#define NV20_3D_TEX_FORMAT_FORMAT_Z16 0x00002c00 |
#define NV20_3D_TEX_FORMAT_FORMAT_Z16_RECT 0x00002d00 |
#define NV20_3D_TEX_FORMAT_FORMAT_DSDT8 0x00002800 |
#define NV20_3D_TEX_FORMAT_FORMAT_HILO16 0x00003300 |
#define NV20_3D_TEX_FORMAT_FORMAT_HILO16_RECT 0x00003600 |
#define NV20_3D_TEX_FORMAT_FORMAT_HILO8 0x00004400 |
#define NV20_3D_TEX_FORMAT_FORMAT_SIGNED_HILO8 0x00004500 |
#define NV20_3D_TEX_FORMAT_FORMAT_HILO8_RECT 0x00004600 |
#define NV20_3D_TEX_FORMAT_FORMAT_SIGNED_HILO8_RECT 0x00004700 |
#define NV20_3D_TEX_FORMAT_MIPMAP 0x00080000 |
#define NV20_3D_TEX_FORMAT_BASE_SIZE_U__MASK 0x00f00000 |
#define NV20_3D_TEX_FORMAT_BASE_SIZE_U__SHIFT 20 |
#define NV20_3D_TEX_FORMAT_BASE_SIZE_V__MASK 0x0f000000 |
#define NV20_3D_TEX_FORMAT_BASE_SIZE_V__SHIFT 24 |
#define NV20_3D_TEX_FORMAT_BASE_SIZE_W__MASK 0xf0000000 |
#define NV20_3D_TEX_FORMAT_BASE_SIZE_W__SHIFT 28 |
#define NV20_3D_TEX_WRAP(i0) (0x00001b08 + 0x40*(i0)) |
#define NV20_3D_TEX_WRAP_S__MASK 0x000000ff |
#define NV20_3D_TEX_WRAP_S__SHIFT 0 |
#define NV20_3D_TEX_WRAP_S_REPEAT 0x00000001 |
#define NV20_3D_TEX_WRAP_S_MIRRORED_REPEAT 0x00000002 |
#define NV20_3D_TEX_WRAP_S_CLAMP_TO_EDGE 0x00000003 |
#define NV20_3D_TEX_WRAP_S_CLAMP_TO_BORDER 0x00000004 |
#define NV20_3D_TEX_WRAP_S_CLAMP 0x00000005 |
#define NV20_3D_TEX_WRAP_T__MASK 0x00000f00 |
#define NV20_3D_TEX_WRAP_T__SHIFT 8 |
#define NV20_3D_TEX_WRAP_T_REPEAT 0x00000100 |
#define NV20_3D_TEX_WRAP_T_MIRRORED_REPEAT 0x00000200 |
#define NV20_3D_TEX_WRAP_T_CLAMP_TO_EDGE 0x00000300 |
#define NV20_3D_TEX_WRAP_T_CLAMP_TO_BORDER 0x00000400 |
#define NV20_3D_TEX_WRAP_T_CLAMP 0x00000500 |
#define NV20_3D_TEX_WRAP_R__MASK 0x000f0000 |
#define NV20_3D_TEX_WRAP_R__SHIFT 16 |
#define NV20_3D_TEX_WRAP_R_REPEAT 0x00010000 |
#define NV20_3D_TEX_WRAP_R_MIRRORED_REPEAT 0x00020000 |
#define NV20_3D_TEX_WRAP_R_CLAMP_TO_EDGE 0x00030000 |
#define NV20_3D_TEX_WRAP_R_CLAMP_TO_BORDER 0x00040000 |
#define NV20_3D_TEX_WRAP_R_CLAMP 0x00050000 |
#define NV20_3D_TEX_ENABLE(i0) (0x00001b0c + 0x40*(i0)) |
#define NV20_3D_TEX_ENABLE_ANISO__MASK 0x00000030 |
#define NV20_3D_TEX_ENABLE_ANISO__SHIFT 4 |
#define NV20_3D_TEX_ENABLE_ANISO_NONE 0x00000000 |
#define NV20_3D_TEX_ENABLE_ANISO_2X 0x00000010 |
#define NV20_3D_TEX_ENABLE_ANISO_4X 0x00000020 |
#define NV20_3D_TEX_ENABLE_ANISO_8X 0x00000030 |
#define NV20_3D_TEX_ENABLE_MIPMAP_MAX_LOD__MASK 0x0003c000 |
#define NV20_3D_TEX_ENABLE_MIPMAP_MAX_LOD__SHIFT 14 |
#define NV20_3D_TEX_ENABLE_MIPMAP_MIN_LOD__MASK 0x3c000000 |
#define NV20_3D_TEX_ENABLE_MIPMAP_MIN_LOD__SHIFT 26 |
#define NV20_3D_TEX_ENABLE_ENABLE 0x40000000 |
#define NV20_3D_TEX_NPOT_PITCH(i0) (0x00001b10 + 0x40*(i0)) |
#define NV20_3D_TEX_NPOT_PITCH_PITCH__MASK 0xffff0000 |
#define NV20_3D_TEX_NPOT_PITCH_PITCH__SHIFT 16 |
#define NV20_3D_TEX_FILTER(i0) (0x00001b14 + 0x40*(i0)) |
#define NV20_3D_TEX_FILTER_LOD_BIAS__MASK 0x00000f00 |
#define NV20_3D_TEX_FILTER_LOD_BIAS__SHIFT 8 |
#define NV20_3D_TEX_FILTER_MINIFY__MASK 0x000f0000 |
#define NV20_3D_TEX_FILTER_MINIFY__SHIFT 16 |
#define NV20_3D_TEX_FILTER_MINIFY_NEAREST 0x00010000 |
#define NV20_3D_TEX_FILTER_MINIFY_LINEAR 0x00020000 |
#define NV20_3D_TEX_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST 0x00030000 |
#define NV20_3D_TEX_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST 0x00040000 |
#define NV20_3D_TEX_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR 0x00050000 |
#define NV20_3D_TEX_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR 0x00060000 |
#define NV20_3D_TEX_FILTER_MAGNIFY__MASK 0x0f000000 |
#define NV20_3D_TEX_FILTER_MAGNIFY__SHIFT 24 |
#define NV20_3D_TEX_FILTER_MAGNIFY_NEAREST 0x01000000 |
#define NV20_3D_TEX_FILTER_MAGNIFY_LINEAR 0x02000000 |
#define NV20_3D_TEX_NPOT_SIZE(i0) (0x00001b1c + 0x40*(i0)) |
#define NV20_3D_TEX_NPOT_SIZE_H__MASK 0x0000ffff |
#define NV20_3D_TEX_NPOT_SIZE_H__SHIFT 0 |
#define NV20_3D_TEX_NPOT_SIZE_W__MASK 0xffff0000 |
#define NV20_3D_TEX_NPOT_SIZE_W__SHIFT 16 |
#define NV20_3D_TEX_PALETTE_OFFSET(i0) (0x00001b20 + 0x40*(i0)) |
#define NV20_3D_TEX_BORDER_COLOR(i0) (0x00001b24 + 0x40*(i0)) |
#define NV20_3D_TEX_BORDER_COLOR_B__MASK 0x000000ff |
#define NV20_3D_TEX_BORDER_COLOR_B__SHIFT 0 |
#define NV20_3D_TEX_BORDER_COLOR_G__MASK 0x0000ff00 |
#define NV20_3D_TEX_BORDER_COLOR_G__SHIFT 8 |
#define NV20_3D_TEX_BORDER_COLOR_R__MASK 0x00ff0000 |
#define NV20_3D_TEX_BORDER_COLOR_R__SHIFT 16 |
#define NV20_3D_TEX_BORDER_COLOR_A__MASK 0xff000000 |
#define NV20_3D_TEX_BORDER_COLOR_A__SHIFT 24 |
#define NV20_3D_RC_IN_ALPHA(i0) (0x00000260 + 0x4*(i0)) |
#define NV20_3D_RC_IN_ALPHA_D_INPUT__MASK 0x0000000f |
#define NV20_3D_RC_IN_ALPHA_D_INPUT__SHIFT 0 |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_CONSTANT_COLOR0 0x00000001 |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_CONSTANT_COLOR1 0x00000002 |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_FOG 0x00000003 |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_PRIMARY_COLOR 0x00000004 |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_SECONDARY_COLOR 0x00000005 |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_TEXTURE0 0x00000008 |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_TEXTURE1 0x00000009 |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_TEXTURE2 0x0000000a |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_TEXTURE3 0x0000000b |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_SPARE0 0x0000000c |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_SPARE1 0x0000000d |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e |
#define NV20_3D_RC_IN_ALPHA_D_INPUT_E_TIMES_F 0x0000000f |
#define NV20_3D_RC_IN_ALPHA_D_COMPONENT_USAGE__MASK 0x00000010 |
#define NV20_3D_RC_IN_ALPHA_D_COMPONENT_USAGE__SHIFT 4 |
#define NV20_3D_RC_IN_ALPHA_D_COMPONENT_USAGE_BLUE 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_D_COMPONENT_USAGE_ALPHA 0x00000010 |
#define NV20_3D_RC_IN_ALPHA_D_MAPPING__MASK 0x000000e0 |
#define NV20_3D_RC_IN_ALPHA_D_MAPPING__SHIFT 5 |
#define NV20_3D_RC_IN_ALPHA_D_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_D_MAPPING_UNSIGNED_INVERT 0x00000020 |
#define NV20_3D_RC_IN_ALPHA_D_MAPPING_EXPAND_NORMAL 0x00000040 |
#define NV20_3D_RC_IN_ALPHA_D_MAPPING_EXPAND_NEGATE 0x00000060 |
#define NV20_3D_RC_IN_ALPHA_D_MAPPING_HALF_BIAS_NORMAL 0x00000080 |
#define NV20_3D_RC_IN_ALPHA_D_MAPPING_HALF_BIAS_NEGATE 0x000000a0 |
#define NV20_3D_RC_IN_ALPHA_D_MAPPING_SIGNED_IDENTITY 0x000000c0 |
#define NV20_3D_RC_IN_ALPHA_D_MAPPING_SIGNED_NEGATE 0x000000e0 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT__MASK 0x00000f00 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT__SHIFT 8 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_CONSTANT_COLOR0 0x00000100 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_CONSTANT_COLOR1 0x00000200 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_FOG 0x00000300 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_PRIMARY_COLOR 0x00000400 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_SECONDARY_COLOR 0x00000500 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_TEXTURE0 0x00000800 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_TEXTURE1 0x00000900 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_TEXTURE2 0x00000a00 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_TEXTURE3 0x00000b00 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_SPARE0 0x00000c00 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_SPARE1 0x00000d00 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV20_3D_RC_IN_ALPHA_C_INPUT_E_TIMES_F 0x00000f00 |
#define NV20_3D_RC_IN_ALPHA_C_COMPONENT_USAGE__MASK 0x00001000 |
#define NV20_3D_RC_IN_ALPHA_C_COMPONENT_USAGE__SHIFT 12 |
#define NV20_3D_RC_IN_ALPHA_C_COMPONENT_USAGE_BLUE 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_C_COMPONENT_USAGE_ALPHA 0x00001000 |
#define NV20_3D_RC_IN_ALPHA_C_MAPPING__MASK 0x0000e000 |
#define NV20_3D_RC_IN_ALPHA_C_MAPPING__SHIFT 13 |
#define NV20_3D_RC_IN_ALPHA_C_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_C_MAPPING_UNSIGNED_INVERT 0x00002000 |
#define NV20_3D_RC_IN_ALPHA_C_MAPPING_EXPAND_NORMAL 0x00004000 |
#define NV20_3D_RC_IN_ALPHA_C_MAPPING_EXPAND_NEGATE 0x00006000 |
#define NV20_3D_RC_IN_ALPHA_C_MAPPING_HALF_BIAS_NORMAL 0x00008000 |
#define NV20_3D_RC_IN_ALPHA_C_MAPPING_HALF_BIAS_NEGATE 0x0000a000 |
#define NV20_3D_RC_IN_ALPHA_C_MAPPING_SIGNED_IDENTITY 0x0000c000 |
#define NV20_3D_RC_IN_ALPHA_C_MAPPING_SIGNED_NEGATE 0x0000e000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT__MASK 0x000f0000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT__SHIFT 16 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_CONSTANT_COLOR0 0x00010000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_CONSTANT_COLOR1 0x00020000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_FOG 0x00030000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_PRIMARY_COLOR 0x00040000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_SECONDARY_COLOR 0x00050000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_TEXTURE0 0x00080000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_TEXTURE1 0x00090000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_TEXTURE2 0x000a0000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_TEXTURE3 0x000b0000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_SPARE0 0x000c0000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_SPARE1 0x000d0000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000 |
#define NV20_3D_RC_IN_ALPHA_B_INPUT_E_TIMES_F 0x000f0000 |
#define NV20_3D_RC_IN_ALPHA_B_COMPONENT_USAGE__MASK 0x00100000 |
#define NV20_3D_RC_IN_ALPHA_B_COMPONENT_USAGE__SHIFT 20 |
#define NV20_3D_RC_IN_ALPHA_B_COMPONENT_USAGE_BLUE 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_B_COMPONENT_USAGE_ALPHA 0x00100000 |
#define NV20_3D_RC_IN_ALPHA_B_MAPPING__MASK 0x00e00000 |
#define NV20_3D_RC_IN_ALPHA_B_MAPPING__SHIFT 21 |
#define NV20_3D_RC_IN_ALPHA_B_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_B_MAPPING_UNSIGNED_INVERT 0x00200000 |
#define NV20_3D_RC_IN_ALPHA_B_MAPPING_EXPAND_NORMAL 0x00400000 |
#define NV20_3D_RC_IN_ALPHA_B_MAPPING_EXPAND_NEGATE 0x00600000 |
#define NV20_3D_RC_IN_ALPHA_B_MAPPING_HALF_BIAS_NORMAL 0x00800000 |
#define NV20_3D_RC_IN_ALPHA_B_MAPPING_HALF_BIAS_NEGATE 0x00a00000 |
#define NV20_3D_RC_IN_ALPHA_B_MAPPING_SIGNED_IDENTITY 0x00c00000 |
#define NV20_3D_RC_IN_ALPHA_B_MAPPING_SIGNED_NEGATE 0x00e00000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT__MASK 0x0f000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT__SHIFT 24 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_CONSTANT_COLOR0 0x01000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_CONSTANT_COLOR1 0x02000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_FOG 0x03000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_PRIMARY_COLOR 0x04000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_SECONDARY_COLOR 0x05000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_TEXTURE0 0x08000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_TEXTURE1 0x09000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_TEXTURE2 0x0a000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_TEXTURE3 0x0b000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_SPARE0 0x0c000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_SPARE1 0x0d000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000 |
#define NV20_3D_RC_IN_ALPHA_A_INPUT_E_TIMES_F 0x0f000000 |
#define NV20_3D_RC_IN_ALPHA_A_COMPONENT_USAGE__MASK 0x10000000 |
#define NV20_3D_RC_IN_ALPHA_A_COMPONENT_USAGE__SHIFT 28 |
#define NV20_3D_RC_IN_ALPHA_A_COMPONENT_USAGE_BLUE 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_A_COMPONENT_USAGE_ALPHA 0x10000000 |
#define NV20_3D_RC_IN_ALPHA_A_MAPPING__MASK 0xe0000000 |
#define NV20_3D_RC_IN_ALPHA_A_MAPPING__SHIFT 29 |
#define NV20_3D_RC_IN_ALPHA_A_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_IN_ALPHA_A_MAPPING_UNSIGNED_INVERT 0x20000000 |
#define NV20_3D_RC_IN_ALPHA_A_MAPPING_EXPAND_NORMAL 0x40000000 |
#define NV20_3D_RC_IN_ALPHA_A_MAPPING_EXPAND_NEGATE 0x60000000 |
#define NV20_3D_RC_IN_ALPHA_A_MAPPING_HALF_BIAS_NORMAL 0x80000000 |
#define NV20_3D_RC_IN_ALPHA_A_MAPPING_HALF_BIAS_NEGATE 0xa0000000 |
#define NV20_3D_RC_IN_ALPHA_A_MAPPING_SIGNED_IDENTITY 0xc0000000 |
#define NV20_3D_RC_IN_ALPHA_A_MAPPING_SIGNED_NEGATE 0xe0000000 |
#define NV20_3D_RC_IN_RGB(i0) (0x00000ac0 + 0x4*(i0)) |
#define NV20_3D_RC_IN_RGB_D_INPUT__MASK 0x0000000f |
#define NV20_3D_RC_IN_RGB_D_INPUT__SHIFT 0 |
#define NV20_3D_RC_IN_RGB_D_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_IN_RGB_D_INPUT_CONSTANT_COLOR0 0x00000001 |
#define NV20_3D_RC_IN_RGB_D_INPUT_CONSTANT_COLOR1 0x00000002 |
#define NV20_3D_RC_IN_RGB_D_INPUT_FOG 0x00000003 |
#define NV20_3D_RC_IN_RGB_D_INPUT_PRIMARY_COLOR 0x00000004 |
#define NV20_3D_RC_IN_RGB_D_INPUT_SECONDARY_COLOR 0x00000005 |
#define NV20_3D_RC_IN_RGB_D_INPUT_TEXTURE0 0x00000008 |
#define NV20_3D_RC_IN_RGB_D_INPUT_TEXTURE1 0x00000009 |
#define NV20_3D_RC_IN_RGB_D_INPUT_TEXTURE2 0x0000000a |
#define NV20_3D_RC_IN_RGB_D_INPUT_TEXTURE3 0x0000000b |
#define NV20_3D_RC_IN_RGB_D_INPUT_SPARE0 0x0000000c |
#define NV20_3D_RC_IN_RGB_D_INPUT_SPARE1 0x0000000d |
#define NV20_3D_RC_IN_RGB_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e |
#define NV20_3D_RC_IN_RGB_D_INPUT_E_TIMES_F 0x0000000f |
#define NV20_3D_RC_IN_RGB_D_COMPONENT_USAGE__MASK 0x00000010 |
#define NV20_3D_RC_IN_RGB_D_COMPONENT_USAGE__SHIFT 4 |
#define NV20_3D_RC_IN_RGB_D_COMPONENT_USAGE_RGB 0x00000000 |
#define NV20_3D_RC_IN_RGB_D_COMPONENT_USAGE_ALPHA 0x00000010 |
#define NV20_3D_RC_IN_RGB_D_MAPPING__MASK 0x000000e0 |
#define NV20_3D_RC_IN_RGB_D_MAPPING__SHIFT 5 |
#define NV20_3D_RC_IN_RGB_D_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_IN_RGB_D_MAPPING_UNSIGNED_INVERT 0x00000020 |
#define NV20_3D_RC_IN_RGB_D_MAPPING_EXPAND_NORMAL 0x00000040 |
#define NV20_3D_RC_IN_RGB_D_MAPPING_EXPAND_NEGATE 0x00000060 |
#define NV20_3D_RC_IN_RGB_D_MAPPING_HALF_BIAS_NORMAL 0x00000080 |
#define NV20_3D_RC_IN_RGB_D_MAPPING_HALF_BIAS_NEGATE 0x000000a0 |
#define NV20_3D_RC_IN_RGB_D_MAPPING_SIGNED_IDENTITY 0x000000c0 |
#define NV20_3D_RC_IN_RGB_D_MAPPING_SIGNED_NEGATE 0x000000e0 |
#define NV20_3D_RC_IN_RGB_C_INPUT__MASK 0x00000f00 |
#define NV20_3D_RC_IN_RGB_C_INPUT__SHIFT 8 |
#define NV20_3D_RC_IN_RGB_C_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_IN_RGB_C_INPUT_CONSTANT_COLOR0 0x00000100 |
#define NV20_3D_RC_IN_RGB_C_INPUT_CONSTANT_COLOR1 0x00000200 |
#define NV20_3D_RC_IN_RGB_C_INPUT_FOG 0x00000300 |
#define NV20_3D_RC_IN_RGB_C_INPUT_PRIMARY_COLOR 0x00000400 |
#define NV20_3D_RC_IN_RGB_C_INPUT_SECONDARY_COLOR 0x00000500 |
#define NV20_3D_RC_IN_RGB_C_INPUT_TEXTURE0 0x00000800 |
#define NV20_3D_RC_IN_RGB_C_INPUT_TEXTURE1 0x00000900 |
#define NV20_3D_RC_IN_RGB_C_INPUT_TEXTURE2 0x00000a00 |
#define NV20_3D_RC_IN_RGB_C_INPUT_TEXTURE3 0x00000b00 |
#define NV20_3D_RC_IN_RGB_C_INPUT_SPARE0 0x00000c00 |
#define NV20_3D_RC_IN_RGB_C_INPUT_SPARE1 0x00000d00 |
#define NV20_3D_RC_IN_RGB_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV20_3D_RC_IN_RGB_C_INPUT_E_TIMES_F 0x00000f00 |
#define NV20_3D_RC_IN_RGB_C_COMPONENT_USAGE__MASK 0x00001000 |
#define NV20_3D_RC_IN_RGB_C_COMPONENT_USAGE__SHIFT 12 |
#define NV20_3D_RC_IN_RGB_C_COMPONENT_USAGE_RGB 0x00000000 |
#define NV20_3D_RC_IN_RGB_C_COMPONENT_USAGE_ALPHA 0x00001000 |
#define NV20_3D_RC_IN_RGB_C_MAPPING__MASK 0x0000e000 |
#define NV20_3D_RC_IN_RGB_C_MAPPING__SHIFT 13 |
#define NV20_3D_RC_IN_RGB_C_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_IN_RGB_C_MAPPING_UNSIGNED_INVERT 0x00002000 |
#define NV20_3D_RC_IN_RGB_C_MAPPING_EXPAND_NORMAL 0x00004000 |
#define NV20_3D_RC_IN_RGB_C_MAPPING_EXPAND_NEGATE 0x00006000 |
#define NV20_3D_RC_IN_RGB_C_MAPPING_HALF_BIAS_NORMAL 0x00008000 |
#define NV20_3D_RC_IN_RGB_C_MAPPING_HALF_BIAS_NEGATE 0x0000a000 |
#define NV20_3D_RC_IN_RGB_C_MAPPING_SIGNED_IDENTITY 0x0000c000 |
#define NV20_3D_RC_IN_RGB_C_MAPPING_SIGNED_NEGATE 0x0000e000 |
#define NV20_3D_RC_IN_RGB_B_INPUT__MASK 0x000f0000 |
#define NV20_3D_RC_IN_RGB_B_INPUT__SHIFT 16 |
#define NV20_3D_RC_IN_RGB_B_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_CONSTANT_COLOR0 0x00010000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_CONSTANT_COLOR1 0x00020000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_FOG 0x00030000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_PRIMARY_COLOR 0x00040000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_SECONDARY_COLOR 0x00050000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_TEXTURE0 0x00080000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_TEXTURE1 0x00090000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_TEXTURE2 0x000a0000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_TEXTURE3 0x000b0000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_SPARE0 0x000c0000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_SPARE1 0x000d0000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000 |
#define NV20_3D_RC_IN_RGB_B_INPUT_E_TIMES_F 0x000f0000 |
#define NV20_3D_RC_IN_RGB_B_COMPONENT_USAGE__MASK 0x00100000 |
#define NV20_3D_RC_IN_RGB_B_COMPONENT_USAGE__SHIFT 20 |
#define NV20_3D_RC_IN_RGB_B_COMPONENT_USAGE_RGB 0x00000000 |
#define NV20_3D_RC_IN_RGB_B_COMPONENT_USAGE_ALPHA 0x00100000 |
#define NV20_3D_RC_IN_RGB_B_MAPPING__MASK 0x00e00000 |
#define NV20_3D_RC_IN_RGB_B_MAPPING__SHIFT 21 |
#define NV20_3D_RC_IN_RGB_B_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_IN_RGB_B_MAPPING_UNSIGNED_INVERT 0x00200000 |
#define NV20_3D_RC_IN_RGB_B_MAPPING_EXPAND_NORMAL 0x00400000 |
#define NV20_3D_RC_IN_RGB_B_MAPPING_EXPAND_NEGATE 0x00600000 |
#define NV20_3D_RC_IN_RGB_B_MAPPING_HALF_BIAS_NORMAL 0x00800000 |
#define NV20_3D_RC_IN_RGB_B_MAPPING_HALF_BIAS_NEGATE 0x00a00000 |
#define NV20_3D_RC_IN_RGB_B_MAPPING_SIGNED_IDENTITY 0x00c00000 |
#define NV20_3D_RC_IN_RGB_B_MAPPING_SIGNED_NEGATE 0x00e00000 |
#define NV20_3D_RC_IN_RGB_A_INPUT__MASK 0x0f000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT__SHIFT 24 |
#define NV20_3D_RC_IN_RGB_A_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_CONSTANT_COLOR0 0x01000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_CONSTANT_COLOR1 0x02000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_FOG 0x03000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_PRIMARY_COLOR 0x04000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_SECONDARY_COLOR 0x05000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_TEXTURE0 0x08000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_TEXTURE1 0x09000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_TEXTURE2 0x0a000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_TEXTURE3 0x0b000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_SPARE0 0x0c000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_SPARE1 0x0d000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000 |
#define NV20_3D_RC_IN_RGB_A_INPUT_E_TIMES_F 0x0f000000 |
#define NV20_3D_RC_IN_RGB_A_COMPONENT_USAGE__MASK 0x10000000 |
#define NV20_3D_RC_IN_RGB_A_COMPONENT_USAGE__SHIFT 28 |
#define NV20_3D_RC_IN_RGB_A_COMPONENT_USAGE_RGB 0x00000000 |
#define NV20_3D_RC_IN_RGB_A_COMPONENT_USAGE_ALPHA 0x10000000 |
#define NV20_3D_RC_IN_RGB_A_MAPPING__MASK 0xe0000000 |
#define NV20_3D_RC_IN_RGB_A_MAPPING__SHIFT 29 |
#define NV20_3D_RC_IN_RGB_A_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_IN_RGB_A_MAPPING_UNSIGNED_INVERT 0x20000000 |
#define NV20_3D_RC_IN_RGB_A_MAPPING_EXPAND_NORMAL 0x40000000 |
#define NV20_3D_RC_IN_RGB_A_MAPPING_EXPAND_NEGATE 0x60000000 |
#define NV20_3D_RC_IN_RGB_A_MAPPING_HALF_BIAS_NORMAL 0x80000000 |
#define NV20_3D_RC_IN_RGB_A_MAPPING_HALF_BIAS_NEGATE 0xa0000000 |
#define NV20_3D_RC_IN_RGB_A_MAPPING_SIGNED_IDENTITY 0xc0000000 |
#define NV20_3D_RC_IN_RGB_A_MAPPING_SIGNED_NEGATE 0xe0000000 |
#define NV20_3D_RC_CONSTANT_COLOR0(i0) (0x00000a60 + 0x4*(i0)) |
#define NV20_3D_RC_CONSTANT_COLOR0_B__MASK 0x000000ff |
#define NV20_3D_RC_CONSTANT_COLOR0_B__SHIFT 0 |
#define NV20_3D_RC_CONSTANT_COLOR0_G__MASK 0x0000ff00 |
#define NV20_3D_RC_CONSTANT_COLOR0_G__SHIFT 8 |
#define NV20_3D_RC_CONSTANT_COLOR0_R__MASK 0x00ff0000 |
#define NV20_3D_RC_CONSTANT_COLOR0_R__SHIFT 16 |
#define NV20_3D_RC_CONSTANT_COLOR0_A__MASK 0xff000000 |
#define NV20_3D_RC_CONSTANT_COLOR0_A__SHIFT 24 |
#define NV20_3D_RC_CONSTANT_COLOR1(i0) (0x00000a80 + 0x4*(i0)) |
#define NV20_3D_RC_CONSTANT_COLOR1_B__MASK 0x000000ff |
#define NV20_3D_RC_CONSTANT_COLOR1_B__SHIFT 0 |
#define NV20_3D_RC_CONSTANT_COLOR1_G__MASK 0x0000ff00 |
#define NV20_3D_RC_CONSTANT_COLOR1_G__SHIFT 8 |
#define NV20_3D_RC_CONSTANT_COLOR1_R__MASK 0x00ff0000 |
#define NV20_3D_RC_CONSTANT_COLOR1_R__SHIFT 16 |
#define NV20_3D_RC_CONSTANT_COLOR1_A__MASK 0xff000000 |
#define NV20_3D_RC_CONSTANT_COLOR1_A__SHIFT 24 |
#define NV20_3D_RC_OUT_ALPHA(i0) (0x00000aa0 + 0x4*(i0)) |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT__MASK 0x0000000f |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT__SHIFT 0 |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_ZERO 0x00000000 |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_CONSTANT_COLOR0 0x00000001 |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_CONSTANT_COLOR1 0x00000002 |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_FOG 0x00000003 |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_PRIMARY_COLOR 0x00000004 |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_SECONDARY_COLOR 0x00000005 |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE0 0x00000008 |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE1 0x00000009 |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE2 0x0000000a |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_TEXTURE3 0x0000000b |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_SPARE0 0x0000000c |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_SPARE1 0x0000000d |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e |
#define NV20_3D_RC_OUT_ALPHA_CD_OUTPUT_E_TIMES_F 0x0000000f |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT__MASK 0x000000f0 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT__SHIFT 4 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_ZERO 0x00000000 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_CONSTANT_COLOR0 0x00000010 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_CONSTANT_COLOR1 0x00000020 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_FOG 0x00000030 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_PRIMARY_COLOR 0x00000040 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_SECONDARY_COLOR 0x00000050 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE0 0x00000080 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE1 0x00000090 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE2 0x000000a0 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_TEXTURE3 0x000000b0 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_SPARE0 0x000000c0 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_SPARE1 0x000000d0 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000000e0 |
#define NV20_3D_RC_OUT_ALPHA_AB_OUTPUT_E_TIMES_F 0x000000f0 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT__MASK 0x00000f00 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT__SHIFT 8 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_ZERO 0x00000000 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_CONSTANT_COLOR0 0x00000100 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_CONSTANT_COLOR1 0x00000200 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_FOG 0x00000300 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_PRIMARY_COLOR 0x00000400 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_SECONDARY_COLOR 0x00000500 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE0 0x00000800 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE1 0x00000900 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE2 0x00000a00 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_TEXTURE3 0x00000b00 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_SPARE0 0x00000c00 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_SPARE1 0x00000d00 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV20_3D_RC_OUT_ALPHA_SUM_OUTPUT_E_TIMES_F 0x00000f00 |
#define NV20_3D_RC_OUT_ALPHA_CD_DOT_PRODUCT 0x00001000 |
#define NV20_3D_RC_OUT_ALPHA_AB_DOT_PRODUCT 0x00002000 |
#define NV20_3D_RC_OUT_ALPHA_MUX_SUM 0x00004000 |
#define NV20_3D_RC_OUT_ALPHA_BIAS__MASK 0x00008000 |
#define NV20_3D_RC_OUT_ALPHA_BIAS__SHIFT 15 |
#define NV20_3D_RC_OUT_ALPHA_BIAS_NONE 0x00000000 |
#define NV20_3D_RC_OUT_ALPHA_BIAS_BIAS_BY_NEGATIVE_ONE_HALF 0x00008000 |
#define NV20_3D_RC_OUT_ALPHA_SCALE__MASK 0x00030000 |
#define NV20_3D_RC_OUT_ALPHA_SCALE__SHIFT 16 |
#define NV20_3D_RC_OUT_ALPHA_SCALE_NONE 0x00000000 |
#define NV20_3D_RC_OUT_ALPHA_SCALE_SCALE_BY_TWO 0x00010000 |
#define NV20_3D_RC_OUT_ALPHA_SCALE_SCALE_BY_FOUR 0x00020000 |
#define NV20_3D_RC_OUT_ALPHA_SCALE_SCALE_BY_ONE_HALF 0x00030000 |
#define NV20_3D_RC_OUT_RGB(i0) (0x00001e40 + 0x4*(i0)) |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT__MASK 0x0000000f |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT__SHIFT 0 |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_ZERO 0x00000000 |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_CONSTANT_COLOR0 0x00000001 |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_CONSTANT_COLOR1 0x00000002 |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_FOG 0x00000003 |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_PRIMARY_COLOR 0x00000004 |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_SECONDARY_COLOR 0x00000005 |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE0 0x00000008 |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE1 0x00000009 |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE2 0x0000000a |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_TEXTURE3 0x0000000b |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_SPARE0 0x0000000c |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_SPARE1 0x0000000d |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e |
#define NV20_3D_RC_OUT_RGB_CD_OUTPUT_E_TIMES_F 0x0000000f |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT__MASK 0x000000f0 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT__SHIFT 4 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_ZERO 0x00000000 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_CONSTANT_COLOR0 0x00000010 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_CONSTANT_COLOR1 0x00000020 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_FOG 0x00000030 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_PRIMARY_COLOR 0x00000040 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_SECONDARY_COLOR 0x00000050 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE0 0x00000080 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE1 0x00000090 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE2 0x000000a0 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_TEXTURE3 0x000000b0 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_SPARE0 0x000000c0 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_SPARE1 0x000000d0 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000000e0 |
#define NV20_3D_RC_OUT_RGB_AB_OUTPUT_E_TIMES_F 0x000000f0 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT__MASK 0x00000f00 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT__SHIFT 8 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_ZERO 0x00000000 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_CONSTANT_COLOR0 0x00000100 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_CONSTANT_COLOR1 0x00000200 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_FOG 0x00000300 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_PRIMARY_COLOR 0x00000400 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_SECONDARY_COLOR 0x00000500 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE0 0x00000800 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE1 0x00000900 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE2 0x00000a00 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_TEXTURE3 0x00000b00 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_SPARE0 0x00000c00 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_SPARE1 0x00000d00 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV20_3D_RC_OUT_RGB_SUM_OUTPUT_E_TIMES_F 0x00000f00 |
#define NV20_3D_RC_OUT_RGB_CD_DOT_PRODUCT 0x00001000 |
#define NV20_3D_RC_OUT_RGB_AB_DOT_PRODUCT 0x00002000 |
#define NV20_3D_RC_OUT_RGB_MUX_SUM 0x00004000 |
#define NV20_3D_RC_OUT_RGB_BIAS__MASK 0x00008000 |
#define NV20_3D_RC_OUT_RGB_BIAS__SHIFT 15 |
#define NV20_3D_RC_OUT_RGB_BIAS_NONE 0x00000000 |
#define NV20_3D_RC_OUT_RGB_BIAS_BIAS_BY_NEGATIVE_ONE_HALF 0x00008000 |
#define NV20_3D_RC_OUT_RGB_SCALE__MASK 0x00030000 |
#define NV20_3D_RC_OUT_RGB_SCALE__SHIFT 16 |
#define NV20_3D_RC_OUT_RGB_SCALE_NONE 0x00000000 |
#define NV20_3D_RC_OUT_RGB_SCALE_SCALE_BY_TWO 0x00010000 |
#define NV20_3D_RC_OUT_RGB_SCALE_SCALE_BY_FOUR 0x00020000 |
#define NV20_3D_RC_OUT_RGB_SCALE_SCALE_BY_ONE_HALF 0x00030000 |
#define NV20_3D_RC_FINAL0 0x00000288 |
#define NV20_3D_RC_FINAL0_D_INPUT__MASK 0x0000000f |
#define NV20_3D_RC_FINAL0_D_INPUT__SHIFT 0 |
#define NV20_3D_RC_FINAL0_D_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_FINAL0_D_INPUT_CONSTANT_COLOR0 0x00000001 |
#define NV20_3D_RC_FINAL0_D_INPUT_CONSTANT_COLOR1 0x00000002 |
#define NV20_3D_RC_FINAL0_D_INPUT_FOG 0x00000003 |
#define NV20_3D_RC_FINAL0_D_INPUT_PRIMARY_COLOR 0x00000004 |
#define NV20_3D_RC_FINAL0_D_INPUT_SECONDARY_COLOR 0x00000005 |
#define NV20_3D_RC_FINAL0_D_INPUT_TEXTURE0 0x00000008 |
#define NV20_3D_RC_FINAL0_D_INPUT_TEXTURE1 0x00000009 |
#define NV20_3D_RC_FINAL0_D_INPUT_TEXTURE2 0x0000000a |
#define NV20_3D_RC_FINAL0_D_INPUT_TEXTURE3 0x0000000b |
#define NV20_3D_RC_FINAL0_D_INPUT_SPARE0 0x0000000c |
#define NV20_3D_RC_FINAL0_D_INPUT_SPARE1 0x0000000d |
#define NV20_3D_RC_FINAL0_D_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0000000e |
#define NV20_3D_RC_FINAL0_D_INPUT_E_TIMES_F 0x0000000f |
#define NV20_3D_RC_FINAL0_D_COMPONENT_USAGE__MASK 0x00000010 |
#define NV20_3D_RC_FINAL0_D_COMPONENT_USAGE__SHIFT 4 |
#define NV20_3D_RC_FINAL0_D_COMPONENT_USAGE_RGB 0x00000000 |
#define NV20_3D_RC_FINAL0_D_COMPONENT_USAGE_ALPHA 0x00000010 |
#define NV20_3D_RC_FINAL0_D_MAPPING__MASK 0x000000e0 |
#define NV20_3D_RC_FINAL0_D_MAPPING__SHIFT 5 |
#define NV20_3D_RC_FINAL0_D_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_FINAL0_D_MAPPING_UNSIGNED_INVERT 0x00000020 |
#define NV20_3D_RC_FINAL0_D_MAPPING_EXPAND_NORMAL 0x00000040 |
#define NV20_3D_RC_FINAL0_D_MAPPING_EXPAND_NEGATE 0x00000060 |
#define NV20_3D_RC_FINAL0_D_MAPPING_HALF_BIAS_NORMAL 0x00000080 |
#define NV20_3D_RC_FINAL0_D_MAPPING_HALF_BIAS_NEGATE 0x000000a0 |
#define NV20_3D_RC_FINAL0_D_MAPPING_SIGNED_IDENTITY 0x000000c0 |
#define NV20_3D_RC_FINAL0_D_MAPPING_SIGNED_NEGATE 0x000000e0 |
#define NV20_3D_RC_FINAL0_C_INPUT__MASK 0x00000f00 |
#define NV20_3D_RC_FINAL0_C_INPUT__SHIFT 8 |
#define NV20_3D_RC_FINAL0_C_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_FINAL0_C_INPUT_CONSTANT_COLOR0 0x00000100 |
#define NV20_3D_RC_FINAL0_C_INPUT_CONSTANT_COLOR1 0x00000200 |
#define NV20_3D_RC_FINAL0_C_INPUT_FOG 0x00000300 |
#define NV20_3D_RC_FINAL0_C_INPUT_PRIMARY_COLOR 0x00000400 |
#define NV20_3D_RC_FINAL0_C_INPUT_SECONDARY_COLOR 0x00000500 |
#define NV20_3D_RC_FINAL0_C_INPUT_TEXTURE0 0x00000800 |
#define NV20_3D_RC_FINAL0_C_INPUT_TEXTURE1 0x00000900 |
#define NV20_3D_RC_FINAL0_C_INPUT_TEXTURE2 0x00000a00 |
#define NV20_3D_RC_FINAL0_C_INPUT_TEXTURE3 0x00000b00 |
#define NV20_3D_RC_FINAL0_C_INPUT_SPARE0 0x00000c00 |
#define NV20_3D_RC_FINAL0_C_INPUT_SPARE1 0x00000d00 |
#define NV20_3D_RC_FINAL0_C_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV20_3D_RC_FINAL0_C_INPUT_E_TIMES_F 0x00000f00 |
#define NV20_3D_RC_FINAL0_C_COMPONENT_USAGE__MASK 0x00001000 |
#define NV20_3D_RC_FINAL0_C_COMPONENT_USAGE__SHIFT 12 |
#define NV20_3D_RC_FINAL0_C_COMPONENT_USAGE_RGB 0x00000000 |
#define NV20_3D_RC_FINAL0_C_COMPONENT_USAGE_ALPHA 0x00001000 |
#define NV20_3D_RC_FINAL0_C_MAPPING__MASK 0x0000e000 |
#define NV20_3D_RC_FINAL0_C_MAPPING__SHIFT 13 |
#define NV20_3D_RC_FINAL0_C_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_FINAL0_C_MAPPING_UNSIGNED_INVERT 0x00002000 |
#define NV20_3D_RC_FINAL0_C_MAPPING_EXPAND_NORMAL 0x00004000 |
#define NV20_3D_RC_FINAL0_C_MAPPING_EXPAND_NEGATE 0x00006000 |
#define NV20_3D_RC_FINAL0_C_MAPPING_HALF_BIAS_NORMAL 0x00008000 |
#define NV20_3D_RC_FINAL0_C_MAPPING_HALF_BIAS_NEGATE 0x0000a000 |
#define NV20_3D_RC_FINAL0_C_MAPPING_SIGNED_IDENTITY 0x0000c000 |
#define NV20_3D_RC_FINAL0_C_MAPPING_SIGNED_NEGATE 0x0000e000 |
#define NV20_3D_RC_FINAL0_B_INPUT__MASK 0x000f0000 |
#define NV20_3D_RC_FINAL0_B_INPUT__SHIFT 16 |
#define NV20_3D_RC_FINAL0_B_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_FINAL0_B_INPUT_CONSTANT_COLOR0 0x00010000 |
#define NV20_3D_RC_FINAL0_B_INPUT_CONSTANT_COLOR1 0x00020000 |
#define NV20_3D_RC_FINAL0_B_INPUT_FOG 0x00030000 |
#define NV20_3D_RC_FINAL0_B_INPUT_PRIMARY_COLOR 0x00040000 |
#define NV20_3D_RC_FINAL0_B_INPUT_SECONDARY_COLOR 0x00050000 |
#define NV20_3D_RC_FINAL0_B_INPUT_TEXTURE0 0x00080000 |
#define NV20_3D_RC_FINAL0_B_INPUT_TEXTURE1 0x00090000 |
#define NV20_3D_RC_FINAL0_B_INPUT_TEXTURE2 0x000a0000 |
#define NV20_3D_RC_FINAL0_B_INPUT_TEXTURE3 0x000b0000 |
#define NV20_3D_RC_FINAL0_B_INPUT_SPARE0 0x000c0000 |
#define NV20_3D_RC_FINAL0_B_INPUT_SPARE1 0x000d0000 |
#define NV20_3D_RC_FINAL0_B_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000 |
#define NV20_3D_RC_FINAL0_B_INPUT_E_TIMES_F 0x000f0000 |
#define NV20_3D_RC_FINAL0_B_COMPONENT_USAGE__MASK 0x00100000 |
#define NV20_3D_RC_FINAL0_B_COMPONENT_USAGE__SHIFT 20 |
#define NV20_3D_RC_FINAL0_B_COMPONENT_USAGE_RGB 0x00000000 |
#define NV20_3D_RC_FINAL0_B_COMPONENT_USAGE_ALPHA 0x00100000 |
#define NV20_3D_RC_FINAL0_B_MAPPING__MASK 0x00e00000 |
#define NV20_3D_RC_FINAL0_B_MAPPING__SHIFT 21 |
#define NV20_3D_RC_FINAL0_B_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_FINAL0_B_MAPPING_UNSIGNED_INVERT 0x00200000 |
#define NV20_3D_RC_FINAL0_B_MAPPING_EXPAND_NORMAL 0x00400000 |
#define NV20_3D_RC_FINAL0_B_MAPPING_EXPAND_NEGATE 0x00600000 |
#define NV20_3D_RC_FINAL0_B_MAPPING_HALF_BIAS_NORMAL 0x00800000 |
#define NV20_3D_RC_FINAL0_B_MAPPING_HALF_BIAS_NEGATE 0x00a00000 |
#define NV20_3D_RC_FINAL0_B_MAPPING_SIGNED_IDENTITY 0x00c00000 |
#define NV20_3D_RC_FINAL0_B_MAPPING_SIGNED_NEGATE 0x00e00000 |
#define NV20_3D_RC_FINAL0_A_INPUT__MASK 0x0f000000 |
#define NV20_3D_RC_FINAL0_A_INPUT__SHIFT 24 |
#define NV20_3D_RC_FINAL0_A_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_CONSTANT_COLOR0 0x01000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_CONSTANT_COLOR1 0x02000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_FOG 0x03000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_PRIMARY_COLOR 0x04000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_SECONDARY_COLOR 0x05000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_TEXTURE0 0x08000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_TEXTURE1 0x09000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_TEXTURE2 0x0a000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_TEXTURE3 0x0b000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_SPARE0 0x0c000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_SPARE1 0x0d000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000 |
#define NV20_3D_RC_FINAL0_A_INPUT_E_TIMES_F 0x0f000000 |
#define NV20_3D_RC_FINAL0_A_COMPONENT_USAGE__MASK 0x10000000 |
#define NV20_3D_RC_FINAL0_A_COMPONENT_USAGE__SHIFT 28 |
#define NV20_3D_RC_FINAL0_A_COMPONENT_USAGE_RGB 0x00000000 |
#define NV20_3D_RC_FINAL0_A_COMPONENT_USAGE_ALPHA 0x10000000 |
#define NV20_3D_RC_FINAL0_A_MAPPING__MASK 0xe0000000 |
#define NV20_3D_RC_FINAL0_A_MAPPING__SHIFT 29 |
#define NV20_3D_RC_FINAL0_A_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_FINAL0_A_MAPPING_UNSIGNED_INVERT 0x20000000 |
#define NV20_3D_RC_FINAL0_A_MAPPING_EXPAND_NORMAL 0x40000000 |
#define NV20_3D_RC_FINAL0_A_MAPPING_EXPAND_NEGATE 0x60000000 |
#define NV20_3D_RC_FINAL0_A_MAPPING_HALF_BIAS_NORMAL 0x80000000 |
#define NV20_3D_RC_FINAL0_A_MAPPING_HALF_BIAS_NEGATE 0xa0000000 |
#define NV20_3D_RC_FINAL0_A_MAPPING_SIGNED_IDENTITY 0xc0000000 |
#define NV20_3D_RC_FINAL0_A_MAPPING_SIGNED_NEGATE 0xe0000000 |
#define NV20_3D_RC_FINAL1 0x0000028c |
#define NV20_3D_RC_FINAL1_COLOR_SUM_CLAMP 0x00000080 |
#define NV20_3D_RC_FINAL1_G_INPUT__MASK 0x00000f00 |
#define NV20_3D_RC_FINAL1_G_INPUT__SHIFT 8 |
#define NV20_3D_RC_FINAL1_G_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_FINAL1_G_INPUT_CONSTANT_COLOR0 0x00000100 |
#define NV20_3D_RC_FINAL1_G_INPUT_CONSTANT_COLOR1 0x00000200 |
#define NV20_3D_RC_FINAL1_G_INPUT_FOG 0x00000300 |
#define NV20_3D_RC_FINAL1_G_INPUT_PRIMARY_COLOR 0x00000400 |
#define NV20_3D_RC_FINAL1_G_INPUT_SECONDARY_COLOR 0x00000500 |
#define NV20_3D_RC_FINAL1_G_INPUT_TEXTURE0 0x00000800 |
#define NV20_3D_RC_FINAL1_G_INPUT_TEXTURE1 0x00000900 |
#define NV20_3D_RC_FINAL1_G_INPUT_TEXTURE2 0x00000a00 |
#define NV20_3D_RC_FINAL1_G_INPUT_TEXTURE3 0x00000b00 |
#define NV20_3D_RC_FINAL1_G_INPUT_SPARE0 0x00000c00 |
#define NV20_3D_RC_FINAL1_G_INPUT_SPARE1 0x00000d00 |
#define NV20_3D_RC_FINAL1_G_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x00000e00 |
#define NV20_3D_RC_FINAL1_G_INPUT_E_TIMES_F 0x00000f00 |
#define NV20_3D_RC_FINAL1_G_COMPONENT_USAGE__MASK 0x00001000 |
#define NV20_3D_RC_FINAL1_G_COMPONENT_USAGE__SHIFT 12 |
#define NV20_3D_RC_FINAL1_G_COMPONENT_USAGE_RGB 0x00000000 |
#define NV20_3D_RC_FINAL1_G_COMPONENT_USAGE_ALPHA 0x00001000 |
#define NV20_3D_RC_FINAL1_G_MAPPING__MASK 0x0000e000 |
#define NV20_3D_RC_FINAL1_G_MAPPING__SHIFT 13 |
#define NV20_3D_RC_FINAL1_G_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_FINAL1_G_MAPPING_UNSIGNED_INVERT 0x00002000 |
#define NV20_3D_RC_FINAL1_G_MAPPING_EXPAND_NORMAL 0x00004000 |
#define NV20_3D_RC_FINAL1_G_MAPPING_EXPAND_NEGATE 0x00006000 |
#define NV20_3D_RC_FINAL1_G_MAPPING_HALF_BIAS_NORMAL 0x00008000 |
#define NV20_3D_RC_FINAL1_G_MAPPING_HALF_BIAS_NEGATE 0x0000a000 |
#define NV20_3D_RC_FINAL1_G_MAPPING_SIGNED_IDENTITY 0x0000c000 |
#define NV20_3D_RC_FINAL1_G_MAPPING_SIGNED_NEGATE 0x0000e000 |
#define NV20_3D_RC_FINAL1_F_INPUT__MASK 0x000f0000 |
#define NV20_3D_RC_FINAL1_F_INPUT__SHIFT 16 |
#define NV20_3D_RC_FINAL1_F_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_FINAL1_F_INPUT_CONSTANT_COLOR0 0x00010000 |
#define NV20_3D_RC_FINAL1_F_INPUT_CONSTANT_COLOR1 0x00020000 |
#define NV20_3D_RC_FINAL1_F_INPUT_FOG 0x00030000 |
#define NV20_3D_RC_FINAL1_F_INPUT_PRIMARY_COLOR 0x00040000 |
#define NV20_3D_RC_FINAL1_F_INPUT_SECONDARY_COLOR 0x00050000 |
#define NV20_3D_RC_FINAL1_F_INPUT_TEXTURE0 0x00080000 |
#define NV20_3D_RC_FINAL1_F_INPUT_TEXTURE1 0x00090000 |
#define NV20_3D_RC_FINAL1_F_INPUT_TEXTURE2 0x000a0000 |
#define NV20_3D_RC_FINAL1_F_INPUT_TEXTURE3 0x000b0000 |
#define NV20_3D_RC_FINAL1_F_INPUT_SPARE0 0x000c0000 |
#define NV20_3D_RC_FINAL1_F_INPUT_SPARE1 0x000d0000 |
#define NV20_3D_RC_FINAL1_F_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x000e0000 |
#define NV20_3D_RC_FINAL1_F_INPUT_E_TIMES_F 0x000f0000 |
#define NV20_3D_RC_FINAL1_F_COMPONENT_USAGE__MASK 0x00100000 |
#define NV20_3D_RC_FINAL1_F_COMPONENT_USAGE__SHIFT 20 |
#define NV20_3D_RC_FINAL1_F_COMPONENT_USAGE_RGB 0x00000000 |
#define NV20_3D_RC_FINAL1_F_COMPONENT_USAGE_ALPHA 0x00100000 |
#define NV20_3D_RC_FINAL1_F_MAPPING__MASK 0x00e00000 |
#define NV20_3D_RC_FINAL1_F_MAPPING__SHIFT 21 |
#define NV20_3D_RC_FINAL1_F_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_FINAL1_F_MAPPING_UNSIGNED_INVERT 0x00200000 |
#define NV20_3D_RC_FINAL1_F_MAPPING_EXPAND_NORMAL 0x00400000 |
#define NV20_3D_RC_FINAL1_F_MAPPING_EXPAND_NEGATE 0x00600000 |
#define NV20_3D_RC_FINAL1_F_MAPPING_HALF_BIAS_NORMAL 0x00800000 |
#define NV20_3D_RC_FINAL1_F_MAPPING_HALF_BIAS_NEGATE 0x00a00000 |
#define NV20_3D_RC_FINAL1_F_MAPPING_SIGNED_IDENTITY 0x00c00000 |
#define NV20_3D_RC_FINAL1_F_MAPPING_SIGNED_NEGATE 0x00e00000 |
#define NV20_3D_RC_FINAL1_E_INPUT__MASK 0x0f000000 |
#define NV20_3D_RC_FINAL1_E_INPUT__SHIFT 24 |
#define NV20_3D_RC_FINAL1_E_INPUT_ZERO 0x00000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_CONSTANT_COLOR0 0x01000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_CONSTANT_COLOR1 0x02000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_FOG 0x03000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_PRIMARY_COLOR 0x04000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_SECONDARY_COLOR 0x05000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_TEXTURE0 0x08000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_TEXTURE1 0x09000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_TEXTURE2 0x0a000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_TEXTURE3 0x0b000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_SPARE0 0x0c000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_SPARE1 0x0d000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_SPARE0_PLUS_SECONDARY_COLOR 0x0e000000 |
#define NV20_3D_RC_FINAL1_E_INPUT_E_TIMES_F 0x0f000000 |
#define NV20_3D_RC_FINAL1_E_COMPONENT_USAGE__MASK 0x10000000 |
#define NV20_3D_RC_FINAL1_E_COMPONENT_USAGE__SHIFT 28 |
#define NV20_3D_RC_FINAL1_E_COMPONENT_USAGE_RGB 0x00000000 |
#define NV20_3D_RC_FINAL1_E_COMPONENT_USAGE_ALPHA 0x10000000 |
#define NV20_3D_RC_FINAL1_E_MAPPING__MASK 0xe0000000 |
#define NV20_3D_RC_FINAL1_E_MAPPING__SHIFT 29 |
#define NV20_3D_RC_FINAL1_E_MAPPING_UNSIGNED_IDENTITY 0x00000000 |
#define NV20_3D_RC_FINAL1_E_MAPPING_UNSIGNED_INVERT 0x20000000 |
#define NV20_3D_RC_FINAL1_E_MAPPING_EXPAND_NORMAL 0x40000000 |
#define NV20_3D_RC_FINAL1_E_MAPPING_EXPAND_NEGATE 0x60000000 |
#define NV20_3D_RC_FINAL1_E_MAPPING_HALF_BIAS_NORMAL 0x80000000 |
#define NV20_3D_RC_FINAL1_E_MAPPING_HALF_BIAS_NEGATE 0xa0000000 |
#define NV20_3D_RC_FINAL1_E_MAPPING_SIGNED_IDENTITY 0xc0000000 |
#define NV20_3D_RC_FINAL1_E_MAPPING_SIGNED_NEGATE 0xe0000000 |
#define NV20_3D_RC_COLOR0 0x00001e20 |
#define NV20_3D_RC_COLOR0_B__MASK 0x000000ff |
#define NV20_3D_RC_COLOR0_B__SHIFT 0 |
#define NV20_3D_RC_COLOR0_G__MASK 0x0000ff00 |
#define NV20_3D_RC_COLOR0_G__SHIFT 8 |
#define NV20_3D_RC_COLOR0_R__MASK 0x00ff0000 |
#define NV20_3D_RC_COLOR0_R__SHIFT 16 |
#define NV20_3D_RC_COLOR0_A__MASK 0xff000000 |
#define NV20_3D_RC_COLOR0_A__SHIFT 24 |
#define NV20_3D_RC_COLOR1 0x00001e24 |
#define NV20_3D_RC_COLOR1_B__MASK 0x000000ff |
#define NV20_3D_RC_COLOR1_B__SHIFT 0 |
#define NV20_3D_RC_COLOR1_G__MASK 0x0000ff00 |
#define NV20_3D_RC_COLOR1_G__SHIFT 8 |
#define NV20_3D_RC_COLOR1_R__MASK 0x00ff0000 |
#define NV20_3D_RC_COLOR1_R__SHIFT 16 |
#define NV20_3D_RC_COLOR1_A__MASK 0xff000000 |
#define NV20_3D_RC_COLOR1_A__SHIFT 24 |
#define NV20_3D_RC_ENABLE 0x00001e60 |
#define NV20_3D_RC_ENABLE_NUM_COMBINERS__MASK 0x0000000f |
#define NV20_3D_RC_ENABLE_NUM_COMBINERS__SHIFT 0 |
#define NV20_3D_POINT_SIZE 0x0000043c |
#define NV20_3D_POINT_PARAMETER(i0) (0x00000a30 + 0x4*(i0)) |
#define NV20_3D_POINT_PARAMETER__ESIZE 0x00000004 |
#define NV20_3D_POINT_PARAMETER__LEN 0x00000008 |
#define NV20_3D_POLYGON_STIPPLE_ENABLE 0x0000147c |
#define NV20_3D_POLYGON_STIPPLE_PATTERN(i0) (0x00001480 + 0x4*(i0)) |
#define NV20_3D_POLYGON_STIPPLE_PATTERN__ESIZE 0x00000004 |
#define NV20_3D_POLYGON_STIPPLE_PATTERN__LEN 0x00000020 |
#define NV20_3D_COLOR_LOGIC_OP_ENABLE 0x000017bc |
#define NV20_3D_COLOR_LOGIC_OP_OP 0x000017c0 |
#define NV20_3D_COLOR_LOGIC_OP_OP_CLEAR 0x00001500 |
#define NV20_3D_COLOR_LOGIC_OP_OP_AND 0x00001501 |
#define NV20_3D_COLOR_LOGIC_OP_OP_AND_REVERSE 0x00001502 |
#define NV20_3D_COLOR_LOGIC_OP_OP_COPY 0x00001503 |
#define NV20_3D_COLOR_LOGIC_OP_OP_AND_INVERTED 0x00001504 |
#define NV20_3D_COLOR_LOGIC_OP_OP_NOOP 0x00001505 |
#define NV20_3D_COLOR_LOGIC_OP_OP_XOR 0x00001506 |
#define NV20_3D_COLOR_LOGIC_OP_OP_OR 0x00001507 |
#define NV20_3D_COLOR_LOGIC_OP_OP_NOR 0x00001508 |
#define NV20_3D_COLOR_LOGIC_OP_OP_EQUIV 0x00001509 |
#define NV20_3D_COLOR_LOGIC_OP_OP_INVERT 0x0000150a |
#define NV20_3D_COLOR_LOGIC_OP_OP_OR_REVERSE 0x0000150b |
#define NV20_3D_COLOR_LOGIC_OP_OP_COPY_INVERTED 0x0000150c |
#define NV20_3D_COLOR_LOGIC_OP_OP_OR_INVERTED 0x0000150d |
#define NV20_3D_COLOR_LOGIC_OP_OP_NAND 0x0000150e |
#define NV20_3D_COLOR_LOGIC_OP_OP_SET 0x0000150f |
#define NV20_3D_DEPTH_CLAMP 0x00001d78 |
#define NV20_3D_MULTISAMPLE_CONTROL 0x00001d7c |
#define NV20_3D_CLEAR_DEPTH_VALUE 0x00001d8c |
#define NV20_3D_CLEAR_VALUE 0x00001d90 |
#define NV20_3D_CLEAR_BUFFERS 0x00001d94 |
#define NV20_3D_CLEAR_BUFFERS_COLOR_A 0x00000080 |
#define NV20_3D_CLEAR_BUFFERS_COLOR_B 0x00000040 |
#define NV20_3D_CLEAR_BUFFERS_COLOR_G 0x00000020 |
#define NV20_3D_CLEAR_BUFFERS_COLOR_R 0x00000010 |
#define NV20_3D_CLEAR_BUFFERS_STENCIL 0x00000002 |
#define NV20_3D_CLEAR_BUFFERS_DEPTH 0x00000001 |
#define NV25_3D_DMA_HIERZ 0x000001b0 |
#define NV25_3D_HIERZ_PITCH 0x0000022c |
#define NV25_3D_HIERZ_OFFSET 0x00000230 |
#define NV20_3D_UNK09F8 0x000009f8 |
#define NV20_3D_UNK09FC 0x000009fc |
#define NV20_3D_UNK17CC 0x000017cc |
#define NV20_3D_UNK17E0 0x000017e0 |
#define NV20_3D_UNK17E4 0x000017e4 |
#define NV20_3D_UNK17E8 0x000017e8 |
#define NV20_3D_UNK17EC 0x000017ec |
#define NV20_3D_UNK17F0 0x000017f0 |
#define NV20_3D_UNK17F4 0x000017f4 |
#define NV20_3D_UNK1D80 0x00001d80 |
#define NV20_3D_UNK1D84 0x00001d84 |
#define NV20_3D_UNK1E68 0x00001e68 |
#define NV20_3D_UNK1E98 0x00001e98 |
#define NV25_3D_UNK01AC 0x000001ac |
#define NV25_3D_UNK0A1C 0x00000a1c |
#define NV25_3D_UNK1D88 0x00001d88 |
#define NV25_3D_UNK1DA4 0x00001da4 |
#endif /* NV20_3D_XML */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv20_context.c |
---|
0,0 → 1,582 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 <stdbool.h> |
#include "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_fbo.h" |
#include "nouveau_util.h" |
#include "nv_object.xml.h" |
#include "nv20_3d.xml.h" |
#include "nv04_driver.h" |
#include "nv10_driver.h" |
#include "nv20_driver.h" |
static void |
nv20_clear(struct gl_context *ctx, GLbitfield buffers) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
uint32_t clear = 0; |
nouveau_validate_framebuffer(ctx); |
nouveau_pushbuf_bufctx(push, nctx->hw.bufctx); |
if (nouveau_pushbuf_validate(push)) { |
nouveau_pushbuf_bufctx(push, NULL); |
return; |
} |
if (buffers & BUFFER_BITS_COLOR) { |
struct nouveau_surface *s = &to_nouveau_renderbuffer( |
fb->_ColorDrawBuffers[0])->surface; |
if (ctx->Color.ColorMask[0][RCOMP]) |
clear |= NV20_3D_CLEAR_BUFFERS_COLOR_R; |
if (ctx->Color.ColorMask[0][GCOMP]) |
clear |= NV20_3D_CLEAR_BUFFERS_COLOR_G; |
if (ctx->Color.ColorMask[0][BCOMP]) |
clear |= NV20_3D_CLEAR_BUFFERS_COLOR_B; |
if (ctx->Color.ColorMask[0][ACOMP]) |
clear |= NV20_3D_CLEAR_BUFFERS_COLOR_A; |
BEGIN_NV04(push, NV20_3D(CLEAR_VALUE), 1); |
PUSH_DATA (push, pack_rgba_clamp_f(s->format, ctx->Color.ClearColor.f)); |
buffers &= ~BUFFER_BITS_COLOR; |
} |
if (buffers & (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) { |
struct nouveau_surface *s = &to_nouveau_renderbuffer( |
fb->Attachment[BUFFER_DEPTH].Renderbuffer)->surface; |
if (buffers & BUFFER_BIT_DEPTH && ctx->Depth.Mask) |
clear |= NV20_3D_CLEAR_BUFFERS_DEPTH; |
if (buffers & BUFFER_BIT_STENCIL && ctx->Stencil.WriteMask[0]) |
clear |= NV20_3D_CLEAR_BUFFERS_STENCIL; |
BEGIN_NV04(push, NV20_3D(CLEAR_DEPTH_VALUE), 1); |
PUSH_DATA (push, pack_zs_f(s->format, ctx->Depth.Clear, |
ctx->Stencil.Clear)); |
buffers &= ~(BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL); |
} |
BEGIN_NV04(push, NV20_3D(CLEAR_BUFFERS), 1); |
PUSH_DATA (push, clear); |
nouveau_pushbuf_bufctx(push, NULL); |
nouveau_clear(ctx, buffers); |
} |
static void |
nv20_hwctx_init(struct gl_context *ctx) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw; |
struct nv04_fifo *fifo = hw->chan->data; |
int i; |
BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1); |
PUSH_DATA (push, hw->eng3d->handle); |
BEGIN_NV04(push, NV20_3D(DMA_NOTIFY), 1); |
PUSH_DATA (push, hw->ntfy->handle); |
BEGIN_NV04(push, NV20_3D(DMA_TEXTURE0), 2); |
PUSH_DATA (push, fifo->vram); |
PUSH_DATA (push, fifo->gart); |
BEGIN_NV04(push, NV20_3D(DMA_COLOR), 2); |
PUSH_DATA (push, fifo->vram); |
PUSH_DATA (push, fifo->vram); |
BEGIN_NV04(push, NV20_3D(DMA_VTXBUF0), 2); |
PUSH_DATA (push, fifo->vram); |
PUSH_DATA (push, fifo->gart); |
BEGIN_NV04(push, NV20_3D(DMA_QUERY), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(RT_HORIZ), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(VIEWPORT_CLIP_HORIZ(0)), 1); |
PUSH_DATA (push, 0xfff << 16 | 0x0); |
BEGIN_NV04(push, NV20_3D(VIEWPORT_CLIP_VERT(0)), 1); |
PUSH_DATA (push, 0xfff << 16 | 0x0); |
for (i = 1; i < NV20_3D_VIEWPORT_CLIP_HORIZ__LEN; i++) { |
BEGIN_NV04(push, NV20_3D(VIEWPORT_CLIP_HORIZ(i)), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(VIEWPORT_CLIP_VERT(i)), 1); |
PUSH_DATA (push, 0); |
} |
BEGIN_NV04(push, NV20_3D(VIEWPORT_CLIP_MODE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, SUBC_3D(0x17e0), 3); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 1.0); |
if (context_chipset(ctx) >= 0x25) { |
BEGIN_NV04(push, NV20_3D(TEX_RCOMP), 1); |
PUSH_DATA (push, NV20_3D_TEX_RCOMP_LEQUAL | 0xdb0); |
} else { |
BEGIN_NV04(push, SUBC_3D(0x1e68), 1); |
PUSH_DATA (push, 0x4b800000); /* 16777216.000000 */ |
BEGIN_NV04(push, NV20_3D(TEX_RCOMP), 1); |
PUSH_DATA (push, NV20_3D_TEX_RCOMP_LEQUAL); |
} |
BEGIN_NV04(push, SUBC_3D(0x290), 1); |
PUSH_DATA (push, 0x10 << 16 | 1); |
BEGIN_NV04(push, SUBC_3D(0x9fc), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, SUBC_3D(0x1d80), 1); |
PUSH_DATA (push, 1); |
BEGIN_NV04(push, SUBC_3D(0x9f8), 1); |
PUSH_DATA (push, 4); |
BEGIN_NV04(push, SUBC_3D(0x17ec), 3); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 1.0); |
PUSH_DATAf(push, 0.0); |
if (context_chipset(ctx) >= 0x25) { |
BEGIN_NV04(push, SUBC_3D(0x1d88), 1); |
PUSH_DATA (push, 3); |
BEGIN_NV04(push, NV25_3D(DMA_HIERZ), 1); |
PUSH_DATA (push, fifo->vram); |
BEGIN_NV04(push, NV25_3D(UNK01AC), 1); |
PUSH_DATA (push, fifo->vram); |
} |
BEGIN_NV04(push, NV20_3D(DMA_FENCE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, SUBC_3D(0x1e98), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV04_GRAPH(3D, NOTIFY), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, SUBC_3D(0x120), 3); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 1); |
PUSH_DATA (push, 2); |
if (context_chipset(ctx) >= 0x25) { |
BEGIN_NV04(push, SUBC_3D(0x1da4), 1); |
PUSH_DATA (push, 0); |
} |
BEGIN_NV04(push, NV20_3D(RT_HORIZ), 2); |
PUSH_DATA (push, 0 << 16 | 0); |
PUSH_DATA (push, 0 << 16 | 0); |
BEGIN_NV04(push, NV20_3D(ALPHA_FUNC_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(ALPHA_FUNC_FUNC), 2); |
PUSH_DATA (push, NV20_3D_ALPHA_FUNC_FUNC_ALWAYS); |
PUSH_DATA (push, 0); |
for (i = 0; i < NV20_3D_TEX__LEN; i++) { |
BEGIN_NV04(push, NV20_3D(TEX_ENABLE(i)), 1); |
PUSH_DATA (push, 0); |
} |
BEGIN_NV04(push, NV20_3D(TEX_SHADER_OP), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(TEX_SHADER_CULL_MODE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(RC_IN_ALPHA(0)), 4); |
PUSH_DATA (push, 0x30d410d0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(RC_OUT_RGB(0)), 4); |
PUSH_DATA (push, 0x00000c00); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(RC_ENABLE), 1); |
PUSH_DATA (push, 0x00011101); |
BEGIN_NV04(push, NV20_3D(RC_FINAL0), 2); |
PUSH_DATA (push, 0x130e0300); |
PUSH_DATA (push, 0x0c091c80); |
BEGIN_NV04(push, NV20_3D(RC_OUT_ALPHA(0)), 4); |
PUSH_DATA (push, 0x00000c00); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(RC_IN_RGB(0)), 4); |
PUSH_DATA (push, 0x20c400c0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(RC_COLOR0), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(RC_CONSTANT_COLOR0(0)), 4); |
PUSH_DATA (push, 0x035125a0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0x40002000); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(MULTISAMPLE_CONTROL), 1); |
PUSH_DATA (push, 0xffff0000); |
BEGIN_NV04(push, NV20_3D(BLEND_FUNC_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(DITHER_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(STENCIL_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(BLEND_FUNC_SRC), 4); |
PUSH_DATA (push, NV20_3D_BLEND_FUNC_SRC_ONE); |
PUSH_DATA (push, NV20_3D_BLEND_FUNC_DST_ZERO); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, NV20_3D_BLEND_EQUATION_FUNC_ADD); |
BEGIN_NV04(push, NV20_3D(STENCIL_MASK), 7); |
PUSH_DATA (push, 0xff); |
PUSH_DATA (push, NV20_3D_STENCIL_FUNC_FUNC_ALWAYS); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0xff); |
PUSH_DATA (push, NV20_3D_STENCIL_OP_FAIL_KEEP); |
PUSH_DATA (push, NV20_3D_STENCIL_OP_ZFAIL_KEEP); |
PUSH_DATA (push, NV20_3D_STENCIL_OP_ZPASS_KEEP); |
BEGIN_NV04(push, NV20_3D(COLOR_LOGIC_OP_ENABLE), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, NV20_3D_COLOR_LOGIC_OP_OP_COPY); |
BEGIN_NV04(push, SUBC_3D(0x17cc), 1); |
PUSH_DATA (push, 0); |
if (context_chipset(ctx) >= 0x25) { |
BEGIN_NV04(push, SUBC_3D(0x1d84), 1); |
PUSH_DATA (push, 1); |
} |
BEGIN_NV04(push, NV20_3D(LIGHTING_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(LIGHT_MODEL), 1); |
PUSH_DATA (push, NV20_3D_LIGHT_MODEL_VIEWER_NONLOCAL); |
BEGIN_NV04(push, NV20_3D(SEPARATE_SPECULAR_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(LIGHT_MODEL_TWO_SIDE_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(ENABLED_LIGHTS), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(NORMALIZE_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(POLYGON_STIPPLE_PATTERN(0)), |
NV20_3D_POLYGON_STIPPLE_PATTERN__LEN); |
for (i = 0; i < NV20_3D_POLYGON_STIPPLE_PATTERN__LEN; i++) { |
PUSH_DATA (push, 0xffffffff); |
} |
BEGIN_NV04(push, NV20_3D(POLYGON_OFFSET_POINT_ENABLE), 3); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(DEPTH_FUNC), 1); |
PUSH_DATA (push, NV20_3D_DEPTH_FUNC_LESS); |
BEGIN_NV04(push, NV20_3D(DEPTH_WRITE_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(DEPTH_TEST_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(POLYGON_OFFSET_FACTOR), 2); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
BEGIN_NV04(push, NV20_3D(DEPTH_CLAMP), 1); |
PUSH_DATA (push, 1); |
if (context_chipset(ctx) < 0x25) { |
BEGIN_NV04(push, SUBC_3D(0x1d84), 1); |
PUSH_DATA (push, 3); |
} |
BEGIN_NV04(push, NV20_3D(POINT_SIZE), 1); |
if (context_chipset(ctx) >= 0x25) |
PUSH_DATAf(push, 1.0); |
else |
PUSH_DATA (push, 8); |
if (context_chipset(ctx) >= 0x25) { |
BEGIN_NV04(push, NV20_3D(POINT_PARAMETERS_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, SUBC_3D(0x0a1c), 1); |
PUSH_DATA (push, 0x800); |
} else { |
BEGIN_NV04(push, NV20_3D(POINT_PARAMETERS_ENABLE), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
} |
BEGIN_NV04(push, NV20_3D(LINE_WIDTH), 1); |
PUSH_DATA (push, 8); |
BEGIN_NV04(push, NV20_3D(LINE_SMOOTH_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(POLYGON_MODE_FRONT), 2); |
PUSH_DATA (push, NV20_3D_POLYGON_MODE_FRONT_FILL); |
PUSH_DATA (push, NV20_3D_POLYGON_MODE_BACK_FILL); |
BEGIN_NV04(push, NV20_3D(CULL_FACE), 2); |
PUSH_DATA (push, NV20_3D_CULL_FACE_BACK); |
PUSH_DATA (push, NV20_3D_FRONT_FACE_CCW); |
BEGIN_NV04(push, NV20_3D(POLYGON_SMOOTH_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(CULL_FACE_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(SHADE_MODEL), 1); |
PUSH_DATA (push, NV20_3D_SHADE_MODEL_SMOOTH); |
BEGIN_NV04(push, NV20_3D(POLYGON_STIPPLE_ENABLE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(TEX_GEN_MODE(0,0)), |
4 * NV20_3D_TEX_GEN_MODE__ESIZE); |
for (i=0; i < 4 * NV20_3D_TEX_GEN_MODE__LEN; i++) |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(FOG_COEFF(0)), 3); |
PUSH_DATAf(push, 1.5); |
PUSH_DATAf(push, -0.090168); |
PUSH_DATAf(push, 0.0); |
BEGIN_NV04(push, NV20_3D(FOG_MODE), 2); |
PUSH_DATA (push, NV20_3D_FOG_MODE_EXP_SIGNED); |
PUSH_DATA (push, NV20_3D_FOG_COORD_FOG); |
BEGIN_NV04(push, NV20_3D(FOG_ENABLE), 2); |
PUSH_DATA (push, 0); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(ENGINE), 1); |
PUSH_DATA (push, NV20_3D_ENGINE_FIXED); |
for (i = 0; i < NV20_3D_TEX_MATRIX_ENABLE__LEN; i++) { |
BEGIN_NV04(push, NV20_3D(TEX_MATRIX_ENABLE(i)), 1); |
PUSH_DATA (push, 0); |
} |
BEGIN_NV04(push, NV20_3D(VERTEX_ATTR_4F_X(1)), 4 * 15); |
PUSH_DATAf(push, 1.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 1.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 1.0); |
PUSH_DATAf(push, 1.0); |
PUSH_DATAf(push, 1.0); |
PUSH_DATAf(push, 1.0); |
PUSH_DATAf(push, 1.0); |
PUSH_DATAf(push, 1.0); |
for (i = 0; i < 12; i++) { |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 1.0); |
} |
BEGIN_NV04(push, NV20_3D(EDGEFLAG_ENABLE), 1); |
PUSH_DATA (push, 1); |
BEGIN_NV04(push, NV20_3D(COLOR_MASK), 1); |
PUSH_DATA (push, 0x00010101); |
BEGIN_NV04(push, NV20_3D(CLEAR_VALUE), 1); |
PUSH_DATA (push, 0); |
BEGIN_NV04(push, NV20_3D(DEPTH_RANGE_NEAR), 2); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 16777216.0); |
BEGIN_NV04(push, NV20_3D(VIEWPORT_TRANSLATE_X), 4); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 16777215.0); |
BEGIN_NV04(push, NV20_3D(VIEWPORT_SCALE_X), 4); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 0.0); |
PUSH_DATAf(push, 16777215.0 * 0.5); |
PUSH_DATAf(push, 65535.0); |
PUSH_KICK (push); |
} |
static void |
nv20_context_destroy(struct gl_context *ctx) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
nv04_surface_takedown(ctx); |
nv20_swtnl_destroy(ctx); |
nv20_vbo_destroy(ctx); |
nouveau_object_del(&nctx->hw.eng3d); |
nouveau_context_deinit(ctx); |
free(ctx); |
} |
static struct gl_context * |
nv20_context_create(struct nouveau_screen *screen, const struct gl_config *visual, |
struct gl_context *share_ctx) |
{ |
struct nouveau_context *nctx; |
struct gl_context *ctx; |
unsigned kelvin_class; |
int ret; |
nctx = CALLOC_STRUCT(nouveau_context); |
if (!nctx) |
return NULL; |
ctx = &nctx->base; |
if (!nouveau_context_init(ctx, screen, visual, share_ctx)) |
goto fail; |
ctx->Extensions.ARB_texture_env_crossbar = true; |
ctx->Extensions.ARB_texture_env_combine = true; |
ctx->Extensions.ARB_texture_env_dot3 = true; |
ctx->Extensions.NV_fog_distance = true; |
ctx->Extensions.NV_texture_rectangle = true; |
if (ctx->Mesa_DXTn) { |
ctx->Extensions.EXT_texture_compression_s3tc = true; |
ctx->Extensions.ANGLE_texture_compression_dxt = true; |
} |
/* GL constants. */ |
ctx->Const.MaxTextureCoordUnits = NV20_TEXTURE_UNITS; |
ctx->Const.FragmentProgram.MaxTextureImageUnits = NV20_TEXTURE_UNITS; |
ctx->Const.MaxTextureUnits = NV20_TEXTURE_UNITS; |
ctx->Const.MaxTextureMaxAnisotropy = 8; |
ctx->Const.MaxTextureLodBias = 15; |
ctx->Driver.Clear = nv20_clear; |
/* 2D engine. */ |
ret = nv04_surface_init(ctx); |
if (!ret) |
goto fail; |
/* 3D engine. */ |
if (context_chipset(ctx) >= 0x25) |
kelvin_class = NV25_3D_CLASS; |
else |
kelvin_class = NV20_3D_CLASS; |
ret = nouveau_object_new(context_chan(ctx), 0xbeef0001, kelvin_class, |
NULL, 0, &nctx->hw.eng3d); |
if (ret) |
goto fail; |
nv20_hwctx_init(ctx); |
nv20_vbo_init(ctx); |
nv20_swtnl_init(ctx); |
return ctx; |
fail: |
nv20_context_destroy(ctx); |
return NULL; |
} |
const struct nouveau_driver nv20_driver = { |
.context_create = nv20_context_create, |
.context_destroy = nv20_context_destroy, |
.surface_copy = nv04_surface_copy, |
.surface_fill = nv04_surface_fill, |
.emit = (nouveau_state_func[]) { |
nv10_emit_alpha_func, |
nv10_emit_blend_color, |
nv10_emit_blend_equation, |
nv10_emit_blend_func, |
nv20_emit_clip_plane, |
nv20_emit_clip_plane, |
nv20_emit_clip_plane, |
nv20_emit_clip_plane, |
nv20_emit_clip_plane, |
nv20_emit_clip_plane, |
nv10_emit_color_mask, |
nv20_emit_color_material, |
nv10_emit_cull_face, |
nv10_emit_front_face, |
nv10_emit_depth, |
nv10_emit_dither, |
nv20_emit_frag, |
nv20_emit_framebuffer, |
nv20_emit_fog, |
nv10_emit_light_enable, |
nv20_emit_light_model, |
nv20_emit_light_source, |
nv20_emit_light_source, |
nv20_emit_light_source, |
nv20_emit_light_source, |
nv20_emit_light_source, |
nv20_emit_light_source, |
nv20_emit_light_source, |
nv20_emit_light_source, |
nv10_emit_line_stipple, |
nv10_emit_line_mode, |
nv20_emit_logic_opcode, |
nv20_emit_material_ambient, |
nv20_emit_material_ambient, |
nv20_emit_material_diffuse, |
nv20_emit_material_diffuse, |
nv20_emit_material_specular, |
nv20_emit_material_specular, |
nv20_emit_material_shininess, |
nv20_emit_material_shininess, |
nv20_emit_modelview, |
nv20_emit_point_mode, |
nv10_emit_point_parameter, |
nv10_emit_polygon_mode, |
nv10_emit_polygon_offset, |
nv10_emit_polygon_stipple, |
nv20_emit_projection, |
nv10_emit_render_mode, |
nv10_emit_scissor, |
nv10_emit_shade_model, |
nv10_emit_stencil_func, |
nv10_emit_stencil_mask, |
nv10_emit_stencil_op, |
nv20_emit_tex_env, |
nv20_emit_tex_env, |
nv20_emit_tex_env, |
nv20_emit_tex_env, |
nv20_emit_tex_gen, |
nv20_emit_tex_gen, |
nv20_emit_tex_gen, |
nv20_emit_tex_gen, |
nv20_emit_tex_mat, |
nv20_emit_tex_mat, |
nv20_emit_tex_mat, |
nv20_emit_tex_mat, |
nv20_emit_tex_obj, |
nv20_emit_tex_obj, |
nv20_emit_tex_obj, |
nv20_emit_tex_obj, |
nv20_emit_viewport, |
nv20_emit_tex_shader |
}, |
.num_emit = NUM_NV20_STATE, |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv20_driver.h |
---|
0,0 → 1,122 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 __NV20_DRIVER_H__ |
#define __NV20_DRIVER_H__ |
enum { |
NOUVEAU_STATE_TEX_SHADER = NUM_NOUVEAU_STATE, |
NUM_NV20_STATE |
}; |
#define NV20_TEXTURE_UNITS 4 |
/* nv20_context.c */ |
extern const struct nouveau_driver nv20_driver; |
/* nv20_render.c */ |
void |
nv20_vbo_init(struct gl_context *ctx); |
void |
nv20_vbo_destroy(struct gl_context *ctx); |
void |
nv20_swtnl_init(struct gl_context *ctx); |
void |
nv20_swtnl_destroy(struct gl_context *ctx); |
/* nv20_state_fb.c */ |
void |
nv20_emit_framebuffer(struct gl_context *ctx, int emit); |
void |
nv20_emit_viewport(struct gl_context *ctx, int emit); |
/* nv20_state_polygon.c */ |
void |
nv20_emit_point_mode(struct gl_context *ctx, int emit); |
/* nv20_state_raster.c */ |
void |
nv20_emit_logic_opcode(struct gl_context *ctx, int emit); |
/* nv20_state_frag.c */ |
void |
nv20_emit_tex_env(struct gl_context *ctx, int emit); |
void |
nv20_emit_frag(struct gl_context *ctx, int emit); |
/* nv20_state_tex.c */ |
void |
nv20_emit_tex_gen(struct gl_context *ctx, int emit); |
void |
nv20_emit_tex_mat(struct gl_context *ctx, int emit); |
void |
nv20_emit_tex_obj(struct gl_context *ctx, int emit); |
void |
nv20_emit_tex_shader(struct gl_context *ctx, int emit); |
/* nv20_state_tnl.c */ |
void |
nv20_emit_clip_plane(struct gl_context *ctx, int emit); |
void |
nv20_emit_color_material(struct gl_context *ctx, int emit); |
void |
nv20_emit_fog(struct gl_context *ctx, int emit); |
void |
nv20_emit_light_model(struct gl_context *ctx, int emit); |
void |
nv20_emit_light_source(struct gl_context *ctx, int emit); |
void |
nv20_emit_material_ambient(struct gl_context *ctx, int emit); |
void |
nv20_emit_material_diffuse(struct gl_context *ctx, int emit); |
void |
nv20_emit_material_specular(struct gl_context *ctx, int emit); |
void |
nv20_emit_material_shininess(struct gl_context *ctx, int emit); |
void |
nv20_emit_modelview(struct gl_context *ctx, int emit); |
void |
nv20_emit_projection(struct gl_context *ctx, int emit); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv20_render.c |
---|
0,0 → 1,224 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nv20_3d.xml.h" |
#include "nv20_driver.h" |
#define NUM_VERTEX_ATTRS 16 |
static void |
nv20_emit_material(struct gl_context *ctx, struct nouveau_array *a, |
const void *v); |
/* Vertex attribute format. */ |
static struct nouveau_attr_info nv20_vertex_attrs[VERT_ATTRIB_MAX] = { |
[VERT_ATTRIB_POS] = { |
.vbo_index = 0, |
.imm_method = NV20_3D_VERTEX_POS_4F_X, |
.imm_fields = 4, |
}, |
[VERT_ATTRIB_NORMAL] = { |
.vbo_index = 2, |
.imm_method = NV20_3D_VERTEX_NOR_3F_X, |
.imm_fields = 3, |
}, |
[VERT_ATTRIB_COLOR0] = { |
.vbo_index = 3, |
.imm_method = NV20_3D_VERTEX_COL_4F, |
.imm_fields = 4, |
}, |
[VERT_ATTRIB_COLOR1] = { |
.vbo_index = 4, |
.imm_method = NV20_3D_VERTEX_COL2_3F, |
.imm_fields = 3, |
}, |
[VERT_ATTRIB_FOG] = { |
.vbo_index = 5, |
.imm_method = NV20_3D_VERTEX_FOG_1F, |
.imm_fields = 1, |
}, |
[VERT_ATTRIB_TEX0] = { |
.vbo_index = 9, |
.imm_method = NV20_3D_VERTEX_TX0_4F_S, |
.imm_fields = 4, |
}, |
[VERT_ATTRIB_TEX1] = { |
.vbo_index = 10, |
.imm_method = NV20_3D_VERTEX_TX1_4F_S, |
.imm_fields = 4, |
}, |
[VERT_ATTRIB_TEX2] = { |
.vbo_index = 11, |
.imm_method = NV20_3D_VERTEX_TX2_4F_S, |
.imm_fields = 4, |
}, |
[VERT_ATTRIB_TEX3] = { |
.vbo_index = 12, |
.imm_method = NV20_3D_VERTEX_TX3_4F_S, |
.imm_fields = 4, |
}, |
[VERT_ATTRIB_GENERIC0] = { |
.emit = nv20_emit_material, |
}, |
[VERT_ATTRIB_GENERIC1] = { |
.emit = nv20_emit_material, |
}, |
[VERT_ATTRIB_GENERIC2] = { |
.emit = nv20_emit_material, |
}, |
[VERT_ATTRIB_GENERIC3] = { |
.emit = nv20_emit_material, |
}, |
[VERT_ATTRIB_GENERIC4] = { |
.emit = nv20_emit_material, |
}, |
[VERT_ATTRIB_GENERIC5] = { |
.emit = nv20_emit_material, |
}, |
[VERT_ATTRIB_GENERIC6] = { |
.emit = nv20_emit_material, |
}, |
[VERT_ATTRIB_GENERIC7] = { |
.emit = nv20_emit_material, |
}, |
[VERT_ATTRIB_GENERIC8] = { |
.emit = nv20_emit_material, |
}, |
[VERT_ATTRIB_GENERIC9] = { |
.emit = nv20_emit_material, |
}, |
}; |
static int |
get_hw_format(int type) |
{ |
switch (type) { |
case GL_FLOAT: |
return NV20_3D_VTXBUF_FMT_TYPE_FLOAT; |
case GL_UNSIGNED_SHORT: |
return NV20_3D_VTXBUF_FMT_TYPE_USHORT; |
case GL_UNSIGNED_BYTE: |
return NV20_3D_VTXBUF_FMT_TYPE_UBYTE; |
default: |
assert(0); |
} |
} |
static void |
nv20_render_set_format(struct gl_context *ctx) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
int i, attr, hw_format; |
FOR_EACH_ATTR(render, i, attr) { |
if (attr >= 0) { |
struct nouveau_array *a = &render->attrs[attr]; |
hw_format = a->stride << 8 | |
a->fields << 4 | |
get_hw_format(a->type); |
} else { |
/* Unused attribute. */ |
hw_format = NV20_3D_VTXBUF_FMT_TYPE_FLOAT; |
} |
BEGIN_NV04(push, NV20_3D(VTXBUF_FMT(i)), 1); |
PUSH_DATA (push, hw_format); |
} |
} |
static void |
nv20_render_bind_vertices(struct gl_context *ctx) |
{ |
struct nouveau_render_state *render = to_render_state(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
int i, attr; |
FOR_EACH_BOUND_ATTR(render, i, attr) { |
struct nouveau_array *a = &render->attrs[attr]; |
BEGIN_NV04(push, NV20_3D(VTXBUF_OFFSET(i)), 1); |
PUSH_MTHD (push, NV20_3D(VTXBUF_OFFSET(i)), BUFCTX_VTX, |
a->bo, a->offset, NOUVEAU_BO_LOW | |
NOUVEAU_BO_OR | NOUVEAU_BO_GART | |
NOUVEAU_BO_RD, 0, |
NV20_3D_VTXBUF_OFFSET_DMA1); |
} |
} |
static void |
nv20_render_release_vertices(struct gl_context *ctx) |
{ |
PUSH_RESET(context_push(ctx), BUFCTX_VTX); |
} |
/* Vertex array rendering defs. */ |
#define RENDER_LOCALS(ctx) |
#define BATCH_VALIDATE() \ |
BEGIN_NV04(push, NV20_3D(VTXBUF_VALIDATE), 1); \ |
PUSH_DATA (push, 0) |
#define BATCH_BEGIN(prim) \ |
BEGIN_NV04(push, NV20_3D(VERTEX_BEGIN_END), 1); \ |
PUSH_DATA (push, prim) |
#define BATCH_END() \ |
BEGIN_NV04(push, NV20_3D(VERTEX_BEGIN_END), 1); \ |
PUSH_DATA (push, 0) |
#define MAX_PACKET 0x400 |
#define MAX_OUT_L 0x100 |
#define BATCH_PACKET_L(n) \ |
BEGIN_NI04(push, NV20_3D(VTXBUF_BATCH), n) |
#define BATCH_OUT_L(i, n) \ |
PUSH_DATA (push, ((n) - 1) << 24 | (i)) |
#define MAX_OUT_I16 0x2 |
#define BATCH_PACKET_I16(n) \ |
BEGIN_NI04(push, NV20_3D(VTXBUF_ELEMENT_U16), n) |
#define BATCH_OUT_I16(i0, i1) \ |
PUSH_DATA (push, (i1) << 16 | (i0)) |
#define MAX_OUT_I32 0x1 |
#define BATCH_PACKET_I32(n) \ |
BEGIN_NI04(push, NV20_3D(VTXBUF_ELEMENT_U32), n) |
#define BATCH_OUT_I32(i) \ |
PUSH_DATA (push, i) |
#define IMM_PACKET(m, n) \ |
BEGIN_NV04(push, SUBC_3D(m), n) |
#define IMM_OUT(x) \ |
PUSH_DATAf(push, x) |
#define TAG(x) nv20_##x |
#include "nouveau_render_t.c" |
#include "nouveau_vbo_t.c" |
#include "nouveau_swtnl_t.c" |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv20_state_fb.c |
---|
0,0 → 1,151 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_fbo.h" |
#include "nouveau_gldefs.h" |
#include "nouveau_util.h" |
#include "nv20_3d.xml.h" |
#include "nv20_driver.h" |
static inline unsigned |
get_rt_format(gl_format format) |
{ |
switch (format) { |
case MESA_FORMAT_XRGB8888: |
return NV20_3D_RT_FORMAT_COLOR_X8R8G8B8; |
case MESA_FORMAT_ARGB8888: |
return NV20_3D_RT_FORMAT_COLOR_A8R8G8B8; |
case MESA_FORMAT_RGB565: |
return NV20_3D_RT_FORMAT_COLOR_R5G6B5; |
case MESA_FORMAT_Z16: |
return NV20_3D_RT_FORMAT_DEPTH_Z16; |
case MESA_FORMAT_Z24_S8: |
return NV20_3D_RT_FORMAT_DEPTH_Z24S8; |
default: |
assert(0); |
} |
} |
static void |
setup_hierz_buffer(struct gl_context *ctx) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct nouveau_framebuffer *nfb = to_nouveau_framebuffer(fb); |
unsigned pitch = align(fb->Width, 128), |
height = align(fb->Height, 2), |
size = pitch * height; |
if (!nfb->hierz.bo || nfb->hierz.bo->size != size) { |
nouveau_bo_ref(NULL, &nfb->hierz.bo); |
nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_VRAM, 0, size, |
NULL, &nfb->hierz.bo); |
} |
BEGIN_NV04(push, NV25_3D(HIERZ_PITCH), 1); |
PUSH_DATA (push, pitch); |
BEGIN_NV04(push, NV25_3D(HIERZ_OFFSET), 1); |
PUSH_MTHDl(push, NV25_3D(HIERZ_OFFSET), BUFCTX_FB, |
nfb->hierz.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); |
} |
void |
nv20_emit_framebuffer(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct nouveau_surface *s; |
unsigned rt_format = NV20_3D_RT_FORMAT_TYPE_LINEAR; |
unsigned rt_pitch = 0, zeta_pitch = 0; |
unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR; |
if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) |
return; |
PUSH_RESET(push, BUFCTX_FB); |
/* Render target */ |
if (fb->_ColorDrawBuffers[0]) { |
s = &to_nouveau_renderbuffer( |
fb->_ColorDrawBuffers[0])->surface; |
rt_format |= get_rt_format(s->format); |
rt_pitch = s->pitch; |
BEGIN_NV04(push, NV20_3D(COLOR_OFFSET), 1); |
PUSH_MTHDl(push, NV20_3D(COLOR_OFFSET), BUFCTX_FB, |
s->bo, 0, bo_flags); |
} |
/* depth/stencil */ |
if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { |
s = &to_nouveau_renderbuffer( |
fb->Attachment[BUFFER_DEPTH].Renderbuffer)->surface; |
rt_format |= get_rt_format(s->format); |
zeta_pitch = s->pitch; |
BEGIN_NV04(push, NV20_3D(ZETA_OFFSET), 1); |
PUSH_MTHDl(push, NV20_3D(ZETA_OFFSET), BUFCTX_FB, |
s->bo, 0, bo_flags); |
if (context_chipset(ctx) >= 0x25) |
setup_hierz_buffer(ctx); |
} else { |
rt_format |= get_rt_format(MESA_FORMAT_Z24_S8); |
zeta_pitch = rt_pitch; |
} |
BEGIN_NV04(push, NV20_3D(RT_FORMAT), 2); |
PUSH_DATA (push, rt_format); |
PUSH_DATA (push, zeta_pitch << 16 | rt_pitch); |
/* Recompute the viewport/scissor state. */ |
context_dirty(ctx, VIEWPORT); |
context_dirty(ctx, SCISSOR); |
} |
void |
nv20_emit_viewport(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
float a[4] = {}; |
get_viewport_translate(ctx, a); |
BEGIN_NV04(push, NV20_3D(VIEWPORT_TRANSLATE_X), 4); |
PUSH_DATAp(push, a, 4); |
BEGIN_NV04(push, NV20_3D(VIEWPORT_CLIP_HORIZ(0)), 1); |
PUSH_DATA (push, (fb->Width - 1) << 16); |
BEGIN_NV04(push, NV20_3D(VIEWPORT_CLIP_VERT(0)), 1); |
PUSH_DATA (push, (fb->Height - 1) << 16); |
context_dirty(ctx, PROJECTION); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv20_state_frag.c |
---|
0,0 → 1,71 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nv20_3d.xml.h" |
#include "nv10_driver.h" |
#include "nv20_driver.h" |
void |
nv20_emit_tex_env(struct gl_context *ctx, int emit) |
{ |
const int i = emit - NOUVEAU_STATE_TEX_ENV0; |
struct nouveau_pushbuf *push = context_push(ctx); |
uint32_t a_in, a_out, c_in, c_out, k; |
nv10_get_general_combiner(ctx, i, &a_in, &a_out, &c_in, &c_out, &k); |
BEGIN_NV04(push, NV20_3D(RC_IN_ALPHA(i)), 1); |
PUSH_DATA (push, a_in); |
BEGIN_NV04(push, NV20_3D(RC_OUT_ALPHA(i)), 1); |
PUSH_DATA (push, a_out); |
BEGIN_NV04(push, NV20_3D(RC_IN_RGB(i)), 1); |
PUSH_DATA (push, c_in); |
BEGIN_NV04(push, NV20_3D(RC_OUT_RGB(i)), 1); |
PUSH_DATA (push, c_out); |
BEGIN_NV04(push, NV20_3D(RC_CONSTANT_COLOR0(i)), 1); |
PUSH_DATA (push, k); |
context_dirty(ctx, FRAG); |
} |
void |
nv20_emit_frag(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
uint64_t in; |
int n; |
nv10_get_final_combiner(ctx, &in, &n); |
BEGIN_NV04(push, NV20_3D(RC_FINAL0), 2); |
PUSH_DATA (push, in); |
PUSH_DATA (push, in >> 32); |
BEGIN_NV04(push, NV20_3D(RC_ENABLE), 1); |
PUSH_DATA (push, n); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv20_state_polygon.c |
---|
0,0 → 1,43 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_gldefs.h" |
#include "nv20_3d.xml.h" |
#include "nv20_driver.h" |
void |
nv20_emit_point_mode(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV20_3D(POINT_SIZE), 1); |
if (context_chipset(ctx) >= 0x25) |
PUSH_DATAf(push, ctx->Point.Size); |
else |
PUSH_DATA (push, (uint32_t)(ctx->Point.Size * 8)); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv20_state_raster.c |
---|
0,0 → 1,42 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_gldefs.h" |
#include "nouveau_util.h" |
#include "nv20_3d.xml.h" |
#include "nv20_driver.h" |
void |
nv20_emit_logic_opcode(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
BEGIN_NV04(push, NV20_3D(COLOR_LOGIC_OP_ENABLE), 2); |
PUSH_DATAb(push, ctx->Color.ColorLogicOpEnabled); |
PUSH_DATA (push, nvgl_logicop_func(ctx->Color.LogicOp)); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv20_state_tex.c |
---|
0,0 → 1,274 |
/* |
* Copyright (C) 2009 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_gldefs.h" |
#include "nouveau_texture.h" |
#include "nv20_3d.xml.h" |
#include "nouveau_util.h" |
#include "nv20_driver.h" |
#include "main/samplerobj.h" |
void |
nv20_emit_tex_gen(struct gl_context *ctx, int emit) |
{ |
const int i = emit - NOUVEAU_STATE_TEX_GEN0; |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_texture_unit *unit = &ctx->Texture.Unit[i]; |
int j; |
for (j = 0; j < 4; j++) { |
if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) { |
struct gl_texgen *coord = get_texgen_coord(unit, j); |
float *k = get_texgen_coeff(coord); |
if (k) { |
BEGIN_NV04(push, NV20_3D(TEX_GEN_COEFF(i, j)), 4); |
PUSH_DATAp(push, k, 4); |
} |
BEGIN_NV04(push, NV20_3D(TEX_GEN_MODE(i, j)), 1); |
PUSH_DATA (push, nvgl_texgen_mode(coord->Mode)); |
} else { |
BEGIN_NV04(push, NV20_3D(TEX_GEN_MODE(i, j)), 1); |
PUSH_DATA (push, 0); |
} |
} |
} |
void |
nv20_emit_tex_mat(struct gl_context *ctx, int emit) |
{ |
const int i = emit - NOUVEAU_STATE_TEX_MAT0; |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
if (nctx->fallback == HWTNL && |
(ctx->Texture._TexMatEnabled & 1 << i)) { |
BEGIN_NV04(push, NV20_3D(TEX_MATRIX_ENABLE(i)), 1); |
PUSH_DATA (push, 1); |
BEGIN_NV04(push, NV20_3D(TEX_MATRIX(i,0)), 16); |
PUSH_DATAm(push, ctx->TextureMatrixStack[i].Top->m); |
} else { |
BEGIN_NV04(push, NV20_3D(TEX_MATRIX_ENABLE(i)), 1); |
PUSH_DATA (push, 0); |
} |
} |
static uint32_t |
get_tex_format_pot(struct gl_texture_image *ti) |
{ |
switch (ti->TexFormat) { |
case MESA_FORMAT_ARGB8888: |
return NV20_3D_TEX_FORMAT_FORMAT_A8R8G8B8; |
case MESA_FORMAT_ARGB1555: |
return NV20_3D_TEX_FORMAT_FORMAT_A1R5G5B5; |
case MESA_FORMAT_ARGB4444: |
return NV20_3D_TEX_FORMAT_FORMAT_A4R4G4B4; |
case MESA_FORMAT_XRGB8888: |
return NV20_3D_TEX_FORMAT_FORMAT_X8R8G8B8; |
case MESA_FORMAT_RGB565: |
return NV20_3D_TEX_FORMAT_FORMAT_R5G6B5; |
case MESA_FORMAT_A8: |
case MESA_FORMAT_I8: |
return NV20_3D_TEX_FORMAT_FORMAT_I8; |
case MESA_FORMAT_L8: |
return NV20_3D_TEX_FORMAT_FORMAT_L8; |
case MESA_FORMAT_RGB_DXT1: |
case MESA_FORMAT_RGBA_DXT1: |
return NV20_3D_TEX_FORMAT_FORMAT_DXT1; |
case MESA_FORMAT_RGBA_DXT3: |
return NV20_3D_TEX_FORMAT_FORMAT_DXT3; |
case MESA_FORMAT_RGBA_DXT5: |
return NV20_3D_TEX_FORMAT_FORMAT_DXT5; |
default: |
assert(0); |
} |
} |
static uint32_t |
get_tex_format_rect(struct gl_texture_image *ti) |
{ |
switch (ti->TexFormat) { |
case MESA_FORMAT_ARGB8888: |
return NV20_3D_TEX_FORMAT_FORMAT_A8R8G8B8_RECT; |
case MESA_FORMAT_ARGB1555: |
return NV20_3D_TEX_FORMAT_FORMAT_A1R5G5B5_RECT; |
case MESA_FORMAT_ARGB4444: |
return NV20_3D_TEX_FORMAT_FORMAT_A4R4G4B4_RECT; |
case MESA_FORMAT_XRGB8888: |
return NV20_3D_TEX_FORMAT_FORMAT_R8G8B8_RECT; |
case MESA_FORMAT_RGB565: |
return NV20_3D_TEX_FORMAT_FORMAT_R5G6B5_RECT; |
case MESA_FORMAT_L8: |
return NV20_3D_TEX_FORMAT_FORMAT_L8_RECT; |
case MESA_FORMAT_A8: |
case MESA_FORMAT_I8: |
return NV20_3D_TEX_FORMAT_FORMAT_I8_RECT; |
default: |
assert(0); |
} |
} |
void |
nv20_emit_tex_obj(struct gl_context *ctx, int emit) |
{ |
const int i = emit - NOUVEAU_STATE_TEX_OBJ0; |
struct nouveau_pushbuf *push = context_push(ctx); |
const int bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART | NOUVEAU_BO_VRAM; |
struct gl_texture_object *t; |
struct nouveau_surface *s; |
struct gl_texture_image *ti; |
const struct gl_sampler_object *sa; |
uint32_t tx_format, tx_filter, tx_wrap, tx_enable; |
PUSH_RESET(push, BUFCTX_TEX(i)); |
if (!ctx->Texture.Unit[i]._ReallyEnabled) { |
BEGIN_NV04(push, NV20_3D(TEX_ENABLE(i)), 1); |
PUSH_DATA (push, 0); |
context_dirty(ctx, TEX_SHADER); |
return; |
} |
t = ctx->Texture.Unit[i]._Current; |
s = &to_nouveau_texture(t)->surfaces[t->BaseLevel]; |
ti = t->Image[0][t->BaseLevel]; |
sa = _mesa_get_samplerobj(ctx, i); |
if (!nouveau_texture_validate(ctx, t)) |
return; |
/* Recompute the texturing registers. */ |
tx_format = ti->DepthLog2 << 28 |
| ti->HeightLog2 << 24 |
| ti->WidthLog2 << 20 |
| NV20_3D_TEX_FORMAT_DIMS_2D |
| NV20_3D_TEX_FORMAT_NO_BORDER |
| 1 << 16; |
tx_wrap = nvgl_wrap_mode(sa->WrapR) << 16 |
| nvgl_wrap_mode(sa->WrapT) << 8 |
| nvgl_wrap_mode(sa->WrapS) << 0; |
tx_filter = nvgl_filter_mode(sa->MagFilter) << 24 |
| nvgl_filter_mode(sa->MinFilter) << 16 |
| 2 << 12; |
tx_enable = NV20_3D_TEX_ENABLE_ENABLE |
| log2i(sa->MaxAnisotropy) << 4; |
if (t->Target == GL_TEXTURE_RECTANGLE) { |
BEGIN_NV04(push, NV20_3D(TEX_NPOT_PITCH(i)), 1); |
PUSH_DATA (push, s->pitch << 16); |
BEGIN_NV04(push, NV20_3D(TEX_NPOT_SIZE(i)), 1); |
PUSH_DATA (push, s->width << 16 | s->height); |
tx_format |= get_tex_format_rect(ti); |
} else { |
tx_format |= get_tex_format_pot(ti); |
} |
if (sa->MinFilter != GL_NEAREST && |
sa->MinFilter != GL_LINEAR) { |
int lod_min = sa->MinLod; |
int lod_max = MIN2(sa->MaxLod, t->_MaxLambda); |
int lod_bias = sa->LodBias |
+ ctx->Texture.Unit[i].LodBias; |
lod_max = CLAMP(lod_max, 0, 15); |
lod_min = CLAMP(lod_min, 0, 15); |
lod_bias = CLAMP(lod_bias, 0, 15); |
tx_format |= NV20_3D_TEX_FORMAT_MIPMAP; |
tx_filter |= lod_bias << 8; |
tx_enable |= lod_min << 26 |
| lod_max << 14; |
} |
/* Write it to the hardware. */ |
BEGIN_NV04(push, NV20_3D(TEX_FORMAT(i)), 1); |
PUSH_MTHD (push, NV20_3D(TEX_FORMAT(i)), BUFCTX_TEX(i), |
s->bo, tx_format, bo_flags | NOUVEAU_BO_OR, |
NV20_3D_TEX_FORMAT_DMA0, |
NV20_3D_TEX_FORMAT_DMA1); |
BEGIN_NV04(push, NV20_3D(TEX_OFFSET(i)), 1); |
PUSH_MTHDl(push, NV20_3D(TEX_OFFSET(i)), BUFCTX_TEX(i), |
s->bo, s->offset, bo_flags); |
BEGIN_NV04(push, NV20_3D(TEX_WRAP(i)), 1); |
PUSH_DATA (push, tx_wrap); |
BEGIN_NV04(push, NV20_3D(TEX_FILTER(i)), 1); |
PUSH_DATA (push, tx_filter); |
BEGIN_NV04(push, NV20_3D(TEX_ENABLE(i)), 1); |
PUSH_DATA (push, tx_enable); |
context_dirty(ctx, TEX_SHADER); |
} |
void |
nv20_emit_tex_shader(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
uint32_t tx_shader_op = 0; |
int i; |
for (i = 0; i < NV20_TEXTURE_UNITS; i++) { |
if (!ctx->Texture.Unit[i]._ReallyEnabled) |
continue; |
tx_shader_op |= NV20_3D_TEX_SHADER_OP_TX0_TEXTURE_2D << 5 * i; |
} |
BEGIN_NV04(push, NV20_3D(TEX_SHADER_OP), 1); |
PUSH_DATA (push, tx_shader_op); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv20_state_tnl.c |
---|
0,0 → 1,376 |
/* |
* Copyright (C) 2009-2010 Francisco Jerez. |
* 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, 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 COPYRIGHT OWNER(S) 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 "nouveau_driver.h" |
#include "nouveau_context.h" |
#include "nouveau_gldefs.h" |
#include "nouveau_util.h" |
#include "nv20_3d.xml.h" |
#include "nv10_driver.h" |
#include "nv20_driver.h" |
#define LIGHT_MODEL_AMBIENT_R(side) \ |
((side) ? NV20_3D_LIGHT_MODEL_BACK_AMBIENT_R : \ |
NV20_3D_LIGHT_MODEL_FRONT_AMBIENT_R) |
#define LIGHT_AMBIENT_R(side, i) \ |
((side) ? NV20_3D_LIGHT_BACK_AMBIENT_R(i) : \ |
NV20_3D_LIGHT_FRONT_AMBIENT_R(i)) |
#define LIGHT_DIFFUSE_R(side, i) \ |
((side) ? NV20_3D_LIGHT_BACK_DIFFUSE_R(i) : \ |
NV20_3D_LIGHT_FRONT_DIFFUSE_R(i)) |
#define LIGHT_SPECULAR_R(side, i) \ |
((side) ? NV20_3D_LIGHT_BACK_SPECULAR_R(i) : \ |
NV20_3D_LIGHT_FRONT_SPECULAR_R(i)) |
#define MATERIAL_FACTOR_R(side) \ |
((side) ? NV20_3D_MATERIAL_FACTOR_BACK_R : \ |
NV20_3D_MATERIAL_FACTOR_FRONT_R) |
#define MATERIAL_FACTOR_A(side) \ |
((side) ? NV20_3D_MATERIAL_FACTOR_BACK_A : \ |
NV20_3D_MATERIAL_FACTOR_FRONT_A) |
#define MATERIAL_SHININESS(side) \ |
((side) ? NV20_3D_BACK_MATERIAL_SHININESS(0) : \ |
NV20_3D_FRONT_MATERIAL_SHININESS(0)) |
void |
nv20_emit_clip_plane(struct gl_context *ctx, int emit) |
{ |
} |
static inline unsigned |
get_material_bitmask(unsigned m) |
{ |
unsigned ret = 0; |
if (m & MAT_BIT_FRONT_EMISSION) |
ret |= NV20_3D_COLOR_MATERIAL_FRONT_EMISSION_COL1; |
if (m & MAT_BIT_FRONT_AMBIENT) |
ret |= NV20_3D_COLOR_MATERIAL_FRONT_AMBIENT_COL1; |
if (m & MAT_BIT_FRONT_DIFFUSE) |
ret |= NV20_3D_COLOR_MATERIAL_FRONT_DIFFUSE_COL1; |
if (m & MAT_BIT_FRONT_SPECULAR) |
ret |= NV20_3D_COLOR_MATERIAL_FRONT_SPECULAR_COL1; |
if (m & MAT_BIT_BACK_EMISSION) |
ret |= NV20_3D_COLOR_MATERIAL_BACK_EMISSION_COL1; |
if (m & MAT_BIT_BACK_AMBIENT) |
ret |= NV20_3D_COLOR_MATERIAL_BACK_AMBIENT_COL1; |
if (m & MAT_BIT_BACK_DIFFUSE) |
ret |= NV20_3D_COLOR_MATERIAL_BACK_DIFFUSE_COL1; |
if (m & MAT_BIT_BACK_SPECULAR) |
ret |= NV20_3D_COLOR_MATERIAL_BACK_SPECULAR_COL1; |
return ret; |
} |
void |
nv20_emit_color_material(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
unsigned mask = get_material_bitmask(ctx->Light._ColorMaterialBitmask); |
BEGIN_NV04(push, NV20_3D(COLOR_MATERIAL), 1); |
PUSH_DATA (push, ctx->Light.ColorMaterialEnabled ? mask : 0); |
} |
static unsigned |
get_fog_mode_signed(unsigned mode) |
{ |
switch (mode) { |
case GL_LINEAR: |
return NV20_3D_FOG_MODE_LINEAR_SIGNED; |
case GL_EXP: |
return NV20_3D_FOG_MODE_EXP_SIGNED; |
case GL_EXP2: |
return NV20_3D_FOG_MODE_EXP2_SIGNED; |
default: |
assert(0); |
} |
} |
static unsigned |
get_fog_mode_unsigned(unsigned mode) |
{ |
switch (mode) { |
case GL_LINEAR: |
return NV20_3D_FOG_MODE_LINEAR_UNSIGNED; |
case GL_EXP: |
return NV20_3D_FOG_MODE_EXP_UNSIGNED; |
case GL_EXP2: |
return NV20_3D_FOG_MODE_EXP2_UNSIGNED; |
default: |
assert(0); |
} |
} |
static unsigned |
get_fog_source(unsigned source, unsigned distance_mode) |
{ |
switch (source) { |
case GL_FOG_COORDINATE_EXT: |
return NV20_3D_FOG_COORD_FOG; |
case GL_FRAGMENT_DEPTH_EXT: |
switch (distance_mode) { |
case GL_EYE_PLANE_ABSOLUTE_NV: |
return NV20_3D_FOG_COORD_DIST_ORTHOGONAL_ABS; |
case GL_EYE_PLANE: |
return NV20_3D_FOG_COORD_DIST_ORTHOGONAL; |
case GL_EYE_RADIAL_NV: |
return NV20_3D_FOG_COORD_DIST_RADIAL; |
default: |
assert(0); |
} |
default: |
assert(0); |
} |
} |
void |
nv20_emit_fog(struct gl_context *ctx, int emit) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_fog_attrib *f = &ctx->Fog; |
unsigned source = nctx->fallback == HWTNL ? |
f->FogCoordinateSource : GL_FOG_COORDINATE_EXT; |
float k[3]; |
nv10_get_fog_coeff(ctx, k); |
BEGIN_NV04(push, NV20_3D(FOG_MODE), 4); |
PUSH_DATA (push, ((source == GL_FRAGMENT_DEPTH_EXT && |
f->FogDistanceMode == GL_EYE_PLANE_ABSOLUTE_NV) ? |
get_fog_mode_unsigned(f->Mode) : |
get_fog_mode_signed(f->Mode))); |
PUSH_DATA (push, get_fog_source(source, f->FogDistanceMode)); |
PUSH_DATAb(push, f->Enabled); |
PUSH_DATA (push, pack_rgba_f(MESA_FORMAT_RGBA8888_REV, f->Color)); |
BEGIN_NV04(push, NV20_3D(FOG_COEFF(0)), 3); |
PUSH_DATAp(push, k, 3); |
} |
void |
nv20_emit_light_model(struct gl_context *ctx, int emit) |
{ |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_lightmodel *m = &ctx->Light.Model; |
BEGIN_NV04(push, NV20_3D(SEPARATE_SPECULAR_ENABLE), 1); |
PUSH_DATAb(push, m->ColorControl == GL_SEPARATE_SPECULAR_COLOR); |
BEGIN_NV04(push, NV20_3D(LIGHT_MODEL), 1); |
PUSH_DATA (push, ((m->LocalViewer ? |
NV20_3D_LIGHT_MODEL_VIEWER_LOCAL : |
NV20_3D_LIGHT_MODEL_VIEWER_NONLOCAL) | |
(_mesa_need_secondary_color(ctx) ? |
NV20_3D_LIGHT_MODEL_SEPARATE_SPECULAR : |
0))); |
BEGIN_NV04(push, NV20_3D(LIGHT_MODEL_TWO_SIDE_ENABLE), 1); |
PUSH_DATAb(push, ctx->Light.Model.TwoSide); |
} |
void |
nv20_emit_light_source(struct gl_context *ctx, int emit) |
{ |
const int i = emit - NOUVEAU_STATE_LIGHT_SOURCE0; |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_light *l = &ctx->Light.Light[i]; |
if (l->_Flags & LIGHT_POSITIONAL) { |
BEGIN_NV04(push, NV20_3D(LIGHT_POSITION_X(i)), 3); |
PUSH_DATAp(push, l->_Position, 3); |
BEGIN_NV04(push, NV20_3D(LIGHT_ATTENUATION_CONSTANT(i)), 3); |
PUSH_DATAf(push, l->ConstantAttenuation); |
PUSH_DATAf(push, l->LinearAttenuation); |
PUSH_DATAf(push, l->QuadraticAttenuation); |
} else { |
BEGIN_NV04(push, NV20_3D(LIGHT_DIRECTION_X(i)), 3); |
PUSH_DATAp(push, l->_VP_inf_norm, 3); |
BEGIN_NV04(push, NV20_3D(LIGHT_HALF_VECTOR_X(i)), 3); |
PUSH_DATAp(push, l->_h_inf_norm, 3); |
} |
if (l->_Flags & LIGHT_SPOT) { |
float k[7]; |
nv10_get_spot_coeff(l, k); |
BEGIN_NV04(push, NV20_3D(LIGHT_SPOT_CUTOFF(i, 0)), 7); |
PUSH_DATAp(push, k, 7); |
} |
} |
#define USE_COLOR_MATERIAL(attr, side) \ |
(ctx->Light.ColorMaterialEnabled && \ |
ctx->Light._ColorMaterialBitmask & (1 << MAT_ATTRIB_##attr(side))) |
void |
nv20_emit_material_ambient(struct gl_context *ctx, int emit) |
{ |
const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT; |
struct nouveau_pushbuf *push = context_push(ctx); |
float (*mat)[4] = ctx->Light.Material.Attrib; |
float c_scene[3], c_factor[3]; |
struct gl_light *l; |
if (USE_COLOR_MATERIAL(AMBIENT, side)) { |
COPY_3V(c_scene, mat[MAT_ATTRIB_EMISSION(side)]); |
COPY_3V(c_factor, ctx->Light.Model.Ambient); |
} else if (USE_COLOR_MATERIAL(EMISSION, side)) { |
SCALE_3V(c_scene, mat[MAT_ATTRIB_AMBIENT(side)], |
ctx->Light.Model.Ambient); |
ASSIGN_3V(c_factor, 1, 1, 1); |
} else { |
COPY_3V(c_scene, ctx->Light._BaseColor[side]); |
ZERO_3V(c_factor); |
} |
BEGIN_NV04(push, SUBC_3D(LIGHT_MODEL_AMBIENT_R(side)), 3); |
PUSH_DATAp(push, c_scene, 3); |
if (ctx->Light.ColorMaterialEnabled) { |
BEGIN_NV04(push, SUBC_3D(MATERIAL_FACTOR_R(side)), 3); |
PUSH_DATAp(push, c_factor, 3); |
} |
foreach(l, &ctx->Light.EnabledList) { |
const int i = l - ctx->Light.Light; |
float *c_light = (USE_COLOR_MATERIAL(AMBIENT, side) ? |
l->Ambient : |
l->_MatAmbient[side]); |
BEGIN_NV04(push, SUBC_3D(LIGHT_AMBIENT_R(side, i)), 3); |
PUSH_DATAp(push, c_light, 3); |
} |
} |
void |
nv20_emit_material_diffuse(struct gl_context *ctx, int emit) |
{ |
const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_DIFFUSE; |
struct nouveau_pushbuf *push = context_push(ctx); |
GLfloat (*mat)[4] = ctx->Light.Material.Attrib; |
struct gl_light *l; |
BEGIN_NV04(push, SUBC_3D(MATERIAL_FACTOR_A(side)), 1); |
PUSH_DATAf(push, mat[MAT_ATTRIB_DIFFUSE(side)][3]); |
foreach(l, &ctx->Light.EnabledList) { |
const int i = l - ctx->Light.Light; |
float *c_light = (USE_COLOR_MATERIAL(DIFFUSE, side) ? |
l->Diffuse : |
l->_MatDiffuse[side]); |
BEGIN_NV04(push, SUBC_3D(LIGHT_DIFFUSE_R(side, i)), 3); |
PUSH_DATAp(push, c_light, 3); |
} |
} |
void |
nv20_emit_material_specular(struct gl_context *ctx, int emit) |
{ |
const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_SPECULAR; |
struct nouveau_pushbuf *push = context_push(ctx); |
struct gl_light *l; |
foreach(l, &ctx->Light.EnabledList) { |
const int i = l - ctx->Light.Light; |
float *c_light = (USE_COLOR_MATERIAL(SPECULAR, side) ? |
l->Specular : |
l->_MatSpecular[side]); |
BEGIN_NV04(push, SUBC_3D(LIGHT_SPECULAR_R(side, i)), 3); |
PUSH_DATAp(push, c_light, 3); |
} |
} |
void |
nv20_emit_material_shininess(struct gl_context *ctx, int emit) |
{ |
const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_SHININESS; |
struct nouveau_pushbuf *push = context_push(ctx); |
float (*mat)[4] = ctx->Light.Material.Attrib; |
float k[6]; |
nv10_get_shininess_coeff( |
CLAMP(mat[MAT_ATTRIB_SHININESS(side)][0], 0, 1024), |
k); |
BEGIN_NV04(push, SUBC_3D(MATERIAL_SHININESS(side)), 6); |
PUSH_DATAp(push, k, 6); |
} |
void |
nv20_emit_modelview(struct gl_context *ctx, int emit) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
GLmatrix *m = ctx->ModelviewMatrixStack.Top; |
if (nctx->fallback != HWTNL) |
return; |
if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled || |
(ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { |
BEGIN_NV04(push, NV20_3D(MODELVIEW_MATRIX(0, 0)), 16); |
PUSH_DATAm(push, m->m); |
} |
if (ctx->Light.Enabled || |
(ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { |
int i, j; |
BEGIN_NV04(push, NV20_3D(INVERSE_MODELVIEW_MATRIX(0, 0)), 12); |
for (i = 0; i < 3; i++) |
for (j = 0; j < 4; j++) |
PUSH_DATAf(push, m->inv[4*i + j]); |
} |
} |
void |
nv20_emit_projection(struct gl_context *ctx, int emit) |
{ |
struct nouveau_context *nctx = to_nouveau_context(ctx); |
struct nouveau_pushbuf *push = context_push(ctx); |
GLmatrix m; |
_math_matrix_ctr(&m); |
get_viewport_scale(ctx, m.m); |
if (nctx->fallback == HWTNL) |
_math_matrix_mul_matrix(&m, &m, &ctx->_ModelProjectMatrix); |
BEGIN_NV04(push, NV20_3D(PROJECTION_MATRIX(0)), 16); |
PUSH_DATAm(push, m.m); |
_math_matrix_dtr(&m); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv_m2mf.xml.h |
---|
0,0 → 1,155 |
#ifndef NV_M2MF_XML |
#define NV_M2MF_XML |
/* Autogenerated file, DO NOT EDIT manually! |
This file was generated by the rules-ng-ng headergen tool in this git repository: |
http://0x04.net/cgit/index.cgi/rules-ng-ng |
git clone git://0x04.net/rules-ng-ng |
The rules-ng-ng source files this header was generated from are: |
- nv_m2mf.xml ( 2710 bytes, from 2010-11-01 00:28:46) |
- copyright.xml ( 6452 bytes, from 2010-11-15 15:10:58) |
- nv_object.xml ( 11547 bytes, from 2010-11-13 23:32:57) |
- nvchipsets.xml ( 3074 bytes, from 2010-11-13 23:32:57) |
- nv_defs.xml ( 4437 bytes, from 2010-11-01 00:28:46) |
Copyright (C) 2006-2010 by the following authors: |
- Artur Huillet <arthur.huillet@free.fr> (ahuillet) |
- Ben Skeggs (darktama, darktama_) |
- B. R. <koala_br@users.sourceforge.net> (koala_br) |
- Carlos Martin <carlosmn@users.sf.net> (carlosmn) |
- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr) |
- Dawid Gajownik <gajownik@users.sf.net> (gajownik) |
- Dmitry Baryshkov |
- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag) |
- EdB <edb_@users.sf.net> (edb_) |
- Erik Waling <erikwailing@users.sf.net> (erikwaling) |
- Francisco Jerez <currojerez@riseup.net> (curro) |
- imirkin <imirkin@users.sf.net> (imirkin) |
- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome) |
- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy) |
- Laurent Carlier <lordheavym@gmail.com> (lordheavy) |
- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1) |
- Maarten Maathuis <madman2003@gmail.com> (stillunknown) |
- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin) |
- Mark Carey <mark.carey@gmail.com> (careym) |
- Matthieu Castet <matthieu.castet@parrot.com> (mat-c) |
- nvidiaman <nvidiaman@users.sf.net> (nvidiaman) |
- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata) |
- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen) |
- Peter Popov <ironpeter@users.sf.net> (ironpeter) |
- Richard Hughes <hughsient@users.sf.net> (hughsient) |
- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar) |
- Serge Martin |
- Simon Raffeiner |
- Stephane Loeuillet <leroutier@users.sf.net> (leroutier) |
- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu) |
- sturmflut <sturmflut@users.sf.net> (sturmflut) |
- Sylvain Munaut <tnt@246tNt.com> |
- Victor Stinner <victor.stinner@haypocalc.com> (haypo) |
- Wladmir van der Laan <laanwj@gmail.com> (miathan6) |
- Younes Manton <younes.m@gmail.com> (ymanton) |
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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
*/ |
#define NV04_M2MF_DMA_NOTIFY 0x00000180 |
#define NV04_M2MF_DMA_BUFFER_IN 0x00000184 |
#define NV04_M2MF_DMA_BUFFER_OUT 0x00000188 |
#define NV50_M2MF_LINEAR_IN 0x00000200 |
#define NV50_M2MF_TILING_MODE_IN 0x00000204 |
#define NV50_M2MF_TILING_PITCH_IN 0x00000208 |
#define NV50_M2MF_TILING_HEIGHT_IN 0x0000020c |
#define NV50_M2MF_TILING_DEPTH_IN 0x00000210 |
#define NV50_M2MF_TILING_POSITION_IN_Z 0x00000214 |
#define NV50_M2MF_TILING_POSITION_IN 0x00000218 |
#define NV50_M2MF_TILING_POSITION_IN_X__MASK 0x0000ffff |
#define NV50_M2MF_TILING_POSITION_IN_X__SHIFT 0 |
#define NV50_M2MF_TILING_POSITION_IN_Y__MASK 0xffff0000 |
#define NV50_M2MF_TILING_POSITION_IN_Y__SHIFT 16 |
#define NV50_M2MF_LINEAR_OUT 0x0000021c |
#define NV50_M2MF_TILING_MODE_OUT 0x00000220 |
#define NV50_M2MF_TILING_PITCH_OUT 0x00000224 |
#define NV50_M2MF_TILING_HEIGHT_OUT 0x00000228 |
#define NV50_M2MF_TILING_DEPTH_OUT 0x0000022c |
#define NV50_M2MF_TILING_POSITION_OUT_Z 0x00000230 |
#define NV50_M2MF_TILING_POSITION_OUT 0x00000234 |
#define NV50_M2MF_TILING_POSITION_OUT_X__MASK 0x0000ffff |
#define NV50_M2MF_TILING_POSITION_OUT_X__SHIFT 0 |
#define NV50_M2MF_TILING_POSITION_OUT_Y__MASK 0xffff0000 |
#define NV50_M2MF_TILING_POSITION_OUT_Y__SHIFT 16 |
#define NV50_M2MF_OFFSET_IN_HIGH 0x00000238 |
#define NV50_M2MF_OFFSET_OUT_HIGH 0x0000023c |
#define NV04_M2MF_OFFSET_IN 0x0000030c |
#define NV04_M2MF_OFFSET_OUT 0x00000310 |
#define NV04_M2MF_PITCH_IN 0x00000314 |
#define NV04_M2MF_PITCH_OUT 0x00000318 |
#define NV04_M2MF_LINE_LENGTH_IN 0x0000031c |
#define NV04_M2MF_LINE_COUNT 0x00000320 |
#define NV04_M2MF_FORMAT 0x00000324 |
#define NV04_M2MF_FORMAT_INPUT_INC__MASK 0x000000ff |
#define NV04_M2MF_FORMAT_INPUT_INC__SHIFT 0 |
#define NV04_M2MF_FORMAT_INPUT_INC_1 0x00000001 |
#define NV04_M2MF_FORMAT_INPUT_INC_2 0x00000002 |
#define NV04_M2MF_FORMAT_INPUT_INC_4 0x00000004 |
#define NV50_M2MF_FORMAT_INPUT_INC_8 0x00000008 |
#define NV50_M2MF_FORMAT_INPUT_INC_16 0x00000010 |
#define NV04_M2MF_FORMAT_OUTPUT_INC__MASK 0x0000ff00 |
#define NV04_M2MF_FORMAT_OUTPUT_INC__SHIFT 8 |
#define NV04_M2MF_FORMAT_OUTPUT_INC_1 0x00000100 |
#define NV04_M2MF_FORMAT_OUTPUT_INC_2 0x00000200 |
#define NV04_M2MF_FORMAT_OUTPUT_INC_4 0x00000400 |
#define NV50_M2MF_FORMAT_OUTPUT_INC_8 0x00000800 |
#define NV50_M2MF_FORMAT_OUTPUT_INC_16 0x00001000 |
#define NV04_M2MF_BUF_NOTIFY 0x00000328 |
#endif /* NV_M2MF_XML */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/nouveau/nv_object.xml.h |
---|
0,0 → 1,301 |
#ifndef _HOME_SKEGGSB_GIT_ENVYTOOLS_RNNDB_NV_OBJECT_XML |
#define _HOME_SKEGGSB_GIT_ENVYTOOLS_RNNDB_NV_OBJECT_XML |
/* WARNING ABOUT NOT EDITING AUTOGENERATED FILE IGNORED, _CLASS SUFFIX HAS |
* BEEN ADDED TO ALL THE OBJECT CLASS DEFINITIONS TO AVOID CONFLICTS WITH |
* THE RING MACROS WE WANT TO USE |
*/ |
/* Autogenerated file, DO NOT EDIT manually! |
This file was generated by the rules-ng-ng headergen tool in this git repository: |
http://0x04.net/cgit/index.cgi/rules-ng-ng |
git clone git://0x04.net/rules-ng-ng |
The rules-ng-ng source files this header was generated from are: |
- /home/skeggsb/git/envytools/rnndb/nv_object.xml ( 12672 bytes, from 2011-10-22 08:01:09) |
- /home/skeggsb/git/envytools/rnndb/copyright.xml ( 6452 bytes, from 2011-10-22 08:01:09) |
- /home/skeggsb/git/envytools/rnndb/nvchipsets.xml ( 3617 bytes, from 2011-10-22 08:01:09) |
- /home/skeggsb/git/envytools/rnndb/nv_defs.xml ( 4437 bytes, from 2011-10-22 08:01:09) |
- /home/skeggsb/git/envytools/rnndb/nv50_defs.xml ( 5468 bytes, from 2011-10-22 08:01:09) |
Copyright (C) 2006-2011 by the following authors: |
- Artur Huillet <arthur.huillet@free.fr> (ahuillet) |
- Ben Skeggs (darktama, darktama_) |
- B. R. <koala_br@users.sourceforge.net> (koala_br) |
- Carlos Martin <carlosmn@users.sf.net> (carlosmn) |
- Christoph Bumiller <e0425955@student.tuwien.ac.at> (calim, chrisbmr) |
- Dawid Gajownik <gajownik@users.sf.net> (gajownik) |
- Dmitry Baryshkov |
- Dmitry Eremin-Solenikov <lumag@users.sf.net> (lumag) |
- EdB <edb_@users.sf.net> (edb_) |
- Erik Waling <erikwailing@users.sf.net> (erikwaling) |
- Francisco Jerez <currojerez@riseup.net> (curro) |
- imirkin <imirkin@users.sf.net> (imirkin) |
- jb17bsome <jb17bsome@bellsouth.net> (jb17bsome) |
- Jeremy Kolb <kjeremy@users.sf.net> (kjeremy) |
- Laurent Carlier <lordheavym@gmail.com> (lordheavy) |
- Luca Barbieri <luca@luca-barbieri.com> (lb, lb1) |
- Maarten Maathuis <madman2003@gmail.com> (stillunknown) |
- Marcin Kościelnicki <koriakin@0x04.net> (mwk, koriakin) |
- Mark Carey <mark.carey@gmail.com> (careym) |
- Matthieu Castet <matthieu.castet@parrot.com> (mat-c) |
- nvidiaman <nvidiaman@users.sf.net> (nvidiaman) |
- Patrice Mandin <patmandin@gmail.com> (pmandin, pmdata) |
- Pekka Paalanen <pq@iki.fi> (pq, ppaalanen) |
- Peter Popov <ironpeter@users.sf.net> (ironpeter) |
- Richard Hughes <hughsient@users.sf.net> (hughsient) |
- Rudi Cilibrasi <cilibrar@users.sf.net> (cilibrar) |
- Serge Martin |
- Simon Raffeiner |
- Stephane Loeuillet <leroutier@users.sf.net> (leroutier) |
- Stephane Marchesin <stephane.marchesin@gmail.com> (marcheu) |
- sturmflut <sturmflut@users.sf.net> (sturmflut) |
- Sylvain Munaut <tnt@246tNt.com> |
- Victor Stinner <victor.stinner@haypocalc.com> (haypo) |
- Wladmir van der Laan <laanwj@gmail.com> (miathan6) |
- Younes Manton <younes.m@gmail.com> (ymanton) |
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 COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
*/ |
#define NV01_DMA_FROM_MEMORY_CLASS 0x00000002 |
#define NV01_DMA_TO_MEMORY_CLASS 0x00000003 |
#define NV01_NULL_CLASS 0x00000030 |
#define NV03_DMA_IN_MEMORY_CLASS 0x0000003d |
#define NV01_OP_CLIP_CLASS 0x00000010 |
#define NV01_OP_BLEND_AND_CLASS 0x00000011 |
#define NV01_BETA_CLASS 0x00000012 |
#define NV04_BETA4_CLASS 0x00000072 |
#define NV01_OP_ROP_AND_CLASS 0x00000013 |
#define NV01_ROP_CLASS 0x00000014 |
#define NV03_ROP_CLASS 0x00000043 |
#define NV01_OP_CHROMA_CLASS 0x00000015 |
#define NV01_OP_PLANE_SWITCH_CLASS 0x00000016 |
#define NV01_CHROMA_CLASS 0x00000017 |
#define NV04_CHROMA_CLASS 0x00000057 |
#define NV01_PATTERN_CLASS 0x00000018 |
#define NV04_PATTERN_CLASS 0x00000044 |
#define NV01_CLIP_CLASS 0x00000019 |
#define NV01_OP_SRCCOPY_AND_CLASS 0x00000064 |
#define NV03_OP_SRCCOPY_CLASS 0x00000065 |
#define NV04_OP_SRCCOPY_PREMULT_CLASS 0x00000066 |
#define NV04_OP_BLEND_PREMULT_CLASS 0x00000067 |
#define NV01_POINT_CLASS 0x0000001a |
#define NV01_LINE_CLASS 0x0000001b |
#define NV01_LIN_CLASS 0x0000001c |
#define NV04_LIN_CLASS 0x0000005c |
#define NV30_LIN_CLASS 0x0000035c |
#define NV40_LIN_CLASS 0x0000305c |
#define NV01_TRI_CLASS 0x0000001d |
#define NV04_TRI_CLASS 0x0000005d |
#define NV01_RECT_CLASS 0x0000001e |
#define NV04_RECT_CLASS 0x0000005e |
#define NV01_BLIT_CLASS 0x0000001f |
#define NV04_BLIT_CLASS 0x0000005f |
#define NV15_BLIT_CLASS 0x0000009f |
#define NV01_IFROMMEM_CLASS 0x00000020 |
#define NV01_IFC_CLASS 0x00000021 |
#define NV04_IFC_CLASS 0x00000061 |
#define NV05_IFC_CLASS 0x00000065 |
#define NV10_IFC_CLASS 0x0000008a |
#define NV30_IFC_CLASS 0x0000038a |
#define NV40_IFC_CLASS 0x0000308a |
#define NV01_BITMAP_CLASS 0x00000022 |
#define NV01_ITOMEM_CLASS 0x00000025 |
#define NV03_SIFC_CLASS 0x00000036 |
#define NV04_SIFC_CLASS 0x00000076 |
#define NV05_SIFC_CLASS 0x00000066 |
#define NV30_SIFC_CLASS 0x00000366 |
#define NV40_SIFC_CLASS 0x00003066 |
#define NV03_SIFM_CLASS 0x00000037 |
#define NV04_SIFM_CLASS 0x00000077 |
#define NV05_SIFM_CLASS 0x00000063 |
#define NV10_SIFM_CLASS 0x00000089 |
#define NV30_SIFM_CLASS 0x00000389 |
#define NV40_SIFM_CLASS 0x00003089 |
#define NV50_SIFM_CLASS 0x00005089 |
#define NV03_SYFM_CLASS 0x00000038 |
#define NV03_GDI_CLASS 0x0000004b |
#define NV04_GDI_CLASS 0x0000004a |
#define NV04_SURFACE_SWZ_CLASS 0x00000052 |
#define NV20_SURFACE_SWZ_CLASS 0x0000009e |
#define NV30_SURFACE_SWZ_CLASS 0x0000039e |
#define NV40_SURFACE_SWZ_CLASS 0x0000309e |
#define NV03_SURFACE_DST_CLASS 0x00000058 |
#define NV03_SURFACE_SRC_CLASS 0x00000059 |
#define NV04_SURFACE_2D_CLASS 0x00000042 |
#define NV10_SURFACE_2D_CLASS 0x00000062 |
#define NV30_SURFACE_2D_CLASS 0x00000362 |
#define NV40_SURFACE_2D_CLASS 0x00003062 |
#define NV50_SURFACE_2D_CLASS 0x00005062 |
#define NV04_INDEX_CLASS 0x00000060 |
#define NV05_INDEX_CLASS 0x00000064 |
#define NV30_INDEX_CLASS 0x00000364 |
#define NV40_INDEX_CLASS 0x00003064 |
#define NV10_TEXUPLOAD_CLASS 0x0000007b |
#define NV30_TEXUPLOAD_CLASS 0x0000037b |
#define NV40_TEXUPLOAD_CLASS 0x0000307b |
#define NV04_DVD_SUBPICTURE_CLASS 0x00000038 |
#define NV10_DVD_SUBPICTURE_CLASS 0x00000088 |
#define NV03_M2MF_CLASS 0x00000039 |
#define NV50_M2MF_CLASS 0x00005039 |
#define NVC0_M2MF_CLASS 0x00009039 |
#define NV03_SURFACE_COLOR_CLASS 0x0000005a |
#define NV03_SURFACE_ZETA_CLASS 0x0000005b |
#define NV03_TEXTURED_TRIANGLE_CLASS 0x00000048 |
#define NV04_TEXTURED_TRIANGLE_CLASS 0x00000054 |
#define NV10_TEXTURED_TRIANGLE_CLASS 0x00000094 |
#define NV04_SURFACE_3D_CLASS 0x00000053 |
#define NV10_SURFACE_3D_CLASS 0x00000093 |
#define NV04_MULTITEX_TRIANGLE_CLASS 0x00000055 |
#define NV10_MULTITEX_TRIANGLE_CLASS 0x00000095 |
#define NV10_3D_CLASS 0x00000056 |
#define NV15_3D_CLASS 0x00000096 |
#define NV11_3D_CLASS 0x00000098 |
#define NV17_3D_CLASS 0x00000099 |
#define NV20_3D_CLASS 0x00000097 |
#define NV25_3D_CLASS 0x00000597 |
#define NV30_3D_CLASS 0x00000397 |
#define NV35_3D_CLASS 0x00000497 |
#define NV34_3D_CLASS 0x00000697 |
#define NV40_3D_CLASS 0x00004097 |
#define NV44_3D_CLASS 0x00004497 |
#define NV50_3D_CLASS 0x00005097 |
#define NV84_3D_CLASS 0x00008297 |
#define NVA0_3D_CLASS 0x00008397 |
#define NVA3_3D_CLASS 0x00008597 |
#define NVAF_3D_CLASS 0x00008697 |
#define NVC0_3D_CLASS 0x00009097 |
#define NVC1_3D_CLASS 0x00009197 |
#define NVC8_3D_CLASS 0x00009297 |
#define NV50_2D_CLASS 0x0000502d |
#define NVC0_2D_CLASS 0x0000902d |
#define NV50_COMPUTE_CLASS 0x000050c0 |
#define NVA3_COMPUTE_CLASS 0x000085c0 |
#define NVC0_COMPUTE_CLASS 0x000090c0 |
#define NVC8_COMPUTE_CLASS 0x000092c0 |
#define NV84_CRYPT_CLASS 0x000074c1 |
#define BLOB_NVC0_PCOPY1_CLASS 0x000090b8 |
#define BLOB_NVC0_PCOPY0_CLASS 0x000090b5 |
#define NV31_MPEG_CLASS 0x00003174 |
#define NV84_MPEG_CLASS 0x00008274 |
#define NV01_SUBCHAN__SIZE 0x00008000 |
#define NV01_SUBCHAN 0x00000000 |
#define NV01_SUBCHAN_OBJECT 0x00000000 |
#define NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH 0x00000010 |
#define NV84_SUBCHAN_SEMAPHORE_ADDRESS_LOW 0x00000014 |
#define NV84_SUBCHAN_SEMAPHORE_SEQUENCE 0x00000018 |
#define NV84_SUBCHAN_SEMAPHORE_TRIGGER 0x0000001c |
#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL 0x00000001 |
#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002 |
#define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004 |
#define NV84_SUBCHAN_NOTIFY_INTR 0x00000020 |
#define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024 |
#define NV10_SUBCHAN_REF_CNT 0x00000050 |
#define NV11_SUBCHAN_DMA_SEMAPHORE 0x00000060 |
#define NV11_SUBCHAN_SEMAPHORE_OFFSET 0x00000064 |
#define NV11_SUBCHAN_SEMAPHORE_ACQUIRE 0x00000068 |
#define NV11_SUBCHAN_SEMAPHORE_RELEASE 0x0000006c |
#define NV40_SUBCHAN_YIELD 0x00000080 |
#define NV01_GRAPH 0x00000000 |
#define NV04_GRAPH_NOP 0x00000100 |
#define NV04_GRAPH_NOTIFY 0x00000104 |
#define NV04_GRAPH_NOTIFY_WRITE 0x00000000 |
#define NV04_GRAPH_NOTIFY_WRITE_AND_AWAKEN 0x00000001 |
#define NVC0_GRAPH_NOTIFY_ADDRESS_HIGH 0x00000104 |
#define NVC0_GRAPH_NOTIFY_ADDRESS_LOW 0x00000108 |
#define NVC0_GRAPH_NOTIFY 0x0000010c |
#define NVC0_GRAPH_NOTIFY_WRITE 0x00000000 |
#define NVC0_GRAPH_NOTIFY_WRITE_AND_AWAKEN 0x00000001 |
#define NV50_GRAPH_SERIALIZE 0x00000110 |
#define NVC0_GRAPH_MACRO_UPLOAD_POS 0x00000114 |
#define NVC0_GRAPH_MACRO_UPLOAD_DATA 0x00000118 |
#define NVC0_GRAPH_MACRO_ID 0x0000011c |
#define NVC0_GRAPH_MACRO_POS 0x00000120 |
#define NVA3_GRAPH_UNK0120 0x00000120 |
#define NVA3_GRAPH_UNK0124 0x00000124 |
#define NVC0_GRAPH_UNK0124 0x00000124 |
#define NVC0_GRAPH_COND_ADDRESS_HIGH 0x00000130 |
#define NVC0_GRAPH_COND_ADDRESS_LOW 0x00000134 |
#define NVC0_GRAPH_COND_MODE 0x00000138 |
#define NVC0_GRAPH_COND_MODE_NEVER 0x00000000 |
#define NVC0_GRAPH_COND_MODE_ALWAYS 0x00000001 |
#define NVC0_GRAPH_COND_MODE_RES_NON_ZERO 0x00000002 |
#define NVC0_GRAPH_COND_MODE_EQUAL 0x00000003 |
#define NVC0_GRAPH_COND_MODE_NOT_EQUAL 0x00000004 |
#define NVC0_GRAPH_UNK013C 0x0000013c |
#define NV40_GRAPH_PM_TRIGGER 0x00000140 |
#define NVC0_GRAPH_UNK0150 0x00000150 |
#define NVC0_GRAPH_UNK0154 0x00000154 |
#define NVC0_GRAPH_SCRATCH(i0) (0x00003400 + 0x4*(i0)) |
#define NVC0_GRAPH_SCRATCH__ESIZE 0x00000004 |
#define NVC0_GRAPH_SCRATCH__LEN 0x00000080 |
#define NVC0_GRAPH_MACRO(i0) (0x00003800 + 0x8*(i0)) |
#define NVC0_GRAPH_MACRO__ESIZE 0x00000008 |
#define NVC0_GRAPH_MACRO__LEN 0x00000080 |
#define NVC0_GRAPH_MACRO_PARAM(i0) (0x00003804 + 0x8*(i0)) |
#define NVC0_GRAPH_MACRO_PARAM__ESIZE 0x00000008 |
#define NVC0_GRAPH_MACRO_PARAM__LEN 0x00000080 |
#endif /* _HOME_SKEGGSB_GIT_ENVYTOOLS_RNNDB_NV_OBJECT_XML */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/Doxyfile |
---|
0,0 → 1,232 |
# Doxyfile 1.3.2-Gideon |
#--------------------------------------------------------------------------- |
# General configuration options |
#--------------------------------------------------------------------------- |
PROJECT_NAME = r200 |
PROJECT_NUMBER = $VERSION$ |
OUTPUT_DIRECTORY = |
OUTPUT_LANGUAGE = English |
USE_WINDOWS_ENCODING = NO |
EXTRACT_ALL = NO |
EXTRACT_PRIVATE = NO |
EXTRACT_STATIC = NO |
EXTRACT_LOCAL_CLASSES = YES |
HIDE_UNDOC_MEMBERS = NO |
HIDE_UNDOC_CLASSES = NO |
HIDE_FRIEND_COMPOUNDS = NO |
HIDE_IN_BODY_DOCS = NO |
BRIEF_MEMBER_DESC = YES |
REPEAT_BRIEF = YES |
ALWAYS_DETAILED_SEC = NO |
INLINE_INHERITED_MEMB = NO |
FULL_PATH_NAMES = NO |
STRIP_FROM_PATH = |
INTERNAL_DOCS = NO |
CASE_SENSE_NAMES = YES |
SHORT_NAMES = NO |
HIDE_SCOPE_NAMES = NO |
SHOW_INCLUDE_FILES = YES |
JAVADOC_AUTOBRIEF = NO |
MULTILINE_CPP_IS_BRIEF = NO |
DETAILS_AT_TOP = NO |
INHERIT_DOCS = YES |
INLINE_INFO = YES |
SORT_MEMBER_DOCS = YES |
DISTRIBUTE_GROUP_DOC = NO |
TAB_SIZE = 8 |
GENERATE_TODOLIST = YES |
GENERATE_TESTLIST = YES |
GENERATE_BUGLIST = YES |
GENERATE_DEPRECATEDLIST= YES |
ALIASES = |
ENABLED_SECTIONS = |
MAX_INITIALIZER_LINES = 30 |
OPTIMIZE_OUTPUT_FOR_C = NO |
OPTIMIZE_OUTPUT_JAVA = NO |
SHOW_USED_FILES = YES |
#--------------------------------------------------------------------------- |
# configuration options related to warning and progress messages |
#--------------------------------------------------------------------------- |
QUIET = NO |
WARNINGS = YES |
WARN_IF_UNDOCUMENTED = YES |
WARN_IF_DOC_ERROR = YES |
WARN_FORMAT = "$file:$line: $text" |
WARN_LOGFILE = |
#--------------------------------------------------------------------------- |
# configuration options related to the input files |
#--------------------------------------------------------------------------- |
INPUT = /home/temp/Mesa/src/drv/r200 |
FILE_PATTERNS = *.c \ |
*.cc \ |
*.cxx \ |
*.cpp \ |
*.c++ \ |
*.java \ |
*.ii \ |
*.ixx \ |
*.ipp \ |
*.i++ \ |
*.inl \ |
*.h \ |
*.hh \ |
*.hxx \ |
*.hpp \ |
*.h++ \ |
*.idl \ |
*.odl \ |
*.cs \ |
*.C \ |
*.H \ |
*.tlh \ |
*.diff \ |
*.patch \ |
*.moc \ |
*.xpm |
RECURSIVE = yes |
EXCLUDE = |
EXCLUDE_SYMLINKS = NO |
EXCLUDE_PATTERNS = |
EXAMPLE_PATH = |
EXAMPLE_PATTERNS = * |
EXAMPLE_RECURSIVE = NO |
IMAGE_PATH = |
INPUT_FILTER = |
FILTER_SOURCE_FILES = NO |
#--------------------------------------------------------------------------- |
# configuration options related to source browsing |
#--------------------------------------------------------------------------- |
SOURCE_BROWSER = NO |
INLINE_SOURCES = NO |
STRIP_CODE_COMMENTS = YES |
REFERENCED_BY_RELATION = YES |
REFERENCES_RELATION = YES |
VERBATIM_HEADERS = YES |
#--------------------------------------------------------------------------- |
# configuration options related to the alphabetical class index |
#--------------------------------------------------------------------------- |
ALPHABETICAL_INDEX = NO |
COLS_IN_ALPHA_INDEX = 5 |
IGNORE_PREFIX = |
#--------------------------------------------------------------------------- |
# configuration options related to the HTML output |
#--------------------------------------------------------------------------- |
GENERATE_HTML = YES |
HTML_OUTPUT = html |
HTML_FILE_EXTENSION = .html |
HTML_HEADER = |
HTML_FOOTER = |
HTML_STYLESHEET = |
HTML_ALIGN_MEMBERS = YES |
GENERATE_HTMLHELP = NO |
CHM_FILE = |
HHC_LOCATION = |
GENERATE_CHI = NO |
BINARY_TOC = NO |
TOC_EXPAND = NO |
DISABLE_INDEX = NO |
ENUM_VALUES_PER_LINE = 4 |
GENERATE_TREEVIEW = NO |
TREEVIEW_WIDTH = 250 |
#--------------------------------------------------------------------------- |
# configuration options related to the LaTeX output |
#--------------------------------------------------------------------------- |
GENERATE_LATEX = YES |
LATEX_OUTPUT = latex |
LATEX_CMD_NAME = latex |
MAKEINDEX_CMD_NAME = makeindex |
COMPACT_LATEX = NO |
PAPER_TYPE = a4wide |
EXTRA_PACKAGES = |
LATEX_HEADER = |
PDF_HYPERLINKS = NO |
USE_PDFLATEX = NO |
LATEX_BATCHMODE = NO |
LATEX_HIDE_INDICES = NO |
#--------------------------------------------------------------------------- |
# configuration options related to the RTF output |
#--------------------------------------------------------------------------- |
GENERATE_RTF = NO |
RTF_OUTPUT = rtf |
COMPACT_RTF = NO |
RTF_HYPERLINKS = NO |
RTF_STYLESHEET_FILE = |
RTF_EXTENSIONS_FILE = |
#--------------------------------------------------------------------------- |
# configuration options related to the man page output |
#--------------------------------------------------------------------------- |
GENERATE_MAN = NO |
MAN_OUTPUT = man |
MAN_EXTENSION = .3 |
MAN_LINKS = NO |
#--------------------------------------------------------------------------- |
# configuration options related to the XML output |
#--------------------------------------------------------------------------- |
GENERATE_XML = yes |
XML_OUTPUT = xml |
XML_SCHEMA = |
XML_DTD = |
#--------------------------------------------------------------------------- |
# configuration options for the AutoGen Definitions output |
#--------------------------------------------------------------------------- |
GENERATE_AUTOGEN_DEF = NO |
#--------------------------------------------------------------------------- |
# configuration options related to the Perl module output |
#--------------------------------------------------------------------------- |
GENERATE_PERLMOD = NO |
PERLMOD_LATEX = NO |
PERLMOD_PRETTY = YES |
PERLMOD_MAKEVAR_PREFIX = |
#--------------------------------------------------------------------------- |
# Configuration options related to the preprocessor |
#--------------------------------------------------------------------------- |
ENABLE_PREPROCESSING = YES |
MACRO_EXPANSION = NO |
EXPAND_ONLY_PREDEF = NO |
SEARCH_INCLUDES = YES |
INCLUDE_PATH = |
INCLUDE_FILE_PATTERNS = |
PREDEFINED = |
EXPAND_AS_DEFINED = |
SKIP_FUNCTION_MACROS = YES |
#--------------------------------------------------------------------------- |
# Configuration::addtions related to external references |
#--------------------------------------------------------------------------- |
TAGFILES = |
GENERATE_TAGFILE = |
ALLEXTERNALS = NO |
EXTERNAL_GROUPS = YES |
PERL_PATH = /usr/bin/perl |
#--------------------------------------------------------------------------- |
# Configuration options related to the dot tool |
#--------------------------------------------------------------------------- |
CLASS_DIAGRAMS = YES |
HIDE_UNDOC_RELATIONS = YES |
HAVE_DOT = NO |
CLASS_GRAPH = YES |
COLLABORATION_GRAPH = YES |
UML_LOOK = NO |
TEMPLATE_RELATIONS = NO |
INCLUDE_GRAPH = YES |
INCLUDED_BY_GRAPH = YES |
CALL_GRAPH = NO |
GRAPHICAL_HIERARCHY = YES |
DOT_IMAGE_FORMAT = png |
DOT_PATH = |
DOTFILE_DIRS = |
MAX_DOT_GRAPH_WIDTH = 1024 |
MAX_DOT_GRAPH_HEIGHT = 1024 |
MAX_DOT_GRAPH_DEPTH = 1000 |
GENERATE_LEGEND = YES |
DOT_CLEANUP = YES |
#--------------------------------------------------------------------------- |
# Configuration::addtions related to the search engine |
#--------------------------------------------------------------------------- |
SEARCHENGINE = NO |
CGI_NAME = search.cgi |
CGI_URL = |
DOC_URL = |
DOC_ABSPATH = |
BIN_ABSPATH = /usr/local/bin/ |
EXT_DOC_PATHS = |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/Makefile.am |
---|
0,0 → 1,58 |
# Copyright © 2012 Matt Turner <mattst88@gmail.com> |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
# copy of this software and associated documentation files (the "Software"), |
# to deal in the Software without restriction, including without limitation |
# the rights to use, copy, modify, merge, publish, distribute, sublicense, |
# and/or sell copies of the Software, and to permit persons to whom the |
# Software is furnished to do so, subject to the following conditions: |
# |
# The above copyright notice and this permission notice (including the next |
# paragraph) shall be included in all copies or substantial portions of the |
# Software. |
# |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
# IN THE SOFTWARE. |
include Makefile.sources |
AM_CFLAGS = \ |
-DRADEON_R200 \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
-I$(top_srcdir)/src/mesa/drivers/dri/common \ |
-I$(top_srcdir)/src/mesa/drivers/dri/r200/server \ |
-I$(top_builddir)/src/mesa/drivers/dri/common \ |
$(DEFINES) \ |
$(VISIBILITY_CFLAGS) \ |
$(RADEON_CFLAGS) |
dridir = $(DRI_DRIVER_INSTALL_DIR) |
if HAVE_R200_DRI |
dri_LTLIBRARIES = r200_dri.la |
endif |
r200_dri_la_SOURCES = \ |
$(R200_C_FILES) |
r200_dri_la_LDFLAGS = -module -avoid-version -shared |
r200_dri_la_LIBADD = \ |
../common/libdricommon.la \ |
$(DRI_LIB_DEPS) \ |
$(RADEON_LIBS) |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
all-local: r200_dri.la |
$(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
ln -f .libs/r200_dri.so $(top_builddir)/$(LIB_DIR)/r200_dri.so; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/Makefile.in |
---|
0,0 → 1,928 |
# 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 Matt Turner <mattst88@gmail.com> |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
# copy of this software and associated documentation files (the "Software"), |
# to deal in the Software without restriction, including without limitation |
# the rights to use, copy, modify, merge, publish, distribute, 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 = $(srcdir)/Makefile.sources $(srcdir)/Makefile.in \ |
$(srcdir)/Makefile.am $(top_srcdir)/bin/depcomp |
subdir = src/mesa/drivers/dri/r200 |
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 = |
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; |
am__vpath_adj = case $$p in \ |
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |
*) f=$$p;; \ |
esac; |
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; |
am__install_max = 40 |
am__nobase_strip_setup = \ |
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` |
am__nobase_strip = \ |
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" |
am__nobase_list = $(am__nobase_strip_setup); \ |
for p in $$list; do echo "$$p $$p"; done | \ |
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ |
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ |
if (++n[$$2] == $(am__install_max)) \ |
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ |
END { for (dir in files) print dir, files[dir] }' |
am__base_list = \ |
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ |
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' |
am__uninstall_files_from_dir = { \ |
test -z "$$files" \ |
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ |
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \ |
$(am__cd) "$$dir" && rm -f $$files; }; \ |
} |
am__installdirs = "$(DESTDIR)$(dridir)" |
LTLIBRARIES = $(dri_LTLIBRARIES) |
am__DEPENDENCIES_1 = |
r200_dri_la_DEPENDENCIES = ../common/libdricommon.la \ |
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) |
am__objects_1 = radeon_buffer_objects.lo radeon_common_context.lo \ |
radeon_common.lo radeon_dma.lo radeon_debug.lo radeon_fbo.lo \ |
radeon_fog.lo radeon_mipmap_tree.lo radeon_pixel_read.lo \ |
radeon_queryobj.lo radeon_span.lo radeon_texture.lo \ |
radeon_tex_copy.lo radeon_tile.lo |
am__objects_2 = r200_context.lo r200_ioctl.lo r200_state.lo \ |
r200_state_init.lo r200_cmdbuf.lo r200_tex.lo r200_texstate.lo \ |
r200_tcl.lo r200_swtcl.lo r200_maos.lo r200_sanity.lo \ |
r200_fragshader.lo r200_vertprog.lo r200_blit.lo \ |
radeon_screen.lo |
am__objects_3 = $(am__objects_1) $(am__objects_2) |
am_r200_dri_la_OBJECTS = $(am__objects_3) |
r200_dri_la_OBJECTS = $(am_r200_dri_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 = |
r200_dri_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ |
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ |
$(r200_dri_la_LDFLAGS) $(LDFLAGS) -o $@ |
@HAVE_R200_DRI_TRUE@am_r200_dri_la_rpath = -rpath $(dridir) |
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 = $(r200_dri_la_SOURCES) |
DIST_SOURCES = $(r200_dri_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@ |
R200_COMMON_FILES = \ |
radeon_buffer_objects.c \ |
radeon_common_context.c \ |
radeon_common.c \ |
radeon_dma.c \ |
radeon_debug.c \ |
radeon_fbo.c \ |
radeon_fog.c \ |
radeon_mipmap_tree.c \ |
radeon_pixel_read.c \ |
radeon_queryobj.c \ |
radeon_span.c \ |
radeon_texture.c \ |
radeon_tex_copy.c \ |
radeon_tile.c |
DRIVER_FILES = \ |
r200_context.c \ |
r200_ioctl.c \ |
r200_state.c \ |
r200_state_init.c \ |
r200_cmdbuf.c \ |
r200_tex.c \ |
r200_texstate.c \ |
r200_tcl.c \ |
r200_swtcl.c \ |
r200_maos.c \ |
r200_sanity.c \ |
r200_fragshader.c \ |
r200_vertprog.c \ |
r200_blit.c \ |
radeon_screen.c |
R200_C_FILES = $(R200_COMMON_FILES) $(DRIVER_FILES) |
AM_CFLAGS = \ |
-DRADEON_R200 \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
-I$(top_srcdir)/src/mesa/drivers/dri/common \ |
-I$(top_srcdir)/src/mesa/drivers/dri/r200/server \ |
-I$(top_builddir)/src/mesa/drivers/dri/common \ |
$(DEFINES) \ |
$(VISIBILITY_CFLAGS) \ |
$(RADEON_CFLAGS) |
dridir = $(DRI_DRIVER_INSTALL_DIR) |
@HAVE_R200_DRI_TRUE@dri_LTLIBRARIES = r200_dri.la |
r200_dri_la_SOURCES = \ |
$(R200_C_FILES) |
r200_dri_la_LDFLAGS = -module -avoid-version -shared |
r200_dri_la_LIBADD = \ |
../common/libdricommon.la \ |
$(DRI_LIB_DEPS) \ |
$(RADEON_LIBS) |
all: all-am |
.SUFFIXES: |
.SUFFIXES: .c .lo .o .obj |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(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/mesa/drivers/dri/r200/Makefile'; \ |
$(am__cd) $(top_srcdir) && \ |
$(AUTOMAKE) --foreign src/mesa/drivers/dri/r200/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; |
$(srcdir)/Makefile.sources: |
$(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): |
install-driLTLIBRARIES: $(dri_LTLIBRARIES) |
@$(NORMAL_INSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
list2=; for p in $$list; do \ |
if test -f $$p; then \ |
list2="$$list2 $$p"; \ |
else :; fi; \ |
done; \ |
test -z "$$list2" || { \ |
echo " $(MKDIR_P) '$(DESTDIR)$(dridir)'"; \ |
$(MKDIR_P) "$(DESTDIR)$(dridir)" || exit 1; \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(dridir)'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(dridir)"; \ |
} |
uninstall-driLTLIBRARIES: |
@$(NORMAL_UNINSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
for p in $$list; do \ |
$(am__strip_dir) \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(dridir)/$$f'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(dridir)/$$f"; \ |
done |
clean-driLTLIBRARIES: |
-test -z "$(dri_LTLIBRARIES)" || rm -f $(dri_LTLIBRARIES) |
@list='$(dri_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}; \ |
} |
r200_dri.la: $(r200_dri_la_OBJECTS) $(r200_dri_la_DEPENDENCIES) $(EXTRA_r200_dri_la_DEPENDENCIES) |
$(AM_V_CCLD)$(r200_dri_la_LINK) $(am_r200_dri_la_rpath) $(r200_dri_la_OBJECTS) $(r200_dri_la_LIBADD) $(LIBS) |
mostlyclean-compile: |
-rm -f *.$(OBJEXT) |
distclean-compile: |
-rm -f *.tab.c |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_blit.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_cmdbuf.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_fragshader.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_ioctl.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_maos.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_sanity.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_state_init.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_swtcl.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_tcl.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_tex.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_texstate.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r200_vertprog.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_buffer_objects.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_common.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_common_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_debug.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_dma.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_fbo.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_fog.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_mipmap_tree.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_pixel_read.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_queryobj.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_screen.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_span.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_tex_copy.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_texture.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_tile.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) all-local |
installdirs: |
for dir in "$(DESTDIR)$(dridir)"; do \ |
test -z "$$dir" || $(MKDIR_P) "$$dir"; \ |
done |
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-driLTLIBRARIES clean-generic clean-libtool \ |
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-driLTLIBRARIES |
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: uninstall-driLTLIBRARIES |
.MAKE: install-am install-strip |
.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \ |
clean-driLTLIBRARIES clean-generic clean-libtool 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-driLTLIBRARIES 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 \ |
uninstall-driLTLIBRARIES |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
all-local: r200_dri.la |
$(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
ln -f .libs/r200_dri.so $(top_builddir)/$(LIB_DIR)/r200_dri.so; |
# 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/src/mesa/drivers/dri/r200/Makefile.sources |
---|
0,0 → 1,34 |
R200_COMMON_FILES = \ |
radeon_buffer_objects.c \ |
radeon_common_context.c \ |
radeon_common.c \ |
radeon_dma.c \ |
radeon_debug.c \ |
radeon_fbo.c \ |
radeon_fog.c \ |
radeon_mipmap_tree.c \ |
radeon_pixel_read.c \ |
radeon_queryobj.c \ |
radeon_span.c \ |
radeon_texture.c \ |
radeon_tex_copy.c \ |
radeon_tile.c |
DRIVER_FILES = \ |
r200_context.c \ |
r200_ioctl.c \ |
r200_state.c \ |
r200_state_init.c \ |
r200_cmdbuf.c \ |
r200_tex.c \ |
r200_texstate.c \ |
r200_tcl.c \ |
r200_swtcl.c \ |
r200_maos.c \ |
r200_sanity.c \ |
r200_fragshader.c \ |
r200_vertprog.c \ |
r200_blit.c \ |
radeon_screen.c |
R200_C_FILES = $(R200_COMMON_FILES) $(DRIVER_FILES) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_blit.c |
---|
0,0 → 1,551 |
/* |
* Copyright (C) 2009 Maciej Cencora <m.cencora@gmail.com> |
* |
* 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, 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 COPYRIGHT OWNER(S) 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 "radeon_common.h" |
#include "r200_context.h" |
#include "r200_blit.h" |
static inline uint32_t cmdpacket0(struct radeon_screen *rscrn, |
int reg, int count) |
{ |
if (count) |
return CP_PACKET0(reg, count - 1); |
return CP_PACKET2; |
} |
/* common formats supported as both textures and render targets */ |
unsigned r200_check_blit(gl_format mesa_format, uint32_t dst_pitch) |
{ |
/* XXX others? BE/LE? */ |
switch (mesa_format) { |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_XRGB8888: |
case MESA_FORMAT_RGB565: |
case MESA_FORMAT_ARGB4444: |
case MESA_FORMAT_ARGB1555: |
case MESA_FORMAT_A8: |
case MESA_FORMAT_L8: |
case MESA_FORMAT_I8: |
/* swizzled */ |
case MESA_FORMAT_RGBA8888: |
case MESA_FORMAT_RGBA8888_REV: |
break; |
default: |
return 0; |
} |
/* Rendering to small buffer doesn't work. |
* Looks like a hw limitation. |
*/ |
if (dst_pitch < 32) |
return 0; |
/* ??? */ |
if (_mesa_get_format_bits(mesa_format, GL_DEPTH_BITS) > 0) |
return 0; |
return 1; |
} |
static inline void emit_vtx_state(struct r200_context *r200) |
{ |
BATCH_LOCALS(&r200->radeon); |
BEGIN_BATCH(14); |
if (r200->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) { |
OUT_BATCH_REGVAL(R200_SE_VAP_CNTL_STATUS, 0); |
} else { |
OUT_BATCH_REGVAL(R200_SE_VAP_CNTL_STATUS, RADEON_TCL_BYPASS); |
} |
OUT_BATCH_REGVAL(R200_SE_VAP_CNTL, (R200_VAP_FORCE_W_TO_ONE | |
(9 << R200_VAP_VF_MAX_VTX_NUM__SHIFT))); |
OUT_BATCH_REGVAL(R200_SE_VTX_STATE_CNTL, 0); |
OUT_BATCH_REGVAL(R200_SE_VTE_CNTL, 0); |
OUT_BATCH_REGVAL(R200_SE_VTX_FMT_0, R200_VTX_XY); |
OUT_BATCH_REGVAL(R200_SE_VTX_FMT_1, (2 << R200_VTX_TEX0_COMP_CNT_SHIFT)); |
OUT_BATCH_REGVAL(RADEON_SE_CNTL, (RADEON_DIFFUSE_SHADE_GOURAUD | |
RADEON_BFACE_SOLID | |
RADEON_FFACE_SOLID | |
RADEON_VTX_PIX_CENTER_OGL | |
RADEON_ROUND_MODE_ROUND | |
RADEON_ROUND_PREC_4TH_PIX)); |
END_BATCH(); |
} |
static void inline emit_tx_setup(struct r200_context *r200, |
gl_format src_mesa_format, |
gl_format dst_mesa_format, |
struct radeon_bo *bo, |
intptr_t offset, |
unsigned width, |
unsigned height, |
unsigned pitch) |
{ |
uint32_t txformat = R200_TXFORMAT_NON_POWER2; |
BATCH_LOCALS(&r200->radeon); |
assert(width <= 2048); |
assert(height <= 2048); |
assert(offset % 32 == 0); |
/* XXX others? BE/LE? */ |
switch (src_mesa_format) { |
case MESA_FORMAT_ARGB8888: |
txformat |= R200_TXFORMAT_ARGB8888 | R200_TXFORMAT_ALPHA_IN_MAP; |
break; |
case MESA_FORMAT_RGBA8888: |
txformat |= R200_TXFORMAT_RGBA8888 | R200_TXFORMAT_ALPHA_IN_MAP; |
break; |
case MESA_FORMAT_RGBA8888_REV: |
txformat |= R200_TXFORMAT_ABGR8888 | R200_TXFORMAT_ALPHA_IN_MAP; |
break; |
case MESA_FORMAT_XRGB8888: |
txformat |= R200_TXFORMAT_ARGB8888; |
break; |
case MESA_FORMAT_RGB565: |
txformat |= R200_TXFORMAT_RGB565; |
break; |
case MESA_FORMAT_ARGB4444: |
txformat |= R200_TXFORMAT_ARGB4444 | R200_TXFORMAT_ALPHA_IN_MAP; |
break; |
case MESA_FORMAT_ARGB1555: |
txformat |= R200_TXFORMAT_ARGB1555 | R200_TXFORMAT_ALPHA_IN_MAP; |
break; |
case MESA_FORMAT_A8: |
case MESA_FORMAT_I8: |
txformat |= R200_TXFORMAT_I8 | R200_TXFORMAT_ALPHA_IN_MAP; |
break; |
case MESA_FORMAT_L8: |
txformat |= R200_TXFORMAT_I8; |
break; |
case MESA_FORMAT_AL88: |
txformat |= R200_TXFORMAT_AI88 | R200_TXFORMAT_ALPHA_IN_MAP; |
break; |
default: |
break; |
} |
if (bo->flags & RADEON_BO_FLAGS_MACRO_TILE) |
offset |= R200_TXO_MACRO_TILE; |
if (bo->flags & RADEON_BO_FLAGS_MICRO_TILE) |
offset |= R200_TXO_MICRO_TILE; |
switch (dst_mesa_format) { |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_XRGB8888: |
case MESA_FORMAT_RGB565: |
case MESA_FORMAT_ARGB4444: |
case MESA_FORMAT_ARGB1555: |
case MESA_FORMAT_A8: |
case MESA_FORMAT_L8: |
case MESA_FORMAT_I8: |
default: |
/* no swizzle required */ |
BEGIN_BATCH(10); |
OUT_BATCH_REGVAL(RADEON_PP_CNTL, (RADEON_TEX_0_ENABLE | |
RADEON_TEX_BLEND_0_ENABLE)); |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND_0, (R200_TXC_ARG_A_ZERO | |
R200_TXC_ARG_B_ZERO | |
R200_TXC_ARG_C_R0_COLOR | |
R200_TXC_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_0, (R200_TXC_CLAMP_0_1 | |
R200_TXC_OUTPUT_REG_R0)); |
OUT_BATCH_REGVAL(R200_PP_TXABLEND_0, (R200_TXA_ARG_A_ZERO | |
R200_TXA_ARG_B_ZERO | |
R200_TXA_ARG_C_R0_ALPHA | |
R200_TXA_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXABLEND2_0, (R200_TXA_CLAMP_0_1 | |
R200_TXA_OUTPUT_REG_R0)); |
END_BATCH(); |
break; |
case MESA_FORMAT_RGBA8888: |
BEGIN_BATCH(10); |
OUT_BATCH_REGVAL(RADEON_PP_CNTL, (RADEON_TEX_0_ENABLE | |
RADEON_TEX_BLEND_0_ENABLE)); |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND_0, (R200_TXC_ARG_A_ZERO | |
R200_TXC_ARG_B_ZERO | |
R200_TXC_ARG_C_R0_COLOR | |
R200_TXC_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_0, (R200_TXC_CLAMP_0_1 | |
R200_TXC_OUTPUT_ROTATE_GBA | |
R200_TXC_OUTPUT_REG_R0)); |
OUT_BATCH_REGVAL(R200_PP_TXABLEND_0, (R200_TXA_ARG_A_ZERO | |
R200_TXA_ARG_B_ZERO | |
R200_TXA_ARG_C_R0_ALPHA | |
R200_TXA_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXABLEND2_0, (R200_TXA_CLAMP_0_1 | |
(R200_TXA_REPL_RED << R200_TXA_REPL_ARG_C_SHIFT) | |
R200_TXA_OUTPUT_REG_R0)); |
END_BATCH(); |
break; |
case MESA_FORMAT_RGBA8888_REV: |
BEGIN_BATCH(34); |
OUT_BATCH_REGVAL(RADEON_PP_CNTL, (RADEON_TEX_0_ENABLE | |
RADEON_TEX_BLEND_0_ENABLE | |
RADEON_TEX_BLEND_1_ENABLE | |
RADEON_TEX_BLEND_2_ENABLE | |
RADEON_TEX_BLEND_3_ENABLE)); |
/* r1.r = r0.b */ |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND_0, (R200_TXC_ARG_A_ZERO | |
R200_TXC_ARG_B_ZERO | |
R200_TXC_ARG_C_R0_COLOR | |
R200_TXC_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_0, (R200_TXC_CLAMP_0_1 | |
R200_TXC_OUTPUT_MASK_R | |
(R200_TXC_REPL_BLUE << R200_TXC_REPL_ARG_C_SHIFT) | |
R200_TXC_OUTPUT_REG_R1)); |
/* r1.a = r0.a */ |
OUT_BATCH_REGVAL(R200_PP_TXABLEND_0, (R200_TXA_ARG_A_ZERO | |
R200_TXA_ARG_B_ZERO | |
R200_TXA_ARG_C_R0_ALPHA | |
R200_TXA_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXABLEND2_0, (R200_TXA_CLAMP_0_1 | |
R200_TXA_OUTPUT_REG_R1)); |
/* r1.g = r0.g */ |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND_1, (R200_TXC_ARG_A_ZERO | |
R200_TXC_ARG_B_ZERO | |
R200_TXC_ARG_C_R0_COLOR | |
R200_TXC_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_1, (R200_TXC_CLAMP_0_1 | |
R200_TXC_OUTPUT_MASK_G | |
(R200_TXC_REPL_GREEN << R200_TXC_REPL_ARG_C_SHIFT) | |
R200_TXC_OUTPUT_REG_R1)); |
/* r1.a = r0.a */ |
OUT_BATCH_REGVAL(R200_PP_TXABLEND_1, (R200_TXA_ARG_A_ZERO | |
R200_TXA_ARG_B_ZERO | |
R200_TXA_ARG_C_R0_ALPHA | |
R200_TXA_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXABLEND2_1, (R200_TXA_CLAMP_0_1 | |
R200_TXA_OUTPUT_REG_R1)); |
/* r1.b = r0.r */ |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND_2, (R200_TXC_ARG_A_ZERO | |
R200_TXC_ARG_B_ZERO | |
R200_TXC_ARG_C_R0_COLOR | |
R200_TXC_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_2, (R200_TXC_CLAMP_0_1 | |
R200_TXC_OUTPUT_MASK_B | |
(R200_TXC_REPL_RED << R200_TXC_REPL_ARG_C_SHIFT) | |
R200_TXC_OUTPUT_REG_R1)); |
/* r1.a = r0.a */ |
OUT_BATCH_REGVAL(R200_PP_TXABLEND_2, (R200_TXA_ARG_A_ZERO | |
R200_TXA_ARG_B_ZERO | |
R200_TXA_ARG_C_R0_ALPHA | |
R200_TXA_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXABLEND2_2, (R200_TXA_CLAMP_0_1 | |
R200_TXA_OUTPUT_REG_R1)); |
/* r0.rgb = r1.rgb */ |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND_3, (R200_TXC_ARG_A_ZERO | |
R200_TXC_ARG_B_ZERO | |
R200_TXC_ARG_C_R1_COLOR | |
R200_TXC_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXCBLEND2_3, (R200_TXC_CLAMP_0_1 | |
R200_TXC_OUTPUT_REG_R0)); |
/* r0.a = r1.a */ |
OUT_BATCH_REGVAL(R200_PP_TXABLEND_3, (R200_TXA_ARG_A_ZERO | |
R200_TXA_ARG_B_ZERO | |
R200_TXA_ARG_C_R1_ALPHA | |
R200_TXA_OP_MADD)); |
OUT_BATCH_REGVAL(R200_PP_TXABLEND2_3, (R200_TXA_CLAMP_0_1 | |
R200_TXA_OUTPUT_REG_R0)); |
END_BATCH(); |
break; |
} |
BEGIN_BATCH(18); |
OUT_BATCH_REGVAL(R200_PP_CNTL_X, 0); |
OUT_BATCH_REGVAL(R200_PP_TXMULTI_CTL_0, 0); |
OUT_BATCH_REGVAL(R200_PP_TXFILTER_0, (R200_CLAMP_S_CLAMP_LAST | |
R200_CLAMP_T_CLAMP_LAST | |
R200_MAG_FILTER_NEAREST | |
R200_MIN_FILTER_NEAREST)); |
OUT_BATCH_REGVAL(R200_PP_TXFORMAT_0, txformat); |
OUT_BATCH_REGVAL(R200_PP_TXFORMAT_X_0, 0); |
OUT_BATCH_REGVAL(R200_PP_TXSIZE_0, ((width - 1) | |
((height - 1) << RADEON_TEX_VSIZE_SHIFT))); |
OUT_BATCH_REGVAL(R200_PP_TXPITCH_0, pitch * _mesa_get_format_bytes(src_mesa_format) - 32); |
OUT_BATCH_REGSEQ(R200_PP_TXOFFSET_0, 1); |
OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); |
END_BATCH(); |
} |
static inline void emit_cb_setup(struct r200_context *r200, |
struct radeon_bo *bo, |
intptr_t offset, |
gl_format mesa_format, |
unsigned pitch, |
unsigned width, |
unsigned height) |
{ |
uint32_t dst_pitch = pitch; |
uint32_t dst_format = 0; |
BATCH_LOCALS(&r200->radeon); |
/* XXX others? BE/LE? */ |
switch (mesa_format) { |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_XRGB8888: |
case MESA_FORMAT_RGBA8888: |
case MESA_FORMAT_RGBA8888_REV: |
dst_format = RADEON_COLOR_FORMAT_ARGB8888; |
break; |
case MESA_FORMAT_RGB565: |
dst_format = RADEON_COLOR_FORMAT_RGB565; |
break; |
case MESA_FORMAT_ARGB4444: |
dst_format = RADEON_COLOR_FORMAT_ARGB4444; |
break; |
case MESA_FORMAT_ARGB1555: |
dst_format = RADEON_COLOR_FORMAT_ARGB1555; |
break; |
case MESA_FORMAT_A8: |
case MESA_FORMAT_L8: |
case MESA_FORMAT_I8: |
dst_format = RADEON_COLOR_FORMAT_RGB8; |
break; |
default: |
break; |
} |
if (bo->flags & RADEON_BO_FLAGS_MACRO_TILE) |
dst_pitch |= R200_COLOR_TILE_ENABLE; |
if (bo->flags & RADEON_BO_FLAGS_MICRO_TILE) |
dst_pitch |= R200_COLOR_MICROTILE_ENABLE; |
BEGIN_BATCH_NO_AUTOSTATE(22); |
OUT_BATCH_REGVAL(R200_RE_AUX_SCISSOR_CNTL, 0); |
OUT_BATCH_REGVAL(R200_RE_CNTL, 0); |
OUT_BATCH_REGVAL(RADEON_RE_TOP_LEFT, 0); |
OUT_BATCH_REGVAL(RADEON_RE_WIDTH_HEIGHT, (((width - 1) << RADEON_RE_WIDTH_SHIFT) | |
((height - 1) << RADEON_RE_HEIGHT_SHIFT))); |
OUT_BATCH_REGVAL(RADEON_RB3D_PLANEMASK, 0xffffffff); |
OUT_BATCH_REGVAL(RADEON_RB3D_BLENDCNTL, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO); |
OUT_BATCH_REGVAL(RADEON_RB3D_CNTL, dst_format); |
OUT_BATCH_REGSEQ(RADEON_RB3D_COLOROFFSET, 1); |
OUT_BATCH_RELOC(offset, bo, offset, 0, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); |
OUT_BATCH_REGSEQ(RADEON_RB3D_COLORPITCH, 1); |
OUT_BATCH_RELOC(dst_pitch, bo, dst_pitch, 0, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); |
END_BATCH(); |
} |
static GLboolean validate_buffers(struct r200_context *r200, |
struct radeon_bo *src_bo, |
struct radeon_bo *dst_bo) |
{ |
int ret; |
radeon_cs_space_reset_bos(r200->radeon.cmdbuf.cs); |
ret = radeon_cs_space_check_with_bo(r200->radeon.cmdbuf.cs, |
src_bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); |
if (ret) |
return GL_FALSE; |
ret = radeon_cs_space_check_with_bo(r200->radeon.cmdbuf.cs, |
dst_bo, 0, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT); |
if (ret) |
return GL_FALSE; |
return GL_TRUE; |
} |
/** |
* Calculate texcoords for given image region. |
* Output values are [minx, maxx, miny, maxy] |
*/ |
static inline void calc_tex_coords(float img_width, float img_height, |
float x, float y, |
float reg_width, float reg_height, |
unsigned flip_y, float *buf) |
{ |
buf[0] = x / img_width; |
buf[1] = buf[0] + reg_width / img_width; |
buf[2] = y / img_height; |
buf[3] = buf[2] + reg_height / img_height; |
if (flip_y) |
{ |
buf[2] = 1.0 - buf[2]; |
buf[3] = 1.0 - buf[3]; |
} |
} |
static inline void emit_draw_packet(struct r200_context *r200, |
unsigned src_width, unsigned src_height, |
unsigned src_x_offset, unsigned src_y_offset, |
unsigned dst_x_offset, unsigned dst_y_offset, |
unsigned reg_width, unsigned reg_height, |
unsigned flip_y) |
{ |
float texcoords[4]; |
float verts[12]; |
BATCH_LOCALS(&r200->radeon); |
calc_tex_coords(src_width, src_height, |
src_x_offset, src_y_offset, |
reg_width, reg_height, |
flip_y, texcoords); |
verts[0] = dst_x_offset; |
verts[1] = dst_y_offset + reg_height; |
verts[2] = texcoords[0]; |
verts[3] = texcoords[3]; |
verts[4] = dst_x_offset + reg_width; |
verts[5] = dst_y_offset + reg_height; |
verts[6] = texcoords[1]; |
verts[7] = texcoords[3]; |
verts[8] = dst_x_offset + reg_width; |
verts[9] = dst_y_offset; |
verts[10] = texcoords[1]; |
verts[11] = texcoords[2]; |
BEGIN_BATCH(14); |
OUT_BATCH(R200_CP_CMD_3D_DRAW_IMMD_2 | (12 << 16)); |
OUT_BATCH(RADEON_CP_VC_CNTL_PRIM_WALK_RING | |
RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST | |
(3 << 16)); |
OUT_BATCH_TABLE(verts, 12); |
END_BATCH(); |
} |
/** |
* Copy a region of [@a width x @a height] pixels from source buffer |
* to destination buffer. |
* @param[in] r200 r200 context |
* @param[in] src_bo source radeon buffer object |
* @param[in] src_offset offset of the source image in the @a src_bo |
* @param[in] src_mesaformat source image format |
* @param[in] src_pitch aligned source image width |
* @param[in] src_width source image width |
* @param[in] src_height source image height |
* @param[in] src_x_offset x offset in the source image |
* @param[in] src_y_offset y offset in the source image |
* @param[in] dst_bo destination radeon buffer object |
* @param[in] dst_offset offset of the destination image in the @a dst_bo |
* @param[in] dst_mesaformat destination image format |
* @param[in] dst_pitch aligned destination image width |
* @param[in] dst_width destination image width |
* @param[in] dst_height destination image height |
* @param[in] dst_x_offset x offset in the destination image |
* @param[in] dst_y_offset y offset in the destination image |
* @param[in] width region width |
* @param[in] height region height |
* @param[in] flip_y set if y coords of the source image need to be flipped |
*/ |
unsigned r200_blit(struct gl_context *ctx, |
struct radeon_bo *src_bo, |
intptr_t src_offset, |
gl_format src_mesaformat, |
unsigned src_pitch, |
unsigned src_width, |
unsigned src_height, |
unsigned src_x_offset, |
unsigned src_y_offset, |
struct radeon_bo *dst_bo, |
intptr_t dst_offset, |
gl_format dst_mesaformat, |
unsigned dst_pitch, |
unsigned dst_width, |
unsigned dst_height, |
unsigned dst_x_offset, |
unsigned dst_y_offset, |
unsigned reg_width, |
unsigned reg_height, |
unsigned flip_y) |
{ |
struct r200_context *r200 = R200_CONTEXT(ctx); |
if (!r200_check_blit(dst_mesaformat, dst_pitch)) |
return GL_FALSE; |
/* Make sure that colorbuffer has even width - hw limitation */ |
if (dst_pitch % 2 > 0) |
++dst_pitch; |
/* Need to clamp the region size to make sure |
* we don't read outside of the source buffer |
* or write outside of the destination buffer. |
*/ |
if (reg_width + src_x_offset > src_width) |
reg_width = src_width - src_x_offset; |
if (reg_height + src_y_offset > src_height) |
reg_height = src_height - src_y_offset; |
if (reg_width + dst_x_offset > dst_width) |
reg_width = dst_width - dst_x_offset; |
if (reg_height + dst_y_offset > dst_height) |
reg_height = dst_height - dst_y_offset; |
if (src_bo == dst_bo) { |
return GL_FALSE; |
} |
if (src_offset % 32 || dst_offset % 32) { |
return GL_FALSE; |
} |
if (0) { |
fprintf(stderr, "src: size [%d x %d], pitch %d, " |
"offset [%d x %d], format %s, bo %p\n", |
src_width, src_height, src_pitch, |
src_x_offset, src_y_offset, |
_mesa_get_format_name(src_mesaformat), |
src_bo); |
fprintf(stderr, "dst: pitch %d, offset[%d x %d], format %s, bo %p\n", |
dst_pitch, dst_x_offset, dst_y_offset, |
_mesa_get_format_name(dst_mesaformat), dst_bo); |
fprintf(stderr, "region: %d x %d\n", reg_width, reg_height); |
} |
/* Flush is needed to make sure that source buffer has correct data */ |
radeonFlush(&r200->radeon.glCtx); |
rcommonEnsureCmdBufSpace(&r200->radeon, 102, __FUNCTION__); |
if (!validate_buffers(r200, src_bo, dst_bo)) |
return GL_FALSE; |
/* 14 */ |
emit_vtx_state(r200); |
/* 52 */ |
emit_tx_setup(r200, src_mesaformat, dst_mesaformat, src_bo, src_offset, src_width, src_height, src_pitch); |
/* 22 */ |
emit_cb_setup(r200, dst_bo, dst_offset, dst_mesaformat, dst_pitch, dst_width, dst_height); |
/* 14 */ |
emit_draw_packet(r200, src_width, src_height, |
src_x_offset, src_y_offset, |
dst_x_offset, dst_y_offset, |
reg_width, reg_height, |
flip_y); |
radeonFlush(ctx); |
return GL_TRUE; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_blit.h |
---|
0,0 → 1,56 |
/* |
* Copyright (C) 2009 Maciej Cencora <m.cencora@gmail.com> |
* |
* 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, 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 COPYRIGHT OWNER(S) 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 R200_BLIT_H |
#define R200_BLIT_H |
void r200_blit_init(struct r200_context *r200); |
unsigned r200_check_blit(gl_format mesa_format, uint32_t dst_pitch); |
unsigned r200_blit(struct gl_context *ctx, |
struct radeon_bo *src_bo, |
intptr_t src_offset, |
gl_format src_mesaformat, |
unsigned src_pitch, |
unsigned src_width, |
unsigned src_height, |
unsigned src_x_offset, |
unsigned src_y_offset, |
struct radeon_bo *dst_bo, |
intptr_t dst_offset, |
gl_format dst_mesaformat, |
unsigned dst_pitch, |
unsigned dst_width, |
unsigned dst_height, |
unsigned dst_x_offset, |
unsigned dst_y_offset, |
unsigned width, |
unsigned height, |
unsigned flip_y); |
#endif // R200_BLIT_H |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_cmdbuf.c |
---|
0,0 → 1,300 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "main/context.h" |
#include "main/simple_list.h" |
#include "radeon_common.h" |
#include "r200_context.h" |
#include "r200_ioctl.h" |
#include "radeon_reg.h" |
/* The state atoms will be emitted in the order they appear in the atom list, |
* so this step is important. |
*/ |
#define insert_at_tail_if(atom_list, atom) \ |
do { \ |
struct radeon_state_atom* current_atom = (atom); \ |
if (current_atom->check) \ |
insert_at_tail((atom_list), current_atom); \ |
} while(0) |
void r200SetUpAtomList( r200ContextPtr rmesa ) |
{ |
int i, mtu; |
mtu = rmesa->radeon.glCtx.Const.MaxTextureUnits; |
make_empty_list(&rmesa->radeon.hw.atomlist); |
rmesa->radeon.hw.atomlist.name = "atom-list"; |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ctx ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.set ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.lin ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msk ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpt ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vtx ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vap ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vte ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msc ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.cst ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.zbs ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcl ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msl ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcg ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.grd ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.fog ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tam ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tf ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.atf ); |
for (i = 0; i < mtu; ++i) |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tex[i] ); |
for (i = 0; i < mtu; ++i) |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.cube[i] ); |
for (i = 0; i < 6; ++i) |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.pix[i] ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[0] ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[1] ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.stp ); |
for (i = 0; i < 8; ++i) |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i] ); |
for (i = 0; i < 3 + mtu; ++i) |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.mat[i] ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.eye ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.glt ); |
for (i = 0; i < 2; ++i) |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.mtl[i] ); |
for (i = 0; i < 6; ++i) |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i] ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.spr ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ptp ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.prf ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.pvs ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[0] ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[1] ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[0] ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[1] ); |
insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.sci ); |
} |
/* Fire a section of the retained (indexed_verts) buffer as a regular |
* primtive. |
*/ |
void r200EmitVbufPrim( r200ContextPtr rmesa, |
GLuint primitive, |
GLuint vertex_nr ) |
{ |
BATCH_LOCALS(&rmesa->radeon); |
assert(!(primitive & R200_VF_PRIM_WALK_IND)); |
radeonEmitState(&rmesa->radeon); |
radeon_print(RADEON_RENDER|RADEON_SWRENDER,RADEON_VERBOSE, |
"%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__, |
rmesa->store.cmd_used/4, primitive, vertex_nr); |
BEGIN_BATCH(3); |
OUT_BATCH_PACKET3_CLIP(R200_CP_CMD_3D_DRAW_VBUF_2, 0); |
OUT_BATCH(primitive | R200_VF_PRIM_WALK_LIST | R200_VF_COLOR_ORDER_RGBA | |
(vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT)); |
END_BATCH(); |
} |
static void r200FireEB(r200ContextPtr rmesa, int vertex_count, int type) |
{ |
BATCH_LOCALS(&rmesa->radeon); |
if (vertex_count > 0) { |
BEGIN_BATCH(8+2); |
OUT_BATCH_PACKET3_CLIP(R200_CP_CMD_3D_DRAW_INDX_2, 0); |
OUT_BATCH(R200_VF_PRIM_WALK_IND | |
R200_VF_COLOR_ORDER_RGBA | |
((vertex_count + 0) << 16) | |
type); |
OUT_BATCH_PACKET3(R200_CP_CMD_INDX_BUFFER, 2); |
OUT_BATCH((0x80 << 24) | (0 << 16) | 0x810); |
OUT_BATCH(rmesa->radeon.tcl.elt_dma_offset); |
OUT_BATCH((vertex_count + 1)/2); |
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs, |
rmesa->radeon.tcl.elt_dma_bo, |
RADEON_GEM_DOMAIN_GTT, 0, 0); |
END_BATCH(); |
} |
} |
void r200FlushElts(struct gl_context *ctx) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
int nr, elt_used = rmesa->tcl.elt_used; |
radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %x %d\n", __FUNCTION__, rmesa->tcl.hw_primitive, elt_used); |
assert( rmesa->radeon.dma.flush == r200FlushElts ); |
rmesa->radeon.dma.flush = NULL; |
nr = elt_used / 2; |
radeon_bo_unmap(rmesa->radeon.tcl.elt_dma_bo); |
r200FireEB(rmesa, nr, rmesa->tcl.hw_primitive); |
radeon_bo_unref(rmesa->radeon.tcl.elt_dma_bo); |
rmesa->radeon.tcl.elt_dma_bo = NULL; |
if (R200_ELT_BUF_SZ > elt_used) |
radeonReturnDmaRegion(&rmesa->radeon, R200_ELT_BUF_SZ - elt_used); |
} |
GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa, |
GLuint primitive, |
GLuint min_nr ) |
{ |
GLushort *retval; |
radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive); |
assert((primitive & R200_VF_PRIM_WALK_IND)); |
radeonEmitState(&rmesa->radeon); |
radeonAllocDmaRegion(&rmesa->radeon, &rmesa->radeon.tcl.elt_dma_bo, |
&rmesa->radeon.tcl.elt_dma_offset, R200_ELT_BUF_SZ, 4); |
rmesa->tcl.elt_used = min_nr * 2; |
radeon_bo_map(rmesa->radeon.tcl.elt_dma_bo, 1); |
retval = rmesa->radeon.tcl.elt_dma_bo->ptr + rmesa->radeon.tcl.elt_dma_offset; |
assert(!rmesa->radeon.dma.flush); |
rmesa->radeon.glCtx.Driver.NeedFlush |= FLUSH_STORED_VERTICES; |
rmesa->radeon.dma.flush = r200FlushElts; |
return retval; |
} |
void r200EmitMaxVtxIndex(r200ContextPtr rmesa, int count) |
{ |
BATCH_LOCALS(&rmesa->radeon); |
BEGIN_BATCH_NO_AUTOSTATE(2); |
OUT_BATCH(CP_PACKET0(R200_SE_VF_MAX_VTX_INDX, 0)); |
OUT_BATCH(count); |
END_BATCH(); |
} |
void r200EmitVertexAOS( r200ContextPtr rmesa, |
GLuint vertex_size, |
struct radeon_bo *bo, |
GLuint offset ) |
{ |
BATCH_LOCALS(&rmesa->radeon); |
radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, "%s: vertex_size 0x%x offset 0x%x \n", |
__FUNCTION__, vertex_size, offset); |
BEGIN_BATCH(7); |
OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, 2); |
OUT_BATCH(1); |
OUT_BATCH(vertex_size | (vertex_size << 8)); |
OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0); |
END_BATCH(); |
} |
void r200EmitAOS(r200ContextPtr rmesa, GLuint nr, GLuint offset) |
{ |
BATCH_LOCALS(&rmesa->radeon); |
uint32_t voffset; |
int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2; |
int i; |
radeon_print(RADEON_RENDER, RADEON_VERBOSE, |
"%s: nr=%d, ofs=0x%08x\n", |
__FUNCTION__, nr, offset); |
BEGIN_BATCH(sz+2+ (nr*2)); |
OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, sz - 1); |
OUT_BATCH(nr); |
{ |
for (i = 0; i + 1 < nr; i += 2) { |
OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) | |
(rmesa->radeon.tcl.aos[i].stride << 8) | |
(rmesa->radeon.tcl.aos[i + 1].components << 16) | |
(rmesa->radeon.tcl.aos[i + 1].stride << 24)); |
voffset = rmesa->radeon.tcl.aos[i + 0].offset + |
offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride; |
OUT_BATCH(voffset); |
voffset = rmesa->radeon.tcl.aos[i + 1].offset + |
offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride; |
OUT_BATCH(voffset); |
} |
if (nr & 1) { |
OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) | |
(rmesa->radeon.tcl.aos[nr - 1].stride << 8)); |
voffset = rmesa->radeon.tcl.aos[nr - 1].offset + |
offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride; |
OUT_BATCH(voffset); |
} |
for (i = 0; i + 1 < nr; i += 2) { |
voffset = rmesa->radeon.tcl.aos[i + 0].offset + |
offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride; |
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs, |
rmesa->radeon.tcl.aos[i+0].bo, |
RADEON_GEM_DOMAIN_GTT, |
0, 0); |
voffset = rmesa->radeon.tcl.aos[i + 1].offset + |
offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride; |
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs, |
rmesa->radeon.tcl.aos[i+1].bo, |
RADEON_GEM_DOMAIN_GTT, |
0, 0); |
} |
if (nr & 1) { |
voffset = rmesa->radeon.tcl.aos[nr - 1].offset + |
offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride; |
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs, |
rmesa->radeon.tcl.aos[nr-1].bo, |
RADEON_GEM_DOMAIN_GTT, |
0, 0); |
} |
} |
END_BATCH(); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_context.c |
---|
0,0 → 1,472 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 <stdbool.h> |
#include "main/glheader.h" |
#include "main/api_arrayelt.h" |
#include "main/api_exec.h" |
#include "main/context.h" |
#include "main/simple_list.h" |
#include "main/imports.h" |
#include "main/extensions.h" |
#include "main/version.h" |
#include "main/vtxfmt.h" |
#include "swrast/swrast.h" |
#include "swrast_setup/swrast_setup.h" |
#include "vbo/vbo.h" |
#include "tnl/tnl.h" |
#include "tnl/t_pipeline.h" |
#include "drivers/common/driverfuncs.h" |
#include "r200_context.h" |
#include "r200_ioctl.h" |
#include "r200_state.h" |
#include "r200_tex.h" |
#include "r200_swtcl.h" |
#include "r200_tcl.h" |
#include "r200_vertprog.h" |
#include "radeon_queryobj.h" |
#include "r200_blit.h" |
#include "radeon_fog.h" |
#include "radeon_span.h" |
#include "utils.h" |
#include "xmlpool.h" /* for symbolic values of enum-type options */ |
/* Return various strings for glGetString(). |
*/ |
static const GLubyte *r200GetString( struct gl_context *ctx, GLenum name ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
static char buffer[128]; |
unsigned offset; |
GLuint agp_mode = (rmesa->radeon.radeonScreen->card_type == RADEON_CARD_PCI)? 0 : |
rmesa->radeon.radeonScreen->AGPMode; |
switch ( name ) { |
case GL_VENDOR: |
return (GLubyte *)"Tungsten Graphics, Inc."; |
case GL_RENDERER: |
offset = driGetRendererString( buffer, "R200", agp_mode ); |
sprintf( & buffer[ offset ], " %sTCL", |
!(rmesa->radeon.TclFallback & R200_TCL_FALLBACK_TCL_DISABLE) |
? "" : "NO-" ); |
return (GLubyte *)buffer; |
default: |
return NULL; |
} |
} |
extern const struct tnl_pipeline_stage _r200_render_stage; |
extern const struct tnl_pipeline_stage _r200_tcl_stage; |
static const struct tnl_pipeline_stage *r200_pipeline[] = { |
/* Try and go straight to t&l |
*/ |
&_r200_tcl_stage, |
/* Catch any t&l fallbacks |
*/ |
&_tnl_vertex_transform_stage, |
&_tnl_normal_transform_stage, |
&_tnl_lighting_stage, |
&_tnl_fog_coordinate_stage, |
&_tnl_texgen_stage, |
&_tnl_texture_transform_stage, |
&_tnl_point_attenuation_stage, |
&_tnl_vertex_program_stage, |
/* Try again to go to tcl? |
* - no good for asymmetric-twoside (do with multipass) |
* - no good for asymmetric-unfilled (do with multipass) |
* - good for material |
* - good for texgen |
* - need to manipulate a bit of state |
* |
* - worth it/not worth it? |
*/ |
/* Else do them here. |
*/ |
/* &_r200_render_stage, */ /* FIXME: bugs with ut2003 */ |
&_tnl_render_stage, /* FALLBACK: */ |
NULL, |
}; |
/* Initialize the driver's misc functions. |
*/ |
static void r200InitDriverFuncs( struct dd_function_table *functions ) |
{ |
functions->GetString = r200GetString; |
} |
static void r200_get_lock(radeonContextPtr radeon) |
{ |
r200ContextPtr rmesa = (r200ContextPtr)radeon; |
drm_radeon_sarea_t *sarea = radeon->sarea; |
R200_STATECHANGE( rmesa, ctx ); |
if (rmesa->radeon.sarea->tiling_enabled) { |
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE; |
} |
else rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &= ~R200_COLOR_TILE_ENABLE; |
if ( sarea->ctx_owner != rmesa->radeon.dri.hwContext ) { |
sarea->ctx_owner = rmesa->radeon.dri.hwContext; |
} |
} |
static void r200_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa) |
{ |
} |
static void r200_emit_query_finish(radeonContextPtr radeon) |
{ |
BATCH_LOCALS(radeon); |
struct radeon_query_object *query = radeon->query.current; |
BEGIN_BATCH_NO_AUTOSTATE(4); |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZPASS_ADDR, 0)); |
OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0); |
END_BATCH(); |
query->curr_offset += sizeof(uint32_t); |
assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE); |
query->emitted_begin = GL_FALSE; |
} |
static void r200_init_vtbl(radeonContextPtr radeon) |
{ |
radeon->vtbl.get_lock = r200_get_lock; |
radeon->vtbl.update_viewport_offset = r200UpdateViewportOffset; |
radeon->vtbl.emit_cs_header = r200_vtbl_emit_cs_header; |
radeon->vtbl.swtcl_flush = r200_swtcl_flush; |
radeon->vtbl.fallback = r200Fallback; |
radeon->vtbl.update_scissor = r200_vtbl_update_scissor; |
radeon->vtbl.emit_query_finish = r200_emit_query_finish; |
radeon->vtbl.check_blit = r200_check_blit; |
radeon->vtbl.blit = r200_blit; |
radeon->vtbl.is_format_renderable = radeonIsFormatRenderable; |
} |
/* Create the device specific rendering context. |
*/ |
GLboolean r200CreateContext( gl_api api, |
const struct gl_config *glVisual, |
__DRIcontext *driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
uint32_t flags, |
unsigned *error, |
void *sharedContextPrivate) |
{ |
__DRIscreen *sPriv = driContextPriv->driScreenPriv; |
radeonScreenPtr screen = (radeonScreenPtr)(sPriv->driverPrivate); |
struct dd_function_table functions; |
r200ContextPtr rmesa; |
struct gl_context *ctx; |
int i; |
int tcl_mode; |
switch (api) { |
case API_OPENGL_COMPAT: |
if (major_version > 1 || minor_version > 3) { |
*error = __DRI_CTX_ERROR_BAD_VERSION; |
return GL_FALSE; |
} |
break; |
case API_OPENGLES: |
break; |
default: |
*error = __DRI_CTX_ERROR_BAD_API; |
return GL_FALSE; |
} |
/* Flag filtering is handled in dri2CreateContextAttribs. |
*/ |
(void) flags; |
assert(glVisual); |
assert(driContextPriv); |
assert(screen); |
/* Allocate the R200 context */ |
rmesa = calloc(1, sizeof(*rmesa)); |
if ( !rmesa ) { |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
return GL_FALSE; |
} |
rmesa->radeon.radeonScreen = screen; |
r200_init_vtbl(&rmesa->radeon); |
/* init exp fog table data */ |
radeonInitStaticFogData(); |
/* Parse configuration files. |
* Do this here so that initialMaxAnisotropy is set before we create |
* the default textures. |
*/ |
driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache, |
screen->driScreen->myNum, "r200"); |
rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache, |
"def_max_anisotropy"); |
if ( sPriv->drm_version.major == 1 |
&& driQueryOptionb( &rmesa->radeon.optionCache, "hyperz" ) ) { |
if ( sPriv->drm_version.minor < 13 ) |
fprintf( stderr, "DRM version 1.%d too old to support HyperZ, " |
"disabling.\n", sPriv->drm_version.minor ); |
else |
rmesa->using_hyperz = GL_TRUE; |
} |
if ( sPriv->drm_version.minor >= 15 ) |
rmesa->texmicrotile = GL_TRUE; |
/* Init default driver functions then plug in our R200-specific functions |
* (the texture functions are especially important) |
*/ |
_mesa_init_driver_functions(&functions); |
r200InitDriverFuncs(&functions); |
r200InitIoctlFuncs(&functions); |
r200InitStateFuncs(&rmesa->radeon, &functions); |
r200InitTextureFuncs(&rmesa->radeon, &functions); |
r200InitShaderFuncs(&functions); |
radeonInitQueryObjFunctions(&functions); |
if (!radeonInitContext(&rmesa->radeon, &functions, |
glVisual, driContextPriv, |
sharedContextPrivate)) { |
free(rmesa); |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
return GL_FALSE; |
} |
rmesa->radeon.swtcl.RenderIndex = ~0; |
rmesa->radeon.hw.all_dirty = 1; |
ctx = &rmesa->radeon.glCtx; |
/* Initialize the software rasterizer and helper modules. |
*/ |
_swrast_CreateContext( ctx ); |
_vbo_CreateContext( ctx ); |
_tnl_CreateContext( ctx ); |
_swsetup_CreateContext( ctx ); |
_ae_create_context( ctx ); |
ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache, |
"texture_units"); |
ctx->Const.FragmentProgram.MaxTextureImageUnits = ctx->Const.MaxTextureUnits; |
ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits; |
ctx->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxTextureUnits; |
ctx->Const.StripTextureBorder = GL_TRUE; |
/* FIXME: When no memory manager is available we should set this |
* to some reasonable value based on texture memory pool size */ |
ctx->Const.MaxTextureLevels = 12; |
ctx->Const.Max3DTextureLevels = 9; |
ctx->Const.MaxCubeTextureLevels = 12; |
ctx->Const.MaxTextureRectSize = 2048; |
ctx->Const.MaxRenderbufferSize = 2048; |
ctx->Const.MaxTextureMaxAnisotropy = 16.0; |
/* No wide AA points. |
*/ |
ctx->Const.MinPointSize = 1.0; |
ctx->Const.MinPointSizeAA = 1.0; |
ctx->Const.MaxPointSizeAA = 1.0; |
ctx->Const.PointSizeGranularity = 0.0625; |
ctx->Const.MaxPointSize = 2047.0; |
/* mesa initialization problem - _mesa_init_point was already called */ |
ctx->Point.MaxSize = ctx->Const.MaxPointSize; |
ctx->Const.MinLineWidth = 1.0; |
ctx->Const.MinLineWidthAA = 1.0; |
ctx->Const.MaxLineWidth = 10.0; |
ctx->Const.MaxLineWidthAA = 10.0; |
ctx->Const.LineWidthGranularity = 0.0625; |
ctx->Const.VertexProgram.MaxNativeInstructions = R200_VSF_MAX_INST; |
ctx->Const.VertexProgram.MaxNativeAttribs = 12; |
ctx->Const.VertexProgram.MaxNativeTemps = R200_VSF_MAX_TEMPS; |
ctx->Const.VertexProgram.MaxNativeParameters = R200_VSF_MAX_PARAM; |
ctx->Const.VertexProgram.MaxNativeAddressRegs = 1; |
ctx->Const.MaxDrawBuffers = 1; |
ctx->Const.MaxColorAttachments = 1; |
ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].PreferDP4 = GL_TRUE; |
/* Install the customized pipeline: |
*/ |
_tnl_destroy_pipeline( ctx ); |
_tnl_install_pipeline( ctx, r200_pipeline ); |
/* Try and keep materials and vertices separate: |
*/ |
/* _tnl_isolate_materials( ctx, GL_TRUE ); */ |
/* Configure swrast and TNL to match hardware characteristics: |
*/ |
_swrast_allow_pixel_fog( ctx, GL_FALSE ); |
_swrast_allow_vertex_fog( ctx, GL_TRUE ); |
_tnl_allow_pixel_fog( ctx, GL_FALSE ); |
_tnl_allow_vertex_fog( ctx, GL_TRUE ); |
for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) { |
_math_matrix_ctr( &rmesa->TexGenMatrix[i] ); |
_math_matrix_set_identity( &rmesa->TexGenMatrix[i] ); |
} |
_math_matrix_ctr( &rmesa->tmpmat ); |
_math_matrix_set_identity( &rmesa->tmpmat ); |
ctx->Extensions.ARB_half_float_pixel = true; |
ctx->Extensions.ARB_occlusion_query = true; |
ctx->Extensions.ARB_texture_border_clamp = true; |
ctx->Extensions.ARB_texture_env_combine = true; |
ctx->Extensions.ARB_texture_env_dot3 = true; |
ctx->Extensions.ARB_texture_env_crossbar = true; |
ctx->Extensions.EXT_blend_color = true; |
ctx->Extensions.EXT_blend_minmax = true; |
ctx->Extensions.EXT_packed_depth_stencil = true; |
ctx->Extensions.EXT_texture_env_dot3 = true; |
ctx->Extensions.EXT_texture_filter_anisotropic = true; |
ctx->Extensions.EXT_texture_mirror_clamp = true; |
ctx->Extensions.ATI_texture_env_combine3 = true; |
ctx->Extensions.ATI_texture_mirror_once = true; |
ctx->Extensions.MESA_pack_invert = true; |
ctx->Extensions.NV_texture_rectangle = true; |
ctx->Extensions.OES_EGL_image = true; |
ctx->Extensions.ARB_occlusion_query = true; |
if (!(rmesa->radeon.radeonScreen->chip_flags & R200_CHIPSET_YCBCR_BROKEN)) { |
/* yuv textures don't work with some chips - R200 / rv280 okay so far |
others get the bit ordering right but don't actually do YUV-RGB conversion */ |
ctx->Extensions.MESA_ycbcr_texture = true; |
} |
if (rmesa->radeon.glCtx.Mesa_DXTn) { |
ctx->Extensions.EXT_texture_compression_s3tc = true; |
ctx->Extensions.ANGLE_texture_compression_dxt = true; |
} |
else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) { |
ctx->Extensions.EXT_texture_compression_s3tc = true; |
ctx->Extensions.ANGLE_texture_compression_dxt = true; |
} |
ctx->Extensions.ARB_texture_cube_map = true; |
ctx->Extensions.EXT_blend_equation_separate = true; |
ctx->Extensions.EXT_blend_func_separate = true; |
ctx->Extensions.ARB_vertex_program = true; |
ctx->Extensions.EXT_gpu_program_parameters = true; |
ctx->Extensions.ATI_fragment_shader = (ctx->Const.MaxTextureUnits == 6); |
ctx->Extensions.ARB_point_sprite = true; |
ctx->Extensions.EXT_point_parameters = true; |
#if 0 |
r200InitDriverFuncs( ctx ); |
r200InitIoctlFuncs( ctx ); |
r200InitStateFuncs( ctx ); |
r200InitTextureFuncs( ctx ); |
#endif |
/* plug in a few more device driver functions */ |
/* XXX these should really go right after _mesa_init_driver_functions() */ |
radeon_fbo_init(&rmesa->radeon); |
radeonInitSpanFuncs( ctx ); |
r200InitTnlFuncs( ctx ); |
r200InitState( rmesa ); |
r200InitSwtcl( ctx ); |
rmesa->prefer_gart_client_texturing = |
(getenv("R200_GART_CLIENT_TEXTURES") != 0); |
tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode"); |
if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) { |
fprintf(stderr, "disabling 3D acceleration\n"); |
FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1); |
} |
else if (tcl_mode == DRI_CONF_TCL_SW || getenv("R200_NO_TCL") || |
!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) { |
if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) { |
rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL; |
fprintf(stderr, "Disabling HW TCL support\n"); |
} |
TCL_FALLBACK(&rmesa->radeon.glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1); |
} |
_mesa_compute_version(ctx); |
/* Exec table initialization requires the version to be computed */ |
_mesa_initialize_dispatch_tables(ctx); |
_mesa_initialize_vbo_vtxfmt(ctx); |
*error = __DRI_CTX_ERROR_SUCCESS; |
return GL_TRUE; |
} |
void r200DestroyContext( __DRIcontext *driContextPriv ) |
{ |
int i; |
r200ContextPtr rmesa = (r200ContextPtr)driContextPriv->driverPrivate; |
if (rmesa) |
{ |
for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS ; i++ ) { |
_math_matrix_dtr( &rmesa->TexGenMatrix[i] ); |
} |
} |
radeonDestroyContext(driContextPriv); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_context.h |
---|
0,0 → 1,658 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 __R200_CONTEXT_H__ |
#define __R200_CONTEXT_H__ |
#include "tnl/t_vertex.h" |
#include "drm.h" |
#include "radeon_drm.h" |
#include "dri_util.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/colormac.h" |
#include "r200_reg.h" |
#include "r200_vertprog.h" |
#ifndef R200_EMIT_VAP_PVS_CNTL |
#error This driver requires a newer libdrm to compile |
#endif |
#include "radeon_screen.h" |
#include "radeon_common.h" |
struct r200_context; |
typedef struct r200_context r200ContextRec; |
typedef struct r200_context *r200ContextPtr; |
#include "main/mm.h" |
struct r200_vertex_program { |
struct gl_vertex_program mesa_program; /* Must be first */ |
int translated; |
/* need excess instr: 1 for late loop checking, 2 for |
additional instr due to instr/attr, 3 for fog */ |
VERTEX_SHADER_INSTRUCTION instr[R200_VSF_MAX_INST + 6]; |
int pos_end; |
int inputs[VERT_ATTRIB_MAX]; |
GLubyte inputmap_rev[16]; |
int native; |
int fogpidx; |
int fogmode; |
}; |
#define R200_TEX_ALL 0x3f |
struct r200_texture_env_state { |
radeonTexObjPtr texobj; |
GLuint outputreg; |
GLuint unitneeded; |
}; |
#define R200_MAX_TEXTURE_UNITS 6 |
struct r200_texture_state { |
struct r200_texture_env_state unit[R200_MAX_TEXTURE_UNITS]; |
}; |
/* Trying to keep these relatively short as the variables are becoming |
* extravagently long. Drop the driver name prefix off the front of |
* everything - I think we know which driver we're in by now, and keep the |
* prefix to 3 letters unless absolutely impossible. |
*/ |
#define CTX_CMD_0 0 |
#define CTX_PP_MISC 1 |
#define CTX_PP_FOG_COLOR 2 |
#define CTX_RE_SOLID_COLOR 3 |
#define CTX_RB3D_BLENDCNTL 4 |
#define CTX_RB3D_DEPTHOFFSET 5 |
#define CTX_RB3D_DEPTHPITCH 6 |
#define CTX_RB3D_ZSTENCILCNTL 7 |
#define CTX_CMD_1 8 |
#define CTX_PP_CNTL 9 |
#define CTX_RB3D_CNTL 10 |
#define CTX_RB3D_COLOROFFSET 11 |
#define CTX_CMD_2 12 /* why */ |
#define CTX_RB3D_COLORPITCH 13 /* why */ |
#define CTX_STATE_SIZE_OLDDRM 14 |
#define CTX_CMD_3 14 |
#define CTX_RB3D_BLENDCOLOR 15 |
#define CTX_RB3D_ABLENDCNTL 16 |
#define CTX_RB3D_CBLENDCNTL 17 |
#define CTX_STATE_SIZE_NEWDRM 18 |
#define SET_CMD_0 0 |
#define SET_SE_CNTL 1 |
#define SET_RE_CNTL 2 /* replace se_coord_fmt */ |
#define SET_STATE_SIZE 3 |
#define VTE_CMD_0 0 |
#define VTE_SE_VTE_CNTL 1 |
#define VTE_STATE_SIZE 2 |
#define LIN_CMD_0 0 |
#define LIN_RE_LINE_PATTERN 1 |
#define LIN_RE_LINE_STATE 2 |
#define LIN_CMD_1 3 |
#define LIN_SE_LINE_WIDTH 4 |
#define LIN_STATE_SIZE 5 |
#define MSK_CMD_0 0 |
#define MSK_RB3D_STENCILREFMASK 1 |
#define MSK_RB3D_ROPCNTL 2 |
#define MSK_RB3D_PLANEMASK 3 |
#define MSK_STATE_SIZE 4 |
#define VPT_CMD_0 0 |
#define VPT_SE_VPORT_XSCALE 1 |
#define VPT_SE_VPORT_XOFFSET 2 |
#define VPT_SE_VPORT_YSCALE 3 |
#define VPT_SE_VPORT_YOFFSET 4 |
#define VPT_SE_VPORT_ZSCALE 5 |
#define VPT_SE_VPORT_ZOFFSET 6 |
#define VPT_STATE_SIZE 7 |
#define ZBS_CMD_0 0 |
#define ZBS_SE_ZBIAS_FACTOR 1 |
#define ZBS_SE_ZBIAS_CONSTANT 2 |
#define ZBS_STATE_SIZE 3 |
#define MSC_CMD_0 0 |
#define MSC_RE_MISC 1 |
#define MSC_STATE_SIZE 2 |
#define TAM_CMD_0 0 |
#define TAM_DEBUG3 1 |
#define TAM_STATE_SIZE 2 |
#define TEX_CMD_0 0 |
#define TEX_PP_TXFILTER 1 /*2c00*/ |
#define TEX_PP_TXFORMAT 2 /*2c04*/ |
#define TEX_PP_TXFORMAT_X 3 /*2c08*/ |
#define TEX_PP_TXSIZE 4 /*2c0c*/ |
#define TEX_PP_TXPITCH 5 /*2c10*/ |
#define TEX_PP_BORDER_COLOR 6 /*2c14*/ |
#define TEX_CMD_1_OLDDRM 7 |
#define TEX_PP_TXOFFSET_OLDDRM 8 /*2d00 */ |
#define TEX_STATE_SIZE_OLDDRM 9 |
#define TEX_PP_CUBIC_FACES 7 |
#define TEX_PP_TXMULTI_CTL 8 |
#define TEX_CMD_1_NEWDRM 9 |
#define TEX_PP_TXOFFSET_NEWDRM 10 |
#define TEX_STATE_SIZE_NEWDRM 11 |
#define CUBE_CMD_0 0 /* 1 register follows */ /* this command unnecessary */ |
#define CUBE_PP_CUBIC_FACES 1 /* 0x2c18 */ /* with new enough drm */ |
#define CUBE_CMD_1 2 /* 5 registers follow */ |
#define CUBE_PP_CUBIC_OFFSET_F1 3 /* 0x2d04 */ |
#define CUBE_PP_CUBIC_OFFSET_F2 4 /* 0x2d08 */ |
#define CUBE_PP_CUBIC_OFFSET_F3 5 /* 0x2d0c */ |
#define CUBE_PP_CUBIC_OFFSET_F4 6 /* 0x2d10 */ |
#define CUBE_PP_CUBIC_OFFSET_F5 7 /* 0x2d14 */ |
#define CUBE_STATE_SIZE 8 |
#define PIX_CMD_0 0 |
#define PIX_PP_TXCBLEND 1 |
#define PIX_PP_TXCBLEND2 2 |
#define PIX_PP_TXABLEND 3 |
#define PIX_PP_TXABLEND2 4 |
#define PIX_STATE_SIZE 5 |
#define TF_CMD_0 0 |
#define TF_TFACTOR_0 1 |
#define TF_TFACTOR_1 2 |
#define TF_TFACTOR_2 3 |
#define TF_TFACTOR_3 4 |
#define TF_TFACTOR_4 5 |
#define TF_TFACTOR_5 6 |
#define TF_STATE_SIZE 7 |
#define ATF_CMD_0 0 |
#define ATF_TFACTOR_0 1 |
#define ATF_TFACTOR_1 2 |
#define ATF_TFACTOR_2 3 |
#define ATF_TFACTOR_3 4 |
#define ATF_TFACTOR_4 5 |
#define ATF_TFACTOR_5 6 |
#define ATF_TFACTOR_6 7 |
#define ATF_TFACTOR_7 8 |
#define ATF_STATE_SIZE 9 |
/* ATI_FRAGMENT_SHADER */ |
#define AFS_CMD_0 0 |
#define AFS_IC0 1 /* 2f00 */ |
#define AFS_IC1 2 /* 2f04 */ |
#define AFS_IA0 3 /* 2f08 */ |
#define AFS_IA1 4 /* 2f0c */ |
#define AFS_STATE_SIZE 33 |
#define PVS_CMD_0 0 |
#define PVS_CNTL_1 1 |
#define PVS_CNTL_2 2 |
#define PVS_STATE_SIZE 3 |
/* those are quite big... */ |
#define VPI_CMD_0 0 |
#define VPI_OPDST_0 1 |
#define VPI_SRC0_0 2 |
#define VPI_SRC1_0 3 |
#define VPI_SRC2_0 4 |
#define VPI_OPDST_63 253 |
#define VPI_SRC0_63 254 |
#define VPI_SRC1_63 255 |
#define VPI_SRC2_63 256 |
#define VPI_STATE_SIZE 257 |
#define VPP_CMD_0 0 |
#define VPP_PARAM0_0 1 |
#define VPP_PARAM1_0 2 |
#define VPP_PARAM2_0 3 |
#define VPP_PARAM3_0 4 |
#define VPP_PARAM0_95 381 |
#define VPP_PARAM1_95 382 |
#define VPP_PARAM2_95 383 |
#define VPP_PARAM3_95 384 |
#define VPP_STATE_SIZE 385 |
#define TCL_CMD_0 0 |
#define TCL_LIGHT_MODEL_CTL_0 1 |
#define TCL_LIGHT_MODEL_CTL_1 2 |
#define TCL_PER_LIGHT_CTL_0 3 |
#define TCL_PER_LIGHT_CTL_1 4 |
#define TCL_PER_LIGHT_CTL_2 5 |
#define TCL_PER_LIGHT_CTL_3 6 |
#define TCL_CMD_1 7 |
#define TCL_UCP_VERT_BLEND_CTL 8 |
#define TCL_STATE_SIZE 9 |
#define MSL_CMD_0 0 |
#define MSL_MATRIX_SELECT_0 1 |
#define MSL_MATRIX_SELECT_1 2 |
#define MSL_MATRIX_SELECT_2 3 |
#define MSL_MATRIX_SELECT_3 4 |
#define MSL_MATRIX_SELECT_4 5 |
#define MSL_STATE_SIZE 6 |
#define TCG_CMD_0 0 |
#define TCG_TEX_PROC_CTL_2 1 |
#define TCG_TEX_PROC_CTL_3 2 |
#define TCG_TEX_PROC_CTL_0 3 |
#define TCG_TEX_PROC_CTL_1 4 |
#define TCG_TEX_CYL_WRAP_CTL 5 |
#define TCG_STATE_SIZE 6 |
#define MTL_CMD_0 0 |
#define MTL_EMMISSIVE_RED 1 |
#define MTL_EMMISSIVE_GREEN 2 |
#define MTL_EMMISSIVE_BLUE 3 |
#define MTL_EMMISSIVE_ALPHA 4 |
#define MTL_AMBIENT_RED 5 |
#define MTL_AMBIENT_GREEN 6 |
#define MTL_AMBIENT_BLUE 7 |
#define MTL_AMBIENT_ALPHA 8 |
#define MTL_DIFFUSE_RED 9 |
#define MTL_DIFFUSE_GREEN 10 |
#define MTL_DIFFUSE_BLUE 11 |
#define MTL_DIFFUSE_ALPHA 12 |
#define MTL_SPECULAR_RED 13 |
#define MTL_SPECULAR_GREEN 14 |
#define MTL_SPECULAR_BLUE 15 |
#define MTL_SPECULAR_ALPHA 16 |
#define MTL_CMD_1 17 |
#define MTL_SHININESS 18 |
#define MTL_STATE_SIZE 19 |
#define VAP_CMD_0 0 |
#define VAP_SE_VAP_CNTL 1 |
#define VAP_STATE_SIZE 2 |
/* Replaces a lot of packet info from radeon |
*/ |
#define VTX_CMD_0 0 |
#define VTX_VTXFMT_0 1 |
#define VTX_VTXFMT_1 2 |
#define VTX_TCL_OUTPUT_VTXFMT_0 3 |
#define VTX_TCL_OUTPUT_VTXFMT_1 4 |
#define VTX_CMD_1 5 |
#define VTX_TCL_OUTPUT_COMPSEL 6 |
#define VTX_CMD_2 7 |
#define VTX_STATE_CNTL 8 |
#define VTX_STATE_SIZE 9 |
/* SPR - point sprite state |
*/ |
#define SPR_CMD_0 0 |
#define SPR_POINT_SPRITE_CNTL 1 |
#define SPR_STATE_SIZE 2 |
#define PTP_CMD_0 0 |
#define PTP_VPORT_SCALE_0 1 |
#define PTP_VPORT_SCALE_1 2 |
#define PTP_VPORT_SCALE_PTSIZE 3 |
#define PTP_VPORT_SCALE_3 4 |
#define PTP_CMD_1 5 |
#define PTP_ATT_CONST_QUAD 6 |
#define PTP_ATT_CONST_LIN 7 |
#define PTP_ATT_CONST_CON 8 |
#define PTP_ATT_CONST_3 9 |
#define PTP_EYE_X 10 |
#define PTP_EYE_Y 11 |
#define PTP_EYE_Z 12 |
#define PTP_EYE_3 13 |
#define PTP_CLAMP_MIN 14 |
#define PTP_CLAMP_MAX 15 |
#define PTP_CLAMP_2 16 |
#define PTP_CLAMP_3 17 |
#define PTP_STATE_SIZE 18 |
#define VTX_COLOR(v,n) (((v)>>(R200_VTX_COLOR_0_SHIFT+(n)*2))&\ |
R200_VTX_COLOR_MASK) |
/** |
* Given the \c R200_SE_VTX_FMT_1 for the current vertex state, determine |
* how many components are in texture coordinate \c n. |
*/ |
#define VTX_TEXn_COUNT(v,n) (((v) >> (3 * n)) & 0x07) |
#define MAT_CMD_0 0 |
#define MAT_ELT_0 1 |
#define MAT_STATE_SIZE 17 |
#define GRD_CMD_0 0 |
#define GRD_VERT_GUARD_CLIP_ADJ 1 |
#define GRD_VERT_GUARD_DISCARD_ADJ 2 |
#define GRD_HORZ_GUARD_CLIP_ADJ 3 |
#define GRD_HORZ_GUARD_DISCARD_ADJ 4 |
#define GRD_STATE_SIZE 5 |
/* position changes frequently when lighting in modelpos - separate |
* out to new state item? |
*/ |
#define LIT_CMD_0 0 |
#define LIT_AMBIENT_RED 1 |
#define LIT_AMBIENT_GREEN 2 |
#define LIT_AMBIENT_BLUE 3 |
#define LIT_AMBIENT_ALPHA 4 |
#define LIT_DIFFUSE_RED 5 |
#define LIT_DIFFUSE_GREEN 6 |
#define LIT_DIFFUSE_BLUE 7 |
#define LIT_DIFFUSE_ALPHA 8 |
#define LIT_SPECULAR_RED 9 |
#define LIT_SPECULAR_GREEN 10 |
#define LIT_SPECULAR_BLUE 11 |
#define LIT_SPECULAR_ALPHA 12 |
#define LIT_POSITION_X 13 |
#define LIT_POSITION_Y 14 |
#define LIT_POSITION_Z 15 |
#define LIT_POSITION_W 16 |
#define LIT_DIRECTION_X 17 |
#define LIT_DIRECTION_Y 18 |
#define LIT_DIRECTION_Z 19 |
#define LIT_DIRECTION_W 20 |
#define LIT_ATTEN_QUADRATIC 21 |
#define LIT_ATTEN_LINEAR 22 |
#define LIT_ATTEN_CONST 23 |
#define LIT_ATTEN_XXX 24 |
#define LIT_CMD_1 25 |
#define LIT_SPOT_DCD 26 |
#define LIT_SPOT_DCM 27 |
#define LIT_SPOT_EXPONENT 28 |
#define LIT_SPOT_CUTOFF 29 |
#define LIT_SPECULAR_THRESH 30 |
#define LIT_RANGE_CUTOFF 31 /* ? */ |
#define LIT_ATTEN_CONST_INV 32 |
#define LIT_STATE_SIZE 33 |
/* Fog |
*/ |
#define FOG_CMD_0 0 |
#define FOG_R 1 |
#define FOG_C 2 |
#define FOG_D 3 |
#define FOG_PAD 4 |
#define FOG_STATE_SIZE 5 |
/* UCP |
*/ |
#define UCP_CMD_0 0 |
#define UCP_X 1 |
#define UCP_Y 2 |
#define UCP_Z 3 |
#define UCP_W 4 |
#define UCP_STATE_SIZE 5 |
/* GLT - Global ambient |
*/ |
#define GLT_CMD_0 0 |
#define GLT_RED 1 |
#define GLT_GREEN 2 |
#define GLT_BLUE 3 |
#define GLT_ALPHA 4 |
#define GLT_STATE_SIZE 5 |
/* EYE |
*/ |
#define EYE_CMD_0 0 |
#define EYE_X 1 |
#define EYE_Y 2 |
#define EYE_Z 3 |
#define EYE_RESCALE_FACTOR 4 |
#define EYE_STATE_SIZE 5 |
/* CST - constant state |
*/ |
#define CST_CMD_0 0 |
#define CST_PP_CNTL_X 1 |
#define CST_CMD_1 2 |
#define CST_RB3D_DEPTHXY_OFFSET 3 |
#define CST_CMD_2 4 |
#define CST_RE_AUX_SCISSOR_CNTL 5 |
#define CST_CMD_4 6 |
#define CST_SE_VAP_CNTL_STATUS 7 |
#define CST_CMD_5 8 |
#define CST_RE_POINTSIZE 9 |
#define CST_CMD_6 10 |
#define CST_SE_TCL_INPUT_VTX_0 11 |
#define CST_SE_TCL_INPUT_VTX_1 12 |
#define CST_SE_TCL_INPUT_VTX_2 13 |
#define CST_SE_TCL_INPUT_VTX_3 14 |
#define CST_STATE_SIZE 15 |
#define PRF_CMD_0 0 |
#define PRF_PP_TRI_PERF 1 |
#define PRF_PP_PERF_CNTL 2 |
#define PRF_STATE_SIZE 3 |
#define SCI_CMD_1 0 |
#define SCI_XY_1 1 |
#define SCI_CMD_2 2 |
#define SCI_XY_2 3 |
#define SCI_STATE_SIZE 4 |
#define R200_QUERYOBJ_CMD_0 0 |
#define R200_QUERYOBJ_DATA_0 1 |
#define R200_QUERYOBJ_CMDSIZE 2 |
#define STP_CMD_0 0 |
#define STP_DATA_0 1 |
#define STP_CMD_1 2 |
#define STP_STATE_SIZE 35 |
struct r200_hw_state { |
/* Hardware state, stored as cmdbuf commands: |
* -- Need to doublebuffer for |
* - reviving state after loss of context |
* - eliding noop statechange loops? (except line stipple count) |
*/ |
struct radeon_state_atom ctx; |
struct radeon_state_atom set; |
struct radeon_state_atom sci; |
struct radeon_state_atom vte; |
struct radeon_state_atom lin; |
struct radeon_state_atom msk; |
struct radeon_state_atom vpt; |
struct radeon_state_atom vap; |
struct radeon_state_atom vtx; |
struct radeon_state_atom tcl; |
struct radeon_state_atom msl; |
struct radeon_state_atom tcg; |
struct radeon_state_atom msc; |
struct radeon_state_atom cst; |
struct radeon_state_atom tam; |
struct radeon_state_atom tf; |
struct radeon_state_atom tex[6]; |
struct radeon_state_atom cube[6]; |
struct radeon_state_atom zbs; |
struct radeon_state_atom mtl[2]; |
struct radeon_state_atom mat[9]; |
struct radeon_state_atom lit[8]; /* includes vec, scl commands */ |
struct radeon_state_atom ucp[6]; |
struct radeon_state_atom pix[6]; /* pixshader stages */ |
struct radeon_state_atom eye; /* eye pos */ |
struct radeon_state_atom grd; /* guard band clipping */ |
struct radeon_state_atom fog; |
struct radeon_state_atom glt; |
struct radeon_state_atom prf; |
struct radeon_state_atom afs[2]; |
struct radeon_state_atom pvs; |
struct radeon_state_atom vpi[2]; |
struct radeon_state_atom vpp[2]; |
struct radeon_state_atom atf; |
struct radeon_state_atom spr; |
struct radeon_state_atom ptp; |
struct radeon_state_atom stp; |
}; |
struct r200_state { |
/* Derived state for internal purposes: |
*/ |
struct r200_texture_state texture; |
GLuint envneeded; |
}; |
#define R200_CMD_BUF_SZ (16*1024) |
#define R200_ELT_BUF_SZ (16*1024) |
/* r200_tcl.c |
*/ |
struct r200_tcl_info { |
GLuint hw_primitive; |
int elt_used; |
}; |
/* r200_swtcl.c |
*/ |
struct r200_swtcl_info { |
radeon_point_func draw_point; |
radeon_line_func draw_line; |
radeon_tri_func draw_tri; |
/** |
* Offset of the 4UB color data within a hardware (swtcl) vertex. |
*/ |
GLuint coloroffset; |
/** |
* Offset of the 3UB specular color data within a hardware (swtcl) vertex. |
*/ |
GLuint specoffset; |
/** |
* Should Mesa project vertex data or will the hardware do it? |
*/ |
GLboolean needproj; |
}; |
/* A maximum total of 29 elements per vertex: 3 floats for position, 3 |
* floats for normal, 4 floats for color, 4 bytes for secondary color, |
* 3 floats for each texture unit (18 floats total). |
* |
* we maybe need add. 4 to prevent segfault if someone specifies |
* GL_TEXTURE6/GL_TEXTURE7 (esp. for the codegen-path) (FIXME: ) |
* |
* The position data is never actually stored here, so 3 elements could be |
* trimmed out of the buffer. |
*/ |
#define R200_MAX_VERTEX_SIZE ((3*6)+11) |
struct r200_context { |
struct radeon_context radeon; |
/* Driver and hardware state management |
*/ |
struct r200_hw_state hw; |
struct r200_state state; |
struct r200_vertex_program *curr_vp_hw; |
/* Vertex buffers |
*/ |
struct radeon_ioctl ioctl; |
struct radeon_store store; |
/* Clientdata textures; |
*/ |
GLuint prefer_gart_client_texturing; |
/* TCL stuff |
*/ |
GLmatrix TexGenMatrix[R200_MAX_TEXTURE_UNITS]; |
GLboolean recheck_texgen[R200_MAX_TEXTURE_UNITS]; |
GLboolean TexGenNeedNormals[R200_MAX_TEXTURE_UNITS]; |
GLuint TexMatEnabled; |
GLuint TexMatCompSel; |
GLuint TexGenEnabled; |
GLuint TexGenCompSel; |
GLmatrix tmpmat; |
/* r200_tcl.c |
*/ |
struct r200_tcl_info tcl; |
/* r200_swtcl.c |
*/ |
struct r200_swtcl_info swtcl; |
GLboolean using_hyperz; |
GLboolean texmicrotile; |
struct ati_fragment_shader *afs_loaded; |
}; |
static inline r200ContextPtr |
R200_CONTEXT(struct gl_context *ctx) |
{ |
return (r200ContextPtr) ctx; |
} |
extern void r200DestroyContext( __DRIcontext *driContextPriv ); |
extern GLboolean r200CreateContext( gl_api api, |
const struct gl_config *glVisual, |
__DRIcontext *driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
uint32_t flags, |
unsigned *error, |
void *sharedContextPrivate); |
extern GLboolean r200MakeCurrent( __DRIcontext *driContextPriv, |
__DRIdrawable *driDrawPriv, |
__DRIdrawable *driReadPriv ); |
extern GLboolean r200UnbindContext( __DRIcontext *driContextPriv ); |
extern void r200_init_texcopy_functions(struct dd_function_table *table); |
/* ================================================================ |
* Debugging: |
*/ |
#define R200_DEBUG RADEON_DEBUG |
#endif /* __R200_CONTEXT_H__ */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_fragshader.c |
---|
0,0 → 1,548 |
/************************************************************************** |
* |
* Copyright 2004 David Airlie |
* 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 DAVID AIRLIE 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 "main/glheader.h" |
#include "main/atifragshader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "tnl/t_context.h" |
#include "program/program.h" |
#include "r200_context.h" |
#include "r200_ioctl.h" |
#include "r200_tex.h" |
#define SET_INST(inst, type) afs_cmd[((inst<<2) + (type<<1) + 1)] |
#define SET_INST_2(inst, type) afs_cmd[((inst<<2) + (type<<1) + 2)] |
static void r200SetFragShaderArg( GLuint *afs_cmd, GLuint opnum, GLuint optype, |
const struct atifragshader_src_register srcReg, |
GLuint argPos, GLuint *tfactor ) |
{ |
const GLuint index = srcReg.Index; |
const GLuint srcmod = srcReg.argMod; |
const GLuint srcrep = srcReg.argRep; |
GLuint reg0 = 0; |
GLuint reg2 = 0; |
GLuint useOddSrc = 0; |
switch(srcrep) { |
case GL_RED: |
reg2 |= R200_TXC_REPL_RED << (R200_TXC_REPL_ARG_A_SHIFT + (2*argPos)); |
if (optype) |
useOddSrc = 1; |
break; |
case GL_GREEN: |
reg2 |= R200_TXC_REPL_GREEN << (R200_TXC_REPL_ARG_A_SHIFT + (2*argPos)); |
if (optype) |
useOddSrc = 1; |
break; |
case GL_BLUE: |
if (!optype) |
reg2 |= R200_TXC_REPL_BLUE << (R200_TXC_REPL_ARG_A_SHIFT + (2*argPos)); |
else |
useOddSrc = 1; |
break; |
case GL_ALPHA: |
if (!optype) |
useOddSrc = 1; |
break; |
} |
if (index >= GL_REG_0_ATI && index <= GL_REG_5_ATI) |
reg0 |= (((index - GL_REG_0_ATI)*2) + 10 + useOddSrc) << (5*argPos); |
else if (index >= GL_CON_0_ATI && index <= GL_CON_7_ATI) { |
if ((*tfactor == 0) || (index == *tfactor)) { |
reg0 |= (R200_TXC_ARG_A_TFACTOR_COLOR + useOddSrc) << (5*argPos); |
reg2 |= (index - GL_CON_0_ATI) << R200_TXC_TFACTOR_SEL_SHIFT; |
*tfactor = index; |
} |
else { |
reg0 |= (R200_TXC_ARG_A_TFACTOR1_COLOR + useOddSrc) << (5*argPos); |
reg2 |= (index - GL_CON_0_ATI) << R200_TXC_TFACTOR1_SEL_SHIFT; |
} |
} |
else if (index == GL_PRIMARY_COLOR_EXT) { |
reg0 |= (R200_TXC_ARG_A_DIFFUSE_COLOR + useOddSrc) << (5*argPos); |
} |
else if (index == GL_SECONDARY_INTERPOLATOR_ATI) { |
reg0 |= (R200_TXC_ARG_A_SPECULAR_COLOR + useOddSrc) << (5*argPos); |
} |
/* GL_ZERO is a noop, for GL_ONE we set the complement */ |
else if (index == GL_ONE) { |
reg0 |= R200_TXC_COMP_ARG_A << (4*argPos); |
} |
if (srcmod & GL_COMP_BIT_ATI) |
reg0 ^= R200_TXC_COMP_ARG_A << (4*argPos); |
if (srcmod & GL_BIAS_BIT_ATI) |
reg0 |= R200_TXC_BIAS_ARG_A << (4*argPos); |
if (srcmod & GL_2X_BIT_ATI) |
reg0 |= R200_TXC_SCALE_ARG_A << (4*argPos); |
if (srcmod & GL_NEGATE_BIT_ATI) |
reg0 ^= R200_TXC_NEG_ARG_A << (4*argPos); |
SET_INST(opnum, optype) |= reg0; |
SET_INST_2(opnum, optype) |= reg2; |
} |
static GLuint dstmask_table[8] = |
{ |
R200_TXC_OUTPUT_MASK_RGB, |
R200_TXC_OUTPUT_MASK_R, |
R200_TXC_OUTPUT_MASK_G, |
R200_TXC_OUTPUT_MASK_RG, |
R200_TXC_OUTPUT_MASK_B, |
R200_TXC_OUTPUT_MASK_RB, |
R200_TXC_OUTPUT_MASK_GB, |
R200_TXC_OUTPUT_MASK_RGB |
}; |
static void r200UpdateFSArith( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint *afs_cmd; |
const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current; |
GLuint pass; |
R200_STATECHANGE( rmesa, afs[0] ); |
R200_STATECHANGE( rmesa, afs[1] ); |
if (shader->NumPasses < 2) { |
afs_cmd = (GLuint *) rmesa->hw.afs[1].cmd; |
} |
else { |
afs_cmd = (GLuint *) rmesa->hw.afs[0].cmd; |
} |
for (pass = 0; pass < shader->NumPasses; pass++) { |
GLuint opnum = 0; |
GLuint pc; |
for (pc = 0; pc < shader->numArithInstr[pass]; pc++) { |
GLuint optype; |
struct atifs_instruction *inst = &shader->Instructions[pass][pc]; |
SET_INST(opnum, 0) = 0; |
SET_INST_2(opnum, 0) = 0; |
SET_INST(opnum, 1) = 0; |
SET_INST_2(opnum, 1) = 0; |
for (optype = 0; optype < 2; optype++) { |
GLuint tfactor = 0; |
if (inst->Opcode[optype]) { |
switch (inst->Opcode[optype]) { |
/* these are all MADD in disguise |
MADD is A * B + C |
so for GL_ADD use arg B/C and make A complement 0 |
for GL_SUB use arg B/C, negate C and make A complement 0 |
for GL_MOV use arg C |
for GL_MUL use arg A |
for GL_MAD all good */ |
case GL_SUB_ATI: |
/* negate C */ |
SET_INST(opnum, optype) |= R200_TXC_NEG_ARG_C; |
/* fallthrough */ |
case GL_ADD_ATI: |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][0], 1, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][1], 2, &tfactor); |
/* A = complement 0 */ |
SET_INST(opnum, optype) |= R200_TXC_COMP_ARG_A; |
SET_INST(opnum, optype) |= R200_TXC_OP_MADD; |
break; |
case GL_MOV_ATI: |
/* put arg0 in C */ |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][0], 2, &tfactor); |
SET_INST(opnum, optype) |= R200_TXC_OP_MADD; |
break; |
case GL_MAD_ATI: |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][2], 2, &tfactor); |
/* fallthrough */ |
case GL_MUL_ATI: |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][0], 0, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][1], 1, &tfactor); |
SET_INST(opnum, optype) |= R200_TXC_OP_MADD; |
break; |
case GL_LERP_ATI: |
/* arg order is not native chip order, swap A and C */ |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][0], 2, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][1], 1, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][2], 0, &tfactor); |
SET_INST(opnum, optype) |= R200_TXC_OP_LERP; |
break; |
case GL_CND_ATI: |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][0], 0, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][1], 1, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][2], 2, &tfactor); |
SET_INST(opnum, optype) |= R200_TXC_OP_CONDITIONAL; |
break; |
case GL_CND0_ATI: |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][0], 0, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][1], 1, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, optype, |
inst->SrcReg[optype][2], 2, &tfactor); |
SET_INST(opnum, optype) |= R200_TXC_OP_CND0; |
break; |
/* cannot specify dot ops as alpha ops directly */ |
case GL_DOT2_ADD_ATI: |
if (optype) |
SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA; |
else { |
r200SetFragShaderArg(afs_cmd, opnum, 0, |
inst->SrcReg[0][0], 0, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, 0, |
inst->SrcReg[0][1], 1, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, 0, |
inst->SrcReg[0][2], 2, &tfactor); |
SET_INST(opnum, 0) |= R200_TXC_OP_DOT2_ADD; |
} |
break; |
case GL_DOT3_ATI: |
if (optype) |
SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA; |
else { |
r200SetFragShaderArg(afs_cmd, opnum, 0, |
inst->SrcReg[0][0], 0, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, 0, |
inst->SrcReg[0][1], 1, &tfactor); |
SET_INST(opnum, 0) |= R200_TXC_OP_DOT3; |
} |
break; |
case GL_DOT4_ATI: |
/* experimental verification: for dot4 setup of alpha args is needed |
(dstmod is ignored, though, so dot2/dot3 should be safe) |
the hardware apparently does R1*R2 + G1*G2 + B1*B2 + A3*A4 |
but the API doesn't allow it */ |
if (optype) |
SET_INST_2(opnum, 1) |= R200_TXA_DOT_ALPHA; |
else { |
r200SetFragShaderArg(afs_cmd, opnum, 0, |
inst->SrcReg[0][0], 0, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, 0, |
inst->SrcReg[0][1], 1, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, 1, |
inst->SrcReg[0][0], 0, &tfactor); |
r200SetFragShaderArg(afs_cmd, opnum, 1, |
inst->SrcReg[0][1], 1, &tfactor); |
SET_INST(opnum, optype) |= R200_TXC_OP_DOT4; |
} |
break; |
} |
} |
/* destination */ |
if (inst->DstReg[optype].Index) { |
GLuint dstreg = inst->DstReg[optype].Index - GL_REG_0_ATI; |
GLuint dstmask = inst->DstReg[optype].dstMask; |
GLuint sat = inst->DstReg[optype].dstMod & GL_SATURATE_BIT_ATI; |
GLuint dstmod = inst->DstReg[optype].dstMod; |
dstmod &= ~GL_SATURATE_BIT_ATI; |
SET_INST_2(opnum, optype) |= (dstreg + 1) << R200_TXC_OUTPUT_REG_SHIFT; |
SET_INST_2(opnum, optype) |= dstmask_table[dstmask]; |
/* fglrx does clamp the last instructions to 0_1 it seems */ |
/* this won't necessarily catch the last instruction |
which writes to reg0 */ |
if (sat || (pc == (shader->numArithInstr[pass] - 1) && |
((pass == 1) || (shader->NumPasses == 1)))) |
SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_0_1; |
else |
/*should we clamp or not? spec is vague, I would suppose yes but fglrx doesn't */ |
SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_8_8; |
/* SET_INST_2(opnum, optype) |= R200_TXC_CLAMP_WRAP;*/ |
switch(dstmod) { |
case GL_2X_BIT_ATI: |
SET_INST_2(opnum, optype) |= R200_TXC_SCALE_2X; |
break; |
case GL_4X_BIT_ATI: |
SET_INST_2(opnum, optype) |= R200_TXC_SCALE_4X; |
break; |
case GL_8X_BIT_ATI: |
SET_INST_2(opnum, optype) |= R200_TXC_SCALE_8X; |
break; |
case GL_HALF_BIT_ATI: |
SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV2; |
break; |
case GL_QUARTER_BIT_ATI: |
SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV4; |
break; |
case GL_EIGHTH_BIT_ATI: |
SET_INST_2(opnum, optype) |= R200_TXC_SCALE_INV8; |
break; |
default: |
break; |
} |
} |
} |
/* fprintf(stderr, "pass %d nr %d inst 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", |
pass, opnum, SET_INST(opnum, 0), SET_INST_2(opnum, 0), |
SET_INST(opnum, 1), SET_INST_2(opnum, 1));*/ |
opnum++; |
} |
afs_cmd = (GLuint *) rmesa->hw.afs[1].cmd; |
} |
rmesa->afs_loaded = ctx->ATIFragmentShader.Current; |
} |
static void r200UpdateFSRouting( struct gl_context *ctx ) { |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current; |
GLuint reg; |
R200_STATECHANGE( rmesa, ctx ); |
R200_STATECHANGE( rmesa, cst ); |
for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) { |
if (shader->swizzlerq & (1 << (2 * reg))) |
/* r coord */ |
set_re_cntl_d3d( ctx, reg, 1); |
/* q coord */ |
else set_re_cntl_d3d( ctx, reg, 0); |
} |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_MULTI_PASS_ENABLE | |
R200_TEX_BLEND_ENABLE_MASK | |
R200_TEX_ENABLE_MASK); |
rmesa->hw.cst.cmd[CST_PP_CNTL_X] &= ~(R200_PPX_PFS_INST_ENABLE_MASK | |
R200_PPX_TEX_ENABLE_MASK | |
R200_PPX_OUTPUT_REG_MASK); |
/* first pass registers use slots 8 - 15 |
but single pass shaders use slots 0 - 7 */ |
if (shader->NumPasses < 2) { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->numArithInstr[0] == 8 ? |
0xff << (R200_TEX_BLEND_0_ENABLE_SHIFT - 1) : |
(0xff >> (8 - shader->numArithInstr[0])) << R200_TEX_BLEND_0_ENABLE_SHIFT; |
} else { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_MULTI_PASS_ENABLE; |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= shader->numArithInstr[1] == 8 ? |
0xff << (R200_TEX_BLEND_0_ENABLE_SHIFT - 1) : |
(0xff >> (8 - shader->numArithInstr[1])) << R200_TEX_BLEND_0_ENABLE_SHIFT; |
rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= |
(0xff >> (8 - shader->numArithInstr[0])) << R200_PPX_FPS_INST0_ENABLE_SHIFT; |
} |
if (shader->NumPasses < 2) { |
for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) { |
GLbitfield targetbit = ctx->Texture.Unit[reg]._ReallyEnabled; |
R200_STATECHANGE( rmesa, tex[reg] ); |
rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = 0; |
if (shader->SetupInst[0][reg].Opcode) { |
GLuint txformat = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] |
& ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); |
GLuint txformat_x = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] & ~R200_TEXCOORD_MASK; |
txformat |= (shader->SetupInst[0][reg].src - GL_TEXTURE0_ARB) |
<< R200_TXFORMAT_ST_ROUTE_SHIFT; |
/* fix up texcoords for proj/non-proj 2d (3d and cube are not defined when |
using projection so don't have to worry there). |
When passing coords, need R200_TEXCOORD_VOLUME, otherwise loose a coord */ |
/* FIXME: someone might rely on default tex coords r/q, which we unfortunately |
don't provide (we have the same problem without shaders) */ |
if (shader->SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) { |
txformat |= R200_TXFORMAT_LOOKUP_DISABLE; |
if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI || |
shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) { |
txformat_x |= R200_TEXCOORD_VOLUME; |
} |
else { |
txformat_x |= R200_TEXCOORD_PROJ; |
} |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg; |
} |
else if (targetbit == TEXTURE_3D_BIT) { |
txformat_x |= R200_TEXCOORD_VOLUME; |
} |
else if (targetbit == TEXTURE_CUBE_BIT) { |
txformat_x |= R200_TEXCOORD_CUBIC_ENV; |
} |
else if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI || |
shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) { |
txformat_x |= R200_TEXCOORD_NONPROJ; |
} |
else { |
txformat_x |= R200_TEXCOORD_PROJ; |
} |
rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] = txformat; |
rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] = txformat_x; |
/* enabling texturing when unit isn't correctly configured may not be safe */ |
if (targetbit) |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg; |
} |
} |
} else { |
/* setup 1st pass */ |
for (reg = 0; reg < R200_MAX_TEXTURE_UNITS; reg++) { |
GLbitfield targetbit = ctx->Texture.Unit[reg]._ReallyEnabled; |
R200_STATECHANGE( rmesa, tex[reg] ); |
GLuint txformat_multi = 0; |
if (shader->SetupInst[0][reg].Opcode) { |
txformat_multi |= (shader->SetupInst[0][reg].src - GL_TEXTURE0_ARB) |
<< R200_PASS1_ST_ROUTE_SHIFT; |
if (shader->SetupInst[0][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) { |
txformat_multi |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE; |
if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI || |
shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) { |
txformat_multi |= R200_PASS1_TEXCOORD_VOLUME; |
} |
else { |
txformat_multi |= R200_PASS1_TEXCOORD_PROJ; |
} |
rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_0_ENABLE << reg; |
} |
else if (targetbit == TEXTURE_3D_BIT) { |
txformat_multi |= R200_PASS1_TEXCOORD_VOLUME; |
} |
else if (targetbit == TEXTURE_CUBE_BIT) { |
txformat_multi |= R200_PASS1_TEXCOORD_CUBIC_ENV; |
} |
else if (shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STR_ATI || |
shader->SetupInst[0][reg].swizzle == GL_SWIZZLE_STQ_ATI) { |
txformat_multi |= R200_PASS1_TEXCOORD_NONPROJ; |
} |
else { |
txformat_multi |= R200_PASS1_TEXCOORD_PROJ; |
} |
if (targetbit) |
rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_0_ENABLE << reg; |
} |
rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = txformat_multi; |
} |
/* setup 2nd pass */ |
for (reg=0; reg < R200_MAX_TEXTURE_UNITS; reg++) { |
GLbitfield targetbit = ctx->Texture.Unit[reg]._ReallyEnabled; |
if (shader->SetupInst[1][reg].Opcode) { |
GLuint coord = shader->SetupInst[1][reg].src; |
GLuint txformat = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] |
& ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); |
GLuint txformat_x = rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] & ~R200_TEXCOORD_MASK; |
R200_STATECHANGE( rmesa, tex[reg] ); |
if (shader->SetupInst[1][reg].Opcode == ATI_FRAGMENT_SHADER_PASS_OP) { |
txformat |= R200_TXFORMAT_LOOKUP_DISABLE; |
txformat_x |= R200_TEXCOORD_VOLUME; |
if (shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI || |
shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) { |
txformat_x |= R200_TEXCOORD_VOLUME; |
} |
else { |
txformat_x |= R200_TEXCOORD_PROJ; |
} |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg; |
} |
else if (targetbit == TEXTURE_3D_BIT) { |
txformat_x |= R200_TEXCOORD_VOLUME; |
} |
else if (targetbit == TEXTURE_CUBE_BIT) { |
txformat_x |= R200_TEXCOORD_CUBIC_ENV; |
} |
else if (shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STR_ATI || |
shader->SetupInst[1][reg].swizzle == GL_SWIZZLE_STQ_ATI) { |
txformat_x |= R200_TEXCOORD_NONPROJ; |
} |
else { |
txformat_x |= R200_TEXCOORD_PROJ; |
} |
if (coord >= GL_REG_0_ATI) { |
GLuint txformat_multi = rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL]; |
txformat_multi |= (coord - GL_REG_0_ATI + 2) << R200_PASS2_COORDS_REG_SHIFT; |
rmesa->hw.tex[reg].cmd[TEX_PP_TXMULTI_CTL] = txformat_multi; |
rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= 1 << |
(R200_PPX_OUTPUT_REG_0_SHIFT + coord - GL_REG_0_ATI); |
} else { |
txformat |= (coord - GL_TEXTURE0_ARB) << R200_TXFORMAT_ST_ROUTE_SHIFT; |
} |
rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT_X] = txformat_x; |
rmesa->hw.tex[reg].cmd[TEX_PP_TXFORMAT] = txformat; |
if (targetbit) |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << reg; |
} |
} |
} |
} |
static void r200UpdateFSConstants( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
const struct ati_fragment_shader *shader = ctx->ATIFragmentShader.Current; |
GLuint i; |
/* update constants */ |
R200_STATECHANGE(rmesa, atf); |
for (i = 0; i < 8; i++) |
{ |
GLubyte con_byte[4]; |
if ((shader->LocalConstDef >> i) & 1) { |
CLAMPED_FLOAT_TO_UBYTE(con_byte[0], shader->Constants[i][0]); |
CLAMPED_FLOAT_TO_UBYTE(con_byte[1], shader->Constants[i][1]); |
CLAMPED_FLOAT_TO_UBYTE(con_byte[2], shader->Constants[i][2]); |
CLAMPED_FLOAT_TO_UBYTE(con_byte[3], shader->Constants[i][3]); |
} |
else { |
CLAMPED_FLOAT_TO_UBYTE(con_byte[0], ctx->ATIFragmentShader.GlobalConstants[i][0]); |
CLAMPED_FLOAT_TO_UBYTE(con_byte[1], ctx->ATIFragmentShader.GlobalConstants[i][1]); |
CLAMPED_FLOAT_TO_UBYTE(con_byte[2], ctx->ATIFragmentShader.GlobalConstants[i][2]); |
CLAMPED_FLOAT_TO_UBYTE(con_byte[3], ctx->ATIFragmentShader.GlobalConstants[i][3]); |
} |
rmesa->hw.atf.cmd[ATF_TFACTOR_0 + i] = radeonPackColor ( |
4, con_byte[0], con_byte[1], con_byte[2], con_byte[3] ); |
} |
} |
/* update routing, constants and arithmetic |
* constants need to be updated always (globals can change, no separate notification) |
* routing needs to be updated always too (non-shader code will overwrite state, plus |
* some of the routing depends on what sort of texture is bound) |
* for both of them, we need to update anyway because of disabling/enabling ati_fs which |
* we'd need to track otherwise |
* arithmetic is only updated if current shader changes (and probably the data should be |
* stored in some DriverData object attached to the mesa atifs object, i.e. binding a |
* shader wouldn't force us to "recompile" the shader). |
*/ |
void r200UpdateFragmentShader( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
r200UpdateFSConstants( ctx ); |
r200UpdateFSRouting( ctx ); |
if (rmesa->afs_loaded != ctx->ATIFragmentShader.Current) |
r200UpdateFSArith( ctx ); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_ioctl.c |
---|
0,0 → 1,96 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 <sched.h> |
#include <errno.h> |
#include "main/glheader.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "main/context.h" |
#include "swrast/swrast.h" |
#include "radeon_common.h" |
#include "r200_context.h" |
#include "r200_ioctl.h" |
#include "radeon_reg.h" |
#define R200_TIMEOUT 512 |
#define R200_IDLE_RETRY 16 |
/* ================================================================ |
* Buffer clear |
*/ |
static void r200Clear( struct gl_context *ctx, GLbitfield mask ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint hwmask, swmask; |
GLuint hwbits = BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT | |
BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL | |
BUFFER_BIT_COLOR0; |
if ( R200_DEBUG & RADEON_IOCTL ) { |
if (rmesa->radeon.sarea) |
fprintf( stderr, "r200Clear %x %d\n", mask, rmesa->radeon.sarea->pfCurrentPage); |
else |
fprintf( stderr, "r200Clear %x radeon->sarea is NULL\n", mask); |
} |
radeonFlush( ctx ); |
hwmask = mask & hwbits; |
swmask = mask & ~hwbits; |
if ( swmask ) { |
if (R200_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, swmask); |
_swrast_Clear( ctx, swmask ); |
} |
if ( !hwmask ) |
return; |
radeonUserClear(ctx, hwmask); |
} |
void r200InitIoctlFuncs( struct dd_function_table *functions ) |
{ |
functions->Clear = r200Clear; |
functions->Finish = radeonFinish; |
functions->Flush = radeonFlush; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_ioctl.h |
---|
0,0 → 1,158 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 __R200_IOCTL_H__ |
#define __R200_IOCTL_H__ |
#include "main/simple_list.h" |
#include "radeon_dri.h" |
#include "radeon_bo_gem.h" |
#include "radeon_cs_gem.h" |
#include "xf86drm.h" |
#include "drm.h" |
#include "radeon_drm.h" |
extern void r200EmitMaxVtxIndex(r200ContextPtr rmesa, int count); |
extern void r200EmitVertexAOS( r200ContextPtr rmesa, |
GLuint vertex_size, |
struct radeon_bo *bo, |
GLuint offset ); |
extern void r200EmitVbufPrim( r200ContextPtr rmesa, |
GLuint primitive, |
GLuint vertex_nr ); |
extern void r200FlushElts(struct gl_context *ctx); |
extern GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa, |
GLuint primitive, |
GLuint min_nr ); |
extern void r200EmitAOS(r200ContextPtr rmesa, GLuint nr, GLuint offset); |
extern void r200InitIoctlFuncs( struct dd_function_table *functions ); |
void r200SetUpAtomList( r200ContextPtr rmesa ); |
/* ================================================================ |
* Helper macros: |
*/ |
/* Close off the last primitive, if it exists. |
*/ |
#define R200_NEWPRIM( rmesa ) \ |
do { \ |
if ( rmesa->radeon.dma.flush ) \ |
rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); \ |
} while (0) |
/* Can accomodate several state changes and primitive changes without |
* actually firing the buffer. |
*/ |
#define R200_STATECHANGE( rmesa, ATOM ) \ |
do { \ |
R200_NEWPRIM( rmesa ); \ |
rmesa->hw.ATOM.dirty = GL_TRUE; \ |
rmesa->radeon.hw.is_dirty = GL_TRUE; \ |
} while (0) |
#define R200_SET_STATE( rmesa, ATOM, index, newvalue ) \ |
do { \ |
uint32_t __index = (index); \ |
uint32_t __dword = (newvalue); \ |
if (__dword != (rmesa)->hw.ATOM.cmd[__index]) { \ |
R200_STATECHANGE( (rmesa), ATOM ); \ |
(rmesa)->hw.ATOM.cmd[__index] = __dword; \ |
} \ |
} while(0) |
#define R200_DB_STATE( ATOM ) \ |
memcpy( rmesa->hw.ATOM.lastcmd, rmesa->hw.ATOM.cmd, \ |
rmesa->hw.ATOM.cmd_size * 4) |
static INLINE int R200_DB_STATECHANGE( |
r200ContextPtr rmesa, |
struct radeon_state_atom *atom ) |
{ |
if (memcmp(atom->cmd, atom->lastcmd, atom->cmd_size*4)) { |
GLuint *tmp; |
R200_NEWPRIM( rmesa ); |
atom->dirty = GL_TRUE; |
rmesa->radeon.hw.is_dirty = GL_TRUE; |
tmp = atom->cmd; |
atom->cmd = atom->lastcmd; |
atom->lastcmd = tmp; |
return 1; |
} |
else |
return 0; |
} |
/* Command lengths. Note that any time you ensure ELTS_BUFSZ or VBUF_BUFSZ |
* are available, you will also be adding an rmesa->state.max_state_size because |
* r200EmitState is called from within r200EmitVbufPrim and r200FlushElts. |
*/ |
#define AOS_BUFSZ(nr) ((3 + ((nr / 2) * 3) + ((nr & 1) * 2) + nr*2)) |
#define VERT_AOS_BUFSZ (5) |
#define ELTS_BUFSZ(nr) (12 + nr * 2) |
#define VBUF_BUFSZ (3) |
#define SCISSOR_BUFSZ (8) |
#define INDEX_BUFSZ (8+2) |
static inline uint32_t cmdpacket3(int cmd_type) |
{ |
drm_radeon_cmd_header_t cmd; |
cmd.i = 0; |
cmd.header.cmd_type = cmd_type; |
return (uint32_t)cmd.i; |
} |
#define OUT_BATCH_PACKET3(packet, num_extra) do { \ |
OUT_BATCH(CP_PACKET2); \ |
OUT_BATCH(CP_PACKET3((packet), (num_extra))); \ |
} while(0) |
#define OUT_BATCH_PACKET3_CLIP(packet, num_extra) do { \ |
OUT_BATCH(CP_PACKET2); \ |
OUT_BATCH(CP_PACKET3((packet), (num_extra))); \ |
} while(0) |
#endif /* __R200_IOCTL_H__ */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_maos.c |
---|
0,0 → 1,15 |
/* Currently, can only use arrays, verts are not implemented, though |
* verts are suspected to be faster. |
* To get an idea how the verts path works, look at the radeon implementation. |
*/ |
#include <string.h> |
#include "r200_context.h" |
#define R200_MAOS_VERTS 0 |
#if (R200_MAOS_VERTS) |
#include "r200_maos_verts.c" |
#else |
#include "r200_maos_arrays.c" |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_maos.h |
---|
0,0 → 1,42 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 __R200_MAOS_H__ |
#define __R200_MAOS_H__ |
#include "r200_context.h" |
extern void r200EmitArrays( struct gl_context *ctx, GLubyte *vimap_rev ); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_maos_arrays.c |
---|
0,0 → 1,199 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/mtypes.h" |
#include "main/colormac.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "swrast_setup/swrast_setup.h" |
#include "math/m_translate.h" |
#include "tnl/tnl.h" |
#include "tnl/t_context.h" |
#include "r200_context.h" |
#include "r200_ioctl.h" |
#include "r200_state.h" |
#include "r200_swtcl.h" |
#include "r200_maos.h" |
#include "r200_tcl.h" |
#if defined(USE_X86_ASM) |
#define COPY_DWORDS( dst, src, nr ) \ |
do { \ |
int __tmp; \ |
__asm__ __volatile__( "rep ; movsl" \ |
: "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \ |
: "0" (nr), \ |
"D" ((long)dst), \ |
"S" ((long)src) ); \ |
} while (0) |
#else |
#define COPY_DWORDS( dst, src, nr ) \ |
do { \ |
int j; \ |
for ( j = 0 ; j < nr ; j++ ) \ |
dst[j] = ((int *)src)[j]; \ |
dst += nr; \ |
} while (0) |
#endif |
/* Emit any changed arrays to new GART memory, re-emit a packet to |
* update the arrays. |
*/ |
void r200EmitArrays( struct gl_context *ctx, GLubyte *vimap_rev ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT( ctx ); |
struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb; |
GLuint nr = 0; |
GLuint vfmt0 = 0, vfmt1 = 0; |
GLuint count = VB->Count; |
GLuint i, emitsize; |
// fprintf(stderr,"emit arrays\n"); |
for ( i = 0; i < 15; i++ ) { |
GLubyte attrib = vimap_rev[i]; |
if (attrib != 255) { |
switch (i) { |
case 0: |
emitsize = (VB->AttribPtr[attrib]->size); |
switch (emitsize) { |
case 4: |
vfmt0 |= R200_VTX_W0; |
/* fallthrough */ |
case 3: |
vfmt0 |= R200_VTX_Z0; |
break; |
case 2: |
break; |
default: assert(0); |
} |
break; |
case 1: |
assert(attrib == VERT_ATTRIB_WEIGHT); |
emitsize = (VB->AttribPtr[attrib]->size); |
vfmt0 |= emitsize << R200_VTX_WEIGHT_COUNT_SHIFT; |
break; |
case 2: |
assert(attrib == VERT_ATTRIB_NORMAL); |
emitsize = 3; |
vfmt0 |= R200_VTX_N0; |
break; |
case 3: |
/* special handling to fix up fog. Will get us into trouble with vbos...*/ |
assert(attrib == VERT_ATTRIB_FOG); |
if (!rmesa->radeon.tcl.aos[i].bo) { |
if (ctx->VertexProgram._Enabled) |
rcommon_emit_vector( ctx, |
&(rmesa->radeon.tcl.aos[nr]), |
(char *)VB->AttribPtr[attrib]->data, |
1, |
VB->AttribPtr[attrib]->stride, |
count); |
else |
rcommon_emit_vecfog( ctx, |
&(rmesa->radeon.tcl.aos[nr]), |
(char *)VB->AttribPtr[attrib]->data, |
VB->AttribPtr[attrib]->stride, |
count); |
} |
vfmt0 |= R200_VTX_DISCRETE_FOG; |
goto after_emit; |
break; |
case 4: |
case 5: |
case 6: |
case 7: |
if (VB->AttribPtr[attrib]->size == 4 && |
(VB->AttribPtr[attrib]->stride != 0 || |
VB->AttribPtr[attrib]->data[0][3] != 1.0)) emitsize = 4; |
else emitsize = 3; |
if (emitsize == 4) |
vfmt0 |= R200_VTX_FP_RGBA << (R200_VTX_COLOR_0_SHIFT + (i - 4) * 2); |
else { |
vfmt0 |= R200_VTX_FP_RGB << (R200_VTX_COLOR_0_SHIFT + (i - 4) * 2); |
} |
break; |
case 8: |
case 9: |
case 10: |
case 11: |
case 12: |
case 13: |
emitsize = VB->AttribPtr[attrib]->size; |
vfmt1 |= emitsize << (R200_VTX_TEX0_COMP_CNT_SHIFT + (i - 8) * 3); |
break; |
case 14: |
emitsize = VB->AttribPtr[attrib]->size >= 2 ? VB->AttribPtr[attrib]->size : 2; |
switch (emitsize) { |
case 2: |
vfmt0 |= R200_VTX_XY1; |
/* fallthrough */ |
case 3: |
vfmt0 |= R200_VTX_Z1; |
/* fallthrough */ |
case 4: |
vfmt0 |= R200_VTX_W1; |
/* fallthrough */ |
} |
break; |
default: |
assert(0); |
emitsize = 0; |
} |
if (!rmesa->radeon.tcl.aos[nr].bo) { |
rcommon_emit_vector( ctx, |
&(rmesa->radeon.tcl.aos[nr]), |
(char *)VB->AttribPtr[attrib]->data, |
emitsize, |
VB->AttribPtr[attrib]->stride, |
count ); |
} |
after_emit: |
assert(nr < 12); |
nr++; |
} |
} |
if (vfmt0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0] || |
vfmt1 != rmesa->hw.vtx.cmd[VTX_VTXFMT_1]) { |
R200_STATECHANGE( rmesa, vtx ); |
rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = vfmt0; |
rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = vfmt1; |
} |
rmesa->radeon.tcl.aos_count = nr; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_reg.h |
---|
0,0 → 1,1597 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 _R200_REG_H_ |
#define _R200_REG_H_ |
#define R200_PP_MISC 0x1c14 |
#define R200_REF_ALPHA_MASK 0x000000ff |
#define R200_ALPHA_TEST_FAIL (0 << 8) |
#define R200_ALPHA_TEST_LESS (1 << 8) |
#define R200_ALPHA_TEST_LEQUAL (2 << 8) |
#define R200_ALPHA_TEST_EQUAL (3 << 8) |
#define R200_ALPHA_TEST_GEQUAL (4 << 8) |
#define R200_ALPHA_TEST_GREATER (5 << 8) |
#define R200_ALPHA_TEST_NEQUAL (6 << 8) |
#define R200_ALPHA_TEST_PASS (7 << 8) |
#define R200_ALPHA_TEST_OP_MASK (7 << 8) |
#define R200_CHROMA_FUNC_FAIL (0 << 16) |
#define R200_CHROMA_FUNC_PASS (1 << 16) |
#define R200_CHROMA_FUNC_NEQUAL (2 << 16) |
#define R200_CHROMA_FUNC_EQUAL (3 << 16) |
#define R200_CHROMA_KEY_NEAREST (0 << 18) |
#define R200_CHROMA_KEY_ZERO (1 << 18) |
#define R200_RIGHT_HAND_CUBE_D3D (0 << 24) |
#define R200_RIGHT_HAND_CUBE_OGL (1 << 24) |
#define R200_PP_FOG_COLOR 0x1c18 |
#define R200_FOG_COLOR_MASK 0x00ffffff |
#define R200_FOG_VERTEX (0 << 24) |
#define R200_FOG_TABLE (1 << 24) |
#define R200_FOG_USE_DEPTH (0 << 25) |
#define R200_FOG_USE_W (1 << 25) |
#define R200_FOG_USE_DIFFUSE_ALPHA (2 << 25) |
#define R200_FOG_USE_SPEC_ALPHA (3 << 25) |
#define R200_FOG_USE_VTX_FOG (4 << 25) |
#define R200_FOG_USE_MASK (7 << 25) |
#define R200_RE_SOLID_COLOR 0x1c1c |
#define R200_RB3D_BLENDCNTL 0x1c20 |
#define R200_COMB_FCN_MASK (7 << 12) |
#define R200_COMB_FCN_ADD_CLAMP (0 << 12) |
#define R200_COMB_FCN_ADD_NOCLAMP (1 << 12) |
#define R200_COMB_FCN_SUB_CLAMP (2 << 12) |
#define R200_COMB_FCN_SUB_NOCLAMP (3 << 12) |
#define R200_COMB_FCN_MIN (4 << 12) |
#define R200_COMB_FCN_MAX (5 << 12) |
#define R200_COMB_FCN_RSUB_CLAMP (6 << 12) |
#define R200_COMB_FCN_RSUB_NOCLAMP (7 << 12) |
#define R200_BLEND_GL_ZERO (32) |
#define R200_BLEND_GL_ONE (33) |
#define R200_BLEND_GL_SRC_COLOR (34) |
#define R200_BLEND_GL_ONE_MINUS_SRC_COLOR (35) |
#define R200_BLEND_GL_DST_COLOR (36) |
#define R200_BLEND_GL_ONE_MINUS_DST_COLOR (37) |
#define R200_BLEND_GL_SRC_ALPHA (38) |
#define R200_BLEND_GL_ONE_MINUS_SRC_ALPHA (39) |
#define R200_BLEND_GL_DST_ALPHA (40) |
#define R200_BLEND_GL_ONE_MINUS_DST_ALPHA (41) |
#define R200_BLEND_GL_SRC_ALPHA_SATURATE (42) /* src factor only */ |
#define R200_BLEND_GL_CONST_COLOR (43) |
#define R200_BLEND_GL_ONE_MINUS_CONST_COLOR (44) |
#define R200_BLEND_GL_CONST_ALPHA (45) |
#define R200_BLEND_GL_ONE_MINUS_CONST_ALPHA (46) |
#define R200_BLEND_MASK (63) |
#define R200_SRC_BLEND_SHIFT (16) |
#define R200_DST_BLEND_SHIFT (24) |
#define R200_RB3D_DEPTHOFFSET 0x1c24 |
#define R200_RB3D_DEPTHPITCH 0x1c28 |
#define R200_DEPTHPITCH_MASK 0x00001ff8 |
#define R200_DEPTH_HYPERZ (3 << 16) |
#define R200_DEPTH_ENDIAN_NO_SWAP (0 << 18) |
#define R200_DEPTH_ENDIAN_WORD_SWAP (1 << 18) |
#define R200_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) |
#define R200_RB3D_ZSTENCILCNTL 0x1c2c |
#define R200_DEPTH_FORMAT_MASK (0xf << 0) |
#define R200_DEPTH_FORMAT_16BIT_INT_Z (0 << 0) |
#define R200_DEPTH_FORMAT_24BIT_INT_Z (2 << 0) |
#define R200_DEPTH_FORMAT_24BIT_FLOAT_Z (3 << 0) |
#define R200_DEPTH_FORMAT_32BIT_INT_Z (4 << 0) |
#define R200_DEPTH_FORMAT_32BIT_FLOAT_Z (5 << 0) |
#define R200_DEPTH_FORMAT_24BIT_FLOAT_W (9 << 0) |
#define R200_DEPTH_FORMAT_32BIT_FLOAT_W (11 << 0) |
#define R200_Z_TEST_NEVER (0 << 4) |
#define R200_Z_TEST_LESS (1 << 4) |
#define R200_Z_TEST_LEQUAL (2 << 4) |
#define R200_Z_TEST_EQUAL (3 << 4) |
#define R200_Z_TEST_GEQUAL (4 << 4) |
#define R200_Z_TEST_GREATER (5 << 4) |
#define R200_Z_TEST_NEQUAL (6 << 4) |
#define R200_Z_TEST_ALWAYS (7 << 4) |
#define R200_Z_TEST_MASK (7 << 4) |
#define R200_Z_HIERARCHY_ENABLE (1 << 8) |
#define R200_STENCIL_TEST_NEVER (0 << 12) |
#define R200_STENCIL_TEST_LESS (1 << 12) |
#define R200_STENCIL_TEST_LEQUAL (2 << 12) |
#define R200_STENCIL_TEST_EQUAL (3 << 12) |
#define R200_STENCIL_TEST_GEQUAL (4 << 12) |
#define R200_STENCIL_TEST_GREATER (5 << 12) |
#define R200_STENCIL_TEST_NEQUAL (6 << 12) |
#define R200_STENCIL_TEST_ALWAYS (7 << 12) |
#define R200_STENCIL_TEST_MASK (0x7 << 12) |
#define R200_STENCIL_FAIL_KEEP (0 << 16) |
#define R200_STENCIL_FAIL_ZERO (1 << 16) |
#define R200_STENCIL_FAIL_REPLACE (2 << 16) |
#define R200_STENCIL_FAIL_INC (3 << 16) |
#define R200_STENCIL_FAIL_DEC (4 << 16) |
#define R200_STENCIL_FAIL_INVERT (5 << 16) |
#define R200_STENCIL_FAIL_INC_WRAP (6 << 16) |
#define R200_STENCIL_FAIL_DEC_WRAP (7 << 16) |
#define R200_STENCIL_FAIL_MASK (0x7 << 16) |
#define R200_STENCIL_ZPASS_KEEP (0 << 20) |
#define R200_STENCIL_ZPASS_ZERO (1 << 20) |
#define R200_STENCIL_ZPASS_REPLACE (2 << 20) |
#define R200_STENCIL_ZPASS_INC (3 << 20) |
#define R200_STENCIL_ZPASS_DEC (4 << 20) |
#define R200_STENCIL_ZPASS_INVERT (5 << 20) |
#define R200_STENCIL_ZPASS_INC_WRAP (6 << 20) |
#define R200_STENCIL_ZPASS_DEC_WRAP (7 << 20) |
#define R200_STENCIL_ZPASS_MASK (0x7 << 20) |
#define R200_STENCIL_ZFAIL_KEEP (0 << 24) |
#define R200_STENCIL_ZFAIL_ZERO (1 << 24) |
#define R200_STENCIL_ZFAIL_REPLACE (2 << 24) |
#define R200_STENCIL_ZFAIL_INC (3 << 24) |
#define R200_STENCIL_ZFAIL_DEC (4 << 24) |
#define R200_STENCIL_ZFAIL_INVERT (5 << 24) |
#define R200_STENCIL_ZFAIL_INC_WRAP (6 << 24) |
#define R200_STENCIL_ZFAIL_DEC_WRAP (7 << 24) |
#define R200_STENCIL_ZFAIL_MASK (0x7 << 24) |
#define R200_Z_COMPRESSION_ENABLE (1 << 28) |
#define R200_FORCE_Z_DIRTY (1 << 29) |
#define R200_Z_WRITE_ENABLE (1 << 30) |
#define R200_Z_DECOMPRESSION_ENABLE (1 << 31) |
/*gap*/ |
#define R200_PP_CNTL 0x1c38 |
#define R200_TEX_0_ENABLE 0x00000010 |
#define R200_TEX_1_ENABLE 0x00000020 |
#define R200_TEX_2_ENABLE 0x00000040 |
#define R200_TEX_3_ENABLE 0x00000080 |
#define R200_TEX_4_ENABLE 0x00000100 |
#define R200_TEX_5_ENABLE 0x00000200 |
#define R200_TEX_ENABLE_MASK 0x000003f0 |
#define R200_FILTER_ROUND_MODE_MASK 0x00000400 |
#define R200_TEX_BLEND_7_ENABLE 0x00000800 |
#define R200_TEX_BLEND_0_ENABLE 0x00001000 |
#define R200_TEX_BLEND_1_ENABLE 0x00002000 |
#define R200_TEX_BLEND_2_ENABLE 0x00004000 |
#define R200_TEX_BLEND_3_ENABLE 0x00008000 |
#define R200_TEX_BLEND_4_ENABLE 0x00010000 |
#define R200_TEX_BLEND_5_ENABLE 0x00020000 |
#define R200_TEX_BLEND_6_ENABLE 0x00040000 |
#define R200_TEX_BLEND_ENABLE_MASK 0x0007f800 |
#define R200_TEX_BLEND_0_ENABLE_SHIFT (12) |
#define R200_MULTI_PASS_ENABLE 0x00080000 |
#define R200_SPECULAR_ENABLE 0x00200000 |
#define R200_FOG_ENABLE 0x00400000 |
#define R200_ALPHA_TEST_ENABLE 0x00800000 |
#define R200_ANTI_ALIAS_NONE 0x00000000 |
#define R200_ANTI_ALIAS_LINE 0x01000000 |
#define R200_ANTI_ALIAS_POLY 0x02000000 |
#define R200_ANTI_ALIAS_MASK 0x03000000 |
#define R200_RB3D_CNTL 0x1c3c |
#define R200_ALPHA_BLEND_ENABLE (1 << 0) |
#define R200_PLANE_MASK_ENABLE (1 << 1) |
#define R200_DITHER_ENABLE (1 << 2) |
#define R200_ROUND_ENABLE (1 << 3) |
#define R200_SCALE_DITHER_ENABLE (1 << 4) |
#define R200_DITHER_INIT (1 << 5) |
#define R200_ROP_ENABLE (1 << 6) |
#define R200_STENCIL_ENABLE (1 << 7) |
#define R200_Z_ENABLE (1 << 8) |
#define R200_DEPTH_XZ_OFFEST_ENABLE (1 << 9) |
#define R200_COLOR_FORMAT_ARGB1555 (3 << 10) |
#define R200_COLOR_FORMAT_RGB565 (4 << 10) |
#define R200_COLOR_FORMAT_ARGB8888 (6 << 10) |
#define R200_COLOR_FORMAT_RGB332 (7 << 10) |
#define R200_COLOR_FORMAT_Y8 (8 << 10) |
#define R200_COLOR_FORMAT_RGB8 (9 << 10) |
#define R200_COLOR_FORMAT_YUV422_VYUY (11 << 10) |
#define R200_COLOR_FORMAT_YUV422_YVYU (12 << 10) |
#define R200_COLOR_FORMAT_aYUV444 (14 << 10) |
#define R200_COLOR_FORMAT_ARGB4444 (15 << 10) |
#define R200_CLRCMP_FLIP_ENABLE (1 << 14) |
#define R200_SEPARATE_ALPHA_ENABLE (1 << 16) |
#define R200_RB3D_COLOROFFSET 0x1c40 |
#define R200_COLOROFFSET_MASK 0xfffffff0 |
#define R200_RE_WIDTH_HEIGHT 0x1c44 |
#define R200_RE_WIDTH_SHIFT 0 |
#define R200_RE_HEIGHT_SHIFT 16 |
#define R200_RB3D_COLORPITCH 0x1c48 |
#define R200_COLORPITCH_MASK 0x000001ff8 |
#define R200_COLOR_TILE_ENABLE (1 << 16) |
#define R200_COLOR_MICROTILE_ENABLE (1 << 17) |
#define R200_COLOR_ENDIAN_NO_SWAP (0 << 18) |
#define R200_COLOR_ENDIAN_WORD_SWAP (1 << 18) |
#define R200_COLOR_ENDIAN_DWORD_SWAP (2 << 18) |
#define R200_SE_CNTL 0x1c4c |
#define R200_FFACE_CULL_CW (0 << 0) |
#define R200_FFACE_CULL_CCW (1 << 0) |
#define R200_FFACE_CULL_DIR_MASK (1 << 0) |
#define R200_BFACE_CULL (0 << 1) |
#define R200_BFACE_SOLID (3 << 1) |
#define R200_FFACE_CULL (0 << 3) |
#define R200_FFACE_SOLID (3 << 3) |
#define R200_FFACE_CULL_MASK (3 << 3) |
#define R200_FLAT_SHADE_VTX_0 (0 << 6) |
#define R200_FLAT_SHADE_VTX_1 (1 << 6) |
#define R200_FLAT_SHADE_VTX_2 (2 << 6) |
#define R200_FLAT_SHADE_VTX_LAST (3 << 6) |
#define R200_DIFFUSE_SHADE_SOLID (0 << 8) |
#define R200_DIFFUSE_SHADE_FLAT (1 << 8) |
#define R200_DIFFUSE_SHADE_GOURAUD (2 << 8) |
#define R200_DIFFUSE_SHADE_MASK (3 << 8) |
#define R200_ALPHA_SHADE_SOLID (0 << 10) |
#define R200_ALPHA_SHADE_FLAT (1 << 10) |
#define R200_ALPHA_SHADE_GOURAUD (2 << 10) |
#define R200_ALPHA_SHADE_MASK (3 << 10) |
#define R200_SPECULAR_SHADE_SOLID (0 << 12) |
#define R200_SPECULAR_SHADE_FLAT (1 << 12) |
#define R200_SPECULAR_SHADE_GOURAUD (2 << 12) |
#define R200_SPECULAR_SHADE_MASK (3 << 12) |
#define R200_FOG_SHADE_SOLID (0 << 14) |
#define R200_FOG_SHADE_FLAT (1 << 14) |
#define R200_FOG_SHADE_GOURAUD (2 << 14) |
#define R200_FOG_SHADE_MASK (3 << 14) |
#define R200_ZBIAS_ENABLE_POINT (1 << 16) |
#define R200_ZBIAS_ENABLE_LINE (1 << 17) |
#define R200_ZBIAS_ENABLE_TRI (1 << 18) |
#define R200_WIDELINE_ENABLE (1 << 20) |
#define R200_DISC_FOG_SHADE_SOLID (0 << 24) |
#define R200_DISC_FOG_SHADE_FLAT (1 << 24) |
#define R200_DISC_FOG_SHADE_GOURAUD (2 << 24) |
#define R200_DISC_FOG_SHADE_MASK (3 << 24) |
#define R200_VTX_PIX_CENTER_D3D (0 << 27) |
#define R200_VTX_PIX_CENTER_OGL (1 << 27) |
#define R200_ROUND_MODE_TRUNC (0 << 28) |
#define R200_ROUND_MODE_ROUND (1 << 28) |
#define R200_ROUND_MODE_ROUND_EVEN (2 << 28) |
#define R200_ROUND_MODE_ROUND_ODD (3 << 28) |
#define R200_ROUND_PREC_16TH_PIX (0 << 30) |
#define R200_ROUND_PREC_8TH_PIX (1 << 30) |
#define R200_ROUND_PREC_4TH_PIX (2 << 30) |
#define R200_ROUND_PREC_HALF_PIX (3 << 30) |
#define R200_RE_CNTL 0x1c50 |
#define R200_STIPPLE_ENABLE 0x1 |
#define R200_SCISSOR_ENABLE 0x2 |
#define R200_PATTERN_ENABLE 0x4 |
#define R200_PERSPECTIVE_ENABLE 0x8 |
#define R200_POINT_SMOOTH 0x20 |
#define R200_VTX_STQ0_D3D 0x00010000 |
#define R200_VTX_STQ1_D3D 0x00040000 |
#define R200_VTX_STQ2_D3D 0x00100000 |
#define R200_VTX_STQ3_D3D 0x00400000 |
#define R200_VTX_STQ4_D3D 0x01000000 |
#define R200_VTX_STQ5_D3D 0x04000000 |
/* gap */ |
#define R200_RE_STIPPLE_ADDR 0x1cc8 |
#define R200_RE_STIPPLE_DATA 0x1ccc |
#define R200_RE_LINE_PATTERN 0x1cd0 |
#define R200_LINE_PATTERN_MASK 0x0000ffff |
#define R200_LINE_REPEAT_COUNT_SHIFT 16 |
#define R200_LINE_PATTERN_START_SHIFT 24 |
#define R200_LINE_PATTERN_LITTLE_BIT_ORDER (0 << 28) |
#define R200_LINE_PATTERN_BIG_BIT_ORDER (1 << 28) |
#define R200_LINE_PATTERN_AUTO_RESET (1 << 29) |
#define R200_RE_LINE_STATE 0x1cd4 |
#define R200_LINE_CURRENT_PTR_SHIFT 0 |
#define R200_LINE_CURRENT_COUNT_SHIFT 8 |
#define R200_RE_SCISSOR_TL_0 0x1cd8 |
#define R200_RE_SCISSOR_BR_0 0x1cdc |
#define R200_RE_SCISSOR_TL_1 0x1ce0 |
#define R200_RE_SCISSOR_BR_1 0x1ce4 |
#define R200_RE_SCISSOR_TL_2 0x1ce8 |
#define R200_RE_SCISSOR_BR_2 0x1cec |
/* gap */ |
#define R200_RB3D_DEPTHXY_OFFSET 0x1d60 |
#define R200_DEPTHX_SHIFT 0 |
#define R200_DEPTHY_SHIFT 16 |
/* gap */ |
#define R200_RB3D_STENCILREFMASK 0x1d7c |
#define R200_STENCIL_REF_SHIFT 0 |
#define R200_STENCIL_REF_MASK (0xff << 0) |
#define R200_STENCIL_MASK_SHIFT 16 |
#define R200_STENCIL_VALUE_MASK (0xff << 16) |
#define R200_STENCIL_WRITEMASK_SHIFT 24 |
#define R200_STENCIL_WRITE_MASK (0xff << 24) |
#define R200_RB3D_ROPCNTL 0x1d80 |
#define R200_ROP_MASK (15 << 8) |
#define R200_ROP_CLEAR (0 << 8) |
#define R200_ROP_NOR (1 << 8) |
#define R200_ROP_AND_INVERTED (2 << 8) |
#define R200_ROP_COPY_INVERTED (3 << 8) |
#define R200_ROP_AND_REVERSE (4 << 8) |
#define R200_ROP_INVERT (5 << 8) |
#define R200_ROP_XOR (6 << 8) |
#define R200_ROP_NAND (7 << 8) |
#define R200_ROP_AND (8 << 8) |
#define R200_ROP_EQUIV (9 << 8) |
#define R200_ROP_NOOP (10 << 8) |
#define R200_ROP_OR_INVERTED (11 << 8) |
#define R200_ROP_COPY (12 << 8) |
#define R200_ROP_OR_REVERSE (13 << 8) |
#define R200_ROP_OR (14 << 8) |
#define R200_ROP_SET (15 << 8) |
#define R200_RB3D_PLANEMASK 0x1d84 |
/* gap */ |
#define R200_SE_VPORT_XSCALE 0x1d98 |
#define R200_SE_VPORT_XOFFSET 0x1d9c |
#define R200_SE_VPORT_YSCALE 0x1da0 |
#define R200_SE_VPORT_YOFFSET 0x1da4 |
#define R200_SE_VPORT_ZSCALE 0x1da8 |
#define R200_SE_VPORT_ZOFFSET 0x1dac |
#define R200_SE_ZBIAS_FACTOR 0x1db0 |
#define R200_SE_ZBIAS_CONSTANT 0x1db4 |
#define R200_SE_LINE_WIDTH 0x1db8 |
#define R200_LINE_WIDTH_SHIFT 0x00000000 |
#define R200_MINPOINTSIZE_SHIFT 0x00000010 |
/* gap */ |
#define R200_SE_VAP_CNTL 0x2080 |
#define R200_VAP_TCL_ENABLE 0x00000001 |
#define R200_VAP_PROG_VTX_SHADER_ENABLE 0x00000004 |
#define R200_VAP_SINGLE_BUF_STATE_ENABLE 0x00000010 |
#define R200_VAP_FORCE_W_TO_ONE 0x00010000 |
#define R200_VAP_D3D_TEX_DEFAULT 0x00020000 |
#define R200_VAP_VF_MAX_VTX_NUM__SHIFT 18 |
#define R200_VAP_DX_CLIP_SPACE_DEF 0x00400000 |
#define R200_SE_VF_CNTL 0x2084 |
#define R200_VF_PRIM_NONE 0x00000000 |
#define R200_VF_PRIM_POINTS 0x00000001 |
#define R200_VF_PRIM_LINES 0x00000002 |
#define R200_VF_PRIM_LINE_STRIP 0x00000003 |
#define R200_VF_PRIM_TRIANGLES 0x00000004 |
#define R200_VF_PRIM_TRIANGLE_FAN 0x00000005 |
#define R200_VF_PRIM_TRIANGLE_STRIP 0x00000006 |
#define R200_VF_PRIM_RECT_LIST 0x00000008 |
#define R200_VF_PRIM_3VRT_POINTS 0x00000009 |
#define R200_VF_PRIM_3VRT_LINES 0x0000000a |
#define R200_VF_PRIM_POINT_SPRITES 0x0000000b |
#define R200_VF_PRIM_LINE_LOOP 0x0000000c |
#define R200_VF_PRIM_QUADS 0x0000000d |
#define R200_VF_PRIM_QUAD_STRIP 0x0000000e |
#define R200_VF_PRIM_POLYGON 0x0000000f |
#define R200_VF_PRIM_MASK 0x0000000f |
#define R200_VF_PRIM_WALK_IND 0x00000010 |
#define R200_VF_PRIM_WALK_LIST 0x00000020 |
#define R200_VF_PRIM_WALK_RING 0x00000030 |
#define R200_VF_PRIM_WALK_MASK 0x00000030 |
#define R200_VF_COLOR_ORDER_RGBA 0x00000040 |
#define R200_VF_TCL_OUTPUT_VTX_ENABLE 0x00000200 |
#define R200_VF_INDEX_SZ_4 0x00000800 |
#define R200_VF_VERTEX_NUMBER_MASK 0xffff0000 |
#define R200_VF_VERTEX_NUMBER_SHIFT 16 |
#define R200_SE_VTX_FMT_0 0x2088 |
#define R200_VTX_XY 0 /* always have xy */ |
#define R200_VTX_Z0 (1<<0) |
#define R200_VTX_W0 (1<<1) |
#define R200_VTX_WEIGHT_COUNT_SHIFT (2) |
#define R200_VTX_PV_MATRIX_SEL (1<<5) |
#define R200_VTX_N0 (1<<6) |
#define R200_VTX_POINT_SIZE (1<<7) |
#define R200_VTX_DISCRETE_FOG (1<<8) |
#define R200_VTX_SHININESS_0 (1<<9) |
#define R200_VTX_SHININESS_1 (1<<10) |
#define R200_VTX_COLOR_NOT_PRESENT 0 |
#define R200_VTX_PK_RGBA 1 |
#define R200_VTX_FP_RGB 2 |
#define R200_VTX_FP_RGBA 3 |
#define R200_VTX_COLOR_MASK 3 |
#define R200_VTX_COLOR_0_SHIFT 11 |
#define R200_VTX_COLOR_1_SHIFT 13 |
#define R200_VTX_COLOR_2_SHIFT 15 |
#define R200_VTX_COLOR_3_SHIFT 17 |
#define R200_VTX_COLOR_4_SHIFT 19 |
#define R200_VTX_COLOR_5_SHIFT 21 |
#define R200_VTX_COLOR_6_SHIFT 23 |
#define R200_VTX_COLOR_7_SHIFT 25 |
#define R200_VTX_XY1 (1<<28) |
#define R200_VTX_Z1 (1<<29) |
#define R200_VTX_W1 (1<<30) |
#define R200_VTX_N1 (1<<31) |
#define R200_SE_VTX_FMT_1 0x208c |
#define R200_VTX_TEX0_COMP_CNT_SHIFT 0 |
#define R200_VTX_TEX1_COMP_CNT_SHIFT 3 |
#define R200_VTX_TEX2_COMP_CNT_SHIFT 6 |
#define R200_VTX_TEX3_COMP_CNT_SHIFT 9 |
#define R200_VTX_TEX4_COMP_CNT_SHIFT 12 |
#define R200_VTX_TEX5_COMP_CNT_SHIFT 15 |
#define R200_SE_TCL_OUTPUT_VTX_FMT_0 0x2090 |
#define R200_SE_TCL_OUTPUT_VTX_FMT_1 0x2094 |
/* gap */ |
#define R200_SE_VTE_CNTL 0x20b0 |
#define R200_VPORT_X_SCALE_ENA 0x00000001 |
#define R200_VPORT_X_OFFSET_ENA 0x00000002 |
#define R200_VPORT_Y_SCALE_ENA 0x00000004 |
#define R200_VPORT_Y_OFFSET_ENA 0x00000008 |
#define R200_VPORT_Z_SCALE_ENA 0x00000010 |
#define R200_VPORT_Z_OFFSET_ENA 0x00000020 |
#define R200_VTX_XY_FMT 0x00000100 |
#define R200_VTX_Z_FMT 0x00000200 |
#define R200_VTX_W0_FMT 0x00000400 |
#define R200_VTX_W0_NORMALIZE 0x00000800 |
#define R200_VTX_ST_DENORMALIZED 0x00001000 |
/* gap */ |
#define R200_SE_VTX_NUM_ARRAYS 0x20c0 |
#define R200_SE_VTX_AOS_ATTR01 0x20c4 |
#define R200_SE_VTX_AOS_ADDR0 0x20c8 |
#define R200_SE_VTX_AOS_ADDR1 0x20cc |
#define R200_SE_VTX_AOS_ATTR23 0x20d0 |
#define R200_SE_VTX_AOS_ADDR2 0x20d4 |
#define R200_SE_VTX_AOS_ADDR3 0x20d8 |
#define R200_SE_VTX_AOS_ATTR45 0x20dc |
#define R200_SE_VTX_AOS_ADDR4 0x20e0 |
#define R200_SE_VTX_AOS_ADDR5 0x20e4 |
#define R200_SE_VTX_AOS_ATTR67 0x20e8 |
#define R200_SE_VTX_AOS_ADDR6 0x20ec |
#define R200_SE_VTX_AOS_ADDR7 0x20f0 |
#define R200_SE_VTX_AOS_ATTR89 0x20f4 |
#define R200_SE_VTX_AOS_ADDR8 0x20f8 |
#define R200_SE_VTX_AOS_ADDR9 0x20fc |
#define R200_SE_VTX_AOS_ATTR1011 0x2100 |
#define R200_SE_VTX_AOS_ADDR10 0x2104 |
#define R200_SE_VTX_AOS_ADDR11 0x2108 |
#define R200_SE_VF_MAX_VTX_INDX 0x210c |
#define R200_SE_VF_MIN_VTX_INDX 0x2110 |
/* gap */ |
#define R200_SE_VAP_CNTL_STATUS 0x2140 |
#define R200_VC_NO_SWAP (0 << 0) |
#define R200_VC_16BIT_SWAP (1 << 0) |
#define R200_VC_32BIT_SWAP (2 << 0) |
/* gap */ |
#define R200_SE_VTX_STATE_CNTL 0x2180 |
#define R200_VSC_COLOR_0_ASSEMBLY_CNTL_SHIFT 0x00000000 |
#define R200_VSC_COLOR_1_ASSEMBLY_CNTL_SHIFT 0x00000002 |
#define R200_VSC_COLOR_2_ASSEMBLY_CNTL_SHIFT 0x00000004 |
#define R200_VSC_COLOR_3_ASSEMBLY_CNTL_SHIFT 0x00000006 |
#define R200_VSC_COLOR_4_ASSEMBLY_CNTL_SHIFT 0x00000008 |
#define R200_VSC_COLOR_5_ASSEMBLY_CNTL_SHIFT 0x0000000a |
#define R200_VSC_COLOR_6_ASSEMBLY_CNTL_SHIFT 0x0000000c |
#define R200_VSC_COLOR_7_ASSEMBLY_CNTL_SHIFT 0x0000000e |
#define R200_VSC_UPDATE_USER_COLOR_0_ENABLE 0x00010000 |
#define R200_VSC_UPDATE_USER_COLOR_1_ENABLE 0x00020000 |
/* gap */ |
#define R200_SE_TCL_VECTOR_INDX_REG 0x2200 |
# define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT 16 |
# define RADEON_VEC_INDX_DWORD_COUNT_SHIFT 28 |
#define R200_SE_TCL_VECTOR_DATA_REG 0x2204 |
#define R200_SE_TCL_SCALAR_INDX_REG 0x2208 |
# define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT 16 |
#define R200_SE_TCL_SCALAR_DATA_REG 0x220c |
/* gap */ |
#define R200_SE_TCL_MATRIX_SEL_0 0x2230 |
#define R200_MODELVIEW_0_SHIFT (0) |
#define R200_MODELVIEW_1_SHIFT (8) |
#define R200_MODELVIEW_2_SHIFT (16) |
#define R200_MODELVIEW_3_SHIFT (24) |
#define R200_SE_TCL_MATRIX_SEL_1 0x2234 |
#define R200_IT_MODELVIEW_0_SHIFT (0) |
#define R200_IT_MODELVIEW_1_SHIFT (8) |
#define R200_IT_MODELVIEW_2_SHIFT (16) |
#define R200_IT_MODELVIEW_3_SHIFT (24) |
#define R200_SE_TCL_MATRIX_SEL_2 0x2238 |
#define R200_MODELPROJECT_0_SHIFT (0) |
#define R200_MODELPROJECT_1_SHIFT (8) |
#define R200_MODELPROJECT_2_SHIFT (16) |
#define R200_MODELPROJECT_3_SHIFT (24) |
#define R200_SE_TCL_MATRIX_SEL_3 0x223c |
#define R200_TEXMAT_0_SHIFT 0 |
#define R200_TEXMAT_1_SHIFT 8 |
#define R200_TEXMAT_2_SHIFT 16 |
#define R200_TEXMAT_3_SHIFT 24 |
#define R200_SE_TCL_MATRIX_SEL_4 0x2240 |
#define R200_TEXMAT_4_SHIFT 0 |
#define R200_TEXMAT_5_SHIFT 8 |
/* gap */ |
#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 |
#define R200_OUTPUT_XYZW (1<<0) |
#define R200_OUTPUT_COLOR_0 (1<<8) |
#define R200_OUTPUT_COLOR_1 (1<<9) |
#define R200_OUTPUT_TEX_0 (1<<16) |
#define R200_OUTPUT_TEX_1 (1<<17) |
#define R200_OUTPUT_TEX_2 (1<<18) |
#define R200_OUTPUT_TEX_3 (1<<19) |
#define R200_OUTPUT_TEX_4 (1<<20) |
#define R200_OUTPUT_TEX_5 (1<<21) |
#define R200_OUTPUT_TEX_MASK (0x3f<<16) |
#define R200_OUTPUT_DISCRETE_FOG (1<<24) |
#define R200_OUTPUT_PT_SIZE (1<<25) |
#define R200_FORCE_INORDER_PROC (1<<31) |
#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254 |
#define R200_VERTEX_POSITION_ADDR__SHIFT 0x00000000 |
#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_1 0x2258 |
#define R200_VTX_COLOR_0_ADDR__SHIFT 0x00000000 |
#define R200_VTX_COLOR_1_ADDR__SHIFT 0x00000008 |
#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_2 0x225c |
#define R200_VTX_TEX_0_ADDR__SHIFT 0x00000000 |
#define R200_VTX_TEX_1_ADDR__SHIFT 0x00000008 |
#define R200_VTX_TEX_2_ADDR__SHIFT 0x00000010 |
#define R200_VTX_TEX_3_ADDR__SHIFT 0x00000018 |
#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_3 0x2260 |
#define R200_VTX_TEX_4_ADDR__SHIFT 0x00000000 |
#define R200_VTX_TEX_5_ADDR__SHIFT 0x00000008 |
/* gap */ |
#define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268 |
#define R200_LIGHTING_ENABLE (1<<0) |
#define R200_LIGHT_IN_MODELSPACE (1<<1) |
#define R200_LOCAL_VIEWER (1<<2) |
#define R200_NORMALIZE_NORMALS (1<<3) |
#define R200_RESCALE_NORMALS (1<<4) |
#define R200_SPECULAR_LIGHTS (1<<5) |
#define R200_DIFFUSE_SPECULAR_COMBINE (1<<6) |
#define R200_LIGHT_ALPHA (1<<7) |
#define R200_LOCAL_LIGHT_VEC_GL (1<<8) |
#define R200_LIGHT_NO_NORMAL_AMBIENT_ONLY (1<<9) |
#define R200_LIGHT_TWOSIDE (1<<10) |
#define R200_FRONT_SHININESS_SOURCE_SHIFT (0xb) |
#define R200_BACK_SHININESS_SOURCE_SHIFT (0xd) |
#define R200_LM0_SOURCE_MATERIAL_0 (0) |
#define R200_LM0_SOURCE_MATERIAL_1 (1) |
#define R200_LM0_SOURCE_VERTEX_SHININESS_0 (2) |
#define R200_LM0_SOURCE_VERTEX_SHININESS_1 (3) |
#define R200_SE_TCL_LIGHT_MODEL_CTL_1 0x226c |
#define R200_LM1_SOURCE_LIGHT_PREMULT (0) |
#define R200_LM1_SOURCE_MATERIAL_0 (1) |
#define R200_LM1_SOURCE_VERTEX_COLOR_0 (2) |
#define R200_LM1_SOURCE_VERTEX_COLOR_1 (3) |
#define R200_LM1_SOURCE_VERTEX_COLOR_2 (4) |
#define R200_LM1_SOURCE_VERTEX_COLOR_3 (5) |
#define R200_LM1_SOURCE_VERTEX_COLOR_4 (6) |
#define R200_LM1_SOURCE_VERTEX_COLOR_5 (7) |
#define R200_LM1_SOURCE_VERTEX_COLOR_6 (8) |
#define R200_LM1_SOURCE_VERTEX_COLOR_7 (9) |
#define R200_LM1_SOURCE_MATERIAL_1 (0xf) |
#define R200_FRONT_EMISSIVE_SOURCE_SHIFT (0) |
#define R200_FRONT_AMBIENT_SOURCE_SHIFT (4) |
#define R200_FRONT_DIFFUSE_SOURCE_SHIFT (8) |
#define R200_FRONT_SPECULAR_SOURCE_SHIFT (12) |
#define R200_BACK_EMISSIVE_SOURCE_SHIFT (16) |
#define R200_BACK_AMBIENT_SOURCE_SHIFT (20) |
#define R200_BACK_DIFFUSE_SOURCE_SHIFT (24) |
#define R200_BACK_SPECULAR_SOURCE_SHIFT (28) |
#define R200_SE_TCL_PER_LIGHT_CTL_0 0x2270 |
#define R200_LIGHT_0_ENABLE (1<<0) |
#define R200_LIGHT_0_ENABLE_AMBIENT (1<<1) |
#define R200_LIGHT_0_ENABLE_SPECULAR (1<<2) |
#define R200_LIGHT_0_IS_LOCAL (1<<3) |
#define R200_LIGHT_0_IS_SPOT (1<<4) |
#define R200_LIGHT_0_DUAL_CONE (1<<5) |
#define R200_LIGHT_0_ENABLE_RANGE_ATTEN (1<<6) |
#define R200_LIGHT_0_CONSTANT_RANGE_ATTEN (1<<7) |
#define R200_LIGHT_1_ENABLE (1<<16) |
#define R200_LIGHT_1_ENABLE_AMBIENT (1<<17) |
#define R200_LIGHT_1_ENABLE_SPECULAR (1<<18) |
#define R200_LIGHT_1_IS_LOCAL (1<<19) |
#define R200_LIGHT_1_IS_SPOT (1<<20) |
#define R200_LIGHT_1_DUAL_CONE (1<<21) |
#define R200_LIGHT_1_ENABLE_RANGE_ATTEN (1<<22) |
#define R200_LIGHT_1_CONSTANT_RANGE_ATTEN (1<<23) |
#define R200_LIGHT_0_SHIFT (0) |
#define R200_LIGHT_1_SHIFT (16) |
#define R200_SE_TCL_PER_LIGHT_CTL_1 0x2274 |
#define R200_LIGHT_2_SHIFT (0) |
#define R200_LIGHT_3_SHIFT (16) |
#define R200_SE_TCL_PER_LIGHT_CTL_2 0x2278 |
#define R200_LIGHT_4_SHIFT (0) |
#define R200_LIGHT_5_SHIFT (16) |
#define R200_SE_TCL_PER_LIGHT_CTL_3 0x227c |
#define R200_LIGHT_6_SHIFT (0) |
#define R200_LIGHT_7_SHIFT (16) |
/* gap */ |
#define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8 |
#define R200_TEXGEN_COMP_MASK (0xf) |
#define R200_TEXGEN_COMP_S (0x1) |
#define R200_TEXGEN_COMP_T (0x2) |
#define R200_TEXGEN_COMP_R (0x4) |
#define R200_TEXGEN_COMP_Q (0x8) |
#define R200_TEXGEN_0_COMP_MASK_SHIFT (0) |
#define R200_TEXGEN_1_COMP_MASK_SHIFT (4) |
#define R200_TEXGEN_2_COMP_MASK_SHIFT (8) |
#define R200_TEXGEN_3_COMP_MASK_SHIFT (12) |
#define R200_TEXGEN_4_COMP_MASK_SHIFT (16) |
#define R200_TEXGEN_5_COMP_MASK_SHIFT (20) |
#define R200_SE_TCL_TEX_PROC_CTL_3 0x22ac |
#define R200_TEXGEN_0_INPUT_TEX_SHIFT (0) |
#define R200_TEXGEN_1_INPUT_TEX_SHIFT (4) |
#define R200_TEXGEN_2_INPUT_TEX_SHIFT (8) |
#define R200_TEXGEN_3_INPUT_TEX_SHIFT (12) |
#define R200_TEXGEN_4_INPUT_TEX_SHIFT (16) |
#define R200_TEXGEN_5_INPUT_TEX_SHIFT (20) |
#define R200_SE_TCL_TEX_PROC_CTL_0 0x22b0 |
#define R200_TEXGEN_TEXMAT_0_ENABLE (1<<0) |
#define R200_TEXGEN_TEXMAT_1_ENABLE (1<<1) |
#define R200_TEXGEN_TEXMAT_2_ENABLE (1<<2) |
#define R200_TEXGEN_TEXMAT_3_ENABLE (1<<3) |
#define R200_TEXGEN_TEXMAT_4_ENABLE (1<<4) |
#define R200_TEXGEN_TEXMAT_5_ENABLE (1<<5) |
#define R200_TEXMAT_0_ENABLE (1<<8) |
#define R200_TEXMAT_1_ENABLE (1<<9) |
#define R200_TEXMAT_2_ENABLE (1<<10) |
#define R200_TEXMAT_3_ENABLE (1<<11) |
#define R200_TEXMAT_4_ENABLE (1<<12) |
#define R200_TEXMAT_5_ENABLE (1<<13) |
#define R200_TEXGEN_FORCE_W_TO_ONE (1<<16) |
#define R200_SE_TCL_TEX_PROC_CTL_1 0x22b4 |
#define R200_TEXGEN_INPUT_MASK (0xf) |
#define R200_TEXGEN_INPUT_TEXCOORD_0 (0) |
#define R200_TEXGEN_INPUT_TEXCOORD_1 (1) |
#define R200_TEXGEN_INPUT_TEXCOORD_2 (2) |
#define R200_TEXGEN_INPUT_TEXCOORD_3 (3) |
#define R200_TEXGEN_INPUT_TEXCOORD_4 (4) |
#define R200_TEXGEN_INPUT_TEXCOORD_5 (5) |
#define R200_TEXGEN_INPUT_OBJ (8) |
#define R200_TEXGEN_INPUT_EYE (9) |
#define R200_TEXGEN_INPUT_EYE_NORMAL (0xa) |
#define R200_TEXGEN_INPUT_EYE_REFLECT (0xb) |
#define R200_TEXGEN_INPUT_SPHERE (0xd) |
#define R200_TEXGEN_0_INPUT_SHIFT (0) |
#define R200_TEXGEN_1_INPUT_SHIFT (4) |
#define R200_TEXGEN_2_INPUT_SHIFT (8) |
#define R200_TEXGEN_3_INPUT_SHIFT (12) |
#define R200_TEXGEN_4_INPUT_SHIFT (16) |
#define R200_TEXGEN_5_INPUT_SHIFT (20) |
#define R200_SE_TC_TEX_CYL_WRAP_CTL 0x22b8 |
/* gap */ |
#define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0 |
#define R200_UCP_IN_CLIP_SPACE (1<<0) |
#define R200_UCP_IN_MODEL_SPACE (1<<1) |
#define R200_UCP_ENABLE_0 (1<<2) |
#define R200_UCP_ENABLE_1 (1<<3) |
#define R200_UCP_ENABLE_2 (1<<4) |
#define R200_UCP_ENABLE_3 (1<<5) |
#define R200_UCP_ENABLE_4 (1<<6) |
#define R200_UCP_ENABLE_5 (1<<7) |
#define R200_TCL_FOG_MASK (3<<8) |
#define R200_TCL_FOG_DISABLE (0<<8) |
#define R200_TCL_FOG_EXP (1<<8) |
#define R200_TCL_FOG_EXP2 (2<<8) |
#define R200_TCL_FOG_LINEAR (3<<8) |
#define R200_RNG_BASED_FOG (1<<10) |
#define R200_CLIP_DISABLE (1<<11) |
#define R200_CULL_FRONT_IS_CW (0<<28) |
#define R200_CULL_FRONT_IS_CCW (1<<28) |
#define R200_CULL_FRONT (1<<29) |
#define R200_CULL_BACK (1<<30) |
#define R200_SE_TCL_POINT_SPRITE_CNTL 0x22c4 |
#define R200_PS_MULT_PVATTENCONST (0<<0) |
#define R200_PS_MULT_PVATTEN (1<<0) |
#define R200_PS_MULT_ATTENCONST (2<<0) |
#define R200_PS_MULT_PVCONST (3<<0) |
#define R200_PS_MULT_CONST (4<<0) |
#define R200_PS_MULT_MASK (7<<0) |
#define R200_PS_LIN_ATT_ZERO (1<<3) |
#define R200_PS_USE_MODEL_EYE_VEC (1<<4) |
#define R200_PS_ATT_ALPHA (1<<5) |
#define R200_PS_UCP_MODE_MASK (3<<6) |
#define R200_PS_GEN_TEX_0 (1<<8) |
#define R200_PS_GEN_TEX_1 (1<<9) |
#define R200_PS_GEN_TEX_2 (1<<10) |
#define R200_PS_GEN_TEX_3 (1<<11) |
#define R200_PS_GEN_TEX_4 (1<<12) |
#define R200_PS_GEN_TEX_5 (1<<13) |
#define R200_PS_GEN_TEX_0_SHIFT (8) |
#define R200_PS_GEN_TEX_MASK (0x3f<<8) |
#define R200_PS_SE_SEL_STATE (1<<16) |
/* gap */ |
/* taken from r300, see comments there */ |
#define R200_VAP_PVS_CNTL_1 0x22d0 |
# define R200_PVS_CNTL_1_PROGRAM_START_SHIFT 0 |
# define R200_PVS_CNTL_1_POS_END_SHIFT 10 |
# define R200_PVS_CNTL_1_PROGRAM_END_SHIFT 20 |
/* Addresses are relative to the vertex program parameters area. */ |
#define R200_VAP_PVS_CNTL_2 0x22d4 |
# define R200_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0 |
# define R200_PVS_CNTL_2_PARAM_COUNT_SHIFT 16 |
/* gap */ |
#define R200_SE_VTX_ST_POS_0_X_4 0x2300 |
#define R200_SE_VTX_ST_POS_0_Y_4 0x2304 |
#define R200_SE_VTX_ST_POS_0_Z_4 0x2308 |
#define R200_SE_VTX_ST_POS_0_W_4 0x230c |
#define R200_SE_VTX_ST_NORM_0_X 0x2310 |
#define R200_SE_VTX_ST_NORM_0_Y 0x2314 |
#define R200_SE_VTX_ST_NORM_0_Z 0x2318 |
#define R200_SE_VTX_ST_PVMS 0x231c |
#define R200_SE_VTX_ST_CLR_0_R 0x2320 |
#define R200_SE_VTX_ST_CLR_0_G 0x2324 |
#define R200_SE_VTX_ST_CLR_0_B 0x2328 |
#define R200_SE_VTX_ST_CLR_0_A 0x232c |
#define R200_SE_VTX_ST_CLR_1_R 0x2330 |
#define R200_SE_VTX_ST_CLR_1_G 0x2334 |
#define R200_SE_VTX_ST_CLR_1_B 0x2338 |
#define R200_SE_VTX_ST_CLR_1_A 0x233c |
#define R200_SE_VTX_ST_CLR_2_R 0x2340 |
#define R200_SE_VTX_ST_CLR_2_G 0x2344 |
#define R200_SE_VTX_ST_CLR_2_B 0x2348 |
#define R200_SE_VTX_ST_CLR_2_A 0x234c |
#define R200_SE_VTX_ST_CLR_3_R 0x2350 |
#define R200_SE_VTX_ST_CLR_3_G 0x2354 |
#define R200_SE_VTX_ST_CLR_3_B 0x2358 |
#define R200_SE_VTX_ST_CLR_3_A 0x235c |
#define R200_SE_VTX_ST_CLR_4_R 0x2360 |
#define R200_SE_VTX_ST_CLR_4_G 0x2364 |
#define R200_SE_VTX_ST_CLR_4_B 0x2368 |
#define R200_SE_VTX_ST_CLR_4_A 0x236c |
#define R200_SE_VTX_ST_CLR_5_R 0x2370 |
#define R200_SE_VTX_ST_CLR_5_G 0x2374 |
#define R200_SE_VTX_ST_CLR_5_B 0x2378 |
#define R200_SE_VTX_ST_CLR_5_A 0x237c |
#define R200_SE_VTX_ST_CLR_6_R 0x2380 |
#define R200_SE_VTX_ST_CLR_6_G 0x2384 |
#define R200_SE_VTX_ST_CLR_6_B 0x2388 |
#define R200_SE_VTX_ST_CLR_6_A 0x238c |
#define R200_SE_VTX_ST_CLR_7_R 0x2390 |
#define R200_SE_VTX_ST_CLR_7_G 0x2394 |
#define R200_SE_VTX_ST_CLR_7_B 0x2398 |
#define R200_SE_VTX_ST_CLR_7_A 0x239c |
#define R200_SE_VTX_ST_TEX_0_S 0x23a0 |
#define R200_SE_VTX_ST_TEX_0_T 0x23a4 |
#define R200_SE_VTX_ST_TEX_0_R 0x23a8 |
#define R200_SE_VTX_ST_TEX_0_Q 0x23ac |
#define R200_SE_VTX_ST_TEX_1_S 0x23b0 |
#define R200_SE_VTX_ST_TEX_1_T 0x23b4 |
#define R200_SE_VTX_ST_TEX_1_R 0x23b8 |
#define R200_SE_VTX_ST_TEX_1_Q 0x23bc |
#define R200_SE_VTX_ST_TEX_2_S 0x23c0 |
#define R200_SE_VTX_ST_TEX_2_T 0x23c4 |
#define R200_SE_VTX_ST_TEX_2_R 0x23c8 |
#define R200_SE_VTX_ST_TEX_2_Q 0x23cc |
#define R200_SE_VTX_ST_TEX_3_S 0x23d0 |
#define R200_SE_VTX_ST_TEX_3_T 0x23d4 |
#define R200_SE_VTX_ST_TEX_3_R 0x23d8 |
#define R200_SE_VTX_ST_TEX_3_Q 0x23dc |
#define R200_SE_VTX_ST_TEX_4_S 0x23e0 |
#define R200_SE_VTX_ST_TEX_4_T 0x23e4 |
#define R200_SE_VTX_ST_TEX_4_R 0x23e8 |
#define R200_SE_VTX_ST_TEX_4_Q 0x23ec |
#define R200_SE_VTX_ST_TEX_5_S 0x23f0 |
#define R200_SE_VTX_ST_TEX_5_T 0x23f4 |
#define R200_SE_VTX_ST_TEX_5_R 0x23f8 |
#define R200_SE_VTX_ST_TEX_5_Q 0x23fc |
#define R200_SE_VTX_ST_PNT_SPRT_SZ 0x2400 |
#define R200_SE_VTX_ST_DISC_FOG 0x2404 |
#define R200_SE_VTX_ST_SHININESS_0 0x2408 |
#define R200_SE_VTX_ST_SHININESS_1 0x240c |
#define R200_SE_VTX_ST_BLND_WT_0 0x2410 |
#define R200_SE_VTX_ST_BLND_WT_1 0x2414 |
#define R200_SE_VTX_ST_BLND_WT_2 0x2418 |
#define R200_SE_VTX_ST_BLND_WT_3 0x241c |
#define R200_SE_VTX_ST_POS_1_X 0x2420 |
#define R200_SE_VTX_ST_POS_1_Y 0x2424 |
#define R200_SE_VTX_ST_POS_1_Z 0x2428 |
#define R200_SE_VTX_ST_POS_1_W 0x242c |
#define R200_SE_VTX_ST_NORM_1_X 0x2430 |
#define R200_SE_VTX_ST_NORM_1_Y 0x2434 |
#define R200_SE_VTX_ST_NORM_1_Z 0x2438 |
#define R200_SE_VTX_ST_USR_CLR_0_R 0x2440 |
#define R200_SE_VTX_ST_USR_CLR_0_G 0x2444 |
#define R200_SE_VTX_ST_USR_CLR_0_B 0x2448 |
#define R200_SE_VTX_ST_USR_CLR_0_A 0x244c |
#define R200_SE_VTX_ST_USR_CLR_1_R 0x2450 |
#define R200_SE_VTX_ST_USR_CLR_1_G 0x2454 |
#define R200_SE_VTX_ST_USR_CLR_1_B 0x2458 |
#define R200_SE_VTX_ST_USR_CLR_1_A 0x245c |
#define R200_SE_VTX_ST_CLR_0_PKD 0x2460 |
#define R200_SE_VTX_ST_CLR_1_PKD 0x2464 |
#define R200_SE_VTX_ST_CLR_2_PKD 0x2468 |
#define R200_SE_VTX_ST_CLR_3_PKD 0x246c |
#define R200_SE_VTX_ST_CLR_4_PKD 0x2470 |
#define R200_SE_VTX_ST_CLR_5_PKD 0x2474 |
#define R200_SE_VTX_ST_CLR_6_PKD 0x2478 |
#define R200_SE_VTX_ST_CLR_7_PKD 0x247c |
#define R200_SE_VTX_ST_POS_0_X_2 0x2480 |
#define R200_SE_VTX_ST_POS_0_Y_2 0x2484 |
#define R200_SE_VTX_ST_PAR_CLR_LD 0x2488 |
#define R200_SE_VTX_ST_USR_CLR_PKD 0x248c |
#define R200_SE_VTX_ST_POS_0_X_3 0x2490 |
#define R200_SE_VTX_ST_POS_0_Y_3 0x2494 |
#define R200_SE_VTX_ST_POS_0_Z_3 0x2498 |
#define R200_SE_VTX_ST_END_OF_PKT 0x249c |
/* gap */ |
#define R200_RE_POINTSIZE 0x2648 |
#define R200_POINTSIZE_SHIFT 0 |
#define R200_MAXPOINTSIZE_SHIFT 16 |
/* gap */ |
#define R200_RE_TOP_LEFT 0x26c0 |
#define R200_RE_LEFT_SHIFT 0 |
#define R200_RE_TOP_SHIFT 16 |
#define R200_RE_MISC 0x26c4 |
#define R200_STIPPLE_COORD_MASK 0x1f |
#define R200_STIPPLE_X_OFFSET_SHIFT 0 |
#define R200_STIPPLE_X_OFFSET_MASK (0x1f << 0) |
#define R200_STIPPLE_Y_OFFSET_SHIFT 8 |
#define R200_STIPPLE_Y_OFFSET_MASK (0x1f << 8) |
#define R200_STIPPLE_LITTLE_BIT_ORDER (0 << 16) |
#define R200_STIPPLE_BIG_BIT_ORDER (1 << 16) |
/* gap */ |
#define R200_RE_AUX_SCISSOR_CNTL 0x26f0 |
#define R200_EXCLUSIVE_SCISSOR_0 0x01000000 |
#define R200_EXCLUSIVE_SCISSOR_1 0x02000000 |
#define R200_EXCLUSIVE_SCISSOR_2 0x04000000 |
#define R200_SCISSOR_ENABLE_0 0x10000000 |
#define R200_SCISSOR_ENABLE_1 0x20000000 |
#define R200_SCISSOR_ENABLE_2 0x40000000 |
/* gap */ |
#define R200_PP_TXFILTER_0 0x2c00 |
#define R200_MAG_FILTER_NEAREST (0 << 0) |
#define R200_MAG_FILTER_LINEAR (1 << 0) |
#define R200_MAG_FILTER_MASK (1 << 0) |
#define R200_MIN_FILTER_NEAREST (0 << 1) |
#define R200_MIN_FILTER_LINEAR (1 << 1) |
#define R200_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1) |
#define R200_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1) |
#define R200_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1) |
#define R200_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1) |
#define R200_MIN_FILTER_ANISO_NEAREST (8 << 1) |
#define R200_MIN_FILTER_ANISO_LINEAR (9 << 1) |
#define R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1) |
#define R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1) |
#define R200_MIN_FILTER_MASK (15 << 1) |
#define R200_MAX_ANISO_1_TO_1 (0 << 5) |
#define R200_MAX_ANISO_2_TO_1 (1 << 5) |
#define R200_MAX_ANISO_4_TO_1 (2 << 5) |
#define R200_MAX_ANISO_8_TO_1 (3 << 5) |
#define R200_MAX_ANISO_16_TO_1 (4 << 5) |
#define R200_MAX_ANISO_MASK (7 << 5) |
#define R200_MAX_MIP_LEVEL_MASK (0x0f << 16) |
#define R200_MAX_MIP_LEVEL_SHIFT 16 |
#define R200_YUV_TO_RGB (1 << 20) |
#define R200_YUV_TEMPERATURE_COOL (0 << 21) |
#define R200_YUV_TEMPERATURE_HOT (1 << 21) |
#define R200_YUV_TEMPERATURE_MASK (1 << 21) |
#define R200_WRAPEN_S (1 << 22) |
#define R200_CLAMP_S_WRAP (0 << 23) |
#define R200_CLAMP_S_MIRROR (1 << 23) |
#define R200_CLAMP_S_CLAMP_LAST (2 << 23) |
#define R200_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) |
#define R200_CLAMP_S_CLAMP_BORDER (4 << 23) |
#define R200_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) |
#define R200_CLAMP_S_CLAMP_GL (6 << 23) |
#define R200_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) |
#define R200_CLAMP_S_MASK (7 << 23) |
#define R200_WRAPEN_T (1 << 26) |
#define R200_CLAMP_T_WRAP (0 << 27) |
#define R200_CLAMP_T_MIRROR (1 << 27) |
#define R200_CLAMP_T_CLAMP_LAST (2 << 27) |
#define R200_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) |
#define R200_CLAMP_T_CLAMP_BORDER (4 << 27) |
#define R200_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) |
#define R200_CLAMP_T_CLAMP_GL (6 << 27) |
#define R200_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) |
#define R200_CLAMP_T_MASK (7 << 27) |
#define R200_KILL_LT_ZERO (1 << 30) |
#define R200_BORDER_MODE_OGL (0 << 31) |
#define R200_BORDER_MODE_D3D (1 << 31) |
#define R200_PP_TXFORMAT_0 0x2c04 |
#define R200_TXFORMAT_I8 (0 << 0) |
#define R200_TXFORMAT_AI88 (1 << 0) |
#define R200_TXFORMAT_RGB332 (2 << 0) |
#define R200_TXFORMAT_ARGB1555 (3 << 0) |
#define R200_TXFORMAT_RGB565 (4 << 0) |
#define R200_TXFORMAT_ARGB4444 (5 << 0) |
#define R200_TXFORMAT_ARGB8888 (6 << 0) |
#define R200_TXFORMAT_RGBA8888 (7 << 0) |
#define R200_TXFORMAT_Y8 (8 << 0) |
#define R200_TXFORMAT_AVYU4444 (9 << 0) |
#define R200_TXFORMAT_VYUY422 (10 << 0) |
#define R200_TXFORMAT_YVYU422 (11 << 0) |
#define R200_TXFORMAT_DXT1 (12 << 0) |
#define R200_TXFORMAT_DXT23 (14 << 0) |
#define R200_TXFORMAT_DXT45 (15 << 0) |
#define R200_TXFORMAT_DVDU88 (18 << 0) |
#define R200_TXFORMAT_LDVDU655 (19 << 0) |
#define R200_TXFORMAT_LDVDU8888 (20 << 0) |
#define R200_TXFORMAT_GR1616 (21 << 0) |
#define R200_TXFORMAT_ABGR8888 (22 << 0) |
#define R200_TXFORMAT_BGR111110 (23 << 0) |
#define R200_TXFORMAT_FORMAT_MASK (31 << 0) |
#define R200_TXFORMAT_FORMAT_SHIFT 0 |
#define R200_TXFORMAT_APPLE_YUV (1 << 5) |
#define R200_TXFORMAT_ALPHA_IN_MAP (1 << 6) |
#define R200_TXFORMAT_NON_POWER2 (1 << 7) |
#define R200_TXFORMAT_WIDTH_MASK (15 << 8) |
#define R200_TXFORMAT_WIDTH_SHIFT 8 |
#define R200_TXFORMAT_HEIGHT_MASK (15 << 12) |
#define R200_TXFORMAT_HEIGHT_SHIFT 12 |
#define R200_TXFORMAT_F5_WIDTH_MASK (15 << 16) /* cube face 5 */ |
#define R200_TXFORMAT_F5_WIDTH_SHIFT 16 |
#define R200_TXFORMAT_F5_HEIGHT_MASK (15 << 20) |
#define R200_TXFORMAT_F5_HEIGHT_SHIFT 20 |
#define R200_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) |
#define R200_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) |
#define R200_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) |
#define R200_TXFORMAT_ST_ROUTE_STQ3 (3 << 24) |
#define R200_TXFORMAT_ST_ROUTE_STQ4 (4 << 24) |
#define R200_TXFORMAT_ST_ROUTE_STQ5 (5 << 24) |
#define R200_TXFORMAT_ST_ROUTE_MASK (7 << 24) |
#define R200_TXFORMAT_ST_ROUTE_SHIFT 24 |
#define R200_TXFORMAT_LOOKUP_DISABLE (1 << 27) |
#define R200_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) |
#define R200_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) |
#define R200_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) |
#define R200_PP_TXFORMAT_X_0 0x2c08 |
#define R200_DEPTH_LOG2_MASK (0xf << 0) |
#define R200_DEPTH_LOG2_SHIFT 0 |
#define R200_VOLUME_FILTER_SHIFT 4 |
#define R200_VOLUME_FILTER_MASK (1 << 4) |
#define R200_VOLUME_FILTER_NEAREST (0 << 4) |
#define R200_VOLUME_FILTER_LINEAR (1 << 4) |
#define R200_WRAPEN_Q (1 << 8) |
#define R200_CLAMP_Q_WRAP (0 << 9) |
#define R200_CLAMP_Q_MIRROR (1 << 9) |
#define R200_CLAMP_Q_CLAMP_LAST (2 << 9) |
#define R200_CLAMP_Q_MIRROR_CLAMP_LAST (3 << 9) |
#define R200_CLAMP_Q_CLAMP_BORDER (4 << 9) |
#define R200_CLAMP_Q_MIRROR_CLAMP_BORDER (5 << 9) |
#define R200_CLAMP_Q_CLAMP_GL (6 << 9) |
#define R200_CLAMP_Q_MIRROR_CLAMP_GL (7 << 9) |
#define R200_CLAMP_Q_MASK (7 << 9) |
#define R200_MIN_MIP_LEVEL_MASK (0x0f << 12) |
#define R200_MIN_MIP_LEVEL_SHIFT 12 |
#define R200_TEXCOORD_NONPROJ (0 << 16) |
#define R200_TEXCOORD_CUBIC_ENV (1 << 16) |
#define R200_TEXCOORD_VOLUME (2 << 16) |
#define R200_TEXCOORD_PROJ (3 << 16) |
#define R200_TEXCOORD_DEPTH (4 << 16) |
#define R200_TEXCOORD_1D_PROJ (5 << 16) |
#define R200_TEXCOORD_1D (6 << 16) |
#define R200_TEXCOORD_ZERO (7 << 16) |
#define R200_TEXCOORD_MASK (7 << 16) |
#define R200_LOD_BIAS_MASK (0xfff80000) |
#define R200_LOD_BIAS_FIXED_ONE (0x08000000) |
#define R200_LOD_BIAS_CORRECTION (0x00600000) |
#define R200_LOD_BIAS_SHIFT 19 |
#define R200_PP_TXSIZE_0 0x2c0c /* NPOT only */ |
#define R200_PP_TX_WIDTHMASK_SHIFT 0 |
#define R200_PP_TX_HEIGHTMASK_SHIFT 16 |
#define R200_PP_TXPITCH_0 0x2c10 /* NPOT only */ |
#define R200_PP_BORDER_COLOR_0 0x2c14 |
#define R200_PP_CUBIC_FACES_0 0x2c18 |
#define R200_FACE_WIDTH_1_SHIFT 0 |
#define R200_FACE_HEIGHT_1_SHIFT 4 |
#define R200_FACE_WIDTH_1_MASK (0xf << 0) |
#define R200_FACE_HEIGHT_1_MASK (0xf << 4) |
#define R200_FACE_WIDTH_2_SHIFT 8 |
#define R200_FACE_HEIGHT_2_SHIFT 12 |
#define R200_FACE_WIDTH_2_MASK (0xf << 8) |
#define R200_FACE_HEIGHT_2_MASK (0xf << 12) |
#define R200_FACE_WIDTH_3_SHIFT 16 |
#define R200_FACE_HEIGHT_3_SHIFT 20 |
#define R200_FACE_WIDTH_3_MASK (0xf << 16) |
#define R200_FACE_HEIGHT_3_MASK (0xf << 20) |
#define R200_FACE_WIDTH_4_SHIFT 24 |
#define R200_FACE_HEIGHT_4_SHIFT 28 |
#define R200_FACE_WIDTH_4_MASK (0xf << 24) |
#define R200_FACE_HEIGHT_4_MASK (0xf << 28) |
#define R200_PP_TXMULTI_CTL_0 0x2c1c /* name from ddx, rest RE... */ |
#define R200_PASS1_TXFORMAT_LOOKUP_DISABLE (1 << 0) |
#define R200_PASS1_TEXCOORD_NONPROJ (0 << 1) |
#define R200_PASS1_TEXCOORD_CUBIC_ENV (1 << 1) |
#define R200_PASS1_TEXCOORD_VOLUME (2 << 1) |
#define R200_PASS1_TEXCOORD_PROJ (3 << 1) |
#define R200_PASS1_TEXCOORD_DEPTH (4 << 1) |
#define R200_PASS1_TEXCOORD_1D_PROJ (5 << 1) |
#define R200_PASS1_TEXCOORD_1D (6 << 1) /* pass1 texcoords only */ |
#define R200_PASS1_TEXCOORD_ZERO (7 << 1) /* verifed for 2d targets! */ |
#define R200_PASS1_TEXCOORD_MASK (7 << 1) /* assumed same values as for pass2 */ |
#define R200_PASS1_ST_ROUTE_STQ0 (0 << 4) |
#define R200_PASS1_ST_ROUTE_STQ1 (1 << 4) |
#define R200_PASS1_ST_ROUTE_STQ2 (2 << 4) |
#define R200_PASS1_ST_ROUTE_STQ3 (3 << 4) |
#define R200_PASS1_ST_ROUTE_STQ4 (4 << 4) |
#define R200_PASS1_ST_ROUTE_STQ5 (5 << 4) |
#define R200_PASS1_ST_ROUTE_MASK (7 << 4) |
#define R200_PASS1_ST_ROUTE_SHIFT (4) |
#define R200_PASS2_COORDS_REG_0 (2 << 24) |
#define R200_PASS2_COORDS_REG_1 (3 << 24) |
#define R200_PASS2_COORDS_REG_2 (4 << 24) |
#define R200_PASS2_COORDS_REG_3 (5 << 24) |
#define R200_PASS2_COORDS_REG_4 (6 << 24) |
#define R200_PASS2_COORDS_REG_5 (7 << 24) |
#define R200_PASS2_COORDS_REG_MASK (0x7 << 24) |
#define R200_PASS2_COORDS_REG_SHIFT (24) |
#define R200_PP_TXFILTER_1 0x2c20 |
#define R200_PP_TXFORMAT_1 0x2c24 |
#define R200_PP_TXFORMAT_X_1 0x2c28 |
#define R200_PP_TXSIZE_1 0x2c2c |
#define R200_PP_TXPITCH_1 0x2c30 |
#define R200_PP_BORDER_COLOR_1 0x2c34 |
#define R200_PP_CUBIC_FACES_1 0x2c38 |
#define R200_PP_TXMULTI_CTL_1 0x2c3c |
#define R200_PP_TXFILTER_2 0x2c40 |
#define R200_PP_TXFORMAT_2 0x2c44 |
#define R200_PP_TXSIZE_2 0x2c4c |
#define R200_PP_TXFORMAT_X_2 0x2c48 |
#define R200_PP_TXPITCH_2 0x2c50 |
#define R200_PP_BORDER_COLOR_2 0x2c54 |
#define R200_PP_CUBIC_FACES_2 0x2c58 |
#define R200_PP_TXMULTI_CTL_2 0x2c5c |
#define R200_PP_TXFILTER_3 0x2c60 |
#define R200_PP_TXFORMAT_3 0x2c64 |
#define R200_PP_TXSIZE_3 0x2c6c |
#define R200_PP_TXFORMAT_X_3 0x2c68 |
#define R200_PP_TXPITCH_3 0x2c70 |
#define R200_PP_BORDER_COLOR_3 0x2c74 |
#define R200_PP_CUBIC_FACES_3 0x2c78 |
#define R200_PP_TXMULTI_CTL_3 0x2c7c |
#define R200_PP_TXFILTER_4 0x2c80 |
#define R200_PP_TXFORMAT_4 0x2c84 |
#define R200_PP_TXSIZE_4 0x2c8c |
#define R200_PP_TXFORMAT_X_4 0x2c88 |
#define R200_PP_TXPITCH_4 0x2c90 |
#define R200_PP_BORDER_COLOR_4 0x2c94 |
#define R200_PP_CUBIC_FACES_4 0x2c98 |
#define R200_PP_TXMULTI_CTL_4 0x2c9c |
#define R200_PP_TXFILTER_5 0x2ca0 |
#define R200_PP_TXFORMAT_5 0x2ca4 |
#define R200_PP_TXSIZE_5 0x2cac |
#define R200_PP_TXFORMAT_X_5 0x2ca8 |
#define R200_PP_TXPITCH_5 0x2cb0 |
#define R200_PP_BORDER_COLOR_5 0x2cb4 |
#define R200_PP_CUBIC_FACES_5 0x2cb8 |
#define R200_PP_TXMULTI_CTL_5 0x2cbc |
/* gap */ |
#define R200_PP_CNTL_X 0x2cc4 /* Reveree engineered from fglrx */ |
#define R200_PPX_TEX_0_ENABLE (1 << 0) |
#define R200_PPX_TEX_1_ENABLE (1 << 1) |
#define R200_PPX_TEX_2_ENABLE (1 << 2) |
#define R200_PPX_TEX_3_ENABLE (1 << 3) |
#define R200_PPX_TEX_4_ENABLE (1 << 4) |
#define R200_PPX_TEX_5_ENABLE (1 << 5) |
#define R200_PPX_TEX_ENABLE_MASK (0x3f << 0) |
#define R200_PPX_OUTPUT_REG_0 (1 << 6) |
#define R200_PPX_OUTPUT_REG_1 (1 << 7) |
#define R200_PPX_OUTPUT_REG_2 (1 << 8) |
#define R200_PPX_OUTPUT_REG_3 (1 << 9) |
#define R200_PPX_OUTPUT_REG_4 (1 << 10) |
#define R200_PPX_OUTPUT_REG_5 (1 << 11) |
#define R200_PPX_OUTPUT_REG_MASK (0x3f << 6) |
#define R200_PPX_OUTPUT_REG_0_SHIFT (6) |
#define R200_PPX_PFS_INST0_ENABLE (1 << 12) |
#define R200_PPX_PFS_INST1_ENABLE (1 << 13) |
#define R200_PPX_PFS_INST2_ENABLE (1 << 14) |
#define R200_PPX_PFS_INST3_ENABLE (1 << 15) |
#define R200_PPX_PFS_INST4_ENABLE (1 << 16) |
#define R200_PPX_PFS_INST5_ENABLE (1 << 17) |
#define R200_PPX_PFS_INST6_ENABLE (1 << 18) |
#define R200_PPX_PFS_INST7_ENABLE (1 << 19) |
#define R200_PPX_PFS_INST_ENABLE_MASK (0xff << 12) |
#define R200_PPX_FPS_INST0_ENABLE_SHIFT (12) |
/* gap */ |
#define R200_PP_TRI_PERF 0x2cf8 |
#define R200_TRI_CUTOFF_MASK (0x1f << 0) |
#define R200_PP_PERF_CNTL 0x2cfc |
#define R200_PP_TXOFFSET_0 0x2d00 |
#define R200_TXO_ENDIAN_NO_SWAP (0 << 0) |
#define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0) |
#define R200_TXO_ENDIAN_WORD_SWAP (2 << 0) |
#define R200_TXO_ENDIAN_HALFDW_SWAP (3 << 0) |
#define R200_TXO_MACRO_TILE (1 << 2) |
#define R200_TXO_MICRO_TILE (1 << 3) |
#define R200_TXO_OFFSET_MASK 0xffffffe0 |
#define R200_TXO_OFFSET_SHIFT 5 |
#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04 |
#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08 |
#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c |
#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10 |
#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14 |
#define R200_PP_TXOFFSET_1 0x2d18 |
#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c |
#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20 |
#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24 |
#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28 |
#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c |
#define R200_PP_TXOFFSET_2 0x2d30 |
#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34 |
#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38 |
#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c |
#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40 |
#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44 |
#define R200_PP_TXOFFSET_3 0x2d48 |
#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c |
#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50 |
#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54 |
#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58 |
#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c |
#define R200_PP_TXOFFSET_4 0x2d60 |
#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64 |
#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68 |
#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c |
#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70 |
#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74 |
#define R200_PP_TXOFFSET_5 0x2d78 |
#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c |
#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80 |
#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84 |
#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88 |
#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c |
/* gap */ |
#define R200_PP_TAM_DEBUG3 0x2d9c |
/* gap */ |
#define R200_PP_TFACTOR_0 0x2ee0 |
#define R200_PP_TFACTOR_1 0x2ee4 |
#define R200_PP_TFACTOR_2 0x2ee8 |
#define R200_PP_TFACTOR_3 0x2eec |
#define R200_PP_TFACTOR_4 0x2ef0 |
#define R200_PP_TFACTOR_5 0x2ef4 |
#define R200_PP_TFACTOR_6 0x2ef8 |
#define R200_PP_TFACTOR_7 0x2efc |
#define R200_PP_TXCBLEND_0 0x2f00 |
#define R200_TXC_ARG_A_ZERO (0) |
#define R200_TXC_ARG_A_CURRENT_COLOR (2) |
#define R200_TXC_ARG_A_CURRENT_ALPHA (3) |
#define R200_TXC_ARG_A_DIFFUSE_COLOR (4) |
#define R200_TXC_ARG_A_DIFFUSE_ALPHA (5) |
#define R200_TXC_ARG_A_SPECULAR_COLOR (6) |
#define R200_TXC_ARG_A_SPECULAR_ALPHA (7) |
#define R200_TXC_ARG_A_TFACTOR_COLOR (8) |
#define R200_TXC_ARG_A_TFACTOR_ALPHA (9) |
#define R200_TXC_ARG_A_R0_COLOR (10) |
#define R200_TXC_ARG_A_R0_ALPHA (11) |
#define R200_TXC_ARG_A_R1_COLOR (12) |
#define R200_TXC_ARG_A_R1_ALPHA (13) |
#define R200_TXC_ARG_A_R2_COLOR (14) |
#define R200_TXC_ARG_A_R2_ALPHA (15) |
#define R200_TXC_ARG_A_R3_COLOR (16) |
#define R200_TXC_ARG_A_R3_ALPHA (17) |
#define R200_TXC_ARG_A_R4_COLOR (18) |
#define R200_TXC_ARG_A_R4_ALPHA (19) |
#define R200_TXC_ARG_A_R5_COLOR (20) |
#define R200_TXC_ARG_A_R5_ALPHA (21) |
#define R200_TXC_ARG_A_TFACTOR1_COLOR (26) |
#define R200_TXC_ARG_A_TFACTOR1_ALPHA (27) |
#define R200_TXC_ARG_A_MASK (31 << 0) |
#define R200_TXC_ARG_A_SHIFT 0 |
#define R200_TXC_ARG_B_ZERO (0<<5) |
#define R200_TXC_ARG_B_CURRENT_COLOR (2<<5) |
#define R200_TXC_ARG_B_CURRENT_ALPHA (3<<5) |
#define R200_TXC_ARG_B_DIFFUSE_COLOR (4<<5) |
#define R200_TXC_ARG_B_DIFFUSE_ALPHA (5<<5) |
#define R200_TXC_ARG_B_SPECULAR_COLOR (6<<5) |
#define R200_TXC_ARG_B_SPECULAR_ALPHA (7<<5) |
#define R200_TXC_ARG_B_TFACTOR_COLOR (8<<5) |
#define R200_TXC_ARG_B_TFACTOR_ALPHA (9<<5) |
#define R200_TXC_ARG_B_R0_COLOR (10<<5) |
#define R200_TXC_ARG_B_R0_ALPHA (11<<5) |
#define R200_TXC_ARG_B_R1_COLOR (12<<5) |
#define R200_TXC_ARG_B_R1_ALPHA (13<<5) |
#define R200_TXC_ARG_B_R2_COLOR (14<<5) |
#define R200_TXC_ARG_B_R2_ALPHA (15<<5) |
#define R200_TXC_ARG_B_R3_COLOR (16<<5) |
#define R200_TXC_ARG_B_R3_ALPHA (17<<5) |
#define R200_TXC_ARG_B_R4_COLOR (18<<5) |
#define R200_TXC_ARG_B_R4_ALPHA (19<<5) |
#define R200_TXC_ARG_B_R5_COLOR (20<<5) |
#define R200_TXC_ARG_B_R5_ALPHA (21<<5) |
#define R200_TXC_ARG_B_TFACTOR1_COLOR (26<<5) |
#define R200_TXC_ARG_B_TFACTOR1_ALPHA (27<<5) |
#define R200_TXC_ARG_B_MASK (31 << 5) |
#define R200_TXC_ARG_B_SHIFT 5 |
#define R200_TXC_ARG_C_ZERO (0<<10) |
#define R200_TXC_ARG_C_CURRENT_COLOR (2<<10) |
#define R200_TXC_ARG_C_CURRENT_ALPHA (3<<10) |
#define R200_TXC_ARG_C_DIFFUSE_COLOR (4<<10) |
#define R200_TXC_ARG_C_DIFFUSE_ALPHA (5<<10) |
#define R200_TXC_ARG_C_SPECULAR_COLOR (6<<10) |
#define R200_TXC_ARG_C_SPECULAR_ALPHA (7<<10) |
#define R200_TXC_ARG_C_TFACTOR_COLOR (8<<10) |
#define R200_TXC_ARG_C_TFACTOR_ALPHA (9<<10) |
#define R200_TXC_ARG_C_R0_COLOR (10<<10) |
#define R200_TXC_ARG_C_R0_ALPHA (11<<10) |
#define R200_TXC_ARG_C_R1_COLOR (12<<10) |
#define R200_TXC_ARG_C_R1_ALPHA (13<<10) |
#define R200_TXC_ARG_C_R2_COLOR (14<<10) |
#define R200_TXC_ARG_C_R2_ALPHA (15<<10) |
#define R200_TXC_ARG_C_R3_COLOR (16<<10) |
#define R200_TXC_ARG_C_R3_ALPHA (17<<10) |
#define R200_TXC_ARG_C_R4_COLOR (18<<10) |
#define R200_TXC_ARG_C_R4_ALPHA (19<<10) |
#define R200_TXC_ARG_C_R5_COLOR (20<<10) |
#define R200_TXC_ARG_C_R5_ALPHA (21<<10) |
#define R200_TXC_ARG_C_TFACTOR1_COLOR (26<<10) |
#define R200_TXC_ARG_C_TFACTOR1_ALPHA (27<<10) |
#define R200_TXC_ARG_C_MASK (31 << 10) |
#define R200_TXC_ARG_C_SHIFT 10 |
#define R200_TXC_COMP_ARG_A (1 << 16) |
#define R200_TXC_COMP_ARG_A_SHIFT (16) |
#define R200_TXC_BIAS_ARG_A (1 << 17) |
#define R200_TXC_SCALE_ARG_A (1 << 18) |
#define R200_TXC_NEG_ARG_A (1 << 19) |
#define R200_TXC_COMP_ARG_B (1 << 20) |
#define R200_TXC_COMP_ARG_B_SHIFT (20) |
#define R200_TXC_BIAS_ARG_B (1 << 21) |
#define R200_TXC_SCALE_ARG_B (1 << 22) |
#define R200_TXC_NEG_ARG_B (1 << 23) |
#define R200_TXC_COMP_ARG_C (1 << 24) |
#define R200_TXC_COMP_ARG_C_SHIFT (24) |
#define R200_TXC_BIAS_ARG_C (1 << 25) |
#define R200_TXC_SCALE_ARG_C (1 << 26) |
#define R200_TXC_NEG_ARG_C (1 << 27) |
#define R200_TXC_OP_MADD (0 << 28) |
#define R200_TXC_OP_CND0 (2 << 28) |
#define R200_TXC_OP_LERP (3 << 28) |
#define R200_TXC_OP_DOT3 (4 << 28) |
#define R200_TXC_OP_DOT4 (5 << 28) |
#define R200_TXC_OP_CONDITIONAL (6 << 28) |
#define R200_TXC_OP_DOT2_ADD (7 << 28) |
#define R200_TXC_OP_MASK (7 << 28) |
#define R200_PP_TXCBLEND2_0 0x2f04 |
#define R200_TXC_TFACTOR_SEL_SHIFT 0 |
#define R200_TXC_TFACTOR_SEL_MASK 0x7 |
#define R200_TXC_TFACTOR1_SEL_SHIFT 4 |
#define R200_TXC_TFACTOR1_SEL_MASK (0x7 << 4) |
#define R200_TXC_SCALE_SHIFT 8 |
#define R200_TXC_SCALE_MASK (7 << 8) |
#define R200_TXC_SCALE_1X (0 << 8) |
#define R200_TXC_SCALE_2X (1 << 8) |
#define R200_TXC_SCALE_4X (2 << 8) |
#define R200_TXC_SCALE_8X (3 << 8) |
#define R200_TXC_SCALE_INV2 (5 << 8) |
#define R200_TXC_SCALE_INV4 (6 << 8) |
#define R200_TXC_SCALE_INV8 (7 << 8) |
#define R200_TXC_CLAMP_SHIFT 12 |
#define R200_TXC_CLAMP_MASK (3 << 12) |
#define R200_TXC_CLAMP_WRAP (0 << 12) |
#define R200_TXC_CLAMP_0_1 (1 << 12) |
#define R200_TXC_CLAMP_8_8 (2 << 12) |
#define R200_TXC_OUTPUT_REG_SHIFT 16 |
#define R200_TXC_OUTPUT_REG_MASK (7 << 16) |
#define R200_TXC_OUTPUT_REG_NONE (0 << 16) |
#define R200_TXC_OUTPUT_REG_R0 (1 << 16) |
#define R200_TXC_OUTPUT_REG_R1 (2 << 16) |
#define R200_TXC_OUTPUT_REG_R2 (3 << 16) |
#define R200_TXC_OUTPUT_REG_R3 (4 << 16) |
#define R200_TXC_OUTPUT_REG_R4 (5 << 16) |
#define R200_TXC_OUTPUT_REG_R5 (6 << 16) |
#define R200_TXC_OUTPUT_MASK_MASK (7 << 20) |
#define R200_TXC_OUTPUT_MASK_RGB (0 << 20) |
#define R200_TXC_OUTPUT_MASK_RG (1 << 20) |
#define R200_TXC_OUTPUT_MASK_RB (2 << 20) |
#define R200_TXC_OUTPUT_MASK_R (3 << 20) |
#define R200_TXC_OUTPUT_MASK_GB (4 << 20) |
#define R200_TXC_OUTPUT_MASK_G (5 << 20) |
#define R200_TXC_OUTPUT_MASK_B (6 << 20) |
#define R200_TXC_OUTPUT_MASK_NONE (7 << 20) |
#define R200_TXC_OUTPUT_ROTATE_RGB (0 << 24) |
#define R200_TXC_OUTPUT_ROTATE_ARG (1 << 24) |
#define R200_TXC_OUTPUT_ROTATE_GBA (2 << 24) |
#define R200_TXC_OUTPUT_ROTATE_RGA (3 << 24) |
#define R200_TXC_REPL_NORMAL 0 |
#define R200_TXC_REPL_RED 1 |
#define R200_TXC_REPL_GREEN 2 |
#define R200_TXC_REPL_BLUE 3 |
#define R200_TXC_REPL_ARG_A_SHIFT 26 |
#define R200_TXC_REPL_ARG_A_MASK (3 << 26) |
#define R200_TXC_REPL_ARG_B_SHIFT 28 |
#define R200_TXC_REPL_ARG_B_MASK (3 << 28) |
#define R200_TXC_REPL_ARG_C_SHIFT 30 |
#define R200_TXC_REPL_ARG_C_MASK (3 << 30) |
#define R200_PP_TXABLEND_0 0x2f08 |
#define R200_TXA_ARG_A_ZERO (0) |
#define R200_TXA_ARG_A_CURRENT_ALPHA (2) /* guess */ |
#define R200_TXA_ARG_A_CURRENT_BLUE (3) /* guess */ |
#define R200_TXA_ARG_A_DIFFUSE_ALPHA (4) |
#define R200_TXA_ARG_A_DIFFUSE_BLUE (5) |
#define R200_TXA_ARG_A_SPECULAR_ALPHA (6) |
#define R200_TXA_ARG_A_SPECULAR_BLUE (7) |
#define R200_TXA_ARG_A_TFACTOR_ALPHA (8) |
#define R200_TXA_ARG_A_TFACTOR_BLUE (9) |
#define R200_TXA_ARG_A_R0_ALPHA (10) |
#define R200_TXA_ARG_A_R0_BLUE (11) |
#define R200_TXA_ARG_A_R1_ALPHA (12) |
#define R200_TXA_ARG_A_R1_BLUE (13) |
#define R200_TXA_ARG_A_R2_ALPHA (14) |
#define R200_TXA_ARG_A_R2_BLUE (15) |
#define R200_TXA_ARG_A_R3_ALPHA (16) |
#define R200_TXA_ARG_A_R3_BLUE (17) |
#define R200_TXA_ARG_A_R4_ALPHA (18) |
#define R200_TXA_ARG_A_R4_BLUE (19) |
#define R200_TXA_ARG_A_R5_ALPHA (20) |
#define R200_TXA_ARG_A_R5_BLUE (21) |
#define R200_TXA_ARG_A_TFACTOR1_ALPHA (26) |
#define R200_TXA_ARG_A_TFACTOR1_BLUE (27) |
#define R200_TXA_ARG_A_MASK (31 << 0) |
#define R200_TXA_ARG_A_SHIFT 0 |
#define R200_TXA_ARG_B_ZERO (0<<5) |
#define R200_TXA_ARG_B_CURRENT_ALPHA (2<<5) /* guess */ |
#define R200_TXA_ARG_B_CURRENT_BLUE (3<<5) /* guess */ |
#define R200_TXA_ARG_B_DIFFUSE_ALPHA (4<<5) |
#define R200_TXA_ARG_B_DIFFUSE_BLUE (5<<5) |
#define R200_TXA_ARG_B_SPECULAR_ALPHA (6<<5) |
#define R200_TXA_ARG_B_SPECULAR_BLUE (7<<5) |
#define R200_TXA_ARG_B_TFACTOR_ALPHA (8<<5) |
#define R200_TXA_ARG_B_TFACTOR_BLUE (9<<5) |
#define R200_TXA_ARG_B_R0_ALPHA (10<<5) |
#define R200_TXA_ARG_B_R0_BLUE (11<<5) |
#define R200_TXA_ARG_B_R1_ALPHA (12<<5) |
#define R200_TXA_ARG_B_R1_BLUE (13<<5) |
#define R200_TXA_ARG_B_R2_ALPHA (14<<5) |
#define R200_TXA_ARG_B_R2_BLUE (15<<5) |
#define R200_TXA_ARG_B_R3_ALPHA (16<<5) |
#define R200_TXA_ARG_B_R3_BLUE (17<<5) |
#define R200_TXA_ARG_B_R4_ALPHA (18<<5) |
#define R200_TXA_ARG_B_R4_BLUE (19<<5) |
#define R200_TXA_ARG_B_R5_ALPHA (20<<5) |
#define R200_TXA_ARG_B_R5_BLUE (21<<5) |
#define R200_TXA_ARG_B_TFACTOR1_ALPHA (26<<5) |
#define R200_TXA_ARG_B_TFACTOR1_BLUE (27<<5) |
#define R200_TXA_ARG_B_MASK (31 << 5) |
#define R200_TXA_ARG_B_SHIFT 5 |
#define R200_TXA_ARG_C_ZERO (0<<10) |
#define R200_TXA_ARG_C_CURRENT_ALPHA (2<<10) /* guess */ |
#define R200_TXA_ARG_C_CURRENT_BLUE (3<<10) /* guess */ |
#define R200_TXA_ARG_C_DIFFUSE_ALPHA (4<<10) |
#define R200_TXA_ARG_C_DIFFUSE_BLUE (5<<10) |
#define R200_TXA_ARG_C_SPECULAR_ALPHA (6<<10) |
#define R200_TXA_ARG_C_SPECULAR_BLUE (7<<10) |
#define R200_TXA_ARG_C_TFACTOR_ALPHA (8<<10) |
#define R200_TXA_ARG_C_TFACTOR_BLUE (9<<10) |
#define R200_TXA_ARG_C_R0_ALPHA (10<<10) |
#define R200_TXA_ARG_C_R0_BLUE (11<<10) |
#define R200_TXA_ARG_C_R1_ALPHA (12<<10) |
#define R200_TXA_ARG_C_R1_BLUE (13<<10) |
#define R200_TXA_ARG_C_R2_ALPHA (14<<10) |
#define R200_TXA_ARG_C_R2_BLUE (15<<10) |
#define R200_TXA_ARG_C_R3_ALPHA (16<<10) |
#define R200_TXA_ARG_C_R3_BLUE (17<<10) |
#define R200_TXA_ARG_C_R4_ALPHA (18<<10) |
#define R200_TXA_ARG_C_R4_BLUE (19<<10) |
#define R200_TXA_ARG_C_R5_ALPHA (20<<10) |
#define R200_TXA_ARG_C_R5_BLUE (21<<10) |
#define R200_TXA_ARG_C_TFACTOR1_ALPHA (26<<10) |
#define R200_TXA_ARG_C_TFACTOR1_BLUE (27<<10) |
#define R200_TXA_ARG_C_MASK (31 << 10) |
#define R200_TXA_ARG_C_SHIFT 10 |
#define R200_TXA_COMP_ARG_A (1 << 16) |
#define R200_TXA_COMP_ARG_A_SHIFT (16) |
#define R200_TXA_BIAS_ARG_A (1 << 17) |
#define R200_TXA_SCALE_ARG_A (1 << 18) |
#define R200_TXA_NEG_ARG_A (1 << 19) |
#define R200_TXA_COMP_ARG_B (1 << 20) |
#define R200_TXA_COMP_ARG_B_SHIFT (20) |
#define R200_TXA_BIAS_ARG_B (1 << 21) |
#define R200_TXA_SCALE_ARG_B (1 << 22) |
#define R200_TXA_NEG_ARG_B (1 << 23) |
#define R200_TXA_COMP_ARG_C (1 << 24) |
#define R200_TXA_COMP_ARG_C_SHIFT (24) |
#define R200_TXA_BIAS_ARG_C (1 << 25) |
#define R200_TXA_SCALE_ARG_C (1 << 26) |
#define R200_TXA_NEG_ARG_C (1 << 27) |
#define R200_TXA_OP_MADD (0 << 28) |
#define R200_TXA_OP_CND0 (2 << 28) |
#define R200_TXA_OP_LERP (3 << 28) |
#define R200_TXA_OP_CONDITIONAL (6 << 28) |
#define R200_TXA_OP_MASK (7 << 28) |
#define R200_PP_TXABLEND2_0 0x2f0c |
#define R200_TXA_TFACTOR_SEL_SHIFT 0 |
#define R200_TXA_TFACTOR_SEL_MASK 0x7 |
#define R200_TXA_TFACTOR1_SEL_SHIFT 4 |
#define R200_TXA_TFACTOR1_SEL_MASK (0x7 << 4) |
#define R200_TXA_SCALE_SHIFT 8 |
#define R200_TXA_SCALE_MASK (7 << 8) |
#define R200_TXA_SCALE_1X (0 << 8) |
#define R200_TXA_SCALE_2X (1 << 8) |
#define R200_TXA_SCALE_4X (2 << 8) |
#define R200_TXA_SCALE_8X (3 << 8) |
#define R200_TXA_SCALE_INV2 (5 << 8) |
#define R200_TXA_SCALE_INV4 (6 << 8) |
#define R200_TXA_SCALE_INV8 (7 << 8) |
#define R200_TXA_CLAMP_SHIFT 12 |
#define R200_TXA_CLAMP_MASK (3 << 12) |
#define R200_TXA_CLAMP_WRAP (0 << 12) |
#define R200_TXA_CLAMP_0_1 (1 << 12) |
#define R200_TXA_CLAMP_8_8 (2 << 12) |
#define R200_TXA_OUTPUT_REG_SHIFT 16 |
#define R200_TXA_OUTPUT_REG_MASK (7 << 16) |
#define R200_TXA_OUTPUT_REG_NONE (0 << 16) |
#define R200_TXA_OUTPUT_REG_R0 (1 << 16) |
#define R200_TXA_OUTPUT_REG_R1 (2 << 16) |
#define R200_TXA_OUTPUT_REG_R2 (3 << 16) |
#define R200_TXA_OUTPUT_REG_R3 (4 << 16) |
#define R200_TXA_OUTPUT_REG_R4 (5 << 16) |
#define R200_TXA_OUTPUT_REG_R5 (6 << 16) |
#define R200_TXA_DOT_ALPHA (1 << 20) |
#define R200_TXA_REPL_NORMAL 0 |
#define R200_TXA_REPL_RED 1 |
#define R200_TXA_REPL_GREEN 2 |
#define R200_TXA_REPL_ARG_A_SHIFT 26 |
#define R200_TXA_REPL_ARG_A_MASK (3 << 26) |
#define R200_TXA_REPL_ARG_B_SHIFT 28 |
#define R200_TXA_REPL_ARG_B_MASK (3 << 28) |
#define R200_TXA_REPL_ARG_C_SHIFT 30 |
#define R200_TXA_REPL_ARG_C_MASK (3 << 30) |
#define R200_PP_TXCBLEND_1 0x2f10 |
#define R200_PP_TXCBLEND2_1 0x2f14 |
#define R200_PP_TXABLEND_1 0x2f18 |
#define R200_PP_TXABLEND2_1 0x2f1c |
#define R200_PP_TXCBLEND_2 0x2f20 |
#define R200_PP_TXCBLEND2_2 0x2f24 |
#define R200_PP_TXABLEND_2 0x2f28 |
#define R200_PP_TXABLEND2_2 0x2f2c |
#define R200_PP_TXCBLEND_3 0x2f30 |
#define R200_PP_TXCBLEND2_3 0x2f34 |
#define R200_PP_TXABLEND_3 0x2f38 |
#define R200_PP_TXABLEND2_3 0x2f3c |
#define R200_PP_TXCBLEND_4 0x2f40 |
#define R200_PP_TXCBLEND2_4 0x2f44 |
#define R200_PP_TXABLEND_4 0x2f48 |
#define R200_PP_TXABLEND2_4 0x2f4c |
#define R200_PP_TXCBLEND_5 0x2f50 |
#define R200_PP_TXCBLEND2_5 0x2f54 |
#define R200_PP_TXABLEND_5 0x2f58 |
#define R200_PP_TXABLEND2_5 0x2f5c |
#define R200_PP_TXCBLEND_6 0x2f60 |
#define R200_PP_TXCBLEND2_6 0x2f64 |
#define R200_PP_TXABLEND_6 0x2f68 |
#define R200_PP_TXABLEND2_6 0x2f6c |
#define R200_PP_TXCBLEND_7 0x2f70 |
#define R200_PP_TXCBLEND2_7 0x2f74 |
#define R200_PP_TXABLEND_7 0x2f78 |
#define R200_PP_TXABLEND2_7 0x2f7c |
#define R200_PP_TXCBLEND_8 0x2f80 |
#define R200_PP_TXCBLEND2_8 0x2f84 |
#define R200_PP_TXABLEND_8 0x2f88 |
#define R200_PP_TXABLEND2_8 0x2f8c |
#define R200_PP_TXCBLEND_9 0x2f90 |
#define R200_PP_TXCBLEND2_9 0x2f94 |
#define R200_PP_TXABLEND_9 0x2f98 |
#define R200_PP_TXABLEND2_9 0x2f9c |
#define R200_PP_TXCBLEND_10 0x2fa0 |
#define R200_PP_TXCBLEND2_10 0x2fa4 |
#define R200_PP_TXABLEND_10 0x2fa8 |
#define R200_PP_TXABLEND2_10 0x2fac |
#define R200_PP_TXCBLEND_11 0x2fb0 |
#define R200_PP_TXCBLEND2_11 0x2fb4 |
#define R200_PP_TXABLEND_11 0x2fb8 |
#define R200_PP_TXABLEND2_11 0x2fbc |
#define R200_PP_TXCBLEND_12 0x2fc0 |
#define R200_PP_TXCBLEND2_12 0x2fc4 |
#define R200_PP_TXABLEND_12 0x2fc8 |
#define R200_PP_TXABLEND2_12 0x2fcc |
#define R200_PP_TXCBLEND_13 0x2fd0 |
#define R200_PP_TXCBLEND2_13 0x2fd4 |
#define R200_PP_TXABLEND_13 0x2fd8 |
#define R200_PP_TXABLEND2_13 0x2fdc |
#define R200_PP_TXCBLEND_14 0x2fe0 |
#define R200_PP_TXCBLEND2_14 0x2fe4 |
#define R200_PP_TXABLEND_14 0x2fe8 |
#define R200_PP_TXABLEND2_14 0x2fec |
#define R200_PP_TXCBLEND_15 0x2ff0 |
#define R200_PP_TXCBLEND2_15 0x2ff4 |
#define R200_PP_TXABLEND_15 0x2ff8 |
#define R200_PP_TXABLEND2_15 0x2ffc |
/* gap */ |
#define R200_RB3D_BLENDCOLOR 0x3218 /* ARGB 8888 */ |
#define R200_RB3D_ABLENDCNTL 0x321C /* see BLENDCTL */ |
#define R200_RB3D_CBLENDCNTL 0x3220 /* see BLENDCTL */ |
/* |
* Offsets in TCL vector state. NOTE: Hardwiring matrix positions. |
* Multiple contexts could collaberate to eliminate state bouncing. |
*/ |
#define R200_VS_LIGHT_AMBIENT_ADDR 0x00000028 |
#define R200_VS_LIGHT_DIFFUSE_ADDR 0x00000030 |
#define R200_VS_LIGHT_SPECULAR_ADDR 0x00000038 |
#define R200_VS_LIGHT_DIRPOS_ADDR 0x00000040 |
#define R200_VS_LIGHT_HWVSPOT_ADDR 0x00000048 |
#define R200_VS_LIGHT_ATTENUATION_ADDR 0x00000050 |
#define R200_VS_SPOT_DUAL_CONE 0x00000058 |
#define R200_VS_GLOBAL_AMBIENT_ADDR 0x0000005C |
#define R200_VS_FOG_PARAM_ADDR 0x0000005D |
#define R200_VS_EYE_VECTOR_ADDR 0x0000005E |
#define R200_VS_UCP_ADDR 0x00000060 |
#define R200_VS_PNT_SPRITE_VPORT_SCALE 0x00000068 |
#define R200_VS_MATRIX_0_MV 0x00000080 |
#define R200_VS_MATRIX_1_INV_MV 0x00000084 |
#define R200_VS_MATRIX_2_MVP 0x00000088 |
#define R200_VS_MATRIX_3_TEX0 0x0000008C |
#define R200_VS_MATRIX_4_TEX1 0x00000090 |
#define R200_VS_MATRIX_5_TEX2 0x00000094 |
#define R200_VS_MATRIX_6_TEX3 0x00000098 |
#define R200_VS_MATRIX_7_TEX4 0x0000009C |
#define R200_VS_MATRIX_8_TEX5 0x000000A0 |
#define R200_VS_MAT_0_EMISS 0x000000B0 |
#define R200_VS_MAT_0_AMB 0x000000B1 |
#define R200_VS_MAT_0_DIF 0x000000B2 |
#define R200_VS_MAT_0_SPEC 0x000000B3 |
#define R200_VS_MAT_1_EMISS 0x000000B4 |
#define R200_VS_MAT_1_AMB 0x000000B5 |
#define R200_VS_MAT_1_DIF 0x000000B6 |
#define R200_VS_MAT_1_SPEC 0x000000B7 |
#define R200_VS_EYE2CLIP_MTX 0x000000B8 |
#define R200_VS_PNT_SPRITE_ATT_CONST 0x000000BC |
#define R200_VS_PNT_SPRITE_EYE_IN_MODEL 0x000000BD |
#define R200_VS_PNT_SPRITE_CLAMP 0x000000BE |
#define R200_VS_MAX 0x000001C0 |
#define R200_PVS_PROG0 0x00000080 |
#define R200_PVS_PROG1 0x00000180 |
#define R200_PVS_PARAM0 0x00000000 |
#define R200_PVS_PARAM1 0x00000100 |
/* |
* Offsets in TCL scalar state |
*/ |
#define R200_SS_LIGHT_DCD_ADDR 0x00000000 |
#define R200_SS_LIGHT_DCM_ADDR 0x00000008 |
#define R200_SS_LIGHT_SPOT_EXPONENT_ADDR 0x00000010 |
#define R200_SS_LIGHT_SPOT_CUTOFF_ADDR 0x00000018 |
#define R200_SS_LIGHT_SPECULAR_THRESH_ADDR 0x00000020 |
#define R200_SS_LIGHT_RANGE_CUTOFF_SQRD 0x00000028 |
#define R200_SS_LIGHT_RANGE_ATT_CONST 0x00000030 |
#define R200_SS_VERT_GUARD_CLIP_ADJ_ADDR 0x00000080 |
#define R200_SS_VERT_GUARD_DISCARD_ADJ_ADDR 0x00000081 |
#define R200_SS_HORZ_GUARD_CLIP_ADJ_ADDR 0x00000082 |
#define R200_SS_HORZ_GUARD_DISCARD_ADJ_ADDR 0x00000083 |
#define R200_SS_MAT_0_SHININESS 0x00000100 |
#define R200_SS_MAT_1_SHININESS 0x00000101 |
/* |
* Matrix indices |
*/ |
#define R200_MTX_MV 0 |
#define R200_MTX_IMV 1 |
#define R200_MTX_MVP 2 |
#define R200_MTX_TEX0 3 |
#define R200_MTX_TEX1 4 |
#define R200_MTX_TEX2 5 |
#define R200_MTX_TEX3 6 |
#define R200_MTX_TEX4 7 |
#define R200_MTX_TEX5 8 |
/* Color formats for 2d packets |
*/ |
#define R200_CP_COLOR_FORMAT_CI8 2 |
#define R200_CP_COLOR_FORMAT_ARGB1555 3 |
#define R200_CP_COLOR_FORMAT_RGB565 4 |
#define R200_CP_COLOR_FORMAT_ARGB8888 6 |
#define R200_CP_COLOR_FORMAT_RGB332 7 |
#define R200_CP_COLOR_FORMAT_RGB8 9 |
#define R200_CP_COLOR_FORMAT_ARGB4444 15 |
/* |
* CP type-3 packets |
*/ |
#define R200_CP_CMD_NOP 0xC0001000 |
#define R200_CP_CMD_NEXT_CHAR 0xC0001900 |
#define R200_CP_CMD_PLY_NEXTSCAN 0xC0001D00 |
#define R200_CP_CMD_SET_SCISSORS 0xC0001E00 |
#define R200_CP_CMD_LOAD_MICROCODE 0xC0002400 |
#define R200_CP_CMD_WAIT_FOR_IDLE 0xC0002600 |
#define R200_CP_CMD_3D_DRAW_VBUF 0xC0002800 |
#define R200_CP_CMD_3D_DRAW_IMMD 0xC0002900 |
#define R200_CP_CMD_3D_DRAW_INDX 0xC0002A00 |
#define R200_CP_CMD_LOAD_PALETTE 0xC0002C00 |
#define R200_CP_CMD_3D_LOAD_VBPNTR 0xC0002F00 |
#define R200_CP_CMD_INDX_BUFFER 0xC0003300 |
#define R200_CP_CMD_3D_DRAW_VBUF_2 0xC0003400 |
#define R200_CP_CMD_3D_DRAW_IMMD_2 0xC0003500 |
#define R200_CP_CMD_3D_DRAW_INDX_2 0xC0003600 |
#define R200_CP_CMD_PAINT 0xC0009100 |
#define R200_CP_CMD_BITBLT 0xC0009200 |
#define R200_CP_CMD_SMALLTEXT 0xC0009300 |
#define R200_CP_CMD_HOSTDATA_BLT 0xC0009400 |
#define R200_CP_CMD_POLYLINE 0xC0009500 |
#define R200_CP_CMD_POLYSCANLINES 0xC0009800 |
#define R200_CP_CMD_PAINT_MULTI 0xC0009A00 |
#define R200_CP_CMD_BITBLT_MULTI 0xC0009B00 |
#define R200_CP_CMD_TRANS_BITBLT 0xC0009C00 |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_sanity.c |
---|
0,0 → 1,1455 |
/************************************************************************** |
Copyright 2002 ATI Technologies Inc., Ontario, Canada, and |
Tungsten Graphics Inc, Cedar Park, TX. |
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 |
on 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 |
ATI, TUNGSTEN GRAPHICS AND/OR THEIR 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 <errno.h> |
#include "main/glheader.h" |
#include "main/imports.h" |
#include "r200_context.h" |
#include "r200_sanity.h" |
#include "radeon_reg.h" |
#include "r200_reg.h" |
/* Set this '1' to get more verbiage. |
*/ |
#define MORE_VERBOSE 1 |
#if MORE_VERBOSE |
#define VERBOSE (R200_DEBUG & RADEON_VERBOSE) |
#define NORMAL (1) |
#else |
#define VERBOSE 0 |
#define NORMAL (R200_DEBUG & RADEON_VERBOSE) |
#endif |
/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in |
* 1.3 cmdbuffers allow all previous state to be updated as well as |
* the tcl scalar and vector areas. |
*/ |
static struct { |
int start; |
int len; |
const char *name; |
} packet[RADEON_MAX_STATE_PACKETS] = { |
{ RADEON_PP_MISC,7,"RADEON_PP_MISC" }, |
{ RADEON_PP_CNTL,3,"RADEON_PP_CNTL" }, |
{ RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" }, |
{ RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" }, |
{ RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" }, |
{ RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" }, |
{ RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" }, |
{ RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" }, |
{ RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" }, |
{ RADEON_SE_CNTL,2,"RADEON_SE_CNTL" }, |
{ RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" }, |
{ RADEON_RE_MISC,1,"RADEON_RE_MISC" }, |
{ RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" }, |
{ RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" }, |
{ RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" }, |
{ RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" }, |
{ RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" }, |
{ RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" }, |
{ RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" }, |
{ RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" }, |
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" }, |
{ R200_PP_TXCBLEND_0, 4, "R200_EMIT_PP_TXCBLEND_0" }, |
{ R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1" }, |
{ R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2" }, |
{ R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3" }, |
{ R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4" }, |
{ R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5" }, |
{ R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6" }, |
{ R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7" }, |
{ R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" }, |
{ R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0" }, |
{ R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0" }, |
{ R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL" }, |
{ R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0" }, |
{ R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2" }, |
{ R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" }, |
{ R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0" }, |
{ R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1" }, |
{ R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2" }, |
{ R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3" }, |
{ R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4" }, |
{ R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5" }, |
{ R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0" }, |
{ R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1" }, |
{ R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2" }, |
{ R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3" }, |
{ R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4" }, |
{ R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5" }, |
{ R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL" }, |
{ R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" }, |
{ R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3" }, |
{ R200_PP_CNTL_X, 1, "R200_PP_CNTL_X" }, |
{ R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET" }, |
{ R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL" }, |
{ R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0" }, |
{ R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1" }, |
{ R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2" }, |
{ R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS" }, |
{ R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL" }, |
{ R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE" }, |
{ R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" }, |
{ R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */ |
{ R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */ |
{ R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1" }, |
{ R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1" }, |
{ R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2" }, |
{ R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2" }, |
{ R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3" }, |
{ R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3" }, |
{ R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4" }, |
{ R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4" }, |
{ R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5" }, |
{ R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5" }, |
{ RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" }, |
{ RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" }, |
{ RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2" }, |
{ R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR" }, |
{ R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL" }, |
{ RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0" }, |
{ RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0" }, |
{ RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1" }, |
{ RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0" }, |
{ RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2" }, |
{ RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0" }, |
{ R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF" }, |
{ R200_PP_TXCBLEND_8, 32, "R200_PP_AFS_0"}, /* 85 */ |
{ R200_PP_TXCBLEND_0, 32, "R200_PP_AFS_1"}, |
{ R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"}, |
{ R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"}, |
{ R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"}, |
{ R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"}, |
{ R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"}, |
{ R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"}, |
{ R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"}, |
{ R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"}, |
}; |
struct reg_names { |
int idx; |
const char *name; |
}; |
static struct reg_names reg_names[] = { |
{ R200_PP_MISC, "R200_PP_MISC" }, |
{ R200_PP_FOG_COLOR, "R200_PP_FOG_COLOR" }, |
{ R200_RE_SOLID_COLOR, "R200_RE_SOLID_COLOR" }, |
{ R200_RB3D_BLENDCNTL, "R200_RB3D_BLENDCNTL" }, |
{ R200_RB3D_DEPTHOFFSET, "R200_RB3D_DEPTHOFFSET" }, |
{ R200_RB3D_DEPTHPITCH, "R200_RB3D_DEPTHPITCH" }, |
{ R200_RB3D_ZSTENCILCNTL, "R200_RB3D_ZSTENCILCNTL" }, |
{ R200_PP_CNTL, "R200_PP_CNTL" }, |
{ R200_RB3D_CNTL, "R200_RB3D_CNTL" }, |
{ R200_RB3D_COLOROFFSET, "R200_RB3D_COLOROFFSET" }, |
{ R200_RE_WIDTH_HEIGHT, "R200_RE_WIDTH_HEIGHT" }, |
{ R200_RB3D_COLORPITCH, "R200_RB3D_COLORPITCH" }, |
{ R200_SE_CNTL, "R200_SE_CNTL" }, |
{ R200_RE_CNTL, "R200_RE_CNTL" }, |
{ R200_RE_MISC, "R200_RE_MISC" }, |
{ R200_RE_STIPPLE_ADDR, "R200_RE_STIPPLE_ADDR" }, |
{ R200_RE_STIPPLE_DATA, "R200_RE_STIPPLE_DATA" }, |
{ R200_RE_LINE_PATTERN, "R200_RE_LINE_PATTERN" }, |
{ R200_RE_LINE_STATE, "R200_RE_LINE_STATE" }, |
{ R200_RE_SCISSOR_TL_0, "R200_RE_SCISSOR_TL_0" }, |
{ R200_RE_SCISSOR_BR_0, "R200_RE_SCISSOR_BR_0" }, |
{ R200_RE_SCISSOR_TL_1, "R200_RE_SCISSOR_TL_1" }, |
{ R200_RE_SCISSOR_BR_1, "R200_RE_SCISSOR_BR_1" }, |
{ R200_RE_SCISSOR_TL_2, "R200_RE_SCISSOR_TL_2" }, |
{ R200_RE_SCISSOR_BR_2, "R200_RE_SCISSOR_BR_2" }, |
{ R200_RB3D_DEPTHXY_OFFSET, "R200_RB3D_DEPTHXY_OFFSET" }, |
{ R200_RB3D_STENCILREFMASK, "R200_RB3D_STENCILREFMASK" }, |
{ R200_RB3D_ROPCNTL, "R200_RB3D_ROPCNTL" }, |
{ R200_RB3D_PLANEMASK, "R200_RB3D_PLANEMASK" }, |
{ R200_SE_VPORT_XSCALE, "R200_SE_VPORT_XSCALE" }, |
{ R200_SE_VPORT_XOFFSET, "R200_SE_VPORT_XOFFSET" }, |
{ R200_SE_VPORT_YSCALE, "R200_SE_VPORT_YSCALE" }, |
{ R200_SE_VPORT_YOFFSET, "R200_SE_VPORT_YOFFSET" }, |
{ R200_SE_VPORT_ZSCALE, "R200_SE_VPORT_ZSCALE" }, |
{ R200_SE_VPORT_ZOFFSET, "R200_SE_VPORT_ZOFFSET" }, |
{ R200_SE_ZBIAS_FACTOR, "R200_SE_ZBIAS_FACTOR" }, |
{ R200_SE_ZBIAS_CONSTANT, "R200_SE_ZBIAS_CONSTANT" }, |
{ R200_SE_LINE_WIDTH, "R200_SE_LINE_WIDTH" }, |
{ R200_SE_VAP_CNTL, "R200_SE_VAP_CNTL" }, |
{ R200_SE_VF_CNTL, "R200_SE_VF_CNTL" }, |
{ R200_SE_VTX_FMT_0, "R200_SE_VTX_FMT_0" }, |
{ R200_SE_VTX_FMT_1, "R200_SE_VTX_FMT_1" }, |
{ R200_SE_TCL_OUTPUT_VTX_FMT_0, "R200_SE_TCL_OUTPUT_VTX_FMT_0" }, |
{ R200_SE_TCL_OUTPUT_VTX_FMT_1, "R200_SE_TCL_OUTPUT_VTX_FMT_1" }, |
{ R200_SE_VTE_CNTL, "R200_SE_VTE_CNTL" }, |
{ R200_SE_VTX_NUM_ARRAYS, "R200_SE_VTX_NUM_ARRAYS" }, |
{ R200_SE_VTX_AOS_ATTR01, "R200_SE_VTX_AOS_ATTR01" }, |
{ R200_SE_VTX_AOS_ADDR0, "R200_SE_VTX_AOS_ADDR0" }, |
{ R200_SE_VTX_AOS_ADDR1, "R200_SE_VTX_AOS_ADDR1" }, |
{ R200_SE_VTX_AOS_ATTR23, "R200_SE_VTX_AOS_ATTR23" }, |
{ R200_SE_VTX_AOS_ADDR2, "R200_SE_VTX_AOS_ADDR2" }, |
{ R200_SE_VTX_AOS_ADDR3, "R200_SE_VTX_AOS_ADDR3" }, |
{ R200_SE_VTX_AOS_ATTR45, "R200_SE_VTX_AOS_ATTR45" }, |
{ R200_SE_VTX_AOS_ADDR4, "R200_SE_VTX_AOS_ADDR4" }, |
{ R200_SE_VTX_AOS_ADDR5, "R200_SE_VTX_AOS_ADDR5" }, |
{ R200_SE_VTX_AOS_ATTR67, "R200_SE_VTX_AOS_ATTR67" }, |
{ R200_SE_VTX_AOS_ADDR6, "R200_SE_VTX_AOS_ADDR6" }, |
{ R200_SE_VTX_AOS_ADDR7, "R200_SE_VTX_AOS_ADDR7" }, |
{ R200_SE_VTX_AOS_ATTR89, "R200_SE_VTX_AOS_ATTR89" }, |
{ R200_SE_VTX_AOS_ADDR8, "R200_SE_VTX_AOS_ADDR8" }, |
{ R200_SE_VTX_AOS_ADDR9, "R200_SE_VTX_AOS_ADDR9" }, |
{ R200_SE_VTX_AOS_ATTR1011, "R200_SE_VTX_AOS_ATTR1011" }, |
{ R200_SE_VTX_AOS_ADDR10, "R200_SE_VTX_AOS_ADDR10" }, |
{ R200_SE_VTX_AOS_ADDR11, "R200_SE_VTX_AOS_ADDR11" }, |
{ R200_SE_VF_MAX_VTX_INDX, "R200_SE_VF_MAX_VTX_INDX" }, |
{ R200_SE_VF_MIN_VTX_INDX, "R200_SE_VF_MIN_VTX_INDX" }, |
{ R200_SE_VTX_STATE_CNTL, "R200_SE_VTX_STATE_CNTL" }, |
{ R200_SE_TCL_VECTOR_INDX_REG, "R200_SE_TCL_VECTOR_INDX_REG" }, |
{ R200_SE_TCL_VECTOR_DATA_REG, "R200_SE_TCL_VECTOR_DATA_REG" }, |
{ R200_SE_TCL_SCALAR_INDX_REG, "R200_SE_TCL_SCALAR_INDX_REG" }, |
{ R200_SE_TCL_SCALAR_DATA_REG, "R200_SE_TCL_SCALAR_DATA_REG" }, |
{ R200_SE_TCL_MATRIX_SEL_0, "R200_SE_TCL_MATRIX_SEL_0" }, |
{ R200_SE_TCL_MATRIX_SEL_1, "R200_SE_TCL_MATRIX_SEL_1" }, |
{ R200_SE_TCL_MATRIX_SEL_2, "R200_SE_TCL_MATRIX_SEL_2" }, |
{ R200_SE_TCL_MATRIX_SEL_3, "R200_SE_TCL_MATRIX_SEL_3" }, |
{ R200_SE_TCL_MATRIX_SEL_4, "R200_SE_TCL_MATRIX_SEL_4" }, |
{ R200_SE_TCL_LIGHT_MODEL_CTL_0, "R200_SE_TCL_LIGHT_MODEL_CTL_0" }, |
{ R200_SE_TCL_LIGHT_MODEL_CTL_1, "R200_SE_TCL_LIGHT_MODEL_CTL_1" }, |
{ R200_SE_TCL_PER_LIGHT_CTL_0, "R200_SE_TCL_PER_LIGHT_CTL_0" }, |
{ R200_SE_TCL_PER_LIGHT_CTL_1, "R200_SE_TCL_PER_LIGHT_CTL_1" }, |
{ R200_SE_TCL_PER_LIGHT_CTL_2, "R200_SE_TCL_PER_LIGHT_CTL_2" }, |
{ R200_SE_TCL_PER_LIGHT_CTL_3, "R200_SE_TCL_PER_LIGHT_CTL_3" }, |
{ R200_SE_TCL_TEX_PROC_CTL_2, "R200_SE_TCL_TEX_PROC_CTL_2" }, |
{ R200_SE_TCL_TEX_PROC_CTL_3, "R200_SE_TCL_TEX_PROC_CTL_3" }, |
{ R200_SE_TCL_TEX_PROC_CTL_0, "R200_SE_TCL_TEX_PROC_CTL_0" }, |
{ R200_SE_TCL_TEX_PROC_CTL_1, "R200_SE_TCL_TEX_PROC_CTL_1" }, |
{ R200_SE_TC_TEX_CYL_WRAP_CTL, "R200_SE_TC_TEX_CYL_WRAP_CTL" }, |
{ R200_SE_TCL_UCP_VERT_BLEND_CTL, "R200_SE_TCL_UCP_VERT_BLEND_CTL" }, |
{ R200_SE_TCL_POINT_SPRITE_CNTL, "R200_SE_TCL_POINT_SPRITE_CNTL" }, |
{ R200_SE_VTX_ST_POS_0_X_4, "R200_SE_VTX_ST_POS_0_X_4" }, |
{ R200_SE_VTX_ST_POS_0_Y_4, "R200_SE_VTX_ST_POS_0_Y_4" }, |
{ R200_SE_VTX_ST_POS_0_Z_4, "R200_SE_VTX_ST_POS_0_Z_4" }, |
{ R200_SE_VTX_ST_POS_0_W_4, "R200_SE_VTX_ST_POS_0_W_4" }, |
{ R200_SE_VTX_ST_NORM_0_X, "R200_SE_VTX_ST_NORM_0_X" }, |
{ R200_SE_VTX_ST_NORM_0_Y, "R200_SE_VTX_ST_NORM_0_Y" }, |
{ R200_SE_VTX_ST_NORM_0_Z, "R200_SE_VTX_ST_NORM_0_Z" }, |
{ R200_SE_VTX_ST_PVMS, "R200_SE_VTX_ST_PVMS" }, |
{ R200_SE_VTX_ST_CLR_0_R, "R200_SE_VTX_ST_CLR_0_R" }, |
{ R200_SE_VTX_ST_CLR_0_G, "R200_SE_VTX_ST_CLR_0_G" }, |
{ R200_SE_VTX_ST_CLR_0_B, "R200_SE_VTX_ST_CLR_0_B" }, |
{ R200_SE_VTX_ST_CLR_0_A, "R200_SE_VTX_ST_CLR_0_A" }, |
{ R200_SE_VTX_ST_CLR_1_R, "R200_SE_VTX_ST_CLR_1_R" }, |
{ R200_SE_VTX_ST_CLR_1_G, "R200_SE_VTX_ST_CLR_1_G" }, |
{ R200_SE_VTX_ST_CLR_1_B, "R200_SE_VTX_ST_CLR_1_B" }, |
{ R200_SE_VTX_ST_CLR_1_A, "R200_SE_VTX_ST_CLR_1_A" }, |
{ R200_SE_VTX_ST_CLR_2_R, "R200_SE_VTX_ST_CLR_2_R" }, |
{ R200_SE_VTX_ST_CLR_2_G, "R200_SE_VTX_ST_CLR_2_G" }, |
{ R200_SE_VTX_ST_CLR_2_B, "R200_SE_VTX_ST_CLR_2_B" }, |
{ R200_SE_VTX_ST_CLR_2_A, "R200_SE_VTX_ST_CLR_2_A" }, |
{ R200_SE_VTX_ST_CLR_3_R, "R200_SE_VTX_ST_CLR_3_R" }, |
{ R200_SE_VTX_ST_CLR_3_G, "R200_SE_VTX_ST_CLR_3_G" }, |
{ R200_SE_VTX_ST_CLR_3_B, "R200_SE_VTX_ST_CLR_3_B" }, |
{ R200_SE_VTX_ST_CLR_3_A, "R200_SE_VTX_ST_CLR_3_A" }, |
{ R200_SE_VTX_ST_CLR_4_R, "R200_SE_VTX_ST_CLR_4_R" }, |
{ R200_SE_VTX_ST_CLR_4_G, "R200_SE_VTX_ST_CLR_4_G" }, |
{ R200_SE_VTX_ST_CLR_4_B, "R200_SE_VTX_ST_CLR_4_B" }, |
{ R200_SE_VTX_ST_CLR_4_A, "R200_SE_VTX_ST_CLR_4_A" }, |
{ R200_SE_VTX_ST_CLR_5_R, "R200_SE_VTX_ST_CLR_5_R" }, |
{ R200_SE_VTX_ST_CLR_5_G, "R200_SE_VTX_ST_CLR_5_G" }, |
{ R200_SE_VTX_ST_CLR_5_B, "R200_SE_VTX_ST_CLR_5_B" }, |
{ R200_SE_VTX_ST_CLR_5_A, "R200_SE_VTX_ST_CLR_5_A" }, |
{ R200_SE_VTX_ST_CLR_6_R, "R200_SE_VTX_ST_CLR_6_R" }, |
{ R200_SE_VTX_ST_CLR_6_G, "R200_SE_VTX_ST_CLR_6_G" }, |
{ R200_SE_VTX_ST_CLR_6_B, "R200_SE_VTX_ST_CLR_6_B" }, |
{ R200_SE_VTX_ST_CLR_6_A, "R200_SE_VTX_ST_CLR_6_A" }, |
{ R200_SE_VTX_ST_CLR_7_R, "R200_SE_VTX_ST_CLR_7_R" }, |
{ R200_SE_VTX_ST_CLR_7_G, "R200_SE_VTX_ST_CLR_7_G" }, |
{ R200_SE_VTX_ST_CLR_7_B, "R200_SE_VTX_ST_CLR_7_B" }, |
{ R200_SE_VTX_ST_CLR_7_A, "R200_SE_VTX_ST_CLR_7_A" }, |
{ R200_SE_VTX_ST_TEX_0_S, "R200_SE_VTX_ST_TEX_0_S" }, |
{ R200_SE_VTX_ST_TEX_0_T, "R200_SE_VTX_ST_TEX_0_T" }, |
{ R200_SE_VTX_ST_TEX_0_R, "R200_SE_VTX_ST_TEX_0_R" }, |
{ R200_SE_VTX_ST_TEX_0_Q, "R200_SE_VTX_ST_TEX_0_Q" }, |
{ R200_SE_VTX_ST_TEX_1_S, "R200_SE_VTX_ST_TEX_1_S" }, |
{ R200_SE_VTX_ST_TEX_1_T, "R200_SE_VTX_ST_TEX_1_T" }, |
{ R200_SE_VTX_ST_TEX_1_R, "R200_SE_VTX_ST_TEX_1_R" }, |
{ R200_SE_VTX_ST_TEX_1_Q, "R200_SE_VTX_ST_TEX_1_Q" }, |
{ R200_SE_VTX_ST_TEX_2_S, "R200_SE_VTX_ST_TEX_2_S" }, |
{ R200_SE_VTX_ST_TEX_2_T, "R200_SE_VTX_ST_TEX_2_T" }, |
{ R200_SE_VTX_ST_TEX_2_R, "R200_SE_VTX_ST_TEX_2_R" }, |
{ R200_SE_VTX_ST_TEX_2_Q, "R200_SE_VTX_ST_TEX_2_Q" }, |
{ R200_SE_VTX_ST_TEX_3_S, "R200_SE_VTX_ST_TEX_3_S" }, |
{ R200_SE_VTX_ST_TEX_3_T, "R200_SE_VTX_ST_TEX_3_T" }, |
{ R200_SE_VTX_ST_TEX_3_R, "R200_SE_VTX_ST_TEX_3_R" }, |
{ R200_SE_VTX_ST_TEX_3_Q, "R200_SE_VTX_ST_TEX_3_Q" }, |
{ R200_SE_VTX_ST_TEX_4_S, "R200_SE_VTX_ST_TEX_4_S" }, |
{ R200_SE_VTX_ST_TEX_4_T, "R200_SE_VTX_ST_TEX_4_T" }, |
{ R200_SE_VTX_ST_TEX_4_R, "R200_SE_VTX_ST_TEX_4_R" }, |
{ R200_SE_VTX_ST_TEX_4_Q, "R200_SE_VTX_ST_TEX_4_Q" }, |
{ R200_SE_VTX_ST_TEX_5_S, "R200_SE_VTX_ST_TEX_5_S" }, |
{ R200_SE_VTX_ST_TEX_5_T, "R200_SE_VTX_ST_TEX_5_T" }, |
{ R200_SE_VTX_ST_TEX_5_R, "R200_SE_VTX_ST_TEX_5_R" }, |
{ R200_SE_VTX_ST_TEX_5_Q, "R200_SE_VTX_ST_TEX_5_Q" }, |
{ R200_SE_VTX_ST_PNT_SPRT_SZ, "R200_SE_VTX_ST_PNT_SPRT_SZ" }, |
{ R200_SE_VTX_ST_DISC_FOG, "R200_SE_VTX_ST_DISC_FOG" }, |
{ R200_SE_VTX_ST_SHININESS_0, "R200_SE_VTX_ST_SHININESS_0" }, |
{ R200_SE_VTX_ST_SHININESS_1, "R200_SE_VTX_ST_SHININESS_1" }, |
{ R200_SE_VTX_ST_BLND_WT_0, "R200_SE_VTX_ST_BLND_WT_0" }, |
{ R200_SE_VTX_ST_BLND_WT_1, "R200_SE_VTX_ST_BLND_WT_1" }, |
{ R200_SE_VTX_ST_BLND_WT_2, "R200_SE_VTX_ST_BLND_WT_2" }, |
{ R200_SE_VTX_ST_BLND_WT_3, "R200_SE_VTX_ST_BLND_WT_3" }, |
{ R200_SE_VTX_ST_POS_1_X, "R200_SE_VTX_ST_POS_1_X" }, |
{ R200_SE_VTX_ST_POS_1_Y, "R200_SE_VTX_ST_POS_1_Y" }, |
{ R200_SE_VTX_ST_POS_1_Z, "R200_SE_VTX_ST_POS_1_Z" }, |
{ R200_SE_VTX_ST_POS_1_W, "R200_SE_VTX_ST_POS_1_W" }, |
{ R200_SE_VTX_ST_NORM_1_X, "R200_SE_VTX_ST_NORM_1_X" }, |
{ R200_SE_VTX_ST_NORM_1_Y, "R200_SE_VTX_ST_NORM_1_Y" }, |
{ R200_SE_VTX_ST_NORM_1_Z, "R200_SE_VTX_ST_NORM_1_Z" }, |
{ R200_SE_VTX_ST_USR_CLR_0_R, "R200_SE_VTX_ST_USR_CLR_0_R" }, |
{ R200_SE_VTX_ST_USR_CLR_0_G, "R200_SE_VTX_ST_USR_CLR_0_G" }, |
{ R200_SE_VTX_ST_USR_CLR_0_B, "R200_SE_VTX_ST_USR_CLR_0_B" }, |
{ R200_SE_VTX_ST_USR_CLR_0_A, "R200_SE_VTX_ST_USR_CLR_0_A" }, |
{ R200_SE_VTX_ST_USR_CLR_1_R, "R200_SE_VTX_ST_USR_CLR_1_R" }, |
{ R200_SE_VTX_ST_USR_CLR_1_G, "R200_SE_VTX_ST_USR_CLR_1_G" }, |
{ R200_SE_VTX_ST_USR_CLR_1_B, "R200_SE_VTX_ST_USR_CLR_1_B" }, |
{ R200_SE_VTX_ST_USR_CLR_1_A, "R200_SE_VTX_ST_USR_CLR_1_A" }, |
{ R200_SE_VTX_ST_CLR_0_PKD, "R200_SE_VTX_ST_CLR_0_PKD" }, |
{ R200_SE_VTX_ST_CLR_1_PKD, "R200_SE_VTX_ST_CLR_1_PKD" }, |
{ R200_SE_VTX_ST_CLR_2_PKD, "R200_SE_VTX_ST_CLR_2_PKD" }, |
{ R200_SE_VTX_ST_CLR_3_PKD, "R200_SE_VTX_ST_CLR_3_PKD" }, |
{ R200_SE_VTX_ST_CLR_4_PKD, "R200_SE_VTX_ST_CLR_4_PKD" }, |
{ R200_SE_VTX_ST_CLR_5_PKD, "R200_SE_VTX_ST_CLR_5_PKD" }, |
{ R200_SE_VTX_ST_CLR_6_PKD, "R200_SE_VTX_ST_CLR_6_PKD" }, |
{ R200_SE_VTX_ST_CLR_7_PKD, "R200_SE_VTX_ST_CLR_7_PKD" }, |
{ R200_SE_VTX_ST_POS_0_X_2, "R200_SE_VTX_ST_POS_0_X_2" }, |
{ R200_SE_VTX_ST_POS_0_Y_2, "R200_SE_VTX_ST_POS_0_Y_2" }, |
{ R200_SE_VTX_ST_PAR_CLR_LD, "R200_SE_VTX_ST_PAR_CLR_LD" }, |
{ R200_SE_VTX_ST_USR_CLR_PKD, "R200_SE_VTX_ST_USR_CLR_PKD" }, |
{ R200_SE_VTX_ST_POS_0_X_3, "R200_SE_VTX_ST_POS_0_X_3" }, |
{ R200_SE_VTX_ST_POS_0_Y_3, "R200_SE_VTX_ST_POS_0_Y_3" }, |
{ R200_SE_VTX_ST_POS_0_Z_3, "R200_SE_VTX_ST_POS_0_Z_3" }, |
{ R200_SE_VTX_ST_END_OF_PKT, "R200_SE_VTX_ST_END_OF_PKT" }, |
{ R200_RE_POINTSIZE, "R200_RE_POINTSIZE" }, |
{ R200_RE_TOP_LEFT, "R200_RE_TOP_LEFT" }, |
{ R200_RE_AUX_SCISSOR_CNTL, "R200_RE_AUX_SCISSOR_CNTL" }, |
{ R200_PP_TXFILTER_0, "R200_PP_TXFILTER_0" }, |
{ R200_PP_TXFORMAT_0, "R200_PP_TXFORMAT_0" }, |
{ R200_PP_TXSIZE_0, "R200_PP_TXSIZE_0" }, |
{ R200_PP_TXFORMAT_X_0, "R200_PP_TXFORMAT_X_0" }, |
{ R200_PP_TXPITCH_0, "R200_PP_TXPITCH_0" }, |
{ R200_PP_BORDER_COLOR_0, "R200_PP_BORDER_COLOR_0" }, |
{ R200_PP_CUBIC_FACES_0, "R200_PP_CUBIC_FACES_0" }, |
{ R200_PP_TXMULTI_CTL_0, "R200_PP_TXMULTI_CTL_0" }, |
{ R200_PP_TXFILTER_1, "R200_PP_TXFILTER_1" }, |
{ R200_PP_TXFORMAT_1, "R200_PP_TXFORMAT_1" }, |
{ R200_PP_TXSIZE_1, "R200_PP_TXSIZE_1" }, |
{ R200_PP_TXFORMAT_X_1, "R200_PP_TXFORMAT_X_1" }, |
{ R200_PP_TXPITCH_1, "R200_PP_TXPITCH_1" }, |
{ R200_PP_BORDER_COLOR_1, "R200_PP_BORDER_COLOR_1" }, |
{ R200_PP_CUBIC_FACES_1, "R200_PP_CUBIC_FACES_1" }, |
{ R200_PP_TXMULTI_CTL_1, "R200_PP_TXMULTI_CTL_1" }, |
{ R200_PP_TXFILTER_2, "R200_PP_TXFILTER_2" }, |
{ R200_PP_TXFORMAT_2, "R200_PP_TXFORMAT_2" }, |
{ R200_PP_TXSIZE_2, "R200_PP_TXSIZE_2" }, |
{ R200_PP_TXFORMAT_X_2, "R200_PP_TXFORMAT_X_2" }, |
{ R200_PP_TXPITCH_2, "R200_PP_TXPITCH_2" }, |
{ R200_PP_BORDER_COLOR_2, "R200_PP_BORDER_COLOR_2" }, |
{ R200_PP_CUBIC_FACES_2, "R200_PP_CUBIC_FACES_2" }, |
{ R200_PP_TXMULTI_CTL_2, "R200_PP_TXMULTI_CTL_2" }, |
{ R200_PP_TXFILTER_3, "R200_PP_TXFILTER_3" }, |
{ R200_PP_TXFORMAT_3, "R200_PP_TXFORMAT_3" }, |
{ R200_PP_TXSIZE_3, "R200_PP_TXSIZE_3" }, |
{ R200_PP_TXFORMAT_X_3, "R200_PP_TXFORMAT_X_3" }, |
{ R200_PP_TXPITCH_3, "R200_PP_TXPITCH_3" }, |
{ R200_PP_BORDER_COLOR_3, "R200_PP_BORDER_COLOR_3" }, |
{ R200_PP_CUBIC_FACES_3, "R200_PP_CUBIC_FACES_3" }, |
{ R200_PP_TXMULTI_CTL_3, "R200_PP_TXMULTI_CTL_3" }, |
{ R200_PP_TXFILTER_4, "R200_PP_TXFILTER_4" }, |
{ R200_PP_TXFORMAT_4, "R200_PP_TXFORMAT_4" }, |
{ R200_PP_TXSIZE_4, "R200_PP_TXSIZE_4" }, |
{ R200_PP_TXFORMAT_X_4, "R200_PP_TXFORMAT_X_4" }, |
{ R200_PP_TXPITCH_4, "R200_PP_TXPITCH_4" }, |
{ R200_PP_BORDER_COLOR_4, "R200_PP_BORDER_COLOR_4" }, |
{ R200_PP_CUBIC_FACES_4, "R200_PP_CUBIC_FACES_4" }, |
{ R200_PP_TXMULTI_CTL_4, "R200_PP_TXMULTI_CTL_4" }, |
{ R200_PP_TXFILTER_5, "R200_PP_TXFILTER_5" }, |
{ R200_PP_TXFORMAT_5, "R200_PP_TXFORMAT_5" }, |
{ R200_PP_TXSIZE_5, "R200_PP_TXSIZE_5" }, |
{ R200_PP_TXFORMAT_X_5, "R200_PP_TXFORMAT_X_5" }, |
{ R200_PP_TXPITCH_5, "R200_PP_TXPITCH_5" }, |
{ R200_PP_BORDER_COLOR_5, "R200_PP_BORDER_COLOR_5" }, |
{ R200_PP_CUBIC_FACES_5, "R200_PP_CUBIC_FACES_5" }, |
{ R200_PP_TXMULTI_CTL_5, "R200_PP_TXMULTI_CTL_5" }, |
{ R200_PP_TXOFFSET_0, "R200_PP_TXOFFSET_0" }, |
{ R200_PP_CUBIC_OFFSET_F1_0, "R200_PP_CUBIC_OFFSET_F1_0" }, |
{ R200_PP_CUBIC_OFFSET_F2_0, "R200_PP_CUBIC_OFFSET_F2_0" }, |
{ R200_PP_CUBIC_OFFSET_F3_0, "R200_PP_CUBIC_OFFSET_F3_0" }, |
{ R200_PP_CUBIC_OFFSET_F4_0, "R200_PP_CUBIC_OFFSET_F4_0" }, |
{ R200_PP_CUBIC_OFFSET_F5_0, "R200_PP_CUBIC_OFFSET_F5_0" }, |
{ R200_PP_TXOFFSET_1, "R200_PP_TXOFFSET_1" }, |
{ R200_PP_CUBIC_OFFSET_F1_1, "R200_PP_CUBIC_OFFSET_F1_1" }, |
{ R200_PP_CUBIC_OFFSET_F2_1, "R200_PP_CUBIC_OFFSET_F2_1" }, |
{ R200_PP_CUBIC_OFFSET_F3_1, "R200_PP_CUBIC_OFFSET_F3_1" }, |
{ R200_PP_CUBIC_OFFSET_F4_1, "R200_PP_CUBIC_OFFSET_F4_1" }, |
{ R200_PP_CUBIC_OFFSET_F5_1, "R200_PP_CUBIC_OFFSET_F5_1" }, |
{ R200_PP_TXOFFSET_2, "R200_PP_TXOFFSET_2" }, |
{ R200_PP_CUBIC_OFFSET_F1_2, "R200_PP_CUBIC_OFFSET_F1_2" }, |
{ R200_PP_CUBIC_OFFSET_F2_2, "R200_PP_CUBIC_OFFSET_F2_2" }, |
{ R200_PP_CUBIC_OFFSET_F3_2, "R200_PP_CUBIC_OFFSET_F3_2" }, |
{ R200_PP_CUBIC_OFFSET_F4_2, "R200_PP_CUBIC_OFFSET_F4_2" }, |
{ R200_PP_CUBIC_OFFSET_F5_2, "R200_PP_CUBIC_OFFSET_F5_2" }, |
{ R200_PP_TXOFFSET_3, "R200_PP_TXOFFSET_3" }, |
{ R200_PP_CUBIC_OFFSET_F1_3, "R200_PP_CUBIC_OFFSET_F1_3" }, |
{ R200_PP_CUBIC_OFFSET_F2_3, "R200_PP_CUBIC_OFFSET_F2_3" }, |
{ R200_PP_CUBIC_OFFSET_F3_3, "R200_PP_CUBIC_OFFSET_F3_3" }, |
{ R200_PP_CUBIC_OFFSET_F4_3, "R200_PP_CUBIC_OFFSET_F4_3" }, |
{ R200_PP_CUBIC_OFFSET_F5_3, "R200_PP_CUBIC_OFFSET_F5_3" }, |
{ R200_PP_TXOFFSET_4, "R200_PP_TXOFFSET_4" }, |
{ R200_PP_CUBIC_OFFSET_F1_4, "R200_PP_CUBIC_OFFSET_F1_4" }, |
{ R200_PP_CUBIC_OFFSET_F2_4, "R200_PP_CUBIC_OFFSET_F2_4" }, |
{ R200_PP_CUBIC_OFFSET_F3_4, "R200_PP_CUBIC_OFFSET_F3_4" }, |
{ R200_PP_CUBIC_OFFSET_F4_4, "R200_PP_CUBIC_OFFSET_F4_4" }, |
{ R200_PP_CUBIC_OFFSET_F5_4, "R200_PP_CUBIC_OFFSET_F5_4" }, |
{ R200_PP_TXOFFSET_5, "R200_PP_TXOFFSET_5" }, |
{ R200_PP_CUBIC_OFFSET_F1_5, "R200_PP_CUBIC_OFFSET_F1_5" }, |
{ R200_PP_CUBIC_OFFSET_F2_5, "R200_PP_CUBIC_OFFSET_F2_5" }, |
{ R200_PP_CUBIC_OFFSET_F3_5, "R200_PP_CUBIC_OFFSET_F3_5" }, |
{ R200_PP_CUBIC_OFFSET_F4_5, "R200_PP_CUBIC_OFFSET_F4_5" }, |
{ R200_PP_CUBIC_OFFSET_F5_5, "R200_PP_CUBIC_OFFSET_F5_5" }, |
{ R200_PP_TAM_DEBUG3, "R200_PP_TAM_DEBUG3" }, |
{ R200_PP_TFACTOR_0, "R200_PP_TFACTOR_0" }, |
{ R200_PP_TFACTOR_1, "R200_PP_TFACTOR_1" }, |
{ R200_PP_TFACTOR_2, "R200_PP_TFACTOR_2" }, |
{ R200_PP_TFACTOR_3, "R200_PP_TFACTOR_3" }, |
{ R200_PP_TFACTOR_4, "R200_PP_TFACTOR_4" }, |
{ R200_PP_TFACTOR_5, "R200_PP_TFACTOR_5" }, |
{ R200_PP_TFACTOR_6, "R200_PP_TFACTOR_6" }, |
{ R200_PP_TFACTOR_7, "R200_PP_TFACTOR_7" }, |
{ R200_PP_TXCBLEND_0, "R200_PP_TXCBLEND_0" }, |
{ R200_PP_TXCBLEND2_0, "R200_PP_TXCBLEND2_0" }, |
{ R200_PP_TXABLEND_0, "R200_PP_TXABLEND_0" }, |
{ R200_PP_TXABLEND2_0, "R200_PP_TXABLEND2_0" }, |
{ R200_PP_TXCBLEND_1, "R200_PP_TXCBLEND_1" }, |
{ R200_PP_TXCBLEND2_1, "R200_PP_TXCBLEND2_1" }, |
{ R200_PP_TXABLEND_1, "R200_PP_TXABLEND_1" }, |
{ R200_PP_TXABLEND2_1, "R200_PP_TXABLEND2_1" }, |
{ R200_PP_TXCBLEND_2, "R200_PP_TXCBLEND_2" }, |
{ R200_PP_TXCBLEND2_2, "R200_PP_TXCBLEND2_2" }, |
{ R200_PP_TXABLEND_2, "R200_PP_TXABLEND_2" }, |
{ R200_PP_TXABLEND2_2, "R200_PP_TXABLEND2_2" }, |
{ R200_PP_TXCBLEND_3, "R200_PP_TXCBLEND_3" }, |
{ R200_PP_TXCBLEND2_3, "R200_PP_TXCBLEND2_3" }, |
{ R200_PP_TXABLEND_3, "R200_PP_TXABLEND_3" }, |
{ R200_PP_TXABLEND2_3, "R200_PP_TXABLEND2_3" }, |
{ R200_PP_TXCBLEND_4, "R200_PP_TXCBLEND_4" }, |
{ R200_PP_TXCBLEND2_4, "R200_PP_TXCBLEND2_4" }, |
{ R200_PP_TXABLEND_4, "R200_PP_TXABLEND_4" }, |
{ R200_PP_TXABLEND2_4, "R200_PP_TXABLEND2_4" }, |
{ R200_PP_TXCBLEND_5, "R200_PP_TXCBLEND_5" }, |
{ R200_PP_TXCBLEND2_5, "R200_PP_TXCBLEND2_5" }, |
{ R200_PP_TXABLEND_5, "R200_PP_TXABLEND_5" }, |
{ R200_PP_TXABLEND2_5, "R200_PP_TXABLEND2_5" }, |
{ R200_PP_TXCBLEND_6, "R200_PP_TXCBLEND_6" }, |
{ R200_PP_TXCBLEND2_6, "R200_PP_TXCBLEND2_6" }, |
{ R200_PP_TXABLEND_6, "R200_PP_TXABLEND_6" }, |
{ R200_PP_TXABLEND2_6, "R200_PP_TXABLEND2_6" }, |
{ R200_PP_TXCBLEND_7, "R200_PP_TXCBLEND_7" }, |
{ R200_PP_TXCBLEND2_7, "R200_PP_TXCBLEND2_7" }, |
{ R200_PP_TXABLEND_7, "R200_PP_TXABLEND_7" }, |
{ R200_PP_TXABLEND2_7, "R200_PP_TXABLEND2_7" }, |
{ R200_RB3D_BLENDCOLOR, "R200_RB3D_BLENDCOLOR" }, |
{ R200_RB3D_ABLENDCNTL, "R200_RB3D_ABLENDCNTL" }, |
{ R200_RB3D_CBLENDCNTL, "R200_RB3D_CBLENDCNTL" }, |
{ R200_SE_TCL_OUTPUT_VTX_COMP_SEL, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" }, |
{ R200_PP_CNTL_X, "R200_PP_CNTL_X" }, |
{ R200_SE_VAP_CNTL_STATUS, "R200_SE_VAP_CNTL_STATUS" }, |
{ R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" }, |
{ R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_1, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_1" }, |
{ R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_2, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_2" }, |
{ R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_3, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_3" }, |
{ R200_PP_TRI_PERF, "R200_PP_TRI_PERF" }, |
{ R200_PP_PERF_CNTL, "R200_PP_PERF_CNTL" }, |
{ R200_PP_TXCBLEND_8, "R200_PP_TXCBLEND_8" }, |
{ R200_PP_TXCBLEND2_8, "R200_PP_TXCBLEND2_8" }, |
{ R200_PP_TXABLEND_8, "R200_PP_TXABLEND_8" }, |
{ R200_PP_TXABLEND2_8, "R200_PP_TXABLEND2_8" }, |
{ R200_PP_TXCBLEND_9, "R200_PP_TXCBLEND_9" }, |
{ R200_PP_TXCBLEND2_9, "R200_PP_TXCBLEND2_9" }, |
{ R200_PP_TXABLEND_9, "R200_PP_TXABLEND_9" }, |
{ R200_PP_TXABLEND2_9, "R200_PP_TXABLEND2_9" }, |
{ R200_PP_TXCBLEND_10, "R200_PP_TXCBLEND_10" }, |
{ R200_PP_TXCBLEND2_10, "R200_PP_TXCBLEND2_10" }, |
{ R200_PP_TXABLEND_10, "R200_PP_TXABLEND_10" }, |
{ R200_PP_TXABLEND2_10, "R200_PP_TXABLEND2_10" }, |
{ R200_PP_TXCBLEND_11, "R200_PP_TXCBLEND_11" }, |
{ R200_PP_TXCBLEND2_11, "R200_PP_TXCBLEND2_11" }, |
{ R200_PP_TXABLEND_11, "R200_PP_TXABLEND_11" }, |
{ R200_PP_TXABLEND2_11, "R200_PP_TXABLEND2_11" }, |
{ R200_PP_TXCBLEND_12, "R200_PP_TXCBLEND_12" }, |
{ R200_PP_TXCBLEND2_12, "R200_PP_TXCBLEND2_12" }, |
{ R200_PP_TXABLEND_12, "R200_PP_TXABLEND_12" }, |
{ R200_PP_TXABLEND2_12, "R200_PP_TXABLEND2_12" }, |
{ R200_PP_TXCBLEND_13, "R200_PP_TXCBLEND_13" }, |
{ R200_PP_TXCBLEND2_13, "R200_PP_TXCBLEND2_13" }, |
{ R200_PP_TXABLEND_13, "R200_PP_TXABLEND_13" }, |
{ R200_PP_TXABLEND2_13, "R200_PP_TXABLEND2_13" }, |
{ R200_PP_TXCBLEND_14, "R200_PP_TXCBLEND_14" }, |
{ R200_PP_TXCBLEND2_14, "R200_PP_TXCBLEND2_14" }, |
{ R200_PP_TXABLEND_14, "R200_PP_TXABLEND_14" }, |
{ R200_PP_TXABLEND2_14, "R200_PP_TXABLEND2_14" }, |
{ R200_PP_TXCBLEND_15, "R200_PP_TXCBLEND_15" }, |
{ R200_PP_TXCBLEND2_15, "R200_PP_TXCBLEND2_15" }, |
{ R200_PP_TXABLEND_15, "R200_PP_TXABLEND_15" }, |
{ R200_PP_TXABLEND2_15, "R200_PP_TXABLEND2_15" }, |
{ R200_VAP_PVS_CNTL_1, "R200_VAP_PVS_CNTL_1" }, |
{ R200_VAP_PVS_CNTL_2, "R200_VAP_PVS_CNTL_2" }, |
}; |
static struct reg_names scalar_names[] = { |
{ R200_SS_LIGHT_DCD_ADDR, "R200_SS_LIGHT_DCD_ADDR" }, |
{ R200_SS_LIGHT_DCM_ADDR, "R200_SS_LIGHT_DCM_ADDR" }, |
{ R200_SS_LIGHT_SPOT_EXPONENT_ADDR, "R200_SS_LIGHT_SPOT_EXPONENT_ADDR" }, |
{ R200_SS_LIGHT_SPOT_CUTOFF_ADDR, "R200_SS_LIGHT_SPOT_CUTOFF_ADDR" }, |
{ R200_SS_LIGHT_SPECULAR_THRESH_ADDR, "R200_SS_LIGHT_SPECULAR_THRESH_ADDR" }, |
{ R200_SS_LIGHT_RANGE_CUTOFF_SQRD, "R200_SS_LIGHT_RANGE_CUTOFF_SQRD" }, |
{ R200_SS_LIGHT_RANGE_ATT_CONST, "R200_SS_LIGHT_RANGE_ATT_CONST" }, |
{ R200_SS_VERT_GUARD_CLIP_ADJ_ADDR, "R200_SS_VERT_GUARD_CLIP_ADJ_ADDR" }, |
{ R200_SS_VERT_GUARD_DISCARD_ADJ_ADDR, "R200_SS_VERT_GUARD_DISCARD_ADJ_ADDR" }, |
{ R200_SS_HORZ_GUARD_CLIP_ADJ_ADDR, "R200_SS_HORZ_GUARD_CLIP_ADJ_ADDR" }, |
{ R200_SS_HORZ_GUARD_DISCARD_ADJ_ADDR, "R200_SS_HORZ_GUARD_DISCARD_ADJ_ADDR" }, |
{ R200_SS_MAT_0_SHININESS, "R200_SS_MAT_0_SHININESS" }, |
{ R200_SS_MAT_1_SHININESS, "R200_SS_MAT_1_SHININESS" }, |
{ 1000, "" }, |
}; |
/* Puff these out to make them look like normal (dword) registers. |
*/ |
static struct reg_names vector_names[] = { |
{ 0, "start" }, |
{ R200_VS_LIGHT_AMBIENT_ADDR, "R200_VS_LIGHT_AMBIENT_ADDR" }, |
{ R200_VS_LIGHT_DIFFUSE_ADDR, "R200_VS_LIGHT_DIFFUSE_ADDR" }, |
{ R200_VS_LIGHT_SPECULAR_ADDR, "R200_VS_LIGHT_SPECULAR_ADDR" }, |
{ R200_VS_LIGHT_DIRPOS_ADDR, "R200_VS_LIGHT_DIRPOS_ADDR" }, |
{ R200_VS_LIGHT_HWVSPOT_ADDR, "R200_VS_LIGHT_HWVSPOT_ADDR" }, |
{ R200_VS_LIGHT_ATTENUATION_ADDR, "R200_VS_LIGHT_ATTENUATION_ADDR" }, |
{ R200_VS_SPOT_DUAL_CONE, "R200_VS_SPOT_DUAL_CONE" }, |
{ R200_VS_GLOBAL_AMBIENT_ADDR, "R200_VS_GLOBAL_AMBIENT_ADDR" }, |
{ R200_VS_FOG_PARAM_ADDR, "R200_VS_FOG_PARAM_ADDR" }, |
{ R200_VS_EYE_VECTOR_ADDR, "R200_VS_EYE_VECTOR_ADDR" }, |
{ R200_VS_UCP_ADDR, "R200_VS_UCP_ADDR" }, |
{ R200_VS_PNT_SPRITE_VPORT_SCALE, "R200_VS_PNT_SPRITE_VPORT_SCALE" }, |
{ R200_VS_MATRIX_0_MV, "R200_VS_MATRIX_0_MV" }, |
{ R200_VS_MATRIX_1_INV_MV, "R200_VS_MATRIX_1_INV_MV" }, |
{ R200_VS_MATRIX_2_MVP, "R200_VS_MATRIX_2_MVP" }, |
{ R200_VS_MATRIX_3_TEX0, "R200_VS_MATRIX_3_TEX0" }, |
{ R200_VS_MATRIX_4_TEX1, "R200_VS_MATRIX_4_TEX1" }, |
{ R200_VS_MATRIX_5_TEX2, "R200_VS_MATRIX_5_TEX2" }, |
{ R200_VS_MATRIX_6_TEX3, "R200_VS_MATRIX_6_TEX3" }, |
{ R200_VS_MATRIX_7_TEX4, "R200_VS_MATRIX_7_TEX4" }, |
{ R200_VS_MATRIX_8_TEX5, "R200_VS_MATRIX_8_TEX5" }, |
{ R200_VS_MAT_0_EMISS, "R200_VS_MAT_0_EMISS" }, |
{ R200_VS_MAT_0_AMB, "R200_VS_MAT_0_AMB" }, |
{ R200_VS_MAT_0_DIF, "R200_VS_MAT_0_DIF" }, |
{ R200_VS_MAT_0_SPEC, "R200_VS_MAT_0_SPEC" }, |
{ R200_VS_MAT_1_EMISS, "R200_VS_MAT_1_EMISS" }, |
{ R200_VS_MAT_1_AMB, "R200_VS_MAT_1_AMB" }, |
{ R200_VS_MAT_1_DIF, "R200_VS_MAT_1_DIF" }, |
{ R200_VS_MAT_1_SPEC, "R200_VS_MAT_1_SPEC" }, |
{ R200_VS_EYE2CLIP_MTX, "R200_VS_EYE2CLIP_MTX" }, |
{ R200_VS_PNT_SPRITE_ATT_CONST, "R200_VS_PNT_SPRITE_ATT_CONST" }, |
{ R200_VS_PNT_SPRITE_EYE_IN_MODEL, "R200_VS_PNT_SPRITE_EYE_IN_MODEL" }, |
{ R200_VS_PNT_SPRITE_CLAMP, "R200_VS_PNT_SPRITE_CLAMP" }, |
{ R200_VS_MAX, "R200_VS_MAX" }, |
{ 1000, "" }, |
}; |
union fi { float f; int i; }; |
#define ISVEC 1 |
#define ISFLOAT 2 |
#define TOUCHED 4 |
struct reg { |
int idx; |
struct reg_names *closest; |
int flags; |
union fi current; |
union fi *values; |
int nvalues; |
int nalloc; |
float vmin, vmax; |
}; |
static struct reg regs[Elements(reg_names)+1]; |
static struct reg scalars[512+1]; |
static struct reg vectors[512*4+1]; |
static int total, total_changed, bufs; |
static void init_regs( void ) |
{ |
struct reg_names *tmp; |
int i; |
for (i = 0 ; i < Elements(regs) ; i++) { |
regs[i].idx = reg_names[i].idx; |
regs[i].closest = ®_names[i]; |
regs[i].flags = 0; |
} |
for (i = 0, tmp = scalar_names ; i < Elements(scalars) ; i++) { |
if (tmp[1].idx == i) tmp++; |
scalars[i].idx = i; |
scalars[i].closest = tmp; |
scalars[i].flags = ISFLOAT; |
} |
for (i = 0, tmp = vector_names ; i < Elements(vectors) ; i++) { |
if (tmp[1].idx*4 == i) tmp++; |
vectors[i].idx = i; |
vectors[i].closest = tmp; |
vectors[i].flags = ISFLOAT|ISVEC; |
} |
regs[Elements(regs)-1].idx = -1; |
scalars[Elements(scalars)-1].idx = -1; |
vectors[Elements(vectors)-1].idx = -1; |
} |
static int find_or_add_value( struct reg *reg, int val ) |
{ |
int j; |
for ( j = 0 ; j < reg->nvalues ; j++) |
if ( val == reg->values[j].i ) |
return 1; |
if (j == reg->nalloc) { |
reg->nalloc += 5; |
reg->nalloc *= 2; |
reg->values = realloc( reg->values, reg->nalloc * sizeof(union fi) ); |
} |
reg->values[reg->nvalues++].i = val; |
return 0; |
} |
static struct reg *lookup_reg( struct reg *tab, int reg ) |
{ |
int i; |
for (i = 0 ; tab[i].idx != -1 ; i++) { |
if (tab[i].idx == reg) |
return &tab[i]; |
} |
fprintf(stderr, "*** unknown reg 0x%x\n", reg); |
return NULL; |
} |
static const char *get_reg_name( struct reg *reg ) |
{ |
static char tmp[80]; |
if (reg->idx == reg->closest->idx) |
return reg->closest->name; |
if (reg->flags & ISVEC) { |
if (reg->idx/4 != reg->closest->idx) |
sprintf(tmp, "%s+%d[%d]", |
reg->closest->name, |
(reg->idx/4) - reg->closest->idx, |
reg->idx%4); |
else |
sprintf(tmp, "%s[%d]", reg->closest->name, reg->idx%4); |
} |
else { |
if (reg->idx != reg->closest->idx) |
sprintf(tmp, "%s+%d", reg->closest->name, reg->idx - reg->closest->idx); |
else |
sprintf(tmp, "%s", reg->closest->name); |
} |
return tmp; |
} |
static int print_int_reg_assignment( struct reg *reg, int data ) |
{ |
int changed = (reg->current.i != data); |
int ever_seen = find_or_add_value( reg, data ); |
if (VERBOSE || (NORMAL && (changed || !ever_seen))) |
fprintf(stderr, " %s <-- 0x%x", get_reg_name(reg), data); |
if (NORMAL) { |
if (!ever_seen) |
fprintf(stderr, " *** BRAND NEW VALUE"); |
else if (changed) |
fprintf(stderr, " *** CHANGED"); |
} |
reg->current.i = data; |
if (VERBOSE || (NORMAL && (changed || !ever_seen))) |
fprintf(stderr, "\n"); |
return changed; |
} |
static int print_float_reg_assignment( struct reg *reg, float data ) |
{ |
int changed = (reg->current.f != data); |
int newmin = (data < reg->vmin); |
int newmax = (data > reg->vmax); |
if (VERBOSE || (NORMAL && (newmin || newmax || changed))) |
fprintf(stderr, " %s <-- %.3f", get_reg_name(reg), data); |
if (NORMAL) { |
if (newmin) { |
fprintf(stderr, " *** NEW MIN (prev %.3f)", reg->vmin); |
reg->vmin = data; |
} |
else if (newmax) { |
fprintf(stderr, " *** NEW MAX (prev %.3f)", reg->vmax); |
reg->vmax = data; |
} |
else if (changed) { |
fprintf(stderr, " *** CHANGED"); |
} |
} |
reg->current.f = data; |
if (VERBOSE || (NORMAL && (newmin || newmax || changed))) |
fprintf(stderr, "\n"); |
return changed; |
} |
static int print_reg_assignment( struct reg *reg, int data ) |
{ |
float_ui32_type datau; |
datau.ui32 = data; |
reg->flags |= TOUCHED; |
if (reg->flags & ISFLOAT) |
return print_float_reg_assignment( reg, datau.f ); |
else |
return print_int_reg_assignment( reg, data ); |
} |
static void print_reg( struct reg *reg ) |
{ |
if (reg->flags & TOUCHED) { |
if (reg->flags & ISFLOAT) { |
fprintf(stderr, " %s == %f\n", get_reg_name(reg), reg->current.f); |
} else { |
fprintf(stderr, " %s == 0x%x\n", get_reg_name(reg), reg->current.i); |
} |
} |
} |
static void dump_state( void ) |
{ |
int i; |
for (i = 0 ; i < Elements(regs) ; i++) |
print_reg( ®s[i] ); |
for (i = 0 ; i < Elements(scalars) ; i++) |
print_reg( &scalars[i] ); |
for (i = 0 ; i < Elements(vectors) ; i++) |
print_reg( &vectors[i] ); |
} |
static int radeon_emit_packets( |
drm_radeon_cmd_header_t header, |
drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
int id = (int)header.packet.packet_id; |
int sz = packet[id].len; |
int *data = (int *)cmdbuf->buf; |
int i; |
if (sz * sizeof(int) > cmdbuf->bufsz) { |
fprintf(stderr, "Packet overflows cmdbuf\n"); |
return -EINVAL; |
} |
if (!packet[id].name) { |
fprintf(stderr, "*** Unknown packet 0 nr %d\n", id ); |
return -EINVAL; |
} |
if (VERBOSE) |
fprintf(stderr, "Packet 0 reg %s nr %d\n", packet[id].name, sz ); |
for ( i = 0 ; i < sz ; i++) { |
struct reg *reg = lookup_reg( regs, packet[id].start + i*4 ); |
if (print_reg_assignment( reg, data[i] )) |
total_changed++; |
total++; |
} |
cmdbuf->buf += sz * sizeof(int); |
cmdbuf->bufsz -= sz * sizeof(int); |
return 0; |
} |
static int radeon_emit_scalars( |
drm_radeon_cmd_header_t header, |
drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
int sz = header.scalars.count; |
int *data = (int *)cmdbuf->buf; |
int start = header.scalars.offset; |
int stride = header.scalars.stride; |
int i; |
if (VERBOSE) |
fprintf(stderr, "emit scalars, start %d stride %d nr %d (end %d)\n", |
start, stride, sz, start + stride * sz); |
for (i = 0 ; i < sz ; i++, start += stride) { |
struct reg *reg = lookup_reg( scalars, start ); |
if (print_reg_assignment( reg, data[i] )) |
total_changed++; |
total++; |
} |
cmdbuf->buf += sz * sizeof(int); |
cmdbuf->bufsz -= sz * sizeof(int); |
return 0; |
} |
static int radeon_emit_scalars2( |
drm_radeon_cmd_header_t header, |
drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
int sz = header.scalars.count; |
int *data = (int *)cmdbuf->buf; |
int start = header.scalars.offset + 0x100; |
int stride = header.scalars.stride; |
int i; |
if (VERBOSE) |
fprintf(stderr, "emit scalars2, start %d stride %d nr %d (end %d)\n", |
start, stride, sz, start + stride * sz); |
if (start + stride * sz > 258) { |
fprintf(stderr, "emit scalars OVERFLOW %d/%d/%d\n", start, stride, sz); |
return -1; |
} |
for (i = 0 ; i < sz ; i++, start += stride) { |
struct reg *reg = lookup_reg( scalars, start ); |
if (print_reg_assignment( reg, data[i] )) |
total_changed++; |
total++; |
} |
cmdbuf->buf += sz * sizeof(int); |
cmdbuf->bufsz -= sz * sizeof(int); |
return 0; |
} |
/* Check: inf/nan/extreme-size? |
* Check: table start, end, nr, etc. |
*/ |
static int radeon_emit_vectors( |
drm_radeon_cmd_header_t header, |
drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
int sz = header.vectors.count; |
int *data = (int *)cmdbuf->buf; |
int start = header.vectors.offset; |
int stride = header.vectors.stride; |
int i,j; |
if (VERBOSE) |
fprintf(stderr, "emit vectors, start %d stride %d nr %d (end %d) (0x%x)\n", |
start, stride, sz, start + stride * sz, header.i); |
/* if (start + stride * (sz/4) > 128) { */ |
/* fprintf(stderr, "emit vectors OVERFLOW %d/%d/%d\n", start, stride, sz); */ |
/* return -1; */ |
/* } */ |
for (i = 0 ; i < sz ; start += stride) { |
int changed = 0; |
for (j = 0 ; j < 4 ; i++,j++) { |
struct reg *reg = lookup_reg( vectors, start*4+j ); |
if (print_reg_assignment( reg, data[i] )) |
changed = 1; |
} |
if (changed) |
total_changed += 4; |
total += 4; |
} |
cmdbuf->buf += sz * sizeof(int); |
cmdbuf->bufsz -= sz * sizeof(int); |
return 0; |
} |
static int radeon_emit_veclinear( |
drm_radeon_cmd_header_t header, |
drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
int sz = header.veclinear.count * 4; |
int *data = (int *)cmdbuf->buf; |
float *fdata =(float *)cmdbuf->buf; |
int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8); |
int i; |
if (1||VERBOSE) |
fprintf(stderr, "emit vectors linear, start %d nr %d (end %d) (0x%x)\n", |
start, sz >> 2, start + (sz >> 2), header.i); |
if (start < 0x60) { |
for (i = 0 ; i < sz ; i += 4) { |
fprintf(stderr, "R200_VS_PARAM %d 0 %f\n", (i >> 2) + start, fdata[i]); |
fprintf(stderr, "R200_VS_PARAM %d 1 %f\n", (i >> 2) + start, fdata[i+1]); |
fprintf(stderr, "R200_VS_PARAM %d 2 %f\n", (i >> 2) + start, fdata[i+2]); |
fprintf(stderr, "R200_VS_PARAM %d 3 %f\n", (i >> 2) + start, fdata[i+3]); |
} |
} |
else if ((start >= 0x100) && (start < 0x160)) { |
for (i = 0 ; i < sz ; i += 4) { |
fprintf(stderr, "R200_VS_PARAM %d 0 %f\n", (i >> 2) + start - 0x100 + 0x60, fdata[i]); |
fprintf(stderr, "R200_VS_PARAM %d 1 %f\n", (i >> 2) + start - 0x100 + 0x60, fdata[i+1]); |
fprintf(stderr, "R200_VS_PARAM %d 2 %f\n", (i >> 2) + start - 0x100 + 0x60, fdata[i+2]); |
fprintf(stderr, "R200_VS_PARAM %d 3 %f\n", (i >> 2) + start - 0x100 + 0x60, fdata[i+3]); |
} |
} |
else if ((start >= 0x80) && (start < 0xc0)) { |
for (i = 0 ; i < sz ; i += 4) { |
fprintf(stderr, "R200_VS_PROG %d OPDST %08x\n", (i >> 2) + start - 0x80, data[i]); |
fprintf(stderr, "R200_VS_PROG %d SRC1 %08x\n", (i >> 2) + start - 0x80, data[i+1]); |
fprintf(stderr, "R200_VS_PROG %d SRC2 %08x\n", (i >> 2) + start - 0x80, data[i+2]); |
fprintf(stderr, "R200_VS_PROG %d SRC3 %08x\n", (i >> 2) + start - 0x80, data[i+3]); |
} |
} |
else if ((start >= 0x180) && (start < 0x1c0)) { |
for (i = 0 ; i < sz ; i += 4) { |
fprintf(stderr, "R200_VS_PROG %d OPDST %08x\n", (i >> 2) + start - 0x180 + 0x40, data[i]); |
fprintf(stderr, "R200_VS_PROG %d SRC1 %08x\n", (i >> 2) + start - 0x180 + 0x40, data[i+1]); |
fprintf(stderr, "R200_VS_PROG %d SRC2 %08x\n", (i >> 2) + start - 0x180 + 0x40, data[i+2]); |
fprintf(stderr, "R200_VS_PROG %d SRC3 %08x\n", (i >> 2) + start - 0x180 + 0x40, data[i+3]); |
} |
} |
else { |
fprintf(stderr, "write to unknown vector area\n"); |
} |
cmdbuf->buf += sz * sizeof(int); |
cmdbuf->bufsz -= sz * sizeof(int); |
return 0; |
} |
#if 0 |
static int print_vertex_format( int vfmt ) |
{ |
if (NORMAL) { |
fprintf(stderr, " %s(%x): %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", |
"vertex format", |
vfmt, |
"xy,", |
(vfmt & R200_VTX_Z0) ? "z," : "", |
(vfmt & R200_VTX_W0) ? "w0," : "", |
(vfmt & R200_VTX_FPCOLOR) ? "fpcolor," : "", |
(vfmt & R200_VTX_FPALPHA) ? "fpalpha," : "", |
(vfmt & R200_VTX_PKCOLOR) ? "pkcolor," : "", |
(vfmt & R200_VTX_FPSPEC) ? "fpspec," : "", |
(vfmt & R200_VTX_FPFOG) ? "fpfog," : "", |
(vfmt & R200_VTX_PKSPEC) ? "pkspec," : "", |
(vfmt & R200_VTX_ST0) ? "st0," : "", |
(vfmt & R200_VTX_ST1) ? "st1," : "", |
(vfmt & R200_VTX_Q1) ? "q1," : "", |
(vfmt & R200_VTX_ST2) ? "st2," : "", |
(vfmt & R200_VTX_Q2) ? "q2," : "", |
(vfmt & R200_VTX_ST3) ? "st3," : "", |
(vfmt & R200_VTX_Q3) ? "q3," : "", |
(vfmt & R200_VTX_Q0) ? "q0," : "", |
(vfmt & R200_VTX_N0) ? "n0," : "", |
(vfmt & R200_VTX_XY1) ? "xy1," : "", |
(vfmt & R200_VTX_Z1) ? "z1," : "", |
(vfmt & R200_VTX_W1) ? "w1," : "", |
(vfmt & R200_VTX_N1) ? "n1," : ""); |
if (!find_or_add_value( &others[V_VTXFMT], vfmt )) |
fprintf(stderr, " *** NEW VALUE"); |
fprintf(stderr, "\n"); |
} |
return 0; |
} |
#endif |
static char *primname[0x10] = { |
"NONE", |
"POINTS", |
"LINES", |
"LINE_STRIP", |
"TRIANGLES", |
"TRIANGLE_FAN", |
"TRIANGLE_STRIP", |
"RECT_LIST", |
NULL, |
"3VRT_POINTS", |
"3VRT_LINES", |
"POINT_SPRITES", |
"LINE_LOOP", |
"QUADS", |
"QUAD_STRIP", |
"POLYGON", |
}; |
static int print_prim_and_flags( int prim ) |
{ |
int numverts; |
if (NORMAL) |
fprintf(stderr, " %s(%x): %s%s%s%s%s%s\n", |
"prim flags", |
prim, |
((prim & 0x30) == R200_VF_PRIM_WALK_IND) ? "IND," : "", |
((prim & 0x30) == R200_VF_PRIM_WALK_LIST) ? "LIST," : "", |
((prim & 0x30) == R200_VF_PRIM_WALK_RING) ? "RING," : "", |
(prim & R200_VF_COLOR_ORDER_RGBA) ? "RGBA," : "BGRA, ", |
(prim & R200_VF_INDEX_SZ_4) ? "INDX-32," : "", |
(prim & R200_VF_TCL_OUTPUT_VTX_ENABLE) ? "TCL_OUT_VTX," : ""); |
numverts = prim>>16; |
if (NORMAL) |
fprintf(stderr, " prim: %s numverts %d\n", primname[prim&0xf], numverts); |
switch (prim & 0xf) { |
case R200_VF_PRIM_NONE: |
case R200_VF_PRIM_POINTS: |
if (numverts < 1) { |
fprintf(stderr, "Bad nr verts for line %d\n", numverts); |
return -1; |
} |
break; |
case R200_VF_PRIM_LINES: |
case R200_VF_PRIM_POINT_SPRITES: |
if ((numverts & 1) || numverts == 0) { |
fprintf(stderr, "Bad nr verts for line %d\n", numverts); |
return -1; |
} |
break; |
case R200_VF_PRIM_LINE_STRIP: |
case R200_VF_PRIM_LINE_LOOP: |
if (numverts < 2) { |
fprintf(stderr, "Bad nr verts for line_strip %d\n", numverts); |
return -1; |
} |
break; |
case R200_VF_PRIM_TRIANGLES: |
case R200_VF_PRIM_3VRT_POINTS: |
case R200_VF_PRIM_3VRT_LINES: |
case R200_VF_PRIM_RECT_LIST: |
if (numverts % 3 || numverts == 0) { |
fprintf(stderr, "Bad nr verts for tri %d\n", numverts); |
return -1; |
} |
break; |
case R200_VF_PRIM_TRIANGLE_FAN: |
case R200_VF_PRIM_TRIANGLE_STRIP: |
case R200_VF_PRIM_POLYGON: |
if (numverts < 3) { |
fprintf(stderr, "Bad nr verts for strip/fan %d\n", numverts); |
return -1; |
} |
break; |
case R200_VF_PRIM_QUADS: |
if (numverts % 4 || numverts == 0) { |
fprintf(stderr, "Bad nr verts for quad %d\n", numverts); |
return -1; |
} |
break; |
case R200_VF_PRIM_QUAD_STRIP: |
if (numverts % 2 || numverts < 4) { |
fprintf(stderr, "Bad nr verts for quadstrip %d\n", numverts); |
return -1; |
} |
break; |
default: |
fprintf(stderr, "Bad primitive\n"); |
return -1; |
} |
return 0; |
} |
/* build in knowledge about each packet type |
*/ |
static int radeon_emit_packet3( drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
int cmdsz; |
int *cmd = (int *)cmdbuf->buf; |
int *tmp; |
int i, stride, size, start; |
cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); |
if ((cmd[0] & RADEON_CP_PACKET_MASK) != RADEON_CP_PACKET3 || |
cmdsz * 4 > cmdbuf->bufsz || |
cmdsz > RADEON_CP_PACKET_MAX_DWORDS) { |
fprintf(stderr, "Bad packet\n"); |
return -EINVAL; |
} |
switch( cmd[0] & ~RADEON_CP_PACKET_COUNT_MASK ) { |
case R200_CP_CMD_NOP: |
if (NORMAL) |
fprintf(stderr, "PACKET3_NOP, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_NEXT_CHAR: |
if (NORMAL) |
fprintf(stderr, "PACKET3_NEXT_CHAR, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_PLY_NEXTSCAN: |
if (NORMAL) |
fprintf(stderr, "PACKET3_PLY_NEXTSCAN, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_SET_SCISSORS: |
if (NORMAL) |
fprintf(stderr, "PACKET3_SET_SCISSORS, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_LOAD_MICROCODE: |
if (NORMAL) |
fprintf(stderr, "PACKET3_LOAD_MICROCODE, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_WAIT_FOR_IDLE: |
if (NORMAL) |
fprintf(stderr, "PACKET3_WAIT_FOR_IDLE, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_3D_DRAW_VBUF: |
if (NORMAL) |
fprintf(stderr, "PACKET3_3D_DRAW_VBUF, %d dwords\n", cmdsz); |
/* print_vertex_format(cmd[1]); */ |
if (print_prim_and_flags(cmd[2])) |
return -EINVAL; |
break; |
case R200_CP_CMD_3D_DRAW_IMMD: |
if (NORMAL) |
fprintf(stderr, "PACKET3_3D_DRAW_IMMD, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_3D_DRAW_INDX: { |
int neltdwords; |
if (NORMAL) |
fprintf(stderr, "PACKET3_3D_DRAW_INDX, %d dwords\n", cmdsz); |
/* print_vertex_format(cmd[1]); */ |
if (print_prim_and_flags(cmd[2])) |
return -EINVAL; |
neltdwords = cmd[2]>>16; |
neltdwords += neltdwords & 1; |
neltdwords /= 2; |
if (neltdwords + 3 != cmdsz) |
fprintf(stderr, "Mismatch in DRAW_INDX, %d vs cmdsz %d\n", |
neltdwords, cmdsz); |
break; |
} |
case R200_CP_CMD_LOAD_PALETTE: |
if (NORMAL) |
fprintf(stderr, "PACKET3_LOAD_PALETTE, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_3D_LOAD_VBPNTR: |
if (NORMAL) { |
fprintf(stderr, "PACKET3_3D_LOAD_VBPNTR, %d dwords\n", cmdsz); |
fprintf(stderr, " nr arrays: %d\n", cmd[1]); |
} |
if (((cmd[1]/2)*3) + ((cmd[1]%2)*2) != cmdsz - 2) { |
fprintf(stderr, " ****** MISMATCH %d/%d *******\n", |
((cmd[1]/2)*3) + ((cmd[1]%2)*2) + 2, cmdsz); |
return -EINVAL; |
} |
if (NORMAL) { |
tmp = cmd+2; |
for (i = 0 ; i < cmd[1] ; i++) { |
if (i & 1) { |
stride = (tmp[0]>>24) & 0xff; |
size = (tmp[0]>>16) & 0xff; |
start = tmp[2]; |
tmp += 3; |
} |
else { |
stride = (tmp[0]>>8) & 0xff; |
size = (tmp[0]) & 0xff; |
start = tmp[1]; |
} |
fprintf(stderr, " array %d: start 0x%x vsize %d vstride %d\n", |
i, start, size, stride ); |
} |
} |
break; |
case R200_CP_CMD_PAINT: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_PAINT, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_BITBLT: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_BITBLT, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_SMALLTEXT: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_SMALLTEXT, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_HOSTDATA_BLT: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_HOSTDATA_BLT, %d dwords\n", |
cmdsz); |
break; |
case R200_CP_CMD_POLYLINE: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_POLYLINE, %d dwords\n", cmdsz); |
break; |
case R200_CP_CMD_POLYSCANLINES: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_POLYSCANLINES, %d dwords\n", |
cmdsz); |
break; |
case R200_CP_CMD_PAINT_MULTI: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_PAINT_MULTI, %d dwords\n", |
cmdsz); |
break; |
case R200_CP_CMD_BITBLT_MULTI: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_BITBLT_MULTI, %d dwords\n", |
cmdsz); |
break; |
case R200_CP_CMD_TRANS_BITBLT: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_TRANS_BITBLT, %d dwords\n", |
cmdsz); |
break; |
case R200_CP_CMD_3D_DRAW_VBUF_2: |
if (NORMAL) |
fprintf(stderr, "R200_CP_CMD_3D_DRAW_VBUF_2, %d dwords\n", |
cmdsz); |
if (print_prim_and_flags(cmd[1])) |
return -EINVAL; |
break; |
case R200_CP_CMD_3D_DRAW_IMMD_2: |
if (NORMAL) |
fprintf(stderr, "R200_CP_CMD_3D_DRAW_IMMD_2, %d dwords\n", |
cmdsz); |
if (print_prim_and_flags(cmd[1])) |
return -EINVAL; |
break; |
case R200_CP_CMD_3D_DRAW_INDX_2: |
if (NORMAL) |
fprintf(stderr, "R200_CP_CMD_3D_DRAW_INDX_2, %d dwords\n", |
cmdsz); |
if (print_prim_and_flags(cmd[1])) |
return -EINVAL; |
break; |
default: |
fprintf(stderr, "UNKNOWN PACKET, %d dwords\n", cmdsz); |
break; |
} |
cmdbuf->buf += cmdsz * 4; |
cmdbuf->bufsz -= cmdsz * 4; |
return 0; |
} |
/* Check cliprects for bounds, then pass on to above: |
*/ |
static int radeon_emit_packet3_cliprect( drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
drm_clip_rect_t *boxes = (drm_clip_rect_t *)cmdbuf->boxes; |
int i = 0; |
if (VERBOSE && total_changed) { |
dump_state(); |
total_changed = 0; |
} |
if (NORMAL) { |
do { |
if ( i < cmdbuf->nbox ) { |
fprintf(stderr, "Emit box %d/%d %d,%d %d,%d\n", |
i, cmdbuf->nbox, |
boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2); |
} |
} while ( ++i < cmdbuf->nbox ); |
} |
if (cmdbuf->nbox == 1) |
cmdbuf->nbox = 0; |
return radeon_emit_packet3( cmdbuf ); |
} |
int r200SanityCmdBuffer( r200ContextPtr rmesa, |
int nbox, |
drm_clip_rect_t *boxes ) |
{ |
int idx; |
drm_radeon_cmd_buffer_t cmdbuf; |
drm_radeon_cmd_header_t header; |
static int inited = 0; |
if (!inited) { |
init_regs(); |
inited = 1; |
} |
cmdbuf.buf = rmesa->store.cmd_buf; |
cmdbuf.bufsz = rmesa->store.cmd_used; |
cmdbuf.boxes = (drm_clip_rect_t *)boxes; |
cmdbuf.nbox = nbox; |
while ( cmdbuf.bufsz >= sizeof(header) ) { |
header.i = *(int *)cmdbuf.buf; |
cmdbuf.buf += sizeof(header); |
cmdbuf.bufsz -= sizeof(header); |
switch (header.header.cmd_type) { |
case RADEON_CMD_PACKET: |
if (radeon_emit_packets( header, &cmdbuf )) { |
fprintf(stderr,"radeon_emit_packets failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_SCALARS: |
if (radeon_emit_scalars( header, &cmdbuf )) { |
fprintf(stderr,"radeon_emit_scalars failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_SCALARS2: |
if (radeon_emit_scalars2( header, &cmdbuf )) { |
fprintf(stderr,"radeon_emit_scalars failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_VECTORS: |
if (radeon_emit_vectors( header, &cmdbuf )) { |
fprintf(stderr,"radeon_emit_vectors failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_DMA_DISCARD: |
idx = header.dma.buf_idx; |
if (NORMAL) |
fprintf(stderr, "RADEON_CMD_DMA_DISCARD buf %d\n", idx); |
bufs++; |
break; |
case RADEON_CMD_PACKET3: |
if (radeon_emit_packet3( &cmdbuf )) { |
fprintf(stderr,"radeon_emit_packet3 failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_PACKET3_CLIP: |
if (radeon_emit_packet3_cliprect( &cmdbuf )) { |
fprintf(stderr,"radeon_emit_packet3_clip failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_WAIT: |
break; |
case RADEON_CMD_VECLINEAR: |
if (radeon_emit_veclinear( header, &cmdbuf )) { |
fprintf(stderr,"radeon_emit_veclinear failed\n"); |
return -EINVAL; |
} |
break; |
default: |
fprintf(stderr,"bad cmd_type %d at %p\n", |
header.header.cmd_type, |
cmdbuf.buf - sizeof(header)); |
return -EINVAL; |
} |
} |
if (0) |
{ |
static int n = 0; |
n++; |
if (n == 10) { |
fprintf(stderr, "Bufs %d Total emitted %d real changes %d (%.2f%%)\n", |
bufs, |
total, total_changed, |
((float)total_changed/(float)total*100.0)); |
fprintf(stderr, "Total emitted per buf: %.2f\n", |
(float)total/(float)bufs); |
fprintf(stderr, "Real changes per buf: %.2f\n", |
(float)total_changed/(float)bufs); |
bufs = n = total = total_changed = 0; |
} |
} |
fprintf(stderr, "leaving %s\n\n\n", __FUNCTION__); |
return 0; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_sanity.h |
---|
0,0 → 1,8 |
#ifndef R200_SANITY_H |
#define R200_SANITY_H |
extern int r200SanityCmdBuffer( r200ContextPtr rmesa, |
int nbox, |
drm_clip_rect_t *boxes ); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_state.c |
---|
0,0 → 1,2470 |
/************************************************************************** |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/imports.h" |
#include "main/api_arrayelt.h" |
#include "main/enums.h" |
#include "main/colormac.h" |
#include "main/light.h" |
#include "main/framebuffer.h" |
#include "main/fbobject.h" |
#include "main/stencil.h" |
#include "swrast/swrast.h" |
#include "vbo/vbo.h" |
#include "tnl/tnl.h" |
#include "tnl/t_pipeline.h" |
#include "swrast_setup/swrast_setup.h" |
#include "drivers/common/meta.h" |
#include "radeon_common.h" |
#include "radeon_mipmap_tree.h" |
#include "r200_context.h" |
#include "r200_ioctl.h" |
#include "r200_state.h" |
#include "r200_tcl.h" |
#include "r200_tex.h" |
#include "r200_swtcl.h" |
#include "r200_vertprog.h" |
/* ============================================================= |
* Alpha blending |
*/ |
static void r200AlphaFunc( struct gl_context *ctx, GLenum func, GLfloat ref ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC]; |
GLubyte refByte; |
CLAMPED_FLOAT_TO_UBYTE(refByte, ref); |
R200_STATECHANGE( rmesa, ctx ); |
pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK); |
pp_misc |= (refByte & R200_REF_ALPHA_MASK); |
switch ( func ) { |
case GL_NEVER: |
pp_misc |= R200_ALPHA_TEST_FAIL; |
break; |
case GL_LESS: |
pp_misc |= R200_ALPHA_TEST_LESS; |
break; |
case GL_EQUAL: |
pp_misc |= R200_ALPHA_TEST_EQUAL; |
break; |
case GL_LEQUAL: |
pp_misc |= R200_ALPHA_TEST_LEQUAL; |
break; |
case GL_GREATER: |
pp_misc |= R200_ALPHA_TEST_GREATER; |
break; |
case GL_NOTEQUAL: |
pp_misc |= R200_ALPHA_TEST_NEQUAL; |
break; |
case GL_GEQUAL: |
pp_misc |= R200_ALPHA_TEST_GEQUAL; |
break; |
case GL_ALWAYS: |
pp_misc |= R200_ALPHA_TEST_PASS; |
break; |
} |
rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc; |
} |
static void r200BlendColor( struct gl_context *ctx, const GLfloat cf[4] ) |
{ |
GLubyte color[4]; |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
R200_STATECHANGE( rmesa, ctx ); |
CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]); |
CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]); |
CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]); |
CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]); |
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = radeonPackColor( 4, color[0], color[1], color[2], color[3] ); |
} |
/** |
* Calculate the hardware blend factor setting. This same function is used |
* for source and destination of both alpha and RGB. |
* |
* \returns |
* The hardware register value for the specified blend factor. This value |
* will need to be shifted into the correct position for either source or |
* destination factor. |
* |
* \todo |
* Since the two cases where source and destination are handled differently |
* are essentially error cases, they should never happen. Determine if these |
* cases can be removed. |
*/ |
static int blend_factor( GLenum factor, GLboolean is_src ) |
{ |
int func; |
switch ( factor ) { |
case GL_ZERO: |
func = R200_BLEND_GL_ZERO; |
break; |
case GL_ONE: |
func = R200_BLEND_GL_ONE; |
break; |
case GL_DST_COLOR: |
func = R200_BLEND_GL_DST_COLOR; |
break; |
case GL_ONE_MINUS_DST_COLOR: |
func = R200_BLEND_GL_ONE_MINUS_DST_COLOR; |
break; |
case GL_SRC_COLOR: |
func = R200_BLEND_GL_SRC_COLOR; |
break; |
case GL_ONE_MINUS_SRC_COLOR: |
func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR; |
break; |
case GL_SRC_ALPHA: |
func = R200_BLEND_GL_SRC_ALPHA; |
break; |
case GL_ONE_MINUS_SRC_ALPHA: |
func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA; |
break; |
case GL_DST_ALPHA: |
func = R200_BLEND_GL_DST_ALPHA; |
break; |
case GL_ONE_MINUS_DST_ALPHA: |
func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA; |
break; |
case GL_SRC_ALPHA_SATURATE: |
func = (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : R200_BLEND_GL_ZERO; |
break; |
case GL_CONSTANT_COLOR: |
func = R200_BLEND_GL_CONST_COLOR; |
break; |
case GL_ONE_MINUS_CONSTANT_COLOR: |
func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR; |
break; |
case GL_CONSTANT_ALPHA: |
func = R200_BLEND_GL_CONST_ALPHA; |
break; |
case GL_ONE_MINUS_CONSTANT_ALPHA: |
func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA; |
break; |
default: |
func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO; |
} |
return func; |
} |
/** |
* Sets both the blend equation and the blend function. |
* This is done in a single |
* function because some blend equations (i.e., \c GL_MIN and \c GL_MAX) |
* change the interpretation of the blend function. |
* Also, make sure that blend function and blend equation are set to their default |
* value if color blending is not enabled, since at least blend equations GL_MIN |
* and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for |
* unknown reasons. |
*/ |
static void r200_set_blend_state( struct gl_context * ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & |
~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE); |
int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
(R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); |
int eqn = R200_COMB_FCN_ADD_CLAMP; |
int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
(R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); |
int eqnA = R200_COMB_FCN_ADD_CLAMP; |
R200_STATECHANGE( rmesa, ctx ); |
if (ctx->Color.ColorLogicOpEnabled) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE; |
rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func; |
rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; |
return; |
} else if (ctx->Color.BlendEnabled) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE; |
} |
else { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl; |
rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func; |
rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; |
return; |
} |
func = (blend_factor( ctx->Color.Blend[0].SrcRGB, GL_TRUE ) << R200_SRC_BLEND_SHIFT) | |
(blend_factor( ctx->Color.Blend[0].DstRGB, GL_FALSE ) << R200_DST_BLEND_SHIFT); |
switch(ctx->Color.Blend[0].EquationRGB) { |
case GL_FUNC_ADD: |
eqn = R200_COMB_FCN_ADD_CLAMP; |
break; |
case GL_FUNC_SUBTRACT: |
eqn = R200_COMB_FCN_SUB_CLAMP; |
break; |
case GL_FUNC_REVERSE_SUBTRACT: |
eqn = R200_COMB_FCN_RSUB_CLAMP; |
break; |
case GL_MIN: |
eqn = R200_COMB_FCN_MIN; |
func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
(R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); |
break; |
case GL_MAX: |
eqn = R200_COMB_FCN_MAX; |
func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
(R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); |
break; |
default: |
fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n", |
__FUNCTION__, __LINE__, ctx->Color.Blend[0].EquationRGB ); |
return; |
} |
funcA = (blend_factor( ctx->Color.Blend[0].SrcA, GL_TRUE ) << R200_SRC_BLEND_SHIFT) | |
(blend_factor( ctx->Color.Blend[0].DstA, GL_FALSE ) << R200_DST_BLEND_SHIFT); |
switch(ctx->Color.Blend[0].EquationA) { |
case GL_FUNC_ADD: |
eqnA = R200_COMB_FCN_ADD_CLAMP; |
break; |
case GL_FUNC_SUBTRACT: |
eqnA = R200_COMB_FCN_SUB_CLAMP; |
break; |
case GL_FUNC_REVERSE_SUBTRACT: |
eqnA = R200_COMB_FCN_RSUB_CLAMP; |
break; |
case GL_MIN: |
eqnA = R200_COMB_FCN_MIN; |
funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
(R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); |
break; |
case GL_MAX: |
eqnA = R200_COMB_FCN_MAX; |
funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
(R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); |
break; |
default: |
fprintf( stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n", |
__FUNCTION__, __LINE__, ctx->Color.Blend[0].EquationA ); |
return; |
} |
rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqnA | funcA; |
rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; |
} |
static void r200BlendEquationSeparate( struct gl_context *ctx, |
GLenum modeRGB, GLenum modeA ) |
{ |
r200_set_blend_state( ctx ); |
} |
static void r200BlendFuncSeparate( struct gl_context *ctx, |
GLenum sfactorRGB, GLenum dfactorRGB, |
GLenum sfactorA, GLenum dfactorA ) |
{ |
r200_set_blend_state( ctx ); |
} |
/* ============================================================= |
* Depth testing |
*/ |
static void r200DepthFunc( struct gl_context *ctx, GLenum func ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
R200_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK; |
switch ( ctx->Depth.Func ) { |
case GL_NEVER: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER; |
break; |
case GL_LESS: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS; |
break; |
case GL_EQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL; |
break; |
case GL_LEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL; |
break; |
case GL_GREATER: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER; |
break; |
case GL_NOTEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL; |
break; |
case GL_GEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL; |
break; |
case GL_ALWAYS: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS; |
break; |
} |
} |
static void r200DepthMask( struct gl_context *ctx, GLboolean flag ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
R200_STATECHANGE( rmesa, ctx ); |
if ( ctx->Depth.Mask ) { |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE; |
} |
} |
/* ============================================================= |
* Fog |
*/ |
static void r200Fogfv( struct gl_context *ctx, GLenum pname, const GLfloat *param ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
union { int i; float f; } c, d; |
GLubyte col[4]; |
GLuint i; |
c.i = rmesa->hw.fog.cmd[FOG_C]; |
d.i = rmesa->hw.fog.cmd[FOG_D]; |
switch (pname) { |
case GL_FOG_MODE: |
if (!ctx->Fog.Enabled) |
return; |
R200_STATECHANGE(rmesa, tcl); |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK; |
switch (ctx->Fog.Mode) { |
case GL_LINEAR: |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR; |
if (ctx->Fog.Start == ctx->Fog.End) { |
c.f = 1.0F; |
d.f = 1.0F; |
} |
else { |
c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); |
d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start); |
} |
break; |
case GL_EXP: |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP; |
c.f = 0.0; |
d.f = -ctx->Fog.Density; |
break; |
case GL_EXP2: |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2; |
c.f = 0.0; |
d.f = -(ctx->Fog.Density * ctx->Fog.Density); |
break; |
default: |
return; |
} |
break; |
case GL_FOG_DENSITY: |
switch (ctx->Fog.Mode) { |
case GL_EXP: |
c.f = 0.0; |
d.f = -ctx->Fog.Density; |
break; |
case GL_EXP2: |
c.f = 0.0; |
d.f = -(ctx->Fog.Density * ctx->Fog.Density); |
break; |
default: |
break; |
} |
break; |
case GL_FOG_START: |
case GL_FOG_END: |
if (ctx->Fog.Mode == GL_LINEAR) { |
if (ctx->Fog.Start == ctx->Fog.End) { |
c.f = 1.0F; |
d.f = 1.0F; |
} else { |
c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); |
d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start); |
} |
} |
break; |
case GL_FOG_COLOR: |
R200_STATECHANGE( rmesa, ctx ); |
_mesa_unclamped_float_rgba_to_ubyte(col, ctx->Fog.Color ); |
i = radeonPackColor( 4, col[0], col[1], col[2], 0 ); |
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK; |
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i; |
break; |
case GL_FOG_COORD_SRC: { |
GLuint out_0 = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]; |
GLuint fog = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR]; |
fog &= ~R200_FOG_USE_MASK; |
if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD || ctx->VertexProgram.Enabled) { |
fog |= R200_FOG_USE_VTX_FOG; |
out_0 |= R200_VTX_DISCRETE_FOG; |
} |
else { |
fog |= R200_FOG_USE_SPEC_ALPHA; |
out_0 &= ~R200_VTX_DISCRETE_FOG; |
} |
if ( fog != rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] ) { |
R200_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog; |
} |
if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) { |
R200_STATECHANGE( rmesa, vtx ); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0; |
} |
break; |
} |
default: |
return; |
} |
if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) { |
R200_STATECHANGE( rmesa, fog ); |
rmesa->hw.fog.cmd[FOG_C] = c.i; |
rmesa->hw.fog.cmd[FOG_D] = d.i; |
} |
} |
/* ============================================================= |
* Culling |
*/ |
static void r200CullFace( struct gl_context *ctx, GLenum unused ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; |
GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL]; |
s |= R200_FFACE_SOLID | R200_BFACE_SOLID; |
t &= ~(R200_CULL_FRONT | R200_CULL_BACK); |
if ( ctx->Polygon.CullFlag ) { |
switch ( ctx->Polygon.CullFaceMode ) { |
case GL_FRONT: |
s &= ~R200_FFACE_SOLID; |
t |= R200_CULL_FRONT; |
break; |
case GL_BACK: |
s &= ~R200_BFACE_SOLID; |
t |= R200_CULL_BACK; |
break; |
case GL_FRONT_AND_BACK: |
s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID); |
t |= (R200_CULL_FRONT | R200_CULL_BACK); |
break; |
} |
} |
if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { |
R200_STATECHANGE(rmesa, set ); |
rmesa->hw.set.cmd[SET_SE_CNTL] = s; |
} |
if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) { |
R200_STATECHANGE(rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t; |
} |
} |
static void r200FrontFace( struct gl_context *ctx, GLenum mode ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
int cull_face = (mode == GL_CW) ? R200_FFACE_CULL_CW : R200_FFACE_CULL_CCW; |
R200_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK; |
R200_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW; |
/* Winding is inverted when rendering to FBO */ |
if (ctx->DrawBuffer && _mesa_is_user_fbo(ctx->DrawBuffer)) |
cull_face = (mode == GL_CCW) ? R200_FFACE_CULL_CW : R200_FFACE_CULL_CCW; |
rmesa->hw.set.cmd[SET_SE_CNTL] |= cull_face; |
if ( mode == GL_CCW ) |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW; |
} |
/* ============================================================= |
* Point state |
*/ |
static void r200PointSize( struct gl_context *ctx, GLfloat size ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd; |
radeon_print(RADEON_STATE, RADEON_TRACE, |
"%s(%p) size: %f, fixed point result: %d.%d (%d/16)\n", |
__func__, ctx, size, |
((GLuint)(ctx->Point.Size * 16.0))/16, |
(((GLuint)(ctx->Point.Size * 16.0))&15)*100/16, |
((GLuint)(ctx->Point.Size * 16.0))&15); |
R200_STATECHANGE( rmesa, cst ); |
R200_STATECHANGE( rmesa, ptp ); |
rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff; |
rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0)); |
/* this is the size param of the point size calculation (point size reg value |
is not used when calculation is active). */ |
fcmd[PTP_VPORT_SCALE_PTSIZE] = ctx->Point.Size; |
} |
static void r200PointParameter( struct gl_context *ctx, GLenum pname, const GLfloat *params) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd; |
switch (pname) { |
case GL_POINT_SIZE_MIN: |
/* Can clamp both in tcl and setup - just set both (as does fglrx) */ |
R200_STATECHANGE( rmesa, lin ); |
R200_STATECHANGE( rmesa, ptp ); |
rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= 0xffff; |
rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Point.MinSize * 16.0) << 16; |
fcmd[PTP_CLAMP_MIN] = ctx->Point.MinSize; |
break; |
case GL_POINT_SIZE_MAX: |
R200_STATECHANGE( rmesa, cst ); |
R200_STATECHANGE( rmesa, ptp ); |
rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= 0xffff; |
rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= (GLuint)(ctx->Point.MaxSize * 16.0) << 16; |
fcmd[PTP_CLAMP_MAX] = ctx->Point.MaxSize; |
break; |
case GL_POINT_DISTANCE_ATTENUATION: |
R200_STATECHANGE( rmesa, vtx ); |
R200_STATECHANGE( rmesa, spr ); |
R200_STATECHANGE( rmesa, ptp ); |
GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd; |
rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= |
~(R200_PS_MULT_MASK | R200_PS_LIN_ATT_ZERO | R200_PS_SE_SEL_STATE); |
/* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in |
r200ValidateState looks like overkill */ |
if (ctx->Point.Params[0] != 1.0 || |
ctx->Point.Params[1] != 0.0 || |
ctx->Point.Params[2] != 0.0 || |
(ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled)) { |
/* all we care for vp would be the ps_se_sel_state setting */ |
fcmd[PTP_ATT_CONST_QUAD] = ctx->Point.Params[2]; |
fcmd[PTP_ATT_CONST_LIN] = ctx->Point.Params[1]; |
fcmd[PTP_ATT_CONST_CON] = ctx->Point.Params[0]; |
rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_MULT_ATTENCONST; |
if (ctx->Point.Params[1] == 0.0) |
rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_LIN_ATT_ZERO; |
/* FIXME: setting this here doesn't look quite ok - we only want to do |
that if we're actually drawing points probably */ |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_PT_SIZE; |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= R200_VTX_POINT_SIZE; |
} |
else { |
rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= |
R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST; |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_PT_SIZE; |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~R200_VTX_POINT_SIZE; |
} |
break; |
case GL_POINT_FADE_THRESHOLD_SIZE: |
/* don't support multisampling, so doesn't matter. */ |
break; |
/* can't do these but don't need them. |
case GL_POINT_SPRITE_R_MODE_NV: |
case GL_POINT_SPRITE_COORD_ORIGIN: */ |
default: |
fprintf(stderr, "bad pname parameter in r200PointParameter\n"); |
return; |
} |
} |
/* ============================================================= |
* Line state |
*/ |
static void r200LineWidth( struct gl_context *ctx, GLfloat widthf ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
R200_STATECHANGE( rmesa, lin ); |
R200_STATECHANGE( rmesa, set ); |
/* Line width is stored in U6.4 format. |
* Same min/max limits for AA, non-AA lines. |
*/ |
rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff; |
rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint) |
(CLAMP(widthf, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth) * 16.0); |
if ( widthf > 1.0 ) { |
rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE; |
} else { |
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE; |
} |
} |
static void r200LineStipple( struct gl_context *ctx, GLint factor, GLushort pattern ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
R200_STATECHANGE( rmesa, lin ); |
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = |
((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern)); |
} |
/* ============================================================= |
* Masks |
*/ |
static void r200ColorMask( struct gl_context *ctx, |
GLboolean r, GLboolean g, |
GLboolean b, GLboolean a ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint mask; |
struct radeon_renderbuffer *rrb; |
GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE; |
rrb = radeon_get_colorbuffer(&rmesa->radeon); |
if (!rrb) |
return; |
mask = radeonPackColor( rrb->cpp, |
ctx->Color.ColorMask[0][RCOMP], |
ctx->Color.ColorMask[0][GCOMP], |
ctx->Color.ColorMask[0][BCOMP], |
ctx->Color.ColorMask[0][ACOMP] ); |
if (!(r && g && b && a)) |
flag |= R200_PLANE_MASK_ENABLE; |
if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) { |
R200_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag; |
} |
if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) { |
R200_STATECHANGE( rmesa, msk ); |
rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask; |
} |
} |
/* ============================================================= |
* Polygon state |
*/ |
static void r200PolygonOffset( struct gl_context *ctx, |
GLfloat factor, GLfloat units ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF; |
float_ui32_type constant = { units * depthScale }; |
float_ui32_type factoru = { factor }; |
/* factor *= 2; */ |
/* constant *= 2; */ |
/* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */ |
R200_STATECHANGE( rmesa, zbs ); |
rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32; |
rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32; |
} |
static void r200PolygonMode( struct gl_context *ctx, GLenum face, GLenum mode ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL); |
/* Can't generally do unfilled via tcl, but some good special |
* cases work. |
*/ |
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, unfilled); |
if (rmesa->radeon.TclFallback) { |
r200ChooseRenderState( ctx ); |
r200ChooseVertexState( ctx ); |
} |
} |
/* ============================================================= |
* Rendering attributes |
* |
* We really don't want to recalculate all this every time we bind a |
* texture. These things shouldn't change all that often, so it makes |
* sense to break them out of the core texture state update routines. |
*/ |
/* Examine lighting and texture state to determine if separate specular |
* should be enabled. |
*/ |
static void r200UpdateSpecular( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL]; |
R200_STATECHANGE( rmesa, tcl ); |
R200_STATECHANGE( rmesa, vtx ); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0; |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1; |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE; |
p &= ~R200_SPECULAR_ENABLE; |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE; |
if (ctx->Light.Enabled && |
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) { |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= |
((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) | |
(R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT)); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0; |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1; |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE; |
p |= R200_SPECULAR_ENABLE; |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= |
~R200_DIFFUSE_SPECULAR_COMBINE; |
} |
else if (ctx->Light.Enabled) { |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= |
((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT)); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0; |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE; |
} else if (ctx->Fog.ColorSumEnabled ) { |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= |
((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) | |
(R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT)); |
p |= R200_SPECULAR_ENABLE; |
} else { |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= |
((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT)); |
} |
if (ctx->Fog.Enabled) { |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= |
((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT)); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1; |
} |
if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) { |
R200_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p; |
} |
/* Update vertex/render formats |
*/ |
if (rmesa->radeon.TclFallback) { |
r200ChooseRenderState( ctx ); |
r200ChooseVertexState( ctx ); |
} |
} |
/* ============================================================= |
* Materials |
*/ |
/* Update on colormaterial, material emmissive/ambient, |
* lightmodel.globalambient |
*/ |
static void update_global_ambient( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
float *fcmd = (float *)R200_DB_STATE( glt ); |
/* Need to do more if both emmissive & ambient are PREMULT: |
* I believe this is not nessary when using source_material. This condition thus |
* will never happen currently, and the function has no dependencies on materials now |
*/ |
if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] & |
((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) | |
(3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0) |
{ |
COPY_3V( &fcmd[GLT_RED], |
ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]); |
ACC_SCALE_3V( &fcmd[GLT_RED], |
ctx->Light.Model.Ambient, |
ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]); |
} |
else |
{ |
COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient ); |
} |
R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt); |
} |
/* Update on change to |
* - light[p].colors |
* - light[p].enabled |
*/ |
static void update_light_colors( struct gl_context *ctx, GLuint p ) |
{ |
struct gl_light *l = &ctx->Light.Light[p]; |
/* fprintf(stderr, "%s\n", __FUNCTION__); */ |
if (l->Enabled) { |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
float *fcmd = (float *)R200_DB_STATE( lit[p] ); |
COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient ); |
COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse ); |
COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular ); |
R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); |
} |
} |
static void r200ColorMaterial( struct gl_context *ctx, GLenum face, GLenum mode ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]; |
light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) | |
(0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) | |
(0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) | |
(0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) | |
(0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) | |
(0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) | |
(0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) | |
(0xf << R200_BACK_SPECULAR_SOURCE_SHIFT)); |
if (ctx->Light.ColorMaterialEnabled) { |
GLuint mask = ctx->Light._ColorMaterialBitmask; |
if (mask & MAT_BIT_FRONT_EMISSION) { |
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
R200_FRONT_EMISSIVE_SOURCE_SHIFT); |
} |
else |
light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << |
R200_FRONT_EMISSIVE_SOURCE_SHIFT); |
if (mask & MAT_BIT_FRONT_AMBIENT) { |
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
R200_FRONT_AMBIENT_SOURCE_SHIFT); |
} |
else |
light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << |
R200_FRONT_AMBIENT_SOURCE_SHIFT); |
if (mask & MAT_BIT_FRONT_DIFFUSE) { |
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
R200_FRONT_DIFFUSE_SOURCE_SHIFT); |
} |
else |
light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << |
R200_FRONT_DIFFUSE_SOURCE_SHIFT); |
if (mask & MAT_BIT_FRONT_SPECULAR) { |
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
R200_FRONT_SPECULAR_SOURCE_SHIFT); |
} |
else { |
light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << |
R200_FRONT_SPECULAR_SOURCE_SHIFT); |
} |
if (mask & MAT_BIT_BACK_EMISSION) { |
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
R200_BACK_EMISSIVE_SOURCE_SHIFT); |
} |
else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << |
R200_BACK_EMISSIVE_SOURCE_SHIFT); |
if (mask & MAT_BIT_BACK_AMBIENT) { |
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
R200_BACK_AMBIENT_SOURCE_SHIFT); |
} |
else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << |
R200_BACK_AMBIENT_SOURCE_SHIFT); |
if (mask & MAT_BIT_BACK_DIFFUSE) { |
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
R200_BACK_DIFFUSE_SOURCE_SHIFT); |
} |
else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << |
R200_BACK_DIFFUSE_SOURCE_SHIFT); |
if (mask & MAT_BIT_BACK_SPECULAR) { |
light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
R200_BACK_SPECULAR_SOURCE_SHIFT); |
} |
else { |
light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << |
R200_BACK_SPECULAR_SOURCE_SHIFT); |
} |
} |
else { |
/* Default to SOURCE_MATERIAL: |
*/ |
light_model_ctl1 |= |
(R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT); |
} |
if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) { |
R200_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1; |
} |
} |
void r200UpdateMaterial( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLfloat (*mat)[4] = ctx->Light.Material.Attrib; |
GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] ); |
GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] ); |
GLuint mask = ~0; |
/* Might be possible and faster to update everything unconditionally? */ |
if (ctx->Light.ColorMaterialEnabled) |
mask &= ~ctx->Light._ColorMaterialBitmask; |
if (R200_DEBUG & RADEON_STATE) |
fprintf(stderr, "%s\n", __FUNCTION__); |
if (mask & MAT_BIT_FRONT_EMISSION) { |
fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0]; |
fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1]; |
fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2]; |
fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3]; |
} |
if (mask & MAT_BIT_FRONT_AMBIENT) { |
fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0]; |
fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1]; |
fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2]; |
fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3]; |
} |
if (mask & MAT_BIT_FRONT_DIFFUSE) { |
fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0]; |
fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1]; |
fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2]; |
fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3]; |
} |
if (mask & MAT_BIT_FRONT_SPECULAR) { |
fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0]; |
fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1]; |
fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2]; |
fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3]; |
} |
if (mask & MAT_BIT_FRONT_SHININESS) { |
fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0]; |
} |
if (mask & MAT_BIT_BACK_EMISSION) { |
fcmd2[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_BACK_EMISSION][0]; |
fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1]; |
fcmd2[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_BACK_EMISSION][2]; |
fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3]; |
} |
if (mask & MAT_BIT_BACK_AMBIENT) { |
fcmd2[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_BACK_AMBIENT][0]; |
fcmd2[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_BACK_AMBIENT][1]; |
fcmd2[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_BACK_AMBIENT][2]; |
fcmd2[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_BACK_AMBIENT][3]; |
} |
if (mask & MAT_BIT_BACK_DIFFUSE) { |
fcmd2[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_BACK_DIFFUSE][0]; |
fcmd2[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_BACK_DIFFUSE][1]; |
fcmd2[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_BACK_DIFFUSE][2]; |
fcmd2[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_BACK_DIFFUSE][3]; |
} |
if (mask & MAT_BIT_BACK_SPECULAR) { |
fcmd2[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_BACK_SPECULAR][0]; |
fcmd2[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_BACK_SPECULAR][1]; |
fcmd2[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_BACK_SPECULAR][2]; |
fcmd2[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_BACK_SPECULAR][3]; |
} |
if (mask & MAT_BIT_BACK_SHININESS) { |
fcmd2[MTL_SHININESS] = mat[MAT_ATTRIB_BACK_SHININESS][0]; |
} |
R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] ); |
R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] ); |
/* currently material changes cannot trigger a global ambient change, I believe this is correct |
update_global_ambient( ctx ); */ |
} |
/* _NEW_LIGHT |
* _NEW_MODELVIEW |
* _MESA_NEW_NEED_EYE_COORDS |
* |
* Uses derived state from mesa: |
* _VP_inf_norm |
* _h_inf_norm |
* _Position |
* _NormSpotDirection |
* _ModelViewInvScale |
* _NeedEyeCoords |
* _EyeZDir |
* |
* which are calculated in light.c and are correct for the current |
* lighting space (model or eye), hence dependencies on _NEW_MODELVIEW |
* and _MESA_NEW_NEED_EYE_COORDS. |
*/ |
static void update_light( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
/* Have to check these, or have an automatic shortcircuit mechanism |
* to remove noop statechanges. (Or just do a better job on the |
* front end). |
*/ |
{ |
GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]; |
if (ctx->_NeedEyeCoords) |
tmp &= ~R200_LIGHT_IN_MODELSPACE; |
else |
tmp |= R200_LIGHT_IN_MODELSPACE; |
if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]) |
{ |
R200_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp; |
} |
} |
{ |
GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye ); |
fcmd[EYE_X] = ctx->_EyeZDir[0]; |
fcmd[EYE_Y] = ctx->_EyeZDir[1]; |
fcmd[EYE_Z] = - ctx->_EyeZDir[2]; |
fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale; |
R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye ); |
} |
if (ctx->Light.Enabled) { |
GLint p; |
for (p = 0 ; p < MAX_LIGHTS; p++) { |
if (ctx->Light.Light[p].Enabled) { |
struct gl_light *l = &ctx->Light.Light[p]; |
GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] ); |
if (l->EyePosition[3] == 0.0) { |
COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm ); |
COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm ); |
fcmd[LIT_POSITION_W] = 0; |
fcmd[LIT_DIRECTION_W] = 0; |
} else { |
COPY_4V( &fcmd[LIT_POSITION_X], l->_Position ); |
fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0]; |
fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1]; |
fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2]; |
fcmd[LIT_DIRECTION_W] = 0; |
} |
R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); |
} |
} |
} |
} |
static void r200Lightfv( struct gl_context *ctx, GLenum light, |
GLenum pname, const GLfloat *params ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLint p = light - GL_LIGHT0; |
struct gl_light *l = &ctx->Light.Light[p]; |
GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd; |
switch (pname) { |
case GL_AMBIENT: |
case GL_DIFFUSE: |
case GL_SPECULAR: |
update_light_colors( ctx, p ); |
break; |
case GL_SPOT_DIRECTION: |
/* picked up in update_light */ |
break; |
case GL_POSITION: { |
/* positions picked up in update_light, but can do flag here */ |
GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL; |
GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; |
R200_STATECHANGE(rmesa, tcl); |
if (l->EyePosition[3] != 0.0F) |
rmesa->hw.tcl.cmd[idx] |= flag; |
else |
rmesa->hw.tcl.cmd[idx] &= ~flag; |
break; |
} |
case GL_SPOT_EXPONENT: |
R200_STATECHANGE(rmesa, lit[p]); |
fcmd[LIT_SPOT_EXPONENT] = params[0]; |
break; |
case GL_SPOT_CUTOFF: { |
GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT; |
GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; |
R200_STATECHANGE(rmesa, lit[p]); |
fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff; |
R200_STATECHANGE(rmesa, tcl); |
if (l->SpotCutoff != 180.0F) |
rmesa->hw.tcl.cmd[idx] |= flag; |
else |
rmesa->hw.tcl.cmd[idx] &= ~flag; |
break; |
} |
case GL_CONSTANT_ATTENUATION: |
R200_STATECHANGE(rmesa, lit[p]); |
fcmd[LIT_ATTEN_CONST] = params[0]; |
if ( params[0] == 0.0 ) |
fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX; |
else |
fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0]; |
break; |
case GL_LINEAR_ATTENUATION: |
R200_STATECHANGE(rmesa, lit[p]); |
fcmd[LIT_ATTEN_LINEAR] = params[0]; |
break; |
case GL_QUADRATIC_ATTENUATION: |
R200_STATECHANGE(rmesa, lit[p]); |
fcmd[LIT_ATTEN_QUADRATIC] = params[0]; |
break; |
default: |
return; |
} |
/* Set RANGE_ATTEN only when needed */ |
switch (pname) { |
case GL_POSITION: |
case GL_CONSTANT_ATTENUATION: |
case GL_LINEAR_ATTENUATION: |
case GL_QUADRATIC_ATTENUATION: { |
GLuint *icmd = (GLuint *)R200_DB_STATE( tcl ); |
GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; |
GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN |
: R200_LIGHT_0_ENABLE_RANGE_ATTEN; |
GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN |
: R200_LIGHT_0_CONSTANT_RANGE_ATTEN; |
if ( l->EyePosition[3] == 0.0F || |
( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) && |
fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) { |
/* Disable attenuation */ |
icmd[idx] &= ~atten_flag; |
} else { |
if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) { |
/* Enable only constant portion of attenuation calculation */ |
icmd[idx] |= ( atten_flag | atten_const_flag ); |
} else { |
/* Enable full attenuation calculation */ |
icmd[idx] &= ~atten_const_flag; |
icmd[idx] |= atten_flag; |
} |
} |
R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl ); |
break; |
} |
default: |
break; |
} |
} |
static void r200UpdateLocalViewer ( struct gl_context *ctx ) |
{ |
/* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and |
GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that |
for these and only these modes). This means specular highlights may turn out |
wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER |
is not set, though it seems to happen rarely and the effect seems quite |
subtle. May need TCL fallback to fix it completely, though I'm not sure |
how you'd identify the cases where the specular highlights indeed will |
be wrong. Don't know if fglrx does something special in that case. |
*/ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
R200_STATECHANGE( rmesa, tcl ); |
if (ctx->Light.Model.LocalViewer || |
ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS) |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER; |
else |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER; |
} |
static void r200LightModelfv( struct gl_context *ctx, GLenum pname, |
const GLfloat *param ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
switch (pname) { |
case GL_LIGHT_MODEL_AMBIENT: |
update_global_ambient( ctx ); |
break; |
case GL_LIGHT_MODEL_LOCAL_VIEWER: |
r200UpdateLocalViewer( ctx ); |
break; |
case GL_LIGHT_MODEL_TWO_SIDE: |
R200_STATECHANGE( rmesa, tcl ); |
if (ctx->Light.Model.TwoSide) |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE; |
else |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE); |
if (rmesa->radeon.TclFallback) { |
r200ChooseRenderState( ctx ); |
r200ChooseVertexState( ctx ); |
} |
break; |
case GL_LIGHT_MODEL_COLOR_CONTROL: |
r200UpdateSpecular(ctx); |
break; |
default: |
break; |
} |
} |
static void r200ShadeModel( struct gl_context *ctx, GLenum mode ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; |
s &= ~(R200_DIFFUSE_SHADE_MASK | |
R200_ALPHA_SHADE_MASK | |
R200_SPECULAR_SHADE_MASK | |
R200_FOG_SHADE_MASK | |
R200_DISC_FOG_SHADE_MASK); |
switch ( mode ) { |
case GL_FLAT: |
s |= (R200_DIFFUSE_SHADE_FLAT | |
R200_ALPHA_SHADE_FLAT | |
R200_SPECULAR_SHADE_FLAT | |
R200_FOG_SHADE_FLAT | |
R200_DISC_FOG_SHADE_FLAT); |
break; |
case GL_SMOOTH: |
s |= (R200_DIFFUSE_SHADE_GOURAUD | |
R200_ALPHA_SHADE_GOURAUD | |
R200_SPECULAR_SHADE_GOURAUD | |
R200_FOG_SHADE_GOURAUD | |
R200_DISC_FOG_SHADE_GOURAUD); |
break; |
default: |
return; |
} |
if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { |
R200_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_SE_CNTL] = s; |
} |
} |
/* ============================================================= |
* User clip planes |
*/ |
static void r200ClipPlane( struct gl_context *ctx, GLenum plane, const GLfloat *eq ) |
{ |
GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0; |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; |
R200_STATECHANGE( rmesa, ucp[p] ); |
rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; |
rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; |
rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; |
rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; |
} |
static void r200UpdateClipPlanes( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint p; |
for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { |
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { |
GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; |
R200_STATECHANGE( rmesa, ucp[p] ); |
rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; |
rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; |
rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; |
rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; |
} |
} |
} |
/* ============================================================= |
* Stencil |
*/ |
static void |
r200StencilFuncSeparate( struct gl_context *ctx, GLenum face, GLenum func, |
GLint ref, GLuint mask ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint refmask = ((_mesa_get_stencil_ref(ctx, 0) << R200_STENCIL_REF_SHIFT) | |
((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT)); |
R200_STATECHANGE( rmesa, ctx ); |
R200_STATECHANGE( rmesa, msk ); |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK; |
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK| |
R200_STENCIL_VALUE_MASK); |
switch ( ctx->Stencil.Function[0] ) { |
case GL_NEVER: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER; |
break; |
case GL_LESS: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS; |
break; |
case GL_EQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL; |
break; |
case GL_LEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL; |
break; |
case GL_GREATER: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER; |
break; |
case GL_NOTEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL; |
break; |
case GL_GEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL; |
break; |
case GL_ALWAYS: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS; |
break; |
} |
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask; |
} |
static void |
r200StencilMaskSeparate( struct gl_context *ctx, GLenum face, GLuint mask ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
R200_STATECHANGE( rmesa, msk ); |
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK; |
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= |
((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT); |
} |
static void |
r200StencilOpSeparate( struct gl_context *ctx, GLenum face, GLenum fail, |
GLenum zfail, GLenum zpass ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
R200_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK | |
R200_STENCIL_ZFAIL_MASK | |
R200_STENCIL_ZPASS_MASK); |
switch ( ctx->Stencil.FailFunc[0] ) { |
case GL_KEEP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP; |
break; |
case GL_ZERO: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO; |
break; |
case GL_REPLACE: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE; |
break; |
case GL_INCR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC; |
break; |
case GL_DECR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC; |
break; |
case GL_INCR_WRAP_EXT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP; |
break; |
case GL_DECR_WRAP_EXT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP; |
break; |
case GL_INVERT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT; |
break; |
} |
switch ( ctx->Stencil.ZFailFunc[0] ) { |
case GL_KEEP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP; |
break; |
case GL_ZERO: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO; |
break; |
case GL_REPLACE: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE; |
break; |
case GL_INCR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC; |
break; |
case GL_DECR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC; |
break; |
case GL_INCR_WRAP_EXT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP; |
break; |
case GL_DECR_WRAP_EXT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP; |
break; |
case GL_INVERT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT; |
break; |
} |
switch ( ctx->Stencil.ZPassFunc[0] ) { |
case GL_KEEP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP; |
break; |
case GL_ZERO: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO; |
break; |
case GL_REPLACE: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE; |
break; |
case GL_INCR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC; |
break; |
case GL_DECR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC; |
break; |
case GL_INCR_WRAP_EXT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP; |
break; |
case GL_DECR_WRAP_EXT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP; |
break; |
case GL_INVERT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT; |
break; |
} |
} |
/* ============================================================= |
* Window position and viewport transformation |
*/ |
/** |
* Called when window size or position changes or viewport or depth range |
* state is changed. We update the hardware viewport state here. |
*/ |
void r200UpdateWindow( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
__DRIdrawable *dPriv = radeon_get_drawable(&rmesa->radeon); |
GLfloat xoffset = 0; |
GLfloat yoffset = dPriv ? (GLfloat) dPriv->h : 0; |
const GLfloat *v = ctx->Viewport._WindowMap.m; |
const GLboolean render_to_fbo = (ctx->DrawBuffer ? _mesa_is_user_fbo(ctx->DrawBuffer) : 0); |
const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF; |
GLfloat y_scale, y_bias; |
if (render_to_fbo) { |
y_scale = 1.0; |
y_bias = 0; |
} else { |
y_scale = -1.0; |
y_bias = yoffset; |
} |
float_ui32_type sx = { v[MAT_SX] }; |
float_ui32_type tx = { v[MAT_TX] + xoffset }; |
float_ui32_type sy = { v[MAT_SY] * y_scale }; |
float_ui32_type ty = { (v[MAT_TY] * y_scale) + y_bias }; |
float_ui32_type sz = { v[MAT_SZ] * depthScale }; |
float_ui32_type tz = { v[MAT_TZ] * depthScale }; |
R200_STATECHANGE( rmesa, vpt ); |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32; |
} |
void r200_vtbl_update_scissor( struct gl_context *ctx ) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
unsigned x1, y1, x2, y2; |
struct radeon_renderbuffer *rrb; |
R200_SET_STATE(r200, set, SET_RE_CNTL, R200_SCISSOR_ENABLE | r200->hw.set.cmd[SET_RE_CNTL]); |
if (r200->radeon.state.scissor.enabled) { |
x1 = r200->radeon.state.scissor.rect.x1; |
y1 = r200->radeon.state.scissor.rect.y1; |
x2 = r200->radeon.state.scissor.rect.x2; |
y2 = r200->radeon.state.scissor.rect.y2; |
} else { |
rrb = radeon_get_colorbuffer(&r200->radeon); |
x1 = 0; |
y1 = 0; |
x2 = rrb->base.Base.Width - 1; |
y2 = rrb->base.Base.Height - 1; |
} |
R200_SET_STATE(r200, sci, SCI_XY_1, x1 | (y1 << 16)); |
R200_SET_STATE(r200, sci, SCI_XY_2, x2 | (y2 << 16)); |
} |
static void r200Viewport( struct gl_context *ctx, GLint x, GLint y, |
GLsizei width, GLsizei height ) |
{ |
/* Don't pipeline viewport changes, conflict with window offset |
* setting below. Could apply deltas to rescue pipelined viewport |
* values, or keep the originals hanging around. |
*/ |
r200UpdateWindow( ctx ); |
radeon_viewport(ctx, x, y, width, height); |
} |
static void r200DepthRange( struct gl_context *ctx, GLclampd nearval, |
GLclampd farval ) |
{ |
r200UpdateWindow( ctx ); |
} |
void r200UpdateViewportOffset( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
__DRIdrawable *dPriv = radeon_get_drawable(&rmesa->radeon); |
GLfloat xoffset = (GLfloat)0; |
GLfloat yoffset = (GLfloat)dPriv->h; |
const GLfloat *v = ctx->Viewport._WindowMap.m; |
float_ui32_type tx; |
float_ui32_type ty; |
tx.f = v[MAT_TX] + xoffset; |
ty.f = (- v[MAT_TY]) + yoffset; |
if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 || |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 ) |
{ |
/* Note: this should also modify whatever data the context reset |
* code uses... |
*/ |
R200_STATECHANGE( rmesa, vpt ); |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; |
/* update polygon stipple x/y screen offset */ |
{ |
GLuint stx, sty; |
GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC]; |
m &= ~(R200_STIPPLE_X_OFFSET_MASK | |
R200_STIPPLE_Y_OFFSET_MASK); |
/* add magic offsets, then invert */ |
stx = 31 - ((-1) & R200_STIPPLE_COORD_MASK); |
sty = 31 - ((dPriv->h - 1) |
& R200_STIPPLE_COORD_MASK); |
m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) | |
(sty << R200_STIPPLE_Y_OFFSET_SHIFT)); |
if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) { |
R200_STATECHANGE( rmesa, msc ); |
rmesa->hw.msc.cmd[MSC_RE_MISC] = m; |
} |
} |
} |
radeonUpdateScissor( ctx ); |
} |
/* ============================================================= |
* Miscellaneous |
*/ |
static void r200RenderMode( struct gl_context *ctx, GLenum mode ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) ); |
} |
static GLuint r200_rop_tab[] = { |
R200_ROP_CLEAR, |
R200_ROP_AND, |
R200_ROP_AND_REVERSE, |
R200_ROP_COPY, |
R200_ROP_AND_INVERTED, |
R200_ROP_NOOP, |
R200_ROP_XOR, |
R200_ROP_OR, |
R200_ROP_NOR, |
R200_ROP_EQUIV, |
R200_ROP_INVERT, |
R200_ROP_OR_REVERSE, |
R200_ROP_COPY_INVERTED, |
R200_ROP_OR_INVERTED, |
R200_ROP_NAND, |
R200_ROP_SET, |
}; |
static void r200LogicOpCode( struct gl_context *ctx, GLenum opcode ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint rop = (GLuint)opcode - GL_CLEAR; |
ASSERT( rop < 16 ); |
R200_STATECHANGE( rmesa, msk ); |
rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop]; |
} |
/* ============================================================= |
* State enable/disable |
*/ |
static void r200Enable( struct gl_context *ctx, GLenum cap, GLboolean state ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint p, flag; |
if ( R200_DEBUG & RADEON_STATE ) |
fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr( cap ), |
state ? "GL_TRUE" : "GL_FALSE" ); |
switch ( cap ) { |
/* Fast track this one... |
*/ |
case GL_TEXTURE_1D: |
case GL_TEXTURE_2D: |
case GL_TEXTURE_3D: |
break; |
case GL_ALPHA_TEST: |
R200_STATECHANGE( rmesa, ctx ); |
if (state) { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE; |
} |
break; |
case GL_BLEND: |
case GL_COLOR_LOGIC_OP: |
r200_set_blend_state( ctx ); |
break; |
case GL_CLIP_PLANE0: |
case GL_CLIP_PLANE1: |
case GL_CLIP_PLANE2: |
case GL_CLIP_PLANE3: |
case GL_CLIP_PLANE4: |
case GL_CLIP_PLANE5: |
p = cap-GL_CLIP_PLANE0; |
R200_STATECHANGE( rmesa, tcl ); |
if (state) { |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p); |
r200ClipPlane( ctx, cap, NULL ); |
} |
else { |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p); |
} |
break; |
case GL_COLOR_MATERIAL: |
r200ColorMaterial( ctx, 0, 0 ); |
r200UpdateMaterial( ctx ); |
break; |
case GL_CULL_FACE: |
r200CullFace( ctx, 0 ); |
break; |
case GL_DEPTH_TEST: |
R200_STATECHANGE(rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE; |
} |
break; |
case GL_DITHER: |
R200_STATECHANGE(rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE; |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE; |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable; |
} |
break; |
case GL_FOG: |
R200_STATECHANGE(rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE; |
r200Fogfv( ctx, GL_FOG_MODE, NULL ); |
} else { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE; |
R200_STATECHANGE(rmesa, tcl); |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK; |
} |
r200UpdateSpecular( ctx ); /* for PK_SPEC */ |
if (rmesa->radeon.TclFallback) |
r200ChooseVertexState( ctx ); |
_mesa_allow_light_in_model( ctx, !state ); |
break; |
case GL_LIGHT0: |
case GL_LIGHT1: |
case GL_LIGHT2: |
case GL_LIGHT3: |
case GL_LIGHT4: |
case GL_LIGHT5: |
case GL_LIGHT6: |
case GL_LIGHT7: |
R200_STATECHANGE(rmesa, tcl); |
p = cap - GL_LIGHT0; |
if (p&1) |
flag = (R200_LIGHT_1_ENABLE | |
R200_LIGHT_1_ENABLE_AMBIENT | |
R200_LIGHT_1_ENABLE_SPECULAR); |
else |
flag = (R200_LIGHT_0_ENABLE | |
R200_LIGHT_0_ENABLE_AMBIENT | |
R200_LIGHT_0_ENABLE_SPECULAR); |
if (state) |
rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag; |
else |
rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag; |
/* |
*/ |
update_light_colors( ctx, p ); |
break; |
case GL_LIGHTING: |
r200UpdateSpecular(ctx); |
/* for reflection map fixup - might set recheck_texgen for all units too */ |
rmesa->radeon.NewGLState |= _NEW_TEXTURE; |
break; |
case GL_LINE_SMOOTH: |
R200_STATECHANGE( rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE; |
} else { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE; |
} |
break; |
case GL_LINE_STIPPLE: |
R200_STATECHANGE( rmesa, set ); |
if ( state ) { |
rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE; |
} else { |
rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE; |
} |
break; |
case GL_NORMALIZE: |
R200_STATECHANGE( rmesa, tcl ); |
if ( state ) { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS; |
} else { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS; |
} |
break; |
/* Pointsize registers on r200 only work for point sprites, and point smooth |
* doesn't work for point sprites (and isn't needed for 1.0 sized aa points). |
* In any case, setting pointmin == pointsizemax == 1.0 for aa points |
* is enough to satisfy conform. |
*/ |
case GL_POINT_SMOOTH: |
break; |
/* These don't really do anything, as we don't use the 3vtx |
* primitives yet. |
*/ |
#if 0 |
case GL_POLYGON_OFFSET_POINT: |
R200_STATECHANGE( rmesa, set ); |
if ( state ) { |
rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT; |
} else { |
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT; |
} |
break; |
case GL_POLYGON_OFFSET_LINE: |
R200_STATECHANGE( rmesa, set ); |
if ( state ) { |
rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE; |
} else { |
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE; |
} |
break; |
#endif |
case GL_POINT_SPRITE_ARB: |
R200_STATECHANGE( rmesa, spr ); |
if ( state ) { |
int i; |
for (i = 0; i < 6; i++) { |
rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= |
ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i); |
} |
} else { |
rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK; |
} |
break; |
case GL_POLYGON_OFFSET_FILL: |
R200_STATECHANGE( rmesa, set ); |
if ( state ) { |
rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI; |
} else { |
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI; |
} |
break; |
case GL_POLYGON_SMOOTH: |
R200_STATECHANGE( rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY; |
} else { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY; |
} |
break; |
case GL_POLYGON_STIPPLE: |
R200_STATECHANGE(rmesa, set ); |
if ( state ) { |
rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE; |
} else { |
rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE; |
} |
break; |
case GL_RESCALE_NORMAL_EXT: { |
GLboolean tmp = ctx->_NeedEyeCoords ? state : !state; |
R200_STATECHANGE( rmesa, tcl ); |
if ( tmp ) { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS; |
} else { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS; |
} |
break; |
} |
case GL_SCISSOR_TEST: |
radeon_firevertices(&rmesa->radeon); |
rmesa->radeon.state.scissor.enabled = state; |
radeonUpdateScissor( ctx ); |
break; |
case GL_STENCIL_TEST: |
{ |
GLboolean hw_stencil = GL_FALSE; |
if (ctx->DrawBuffer) { |
struct radeon_renderbuffer *rrbStencil |
= radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); |
hw_stencil = (rrbStencil && rrbStencil->bo); |
} |
if (hw_stencil) { |
R200_STATECHANGE( rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE; |
} |
} else { |
FALLBACK( rmesa, R200_FALLBACK_STENCIL, state ); |
} |
} |
break; |
case GL_TEXTURE_GEN_Q: |
case GL_TEXTURE_GEN_R: |
case GL_TEXTURE_GEN_S: |
case GL_TEXTURE_GEN_T: |
/* Picked up in r200UpdateTextureState. |
*/ |
rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE; |
break; |
case GL_COLOR_SUM_EXT: |
r200UpdateSpecular ( ctx ); |
break; |
case GL_VERTEX_PROGRAM_ARB: |
if (!state) { |
GLuint i; |
rmesa->curr_vp_hw = NULL; |
R200_STATECHANGE( rmesa, vap ); |
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE; |
/* mark all tcl atoms (tcl vector state got overwritten) dirty |
not sure about tcl scalar state - we need at least grd |
with vert progs too. |
ucp looks like it doesn't get overwritten (may even work |
with vp for pos-invariant progs if we're lucky) */ |
R200_STATECHANGE( rmesa, mtl[0] ); |
R200_STATECHANGE( rmesa, mtl[1] ); |
R200_STATECHANGE( rmesa, fog ); |
R200_STATECHANGE( rmesa, glt ); |
R200_STATECHANGE( rmesa, eye ); |
for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) { |
R200_STATECHANGE( rmesa, mat[i] ); |
} |
for (i = 0 ; i < 8; i++) { |
R200_STATECHANGE( rmesa, lit[i] ); |
} |
R200_STATECHANGE( rmesa, tcl ); |
for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) { |
if (ctx->Transform.ClipPlanesEnabled & (1 << i)) { |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i); |
} |
/* else { |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i); |
}*/ |
} |
/* ugly. Need to call everything which might change compsel. */ |
r200UpdateSpecular( ctx ); |
#if 0 |
/* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM), |
but without it doom3 locks up at always the same places. Why? */ |
/* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before |
accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */ |
r200UpdateTextureState( ctx ); |
/* if we call r200UpdateTextureState we need the code below because we are calling it with |
non-current derived enabled values which may revert the state atoms for frag progs even when |
they already got disabled... ugh |
Should really figure out why we need to call r200UpdateTextureState in the first place */ |
GLuint unit; |
for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) { |
R200_STATECHANGE( rmesa, pix[unit] ); |
R200_STATECHANGE( rmesa, tex[unit] ); |
rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= |
~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); |
rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT; |
/* need to guard this with drmSupportsFragmentShader? Should never get here if |
we don't announce ATI_fs, right? */ |
rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0; |
} |
R200_STATECHANGE( rmesa, cst ); |
R200_STATECHANGE( rmesa, tf ); |
rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0; |
#endif |
} |
else { |
/* picked up later */ |
} |
/* call functions which change hw state based on ARB_vp enabled or not. */ |
r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL ); |
r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL ); |
break; |
case GL_VERTEX_PROGRAM_POINT_SIZE_ARB: |
r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL ); |
break; |
case GL_FRAGMENT_SHADER_ATI: |
if ( !state ) { |
/* restore normal tex env colors and make sure tex env combine will get updated |
mark env atoms dirty (as their data was overwritten by afs even |
if they didn't change) and restore tex coord routing */ |
GLuint unit; |
for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) { |
R200_STATECHANGE( rmesa, pix[unit] ); |
R200_STATECHANGE( rmesa, tex[unit] ); |
rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= |
~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); |
rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT; |
rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0; |
} |
R200_STATECHANGE( rmesa, cst ); |
R200_STATECHANGE( rmesa, tf ); |
rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0; |
} |
else { |
/* need to mark this dirty as pix/tf atoms have overwritten the data |
even if the data in the atoms didn't change */ |
R200_STATECHANGE( rmesa, atf ); |
R200_STATECHANGE( rmesa, afs[1] ); |
/* everything else picked up in r200UpdateTextureState hopefully */ |
} |
break; |
default: |
return; |
} |
} |
void r200LightingSpaceChange( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLboolean tmp; |
if (R200_DEBUG & RADEON_STATE) |
fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords, |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]); |
if (ctx->_NeedEyeCoords) |
tmp = ctx->Transform.RescaleNormals; |
else |
tmp = !ctx->Transform.RescaleNormals; |
R200_STATECHANGE( rmesa, tcl ); |
if ( tmp ) { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS; |
} else { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS; |
} |
if (R200_DEBUG & RADEON_STATE) |
fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords, |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]); |
} |
/* ============================================================= |
* Deferred state management - matrices, textures, other? |
*/ |
static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx ) |
{ |
float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0; |
int i; |
for (i = 0 ; i < 4 ; i++) { |
*dest++ = src[i]; |
*dest++ = src[i+4]; |
*dest++ = src[i+8]; |
*dest++ = src[i+12]; |
} |
R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); |
} |
static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx ) |
{ |
float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0; |
memcpy(dest, src, 16*sizeof(float)); |
R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); |
} |
static void update_texturematrix( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT( ctx ); |
GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]; |
GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]; |
int unit; |
if (R200_DEBUG & RADEON_STATE) |
fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__, |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]); |
rmesa->TexMatEnabled = 0; |
rmesa->TexMatCompSel = 0; |
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) { |
if (!ctx->Texture.Unit[unit]._ReallyEnabled) |
continue; |
if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) { |
rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE| |
R200_TEXMAT_0_ENABLE) << unit; |
rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit; |
if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) { |
/* Need to preconcatenate any active texgen |
* obj/eyeplane matrices: |
*/ |
_math_matrix_mul_matrix( &rmesa->tmpmat, |
ctx->TextureMatrixStack[unit].Top, |
&rmesa->TexGenMatrix[unit] ); |
upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit ); |
} |
else { |
upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m, |
R200_MTX_TEX0+unit ); |
} |
} |
else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) { |
upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m, |
R200_MTX_TEX0+unit ); |
} |
} |
tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled); |
if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) { |
R200_STATECHANGE(rmesa, tcg); |
rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc; |
} |
compsel &= ~R200_OUTPUT_TEX_MASK; |
compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel; |
if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) { |
R200_STATECHANGE(rmesa, vtx); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel; |
} |
} |
static GLboolean r200ValidateBuffers(struct gl_context *ctx) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
struct radeon_renderbuffer *rrb; |
struct radeon_dma_bo *dma_bo; |
int i, ret; |
if (RADEON_DEBUG & RADEON_IOCTL) |
fprintf(stderr, "%s\n", __FUNCTION__); |
radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs); |
rrb = radeon_get_colorbuffer(&rmesa->radeon); |
/* color buffer */ |
if (rrb && rrb->bo) { |
radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo, |
0, RADEON_GEM_DOMAIN_VRAM); |
} |
/* depth buffer */ |
rrb = radeon_get_depthbuffer(&rmesa->radeon); |
/* color buffer */ |
if (rrb && rrb->bo) { |
radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo, |
0, RADEON_GEM_DOMAIN_VRAM); |
} |
for (i = 0; i < ctx->Const.FragmentProgram.MaxTextureImageUnits; ++i) { |
radeonTexObj *t; |
if (!ctx->Texture.Unit[i]._ReallyEnabled) |
continue; |
t = radeon_tex_obj(ctx->Texture.Unit[i]._Current); |
if (t->image_override && t->bo) |
radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo, |
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); |
else if (t->mt->bo) |
radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo, |
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); |
} |
dma_bo = first_elem(&rmesa->radeon.dma.reserved); |
{ |
ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, dma_bo->bo, RADEON_GEM_DOMAIN_GTT, 0); |
if (ret) |
return GL_FALSE; |
} |
return GL_TRUE; |
} |
GLboolean r200ValidateState( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint new_state = rmesa->radeon.NewGLState; |
if (new_state & _NEW_BUFFERS) { |
_mesa_update_framebuffer(ctx); |
/* this updates the DrawBuffer's Width/Height if it's a FBO */ |
_mesa_update_draw_buffer_bounds(ctx); |
R200_STATECHANGE(rmesa, ctx); |
} |
if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) { |
r200UpdateTextureState( ctx ); |
new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */ |
r200UpdateLocalViewer( ctx ); |
} |
/* we need to do a space check here */ |
if (!r200ValidateBuffers(ctx)) |
return GL_FALSE; |
/* FIXME: don't really need most of these when vertex progs are enabled */ |
/* Need an event driven matrix update? |
*/ |
if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) |
upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP ); |
/* Need these for lighting (shouldn't upload otherwise) |
*/ |
if (new_state & (_NEW_MODELVIEW)) { |
upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV ); |
upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV ); |
} |
/* Does this need to be triggered on eg. modelview for |
* texgen-derived objplane/eyeplane matrices? |
*/ |
if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) { |
update_texturematrix( ctx ); |
} |
if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) { |
update_light( ctx ); |
} |
/* emit all active clip planes if projection matrix changes. |
*/ |
if (new_state & (_NEW_PROJECTION)) { |
if (ctx->Transform.ClipPlanesEnabled) |
r200UpdateClipPlanes( ctx ); |
} |
if (new_state & (_NEW_PROGRAM| |
_NEW_PROGRAM_CONSTANTS | |
/* need to test for pretty much anything due to possible parameter bindings */ |
_NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM| |
_NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX| |
_NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) { |
if (ctx->VertexProgram._Enabled) { |
r200SetupVertexProg( ctx ); |
} |
else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0); |
} |
rmesa->radeon.NewGLState = 0; |
return GL_TRUE; |
} |
static void r200InvalidateState( struct gl_context *ctx, GLuint new_state ) |
{ |
_swrast_InvalidateState( ctx, new_state ); |
_swsetup_InvalidateState( ctx, new_state ); |
_vbo_InvalidateState( ctx, new_state ); |
_tnl_InvalidateState( ctx, new_state ); |
_ae_invalidate_state( ctx, new_state ); |
R200_CONTEXT(ctx)->radeon.NewGLState |= new_state; |
} |
/* A hack. The r200 can actually cope just fine with materials |
* between begin/ends, so fix this. |
* Should map to inputs just like the generic vertex arrays for vertex progs. |
* In theory there could still be too many and we'd still need a fallback. |
*/ |
static GLboolean check_material( struct gl_context *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLint i; |
for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; |
i < _TNL_ATTRIB_MAT_BACK_INDEXES; |
i++) |
if (tnl->vb.AttribPtr[i] && |
tnl->vb.AttribPtr[i]->stride) |
return GL_TRUE; |
return GL_FALSE; |
} |
static void r200WrapRunPipeline( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLboolean has_material; |
if (0) |
fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->radeon.NewGLState); |
/* Validate state: |
*/ |
if (rmesa->radeon.NewGLState) |
if (!r200ValidateState( ctx )) |
FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE); |
has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx ); |
if (has_material) { |
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE ); |
} |
/* Run the pipeline. |
*/ |
_tnl_run_pipeline( ctx ); |
if (has_material) { |
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE ); |
} |
} |
static void r200PolygonStipple( struct gl_context *ctx, const GLubyte *mask ) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
GLint i; |
radeon_firevertices(&r200->radeon); |
radeon_print(RADEON_STATE, RADEON_TRACE, |
"%s(%p) first 32 bits are %x.\n", |
__func__, |
ctx, |
*(uint32_t*)mask); |
R200_STATECHANGE(r200, stp); |
/* Must flip pattern upside down. |
*/ |
for ( i = 31 ; i >= 0; i--) { |
r200->hw.stp.cmd[3 + i] = ((GLuint *) mask)[i]; |
} |
} |
/* Initialize the driver's state functions. |
*/ |
void r200InitStateFuncs( radeonContextPtr radeon, struct dd_function_table *functions ) |
{ |
functions->UpdateState = r200InvalidateState; |
functions->LightingSpaceChange = r200LightingSpaceChange; |
functions->DrawBuffer = radeonDrawBuffer; |
functions->ReadBuffer = radeonReadBuffer; |
functions->CopyPixels = _mesa_meta_CopyPixels; |
functions->DrawPixels = _mesa_meta_DrawPixels; |
functions->ReadPixels = radeonReadPixels; |
functions->AlphaFunc = r200AlphaFunc; |
functions->BlendColor = r200BlendColor; |
functions->BlendEquationSeparate = r200BlendEquationSeparate; |
functions->BlendFuncSeparate = r200BlendFuncSeparate; |
functions->ClipPlane = r200ClipPlane; |
functions->ColorMask = r200ColorMask; |
functions->CullFace = r200CullFace; |
functions->DepthFunc = r200DepthFunc; |
functions->DepthMask = r200DepthMask; |
functions->DepthRange = r200DepthRange; |
functions->Enable = r200Enable; |
functions->Fogfv = r200Fogfv; |
functions->FrontFace = r200FrontFace; |
functions->Hint = NULL; |
functions->LightModelfv = r200LightModelfv; |
functions->Lightfv = r200Lightfv; |
functions->LineStipple = r200LineStipple; |
functions->LineWidth = r200LineWidth; |
functions->LogicOpcode = r200LogicOpCode; |
functions->PolygonMode = r200PolygonMode; |
functions->PolygonOffset = r200PolygonOffset; |
functions->PolygonStipple = r200PolygonStipple; |
functions->PointParameterfv = r200PointParameter; |
functions->PointSize = r200PointSize; |
functions->RenderMode = r200RenderMode; |
functions->Scissor = radeonScissor; |
functions->ShadeModel = r200ShadeModel; |
functions->StencilFuncSeparate = r200StencilFuncSeparate; |
functions->StencilMaskSeparate = r200StencilMaskSeparate; |
functions->StencilOpSeparate = r200StencilOpSeparate; |
functions->Viewport = r200Viewport; |
} |
void r200InitTnlFuncs( struct gl_context *ctx ) |
{ |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial; |
TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_state.h |
---|
0,0 → 1,63 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 __R200_STATE_H__ |
#define __R200_STATE_H__ |
#include "r200_context.h" |
extern void r200InitState( r200ContextPtr rmesa ); |
extern void r200InitStateFuncs( radeonContextPtr radeon, struct dd_function_table *functions ); |
extern void r200InitTnlFuncs( struct gl_context *ctx ); |
extern void r200UpdateMaterial( struct gl_context *ctx ); |
extern void r200UpdateViewportOffset( struct gl_context *ctx ); |
extern void r200UpdateWindow( struct gl_context *ctx ); |
extern void r200UpdateDrawBuffer(struct gl_context *ctx); |
extern GLboolean r200ValidateState( struct gl_context *ctx ); |
extern void r200_vtbl_update_scissor( struct gl_context *ctx ); |
extern void r200Fallback( struct gl_context *ctx, GLuint bit, GLboolean mode ); |
#define FALLBACK( rmesa, bit, mode ) do { \ |
if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n", \ |
__FUNCTION__, bit, mode ); \ |
r200Fallback( &rmesa->radeon.glCtx, bit, mode ); \ |
} while (0) |
extern void r200LightingSpaceChange( struct gl_context *ctx ); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_state_init.c |
---|
0,0 → 1,1298 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/imports.h" |
#include "main/enums.h" |
#include "main/colormac.h" |
#include "main/api_arrayelt.h" |
#include "swrast/swrast.h" |
#include "vbo/vbo.h" |
#include "tnl/t_pipeline.h" |
#include "swrast_setup/swrast_setup.h" |
#include "radeon_common.h" |
#include "radeon_mipmap_tree.h" |
#include "r200_context.h" |
#include "r200_ioctl.h" |
#include "r200_state.h" |
#include "radeon_queryobj.h" |
#include "xmlpool.h" |
/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in |
* 1.3 cmdbuffers allow all previous state to be updated as well as |
* the tcl scalar and vector areas. |
*/ |
static struct { |
int start; |
int len; |
const char *name; |
} packet[RADEON_MAX_STATE_PACKETS] = { |
{RADEON_PP_MISC, 7, "RADEON_PP_MISC"}, |
{RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"}, |
{RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"}, |
{RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"}, |
{RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"}, |
{RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"}, |
{RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"}, |
{RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"}, |
{RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"}, |
{RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"}, |
{RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"}, |
{RADEON_RE_MISC, 1, "RADEON_RE_MISC"}, |
{RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"}, |
{RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"}, |
{RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"}, |
{RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"}, |
{RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"}, |
{RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"}, |
{RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"}, |
{RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"}, |
{RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17, |
"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"}, |
{R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"}, |
{R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"}, |
{R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"}, |
{R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"}, |
{R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"}, |
{R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"}, |
{R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"}, |
{R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"}, |
{R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"}, |
{R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"}, |
{R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"}, |
{R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"}, |
{R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"}, |
{R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"}, |
{R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"}, |
{R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"}, |
{R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"}, |
{R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"}, |
{R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"}, |
{R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"}, |
{R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"}, |
{R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"}, |
{R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"}, |
{R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"}, |
{R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"}, |
{R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"}, |
{R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"}, |
{R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"}, |
{R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, |
"R200_SE_TCL_OUTPUT_VTX_COMP_SEL"}, |
{R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"}, |
{R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"}, |
{R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"}, |
{R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"}, |
{R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"}, |
{R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"}, |
{R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"}, |
{R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"}, |
{R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"}, |
{R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"}, |
{R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, |
"R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"}, |
{R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */ |
{R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */ |
{R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"}, |
{R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"}, |
{R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"}, |
{R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"}, |
{R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"}, |
{R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"}, |
{R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"}, |
{R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"}, |
{R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"}, |
{R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"}, |
{RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"}, |
{RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"}, |
{RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"}, |
{R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"}, |
{R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"}, |
{RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"}, |
{RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"}, |
{RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"}, |
{RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"}, |
{RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"}, |
{RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"}, |
{R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"}, |
{R200_PP_TXCBLEND_8, 32, "R200_PP_AFS_0"}, /* 85 */ |
{R200_PP_TXCBLEND_0, 32, "R200_PP_AFS_1"}, |
{R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"}, |
{R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"}, |
{R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"}, |
{R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"}, |
{R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"}, |
{R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"}, |
{R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"}, |
{R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"}, |
}; |
/* ============================================================= |
* State initialization |
*/ |
static int cmdpkt( r200ContextPtr rmesa, int id ) |
{ |
return CP_PACKET0(packet[id].start, packet[id].len - 1); |
} |
static int cmdvec( int offset, int stride, int count ) |
{ |
drm_radeon_cmd_header_t h; |
h.i = 0; |
h.vectors.cmd_type = RADEON_CMD_VECTORS; |
h.vectors.offset = offset; |
h.vectors.stride = stride; |
h.vectors.count = count; |
return h.i; |
} |
/* warning: the count here is divided by 4 compared to other cmds |
(so it doesn't exceed the char size)! */ |
static int cmdveclinear( int offset, int count ) |
{ |
drm_radeon_cmd_header_t h; |
h.i = 0; |
h.veclinear.cmd_type = RADEON_CMD_VECLINEAR; |
h.veclinear.addr_lo = offset & 0xff; |
h.veclinear.addr_hi = (offset & 0xff00) >> 8; |
h.veclinear.count = count; |
return h.i; |
} |
static int cmdscl( int offset, int stride, int count ) |
{ |
drm_radeon_cmd_header_t h; |
h.i = 0; |
h.scalars.cmd_type = RADEON_CMD_SCALARS; |
h.scalars.offset = offset; |
h.scalars.stride = stride; |
h.scalars.count = count; |
return h.i; |
} |
static int cmdscl2( int offset, int stride, int count ) |
{ |
drm_radeon_cmd_header_t h; |
h.i = 0; |
h.scalars.cmd_type = RADEON_CMD_SCALARS2; |
h.scalars.offset = offset - 0x100; |
h.scalars.stride = stride; |
h.scalars.count = count; |
return h.i; |
} |
/** |
* Check functions are used to check if state is active. |
* If it is active check function returns maximum emit size. |
*/ |
#define CHECK( NM, FLAG, ADD ) \ |
static int check_##NM( struct gl_context *ctx, struct radeon_state_atom *atom) \ |
{ \ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); \ |
(void) rmesa; \ |
return (FLAG) ? atom->cmd_size + (ADD) : 0; \ |
} |
#define TCL_CHECK( NM, FLAG, ADD ) \ |
static int check_##NM( struct gl_context *ctx, struct radeon_state_atom *atom) \ |
{ \ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); \ |
return (!rmesa->radeon.TclFallback && !ctx->VertexProgram._Enabled && (FLAG)) ? atom->cmd_size + (ADD) : 0; \ |
} |
#define TCL_OR_VP_CHECK( NM, FLAG, ADD ) \ |
static int check_##NM( struct gl_context *ctx, struct radeon_state_atom *atom ) \ |
{ \ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); \ |
return (!rmesa->radeon.TclFallback && (FLAG)) ? atom->cmd_size + (ADD) : 0; \ |
} |
#define VP_CHECK( NM, FLAG, ADD ) \ |
static int check_##NM( struct gl_context *ctx, struct radeon_state_atom *atom ) \ |
{ \ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); \ |
(void) atom; \ |
return (!rmesa->radeon.TclFallback && ctx->VertexProgram._Enabled && (FLAG)) ? atom->cmd_size + (ADD) : 0; \ |
} |
CHECK( always, GL_TRUE, 0 ) |
CHECK( always_add4, GL_TRUE, 4 ) |
CHECK( never, GL_FALSE, 0 ) |
CHECK( tex_any, ctx->Texture._EnabledUnits, 0 ) |
CHECK( tf, (ctx->Texture._EnabledUnits && !ctx->ATIFragmentShader._Enabled), 0 ); |
CHECK( pix_zero, !ctx->ATIFragmentShader._Enabled, 0 ) |
CHECK( texenv, (rmesa->state.envneeded & (1 << (atom->idx)) && !ctx->ATIFragmentShader._Enabled), 0 ) |
CHECK( afs_pass1, (ctx->ATIFragmentShader._Enabled && (ctx->ATIFragmentShader.Current->NumPasses > 1)), 0 ) |
CHECK( afs, ctx->ATIFragmentShader._Enabled, 0 ) |
CHECK( tex_cube, rmesa->state.texture.unit[atom->idx].unitneeded & TEXTURE_CUBE_BIT, 3 + 3*5 - CUBE_STATE_SIZE ) |
CHECK( tex_cube_cs, rmesa->state.texture.unit[atom->idx].unitneeded & TEXTURE_CUBE_BIT, 2 + 4*5 - CUBE_STATE_SIZE ) |
TCL_CHECK( tcl_fog_add4, ctx->Fog.Enabled, 4 ) |
TCL_CHECK( tcl, GL_TRUE, 0 ) |
TCL_CHECK( tcl_add8, GL_TRUE, 8 ) |
TCL_CHECK( tcl_add4, GL_TRUE, 4 ) |
TCL_CHECK( tcl_tex_add4, rmesa->state.texture.unit[atom->idx].unitneeded, 4 ) |
TCL_CHECK( tcl_lighting_add4, ctx->Light.Enabled, 4 ) |
TCL_CHECK( tcl_lighting_add6, ctx->Light.Enabled, 6 ) |
TCL_CHECK( tcl_light_add6, ctx->Light.Enabled && ctx->Light.Light[atom->idx].Enabled, 6 ) |
TCL_OR_VP_CHECK( tcl_ucp_add4, (ctx->Transform.ClipPlanesEnabled & (1 << (atom->idx))), 4 ) |
TCL_OR_VP_CHECK( tcl_or_vp, GL_TRUE, 0 ) |
TCL_OR_VP_CHECK( tcl_or_vp_add2, GL_TRUE, 2 ) |
VP_CHECK( tcl_vp, GL_TRUE, 0 ) |
VP_CHECK( tcl_vp_add4, GL_TRUE, 4 ) |
VP_CHECK( tcl_vp_size_add4, ctx->VertexProgram.Current->Base.NumNativeInstructions > 64, 4 ) |
VP_CHECK( tcl_vpp_size_add4, ctx->VertexProgram.Current->Base.NumNativeParameters > 96, 4 ) |
#define OUT_VEC(hdr, data) do { \ |
drm_radeon_cmd_header_t h; \ |
h.i = hdr; \ |
OUT_BATCH(CP_PACKET0(RADEON_SE_TCL_STATE_FLUSH, 0)); \ |
OUT_BATCH(0); \ |
OUT_BATCH(CP_PACKET0(R200_SE_TCL_VECTOR_INDX_REG, 0)); \ |
OUT_BATCH(h.vectors.offset | (h.vectors.stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); \ |
OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_VECTOR_DATA_REG, h.vectors.count - 1)); \ |
OUT_BATCH_TABLE((data), h.vectors.count); \ |
} while(0) |
#define OUT_VECLINEAR(hdr, data) do { \ |
drm_radeon_cmd_header_t h; \ |
uint32_t _start, _sz; \ |
h.i = hdr; \ |
_start = h.veclinear.addr_lo | (h.veclinear.addr_hi << 8); \ |
_sz = h.veclinear.count * 4; \ |
if (_sz) { \ |
BEGIN_BATCH_NO_AUTOSTATE(dwords); \ |
OUT_BATCH(CP_PACKET0(RADEON_SE_TCL_STATE_FLUSH, 0)); \ |
OUT_BATCH(0); \ |
OUT_BATCH(CP_PACKET0(R200_SE_TCL_VECTOR_INDX_REG, 0)); \ |
OUT_BATCH(_start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); \ |
OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_VECTOR_DATA_REG, _sz - 1)); \ |
OUT_BATCH_TABLE((data), _sz); \ |
END_BATCH(); \ |
} \ |
} while(0) |
#define OUT_SCL(hdr, data) do { \ |
drm_radeon_cmd_header_t h; \ |
h.i = hdr; \ |
OUT_BATCH(CP_PACKET0(R200_SE_TCL_SCALAR_INDX_REG, 0)); \ |
OUT_BATCH((h.scalars.offset) | (h.scalars.stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); \ |
OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_SCALAR_DATA_REG, h.scalars.count - 1)); \ |
OUT_BATCH_TABLE((data), h.scalars.count); \ |
} while(0) |
#define OUT_SCL2(hdr, data) do { \ |
drm_radeon_cmd_header_t h; \ |
h.i = hdr; \ |
OUT_BATCH(CP_PACKET0(R200_SE_TCL_SCALAR_INDX_REG, 0)); \ |
OUT_BATCH((h.scalars.offset + 0x100) | (h.scalars.stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); \ |
OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_SCALAR_DATA_REG, h.scalars.count - 1)); \ |
OUT_BATCH_TABLE((data), h.scalars.count); \ |
} while(0) |
static int check_rrb(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
struct radeon_renderbuffer *rrb; |
rrb = radeon_get_colorbuffer(&r200->radeon); |
if (!rrb || !rrb->bo) |
return 0; |
return atom->cmd_size; |
} |
static int check_polygon_stipple(struct gl_context *ctx, |
struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
if (r200->hw.set.cmd[SET_RE_CNTL] & R200_STIPPLE_ENABLE) |
return atom->cmd_size; |
return 0; |
} |
static void mtl_emit(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
BATCH_LOCALS(&r200->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_VEC(atom->cmd[MTL_CMD_0], (atom->cmd+1)); |
OUT_SCL2(atom->cmd[MTL_CMD_1], (atom->cmd + 18)); |
END_BATCH(); |
} |
static void lit_emit(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
BATCH_LOCALS(&r200->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_VEC(atom->cmd[LIT_CMD_0], atom->cmd+1); |
OUT_SCL(atom->cmd[LIT_CMD_1], atom->cmd+LIT_CMD_1+1); |
END_BATCH(); |
} |
static void ptp_emit(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
BATCH_LOCALS(&r200->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_VEC(atom->cmd[PTP_CMD_0], atom->cmd+1); |
OUT_VEC(atom->cmd[PTP_CMD_1], atom->cmd+PTP_CMD_1+1); |
END_BATCH(); |
} |
static void veclinear_emit(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
BATCH_LOCALS(&r200->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
OUT_VECLINEAR(atom->cmd[0], atom->cmd+1); |
} |
static void scl_emit(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
BATCH_LOCALS(&r200->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_SCL(atom->cmd[0], atom->cmd+1); |
END_BATCH(); |
} |
static void vec_emit(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
BATCH_LOCALS(&r200->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_VEC(atom->cmd[0], atom->cmd+1); |
END_BATCH(); |
} |
static int check_always_ctx( struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
struct radeon_renderbuffer *rrb, *drb; |
uint32_t dwords; |
rrb = radeon_get_colorbuffer(&r200->radeon); |
if (!rrb || !rrb->bo) { |
return 0; |
} |
drb = radeon_get_depthbuffer(&r200->radeon); |
dwords = 10; |
if (drb) |
dwords += 6; |
if (rrb) |
dwords += 8; |
if (atom->cmd_size == CTX_STATE_SIZE_NEWDRM) |
dwords += 4; |
return dwords; |
} |
static void ctx_emit_cs(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
BATCH_LOCALS(&r200->radeon); |
struct radeon_renderbuffer *rrb, *drb; |
uint32_t cbpitch = 0; |
uint32_t zbpitch = 0; |
uint32_t dwords = atom->check(ctx, atom); |
uint32_t depth_fmt; |
rrb = radeon_get_colorbuffer(&r200->radeon); |
if (!rrb || !rrb->bo) { |
return; |
} |
atom->cmd[CTX_RB3D_CNTL] &= ~(0xf << 10); |
if (rrb->cpp == 4) |
atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB8888; |
else switch (rrb->base.Base.Format) { |
case MESA_FORMAT_RGB565: |
atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_RGB565; |
break; |
case MESA_FORMAT_ARGB4444: |
atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB4444; |
break; |
case MESA_FORMAT_ARGB1555: |
atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB1555; |
break; |
default: |
_mesa_problem(ctx, "Unexpected format in ctx_emit_cs"); |
} |
cbpitch = (rrb->pitch / rrb->cpp); |
if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE) |
cbpitch |= R200_COLOR_TILE_ENABLE; |
if (rrb->bo->flags & RADEON_BO_FLAGS_MICRO_TILE) |
cbpitch |= R200_COLOR_MICROTILE_ENABLE; |
drb = radeon_get_depthbuffer(&r200->radeon); |
if (drb) { |
zbpitch = (drb->pitch / drb->cpp); |
if (drb->cpp == 4) |
depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z; |
else |
depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z; |
atom->cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_DEPTH_FORMAT_MASK; |
atom->cmd[CTX_RB3D_ZSTENCILCNTL] |= depth_fmt; |
} |
/* output the first 7 bytes of context */ |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
/* In the CS case we need to split this up */ |
OUT_BATCH(CP_PACKET0(packet[0].start, 3)); |
OUT_BATCH_TABLE((atom->cmd + 1), 4); |
if (drb) { |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_DEPTHOFFSET, 0)); |
OUT_BATCH_RELOC(0, drb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_DEPTHPITCH, 0)); |
OUT_BATCH(zbpitch); |
} |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZSTENCILCNTL, 0)); |
OUT_BATCH(atom->cmd[CTX_RB3D_ZSTENCILCNTL]); |
OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 1)); |
OUT_BATCH(atom->cmd[CTX_PP_CNTL]); |
OUT_BATCH(atom->cmd[CTX_RB3D_CNTL]); |
if (rrb) { |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_COLOROFFSET, 0)); |
OUT_BATCH_RELOC(rrb->draw_offset, rrb->bo, rrb->draw_offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0)); |
OUT_BATCH_RELOC(cbpitch, rrb->bo, cbpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0); |
} |
if (atom->cmd_size == CTX_STATE_SIZE_NEWDRM) { |
OUT_BATCH_TABLE((atom->cmd + 14), 4); |
} |
END_BATCH(); |
} |
static int get_tex_mm_size(struct gl_context* ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
uint32_t dwords = atom->cmd_size + 2; |
int hastexture = 1; |
int i = atom->idx; |
radeonTexObj *t = r200->state.texture.unit[i].texobj; |
if (!t) |
hastexture = 0; |
else { |
if (!t->mt && !t->bo) |
hastexture = 0; |
} |
if (!hastexture) |
dwords -= 4; |
return dwords; |
} |
static int check_tex_pair_mm(struct gl_context* ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
/** XOR is bit flip operation so use it for finding pair */ |
if (!(r200->state.texture.unit[atom->idx].unitneeded | r200->state.texture.unit[atom->idx ^ 1].unitneeded)) |
return 0; |
return get_tex_mm_size(ctx, atom); |
} |
static int check_tex_mm(struct gl_context* ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
if (!(r200->state.texture.unit[atom->idx].unitneeded)) |
return 0; |
return get_tex_mm_size(ctx, atom); |
} |
static void tex_emit_mm(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
BATCH_LOCALS(&r200->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
int i = atom->idx; |
radeonTexObj *t = r200->state.texture.unit[i].texobj; |
if (!r200->state.texture.unit[i].unitneeded && !(dwords <= atom->cmd_size)) |
dwords -= 4; |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_BATCH(CP_PACKET0(R200_PP_TXFILTER_0 + (32 * i), 7)); |
OUT_BATCH_TABLE((atom->cmd + 1), 8); |
if (dwords > atom->cmd_size) { |
OUT_BATCH(CP_PACKET0(R200_PP_TXOFFSET_0 + (24 * i), 0)); |
if (t->mt && !t->image_override) { |
OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0, |
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); |
} else { |
if (t->bo) |
OUT_BATCH_RELOC(t->tile_bits, t->bo, 0, |
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); |
} |
} |
END_BATCH(); |
} |
static void cube_emit_cs(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r200ContextPtr r200 = R200_CONTEXT(ctx); |
BATCH_LOCALS(&r200->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
int i = atom->idx, j; |
radeonTexObj *t = r200->state.texture.unit[i].texobj; |
radeon_mipmap_level *lvl; |
if (!(t && !t->image_override)) |
dwords = 2; |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_BATCH_TABLE(atom->cmd, 2); |
if (t && !t->image_override) { |
lvl = &t->mt->levels[0]; |
for (j = 1; j <= 5; j++) { |
OUT_BATCH(CP_PACKET0(R200_PP_CUBIC_OFFSET_F1_0 + (24*i) + (4 * (j-1)), 0)); |
OUT_BATCH_RELOC(lvl->faces[j].offset, t->mt->bo, lvl->faces[j].offset, |
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); |
} |
} |
END_BATCH(); |
} |
/* Initialize the context's hardware state. |
*/ |
void r200InitState( r200ContextPtr rmesa ) |
{ |
struct gl_context *ctx = &rmesa->radeon.glCtx; |
GLuint i; |
rmesa->radeon.Fallback = 0; |
rmesa->radeon.hw.max_state_size = 0; |
#define ALLOC_STATE( ATOM, CHK, SZ, NM, IDX ) \ |
do { \ |
rmesa->hw.ATOM.cmd_size = SZ; \ |
rmesa->hw.ATOM.cmd = (GLuint *) calloc(SZ, sizeof(int)); \ |
rmesa->hw.ATOM.lastcmd = (GLuint *) calloc(SZ, sizeof(int)); \ |
rmesa->hw.ATOM.name = NM; \ |
rmesa->hw.ATOM.idx = IDX; \ |
if (check_##CHK != check_never) { \ |
rmesa->hw.ATOM.check = check_##CHK; \ |
rmesa->radeon.hw.max_state_size += SZ * sizeof(int); \ |
} else { \ |
rmesa->hw.ATOM.check = NULL; \ |
} \ |
rmesa->hw.ATOM.dirty = GL_FALSE; \ |
} while (0) |
/* Allocate state buffers: |
*/ |
ALLOC_STATE( ctx, always_add4, CTX_STATE_SIZE_NEWDRM, "CTX/context", 0 ); |
rmesa->hw.ctx.emit = ctx_emit_cs; |
rmesa->hw.ctx.check = check_always_ctx; |
ALLOC_STATE( set, always, SET_STATE_SIZE, "SET/setup", 0 ); |
ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 ); |
ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 ); |
ALLOC_STATE( vpt, always, VPT_STATE_SIZE, "VPT/viewport", 0 ); |
ALLOC_STATE( vtx, always, VTX_STATE_SIZE, "VTX/vertex", 0 ); |
ALLOC_STATE( vap, always, VAP_STATE_SIZE, "VAP/vap", 0 ); |
ALLOC_STATE( vte, always, VTE_STATE_SIZE, "VTE/vte", 0 ); |
ALLOC_STATE( msc, always, MSC_STATE_SIZE, "MSC/misc", 0 ); |
ALLOC_STATE( cst, always, CST_STATE_SIZE, "CST/constant", 0 ); |
ALLOC_STATE( zbs, always, ZBS_STATE_SIZE, "ZBS/zbias", 0 ); |
ALLOC_STATE( tf, tf, TF_STATE_SIZE, "TF/tfactor", 0 ); |
{ |
int state_size = TEX_STATE_SIZE_NEWDRM; |
if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200) { |
/* make sure texture units 0/1 are emitted pair-wise for r200 t0 hang workaround */ |
ALLOC_STATE( tex[0], tex_pair_mm, state_size, "TEX/tex-0", 0 ); |
ALLOC_STATE( tex[1], tex_pair_mm, state_size, "TEX/tex-1", 1 ); |
ALLOC_STATE( tam, tex_any, TAM_STATE_SIZE, "TAM/tam", 0 ); |
} |
else { |
ALLOC_STATE( tex[0], tex_mm, state_size, "TEX/tex-0", 0 ); |
ALLOC_STATE( tex[1], tex_mm, state_size, "TEX/tex-1", 1 ); |
ALLOC_STATE( tam, never, TAM_STATE_SIZE, "TAM/tam", 0 ); |
} |
ALLOC_STATE( tex[2], tex_mm, state_size, "TEX/tex-2", 2 ); |
ALLOC_STATE( tex[3], tex_mm, state_size, "TEX/tex-3", 3 ); |
ALLOC_STATE( tex[4], tex_mm, state_size, "TEX/tex-4", 4 ); |
ALLOC_STATE( tex[5], tex_mm, state_size, "TEX/tex-5", 5 ); |
ALLOC_STATE( atf, afs, ATF_STATE_SIZE, "ATF/tfactor", 0 ); |
ALLOC_STATE( afs[0], afs_pass1, AFS_STATE_SIZE, "AFS/afsinst-0", 0 ); |
ALLOC_STATE( afs[1], afs, AFS_STATE_SIZE, "AFS/afsinst-1", 1 ); |
} |
ALLOC_STATE( stp, polygon_stipple, STP_STATE_SIZE, "STP/stp", 0 ); |
for (i = 0; i < 6; i++) |
rmesa->hw.tex[i].emit = tex_emit_mm; |
ALLOC_STATE( cube[0], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-0", 0 ); |
ALLOC_STATE( cube[1], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-1", 1 ); |
ALLOC_STATE( cube[2], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-2", 2 ); |
ALLOC_STATE( cube[3], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-3", 3 ); |
ALLOC_STATE( cube[4], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-4", 4 ); |
ALLOC_STATE( cube[5], tex_cube, CUBE_STATE_SIZE, "CUBE/tex-5", 5 ); |
for (i = 0; i < 6; i++) { |
rmesa->hw.cube[i].emit = cube_emit_cs; |
rmesa->hw.cube[i].check = check_tex_cube_cs; |
} |
ALLOC_STATE( pvs, tcl_vp, PVS_STATE_SIZE, "PVS/pvscntl", 0 ); |
ALLOC_STATE( vpi[0], tcl_vp_add4, VPI_STATE_SIZE, "VP/vertexprog-0", 0 ); |
ALLOC_STATE( vpi[1], tcl_vp_size_add4, VPI_STATE_SIZE, "VP/vertexprog-1", 1 ); |
ALLOC_STATE( vpp[0], tcl_vp_add4, VPP_STATE_SIZE, "VPP/vertexparam-0", 0 ); |
ALLOC_STATE( vpp[1], tcl_vpp_size_add4, VPP_STATE_SIZE, "VPP/vertexparam-1", 1 ); |
/* FIXME: this atom has two commands, we need only one (ucp_vert_blend) for vp */ |
ALLOC_STATE( tcl, tcl_or_vp, TCL_STATE_SIZE, "TCL/tcl", 0 ); |
ALLOC_STATE( msl, tcl, MSL_STATE_SIZE, "MSL/matrix-select", 0 ); |
ALLOC_STATE( tcg, tcl, TCG_STATE_SIZE, "TCG/texcoordgen", 0 ); |
ALLOC_STATE( mtl[0], tcl_lighting_add6, MTL_STATE_SIZE, "MTL0/material0", 0 ); |
ALLOC_STATE( mtl[1], tcl_lighting_add6, MTL_STATE_SIZE, "MTL1/material1", 1 ); |
ALLOC_STATE( grd, tcl_or_vp_add2, GRD_STATE_SIZE, "GRD/guard-band", 0 ); |
ALLOC_STATE( fog, tcl_fog_add4, FOG_STATE_SIZE, "FOG/fog", 0 ); |
ALLOC_STATE( glt, tcl_lighting_add4, GLT_STATE_SIZE, "GLT/light-global", 0 ); |
ALLOC_STATE( eye, tcl_lighting_add4, EYE_STATE_SIZE, "EYE/eye-vector", 0 ); |
ALLOC_STATE( mat[R200_MTX_MV], tcl_add4, MAT_STATE_SIZE, "MAT/modelview", 0 ); |
ALLOC_STATE( mat[R200_MTX_IMV], tcl_add4, MAT_STATE_SIZE, "MAT/it-modelview", 0 ); |
ALLOC_STATE( mat[R200_MTX_MVP], tcl_add4, MAT_STATE_SIZE, "MAT/modelproject", 0 ); |
ALLOC_STATE( mat[R200_MTX_TEX0], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat0", 0 ); |
ALLOC_STATE( mat[R200_MTX_TEX1], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat1", 1 ); |
ALLOC_STATE( mat[R200_MTX_TEX2], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat2", 2 ); |
ALLOC_STATE( mat[R200_MTX_TEX3], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat3", 3 ); |
ALLOC_STATE( mat[R200_MTX_TEX4], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat4", 4 ); |
ALLOC_STATE( mat[R200_MTX_TEX5], tcl_tex_add4, MAT_STATE_SIZE, "MAT/texmat5", 5 ); |
ALLOC_STATE( ucp[0], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-0", 0 ); |
ALLOC_STATE( ucp[1], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-1", 1 ); |
ALLOC_STATE( ucp[2], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-2", 2 ); |
ALLOC_STATE( ucp[3], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-3", 3 ); |
ALLOC_STATE( ucp[4], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-4", 4 ); |
ALLOC_STATE( ucp[5], tcl_ucp_add4, UCP_STATE_SIZE, "UCP/userclip-5", 5 ); |
ALLOC_STATE( lit[0], tcl_light_add6, LIT_STATE_SIZE, "LIT/light-0", 0 ); |
ALLOC_STATE( lit[1], tcl_light_add6, LIT_STATE_SIZE, "LIT/light-1", 1 ); |
ALLOC_STATE( lit[2], tcl_light_add6, LIT_STATE_SIZE, "LIT/light-2", 2 ); |
ALLOC_STATE( lit[3], tcl_light_add6, LIT_STATE_SIZE, "LIT/light-3", 3 ); |
ALLOC_STATE( lit[4], tcl_light_add6, LIT_STATE_SIZE, "LIT/light-4", 4 ); |
ALLOC_STATE( lit[5], tcl_light_add6, LIT_STATE_SIZE, "LIT/light-5", 5 ); |
ALLOC_STATE( lit[6], tcl_light_add6, LIT_STATE_SIZE, "LIT/light-6", 6 ); |
ALLOC_STATE( lit[7], tcl_light_add6, LIT_STATE_SIZE, "LIT/light-7", 7 ); |
ALLOC_STATE( sci, rrb, SCI_STATE_SIZE, "SCI/scissor", 0 ); |
ALLOC_STATE( pix[0], pix_zero, PIX_STATE_SIZE, "PIX/pixstage-0", 0 ); |
ALLOC_STATE( pix[1], texenv, PIX_STATE_SIZE, "PIX/pixstage-1", 1 ); |
ALLOC_STATE( pix[2], texenv, PIX_STATE_SIZE, "PIX/pixstage-2", 2 ); |
ALLOC_STATE( pix[3], texenv, PIX_STATE_SIZE, "PIX/pixstage-3", 3 ); |
ALLOC_STATE( pix[4], texenv, PIX_STATE_SIZE, "PIX/pixstage-4", 4 ); |
ALLOC_STATE( pix[5], texenv, PIX_STATE_SIZE, "PIX/pixstage-5", 5 ); |
ALLOC_STATE( prf, always, PRF_STATE_SIZE, "PRF/performance-tri", 0 ); |
ALLOC_STATE( spr, always, SPR_STATE_SIZE, "SPR/pointsprite", 0 ); |
ALLOC_STATE( ptp, tcl_add8, PTP_STATE_SIZE, "PTP/pointparams", 0 ); |
r200SetUpAtomList( rmesa ); |
/* Fill in the packet headers: |
*/ |
rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_MISC); |
rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CNTL); |
rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(rmesa, RADEON_EMIT_RB3D_COLORPITCH); |
rmesa->hw.ctx.cmd[CTX_CMD_3] = cmdpkt(rmesa, R200_EMIT_RB3D_BLENDCOLOR); |
rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RE_LINE_PATTERN); |
rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_SE_LINE_WIDTH); |
rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RB3D_STENCILREFMASK); |
rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_VPORT_XSCALE); |
rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_CNTL); |
rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RE_MISC); |
rmesa->hw.cst.cmd[CST_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CNTL_X); |
rmesa->hw.cst.cmd[CST_CMD_1] = cmdpkt(rmesa, R200_EMIT_RB3D_DEPTHXY_OFFSET); |
rmesa->hw.cst.cmd[CST_CMD_2] = cmdpkt(rmesa, R200_EMIT_RE_AUX_SCISSOR_CNTL); |
rmesa->hw.cst.cmd[CST_CMD_4] = cmdpkt(rmesa, R200_EMIT_SE_VAP_CNTL_STATUS); |
rmesa->hw.cst.cmd[CST_CMD_5] = cmdpkt(rmesa, R200_EMIT_RE_POINTSIZE); |
rmesa->hw.cst.cmd[CST_CMD_6] = cmdpkt(rmesa, R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0); |
rmesa->hw.tam.cmd[TAM_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TAM_DEBUG3); |
rmesa->hw.tf.cmd[TF_CMD_0] = cmdpkt(rmesa, R200_EMIT_TFACTOR_0); |
rmesa->hw.atf.cmd[ATF_CMD_0] = cmdpkt(rmesa, R200_EMIT_ATF_TFACTOR); |
rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_0); |
rmesa->hw.tex[0].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_0); |
rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_1); |
rmesa->hw.tex[1].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_1); |
rmesa->hw.tex[2].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_2); |
rmesa->hw.tex[2].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_2); |
rmesa->hw.tex[3].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_3); |
rmesa->hw.tex[3].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_3); |
rmesa->hw.tex[4].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_4); |
rmesa->hw.tex[4].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_4); |
rmesa->hw.tex[5].cmd[TEX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCTLALL_5); |
rmesa->hw.tex[5].cmd[TEX_CMD_1_NEWDRM] = cmdpkt(rmesa, R200_EMIT_PP_TXOFFSET_5); |
rmesa->hw.afs[0].cmd[AFS_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_AFS_0); |
rmesa->hw.afs[1].cmd[AFS_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_AFS_1); |
rmesa->hw.pvs.cmd[PVS_CMD_0] = cmdpkt(rmesa, R200_EMIT_VAP_PVS_CNTL); |
rmesa->hw.cube[0].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_0); |
rmesa->hw.cube[0].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_0); |
rmesa->hw.cube[1].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_1); |
rmesa->hw.cube[1].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_1); |
rmesa->hw.cube[2].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_2); |
rmesa->hw.cube[2].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_2); |
rmesa->hw.cube[3].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_3); |
rmesa->hw.cube[3].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_3); |
rmesa->hw.cube[4].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_4); |
rmesa->hw.cube[4].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_4); |
rmesa->hw.cube[5].cmd[CUBE_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_FACES_5); |
rmesa->hw.cube[5].cmd[CUBE_CMD_1] = cmdpkt(rmesa, R200_EMIT_PP_CUBIC_OFFSETS_5); |
rmesa->hw.pix[0].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_0); |
rmesa->hw.pix[1].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_1); |
rmesa->hw.pix[2].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_2); |
rmesa->hw.pix[3].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_3); |
rmesa->hw.pix[4].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_4); |
rmesa->hw.pix[5].cmd[PIX_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TXCBLEND_5); |
rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_ZBIAS_FACTOR); |
rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(rmesa, R200_EMIT_TCL_LIGHT_MODEL_CTL_0); |
rmesa->hw.tcl.cmd[TCL_CMD_1] = cmdpkt(rmesa, R200_EMIT_TCL_UCP_VERT_BLEND_CTL); |
rmesa->hw.tcg.cmd[TCG_CMD_0] = cmdpkt(rmesa, R200_EMIT_TEX_PROC_CTL_2); |
rmesa->hw.msl.cmd[MSL_CMD_0] = cmdpkt(rmesa, R200_EMIT_MATRIX_SELECT_0); |
rmesa->hw.vap.cmd[VAP_CMD_0] = cmdpkt(rmesa, R200_EMIT_VAP_CTL); |
rmesa->hw.vtx.cmd[VTX_CMD_0] = cmdpkt(rmesa, R200_EMIT_VTX_FMT_0); |
rmesa->hw.vtx.cmd[VTX_CMD_1] = cmdpkt(rmesa, R200_EMIT_OUTPUT_VTX_COMP_SEL); |
rmesa->hw.vtx.cmd[VTX_CMD_2] = cmdpkt(rmesa, R200_EMIT_SE_VTX_STATE_CNTL); |
rmesa->hw.vte.cmd[VTE_CMD_0] = cmdpkt(rmesa, R200_EMIT_VTE_CNTL); |
rmesa->hw.prf.cmd[PRF_CMD_0] = cmdpkt(rmesa, R200_EMIT_PP_TRI_PERF_CNTL); |
rmesa->hw.spr.cmd[SPR_CMD_0] = cmdpkt(rmesa, R200_EMIT_TCL_POINT_SPRITE_CNTL); |
rmesa->hw.sci.cmd[SCI_CMD_1] = CP_PACKET0(R200_RE_TOP_LEFT, 0); |
rmesa->hw.sci.cmd[SCI_CMD_2] = CP_PACKET0(R200_RE_WIDTH_HEIGHT, 0); |
rmesa->hw.stp.cmd[STP_CMD_0] = CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0); |
rmesa->hw.stp.cmd[STP_DATA_0] = 0; |
rmesa->hw.stp.cmd[STP_CMD_1] = CP_PACKET0_ONE(RADEON_RE_STIPPLE_DATA, 31); |
rmesa->hw.mtl[0].emit = mtl_emit; |
rmesa->hw.mtl[1].emit = mtl_emit; |
rmesa->hw.vpi[0].emit = veclinear_emit; |
rmesa->hw.vpi[1].emit = veclinear_emit; |
rmesa->hw.vpp[0].emit = veclinear_emit; |
rmesa->hw.vpp[1].emit = veclinear_emit; |
rmesa->hw.grd.emit = scl_emit; |
rmesa->hw.fog.emit = vec_emit; |
rmesa->hw.glt.emit = vec_emit; |
rmesa->hw.eye.emit = vec_emit; |
for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) |
rmesa->hw.mat[i].emit = vec_emit; |
for (i = 0; i < 8; i++) |
rmesa->hw.lit[i].emit = lit_emit; |
for (i = 0; i < 6; i++) |
rmesa->hw.ucp[i].emit = vec_emit; |
rmesa->hw.ptp.emit = ptp_emit; |
rmesa->hw.mtl[0].cmd[MTL_CMD_0] = |
cmdvec( R200_VS_MAT_0_EMISS, 1, 16 ); |
rmesa->hw.mtl[0].cmd[MTL_CMD_1] = |
cmdscl2( R200_SS_MAT_0_SHININESS, 1, 1 ); |
rmesa->hw.mtl[1].cmd[MTL_CMD_0] = |
cmdvec( R200_VS_MAT_1_EMISS, 1, 16 ); |
rmesa->hw.mtl[1].cmd[MTL_CMD_1] = |
cmdscl2( R200_SS_MAT_1_SHININESS, 1, 1 ); |
rmesa->hw.vpi[0].cmd[VPI_CMD_0] = |
cmdveclinear( R200_PVS_PROG0, 64 ); |
rmesa->hw.vpi[1].cmd[VPI_CMD_0] = |
cmdveclinear( R200_PVS_PROG1, 64 ); |
rmesa->hw.vpp[0].cmd[VPP_CMD_0] = |
cmdveclinear( R200_PVS_PARAM0, 96 ); |
rmesa->hw.vpp[1].cmd[VPP_CMD_0] = |
cmdveclinear( R200_PVS_PARAM1, 96 ); |
rmesa->hw.grd.cmd[GRD_CMD_0] = |
cmdscl( R200_SS_VERT_GUARD_CLIP_ADJ_ADDR, 1, 4 ); |
rmesa->hw.fog.cmd[FOG_CMD_0] = |
cmdvec( R200_VS_FOG_PARAM_ADDR, 1, 4 ); |
rmesa->hw.glt.cmd[GLT_CMD_0] = |
cmdvec( R200_VS_GLOBAL_AMBIENT_ADDR, 1, 4 ); |
rmesa->hw.eye.cmd[EYE_CMD_0] = |
cmdvec( R200_VS_EYE_VECTOR_ADDR, 1, 4 ); |
rmesa->hw.mat[R200_MTX_MV].cmd[MAT_CMD_0] = |
cmdvec( R200_VS_MATRIX_0_MV, 1, 16); |
rmesa->hw.mat[R200_MTX_IMV].cmd[MAT_CMD_0] = |
cmdvec( R200_VS_MATRIX_1_INV_MV, 1, 16); |
rmesa->hw.mat[R200_MTX_MVP].cmd[MAT_CMD_0] = |
cmdvec( R200_VS_MATRIX_2_MVP, 1, 16); |
rmesa->hw.mat[R200_MTX_TEX0].cmd[MAT_CMD_0] = |
cmdvec( R200_VS_MATRIX_3_TEX0, 1, 16); |
rmesa->hw.mat[R200_MTX_TEX1].cmd[MAT_CMD_0] = |
cmdvec( R200_VS_MATRIX_4_TEX1, 1, 16); |
rmesa->hw.mat[R200_MTX_TEX2].cmd[MAT_CMD_0] = |
cmdvec( R200_VS_MATRIX_5_TEX2, 1, 16); |
rmesa->hw.mat[R200_MTX_TEX3].cmd[MAT_CMD_0] = |
cmdvec( R200_VS_MATRIX_6_TEX3, 1, 16); |
rmesa->hw.mat[R200_MTX_TEX4].cmd[MAT_CMD_0] = |
cmdvec( R200_VS_MATRIX_7_TEX4, 1, 16); |
rmesa->hw.mat[R200_MTX_TEX5].cmd[MAT_CMD_0] = |
cmdvec( R200_VS_MATRIX_8_TEX5, 1, 16); |
for (i = 0 ; i < 8; i++) { |
rmesa->hw.lit[i].cmd[LIT_CMD_0] = |
cmdvec( R200_VS_LIGHT_AMBIENT_ADDR + i, 8, 24 ); |
rmesa->hw.lit[i].cmd[LIT_CMD_1] = |
cmdscl( R200_SS_LIGHT_DCD_ADDR + i, 8, 7 ); |
} |
for (i = 0 ; i < 6; i++) { |
rmesa->hw.ucp[i].cmd[UCP_CMD_0] = |
cmdvec( R200_VS_UCP_ADDR + i, 1, 4 ); |
} |
rmesa->hw.ptp.cmd[PTP_CMD_0] = |
cmdvec( R200_VS_PNT_SPRITE_VPORT_SCALE, 1, 4 ); |
rmesa->hw.ptp.cmd[PTP_CMD_1] = |
cmdvec( R200_VS_PNT_SPRITE_ATT_CONST, 1, 12 ); |
/* Initial Harware state: |
*/ |
rmesa->hw.ctx.cmd[CTX_PP_MISC] = (R200_ALPHA_TEST_PASS |
/* | R200_RIGHT_HAND_CUBE_OGL*/); |
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (R200_FOG_VERTEX | |
R200_FOG_USE_SPEC_ALPHA); |
rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000; |
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = (R200_COMB_FCN_ADD_CLAMP | |
(R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
(R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT)); |
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = 0x00000000; |
rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = (R200_COMB_FCN_ADD_CLAMP | |
(R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
(R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT)); |
rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = (R200_COMB_FCN_ADD_CLAMP | |
(R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
(R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT)); |
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] = |
rmesa->radeon.radeonScreen->depthOffset + rmesa->radeon.radeonScreen->fbLocation; |
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] = |
((rmesa->radeon.radeonScreen->depthPitch & |
R200_DEPTHPITCH_MASK) | |
R200_DEPTH_ENDIAN_NO_SWAP); |
if (rmesa->using_hyperz) |
rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] |= R200_DEPTH_HYPERZ; |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (R200_Z_TEST_LESS | |
R200_STENCIL_TEST_ALWAYS | |
R200_STENCIL_FAIL_KEEP | |
R200_STENCIL_ZPASS_KEEP | |
R200_STENCIL_ZFAIL_KEEP | |
R200_Z_WRITE_ENABLE); |
if (rmesa->using_hyperz) { |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_COMPRESSION_ENABLE | |
R200_Z_DECOMPRESSION_ENABLE; |
/* if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200) |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_HIERARCHY_ENABLE;*/ |
} |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] = (R200_ANTI_ALIAS_NONE |
| R200_TEX_BLEND_0_ENABLE); |
switch ( driQueryOptioni( &rmesa->radeon.optionCache, "dither_mode" ) ) { |
case DRI_CONF_DITHER_XERRORDIFFRESET: |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_INIT; |
break; |
case DRI_CONF_DITHER_ORDERED: |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_SCALE_DITHER_ENABLE; |
break; |
} |
if ( driQueryOptioni( &rmesa->radeon.optionCache, "round_mode" ) == |
DRI_CONF_ROUND_ROUND ) |
rmesa->radeon.state.color.roundEnable = R200_ROUND_ENABLE; |
else |
rmesa->radeon.state.color.roundEnable = 0; |
if ( driQueryOptioni (&rmesa->radeon.optionCache, "color_reduction" ) == |
DRI_CONF_COLOR_REDUCTION_DITHER ) |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE; |
else |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable; |
rmesa->hw.prf.cmd[PRF_PP_TRI_PERF] = R200_TRI_CUTOFF_MASK - R200_TRI_CUTOFF_MASK * |
driQueryOptionf (&rmesa->radeon.optionCache,"texture_blend_quality"); |
rmesa->hw.prf.cmd[PRF_PP_PERF_CNTL] = 0; |
rmesa->hw.set.cmd[SET_SE_CNTL] = (R200_FFACE_CULL_CCW | |
R200_BFACE_SOLID | |
R200_FFACE_SOLID | |
R200_FLAT_SHADE_VTX_LAST | |
R200_DIFFUSE_SHADE_GOURAUD | |
R200_ALPHA_SHADE_GOURAUD | |
R200_SPECULAR_SHADE_GOURAUD | |
R200_FOG_SHADE_GOURAUD | |
R200_DISC_FOG_SHADE_GOURAUD | |
R200_VTX_PIX_CENTER_OGL | |
R200_ROUND_MODE_TRUNC | |
R200_ROUND_PREC_8TH_PIX); |
rmesa->hw.set.cmd[SET_RE_CNTL] = (R200_PERSPECTIVE_ENABLE | |
R200_SCISSOR_ENABLE); |
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = ((1 << 16) | 0xffff); |
rmesa->hw.lin.cmd[LIN_RE_LINE_STATE] = |
((0 << R200_LINE_CURRENT_PTR_SHIFT) | |
(1 << R200_LINE_CURRENT_COUNT_SHIFT)); |
rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (1 << 4); |
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] = |
((0x00 << R200_STENCIL_REF_SHIFT) | |
(0xff << R200_STENCIL_MASK_SHIFT) | |
(0xff << R200_STENCIL_WRITEMASK_SHIFT)); |
rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = R200_ROP_COPY; |
rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = 0xffffffff; |
rmesa->hw.tam.cmd[TAM_DEBUG3] = 0; |
rmesa->hw.msc.cmd[MSC_RE_MISC] = |
((0 << R200_STIPPLE_X_OFFSET_SHIFT) | |
(0 << R200_STIPPLE_Y_OFFSET_SHIFT) | |
R200_STIPPLE_BIG_BIT_ORDER); |
rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0; |
rmesa->hw.cst.cmd[CST_RB3D_DEPTHXY_OFFSET] = 0; |
rmesa->hw.cst.cmd[CST_RE_AUX_SCISSOR_CNTL] = 0x0; |
rmesa->hw.cst.cmd[CST_SE_VAP_CNTL_STATUS] = |
#ifdef MESA_BIG_ENDIAN |
R200_VC_32BIT_SWAP; |
#else |
R200_VC_NO_SWAP; |
#endif |
if (!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) { |
/* Bypass TCL */ |
rmesa->hw.cst.cmd[CST_SE_VAP_CNTL_STATUS] |= (1<<8); |
} |
rmesa->hw.cst.cmd[CST_RE_POINTSIZE] = |
(((GLuint)(ctx->Const.MaxPointSize * 16.0)) << R200_MAXPOINTSIZE_SHIFT) | 0x10; |
rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_0] = |
(0x0 << R200_VERTEX_POSITION_ADDR__SHIFT); |
rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_1] = |
(0x02 << R200_VTX_COLOR_0_ADDR__SHIFT) | |
(0x03 << R200_VTX_COLOR_1_ADDR__SHIFT); |
rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_2] = |
(0x06 << R200_VTX_TEX_0_ADDR__SHIFT) | |
(0x07 << R200_VTX_TEX_1_ADDR__SHIFT) | |
(0x08 << R200_VTX_TEX_2_ADDR__SHIFT) | |
(0x09 << R200_VTX_TEX_3_ADDR__SHIFT); |
rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_3] = |
(0x0A << R200_VTX_TEX_4_ADDR__SHIFT) | |
(0x0B << R200_VTX_TEX_5_ADDR__SHIFT); |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = 0x00000000; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = 0x00000000; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = 0x00000000; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = 0x00000000; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = 0x00000000; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = 0x00000000; |
for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) { |
rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] = R200_BORDER_MODE_OGL; |
rmesa->hw.tex[i].cmd[TEX_PP_TXFORMAT] = |
((i << R200_TXFORMAT_ST_ROUTE_SHIFT) | /* <-- note i */ |
(2 << R200_TXFORMAT_WIDTH_SHIFT) | |
(2 << R200_TXFORMAT_HEIGHT_SHIFT)); |
rmesa->hw.tex[i].cmd[TEX_PP_BORDER_COLOR] = 0; |
rmesa->hw.tex[i].cmd[TEX_PP_TXFORMAT_X] = |
(/* R200_TEXCOORD_PROJ | */ |
R200_LOD_BIAS_CORRECTION); /* Small default bias */ |
rmesa->hw.tex[i].cmd[TEX_PP_TXOFFSET_NEWDRM] = |
rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
rmesa->hw.tex[i].cmd[TEX_PP_CUBIC_FACES] = 0; |
rmesa->hw.tex[i].cmd[TEX_PP_TXMULTI_CTL] = 0; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_FACES] = 0; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F1] = |
rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F2] = |
rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F3] = |
rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F4] = |
rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F5] = |
rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
rmesa->hw.pix[i].cmd[PIX_PP_TXCBLEND] = |
(R200_TXC_ARG_A_ZERO | |
R200_TXC_ARG_B_ZERO | |
R200_TXC_ARG_C_DIFFUSE_COLOR | |
R200_TXC_OP_MADD); |
rmesa->hw.pix[i].cmd[PIX_PP_TXCBLEND2] = |
((i << R200_TXC_TFACTOR_SEL_SHIFT) | |
R200_TXC_SCALE_1X | |
R200_TXC_CLAMP_0_1 | |
R200_TXC_OUTPUT_REG_R0); |
rmesa->hw.pix[i].cmd[PIX_PP_TXABLEND] = |
(R200_TXA_ARG_A_ZERO | |
R200_TXA_ARG_B_ZERO | |
R200_TXA_ARG_C_DIFFUSE_ALPHA | |
R200_TXA_OP_MADD); |
rmesa->hw.pix[i].cmd[PIX_PP_TXABLEND2] = |
((i << R200_TXA_TFACTOR_SEL_SHIFT) | |
R200_TXA_SCALE_1X | |
R200_TXA_CLAMP_0_1 | |
R200_TXA_OUTPUT_REG_R0); |
} |
rmesa->hw.tf.cmd[TF_TFACTOR_0] = 0; |
rmesa->hw.tf.cmd[TF_TFACTOR_1] = 0; |
rmesa->hw.tf.cmd[TF_TFACTOR_2] = 0; |
rmesa->hw.tf.cmd[TF_TFACTOR_3] = 0; |
rmesa->hw.tf.cmd[TF_TFACTOR_4] = 0; |
rmesa->hw.tf.cmd[TF_TFACTOR_5] = 0; |
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = |
(R200_VAP_TCL_ENABLE | |
(0x9 << R200_VAP_VF_MAX_VTX_NUM__SHIFT)); |
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = |
(R200_VPORT_X_SCALE_ENA | |
R200_VPORT_Y_SCALE_ENA | |
R200_VPORT_Z_SCALE_ENA | |
R200_VPORT_X_OFFSET_ENA | |
R200_VPORT_Y_OFFSET_ENA | |
R200_VPORT_Z_OFFSET_ENA | |
/* FIXME: Turn on for tex rect only */ |
R200_VTX_ST_DENORMALIZED | |
R200_VTX_W0_FMT); |
rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = 0; |
rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = 0; |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = |
((R200_VTX_Z0 | R200_VTX_W0 | |
(R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT))); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] = 0; |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = (R200_OUTPUT_XYZW); |
rmesa->hw.vtx.cmd[VTX_STATE_CNTL] = R200_VSC_UPDATE_USER_COLOR_0_ENABLE; |
/* Matrix selection */ |
rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_0] = |
(R200_MTX_MV << R200_MODELVIEW_0_SHIFT); |
rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_1] = |
(R200_MTX_IMV << R200_IT_MODELVIEW_0_SHIFT); |
rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_2] = |
(R200_MTX_MVP << R200_MODELPROJECT_0_SHIFT); |
rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_3] = |
((R200_MTX_TEX0 << R200_TEXMAT_0_SHIFT) | |
(R200_MTX_TEX1 << R200_TEXMAT_1_SHIFT) | |
(R200_MTX_TEX2 << R200_TEXMAT_2_SHIFT) | |
(R200_MTX_TEX3 << R200_TEXMAT_3_SHIFT)); |
rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_4] = |
((R200_MTX_TEX4 << R200_TEXMAT_4_SHIFT) | |
(R200_MTX_TEX5 << R200_TEXMAT_5_SHIFT)); |
/* General TCL state */ |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = |
(R200_SPECULAR_LIGHTS | |
R200_DIFFUSE_SPECULAR_COMBINE | |
R200_LOCAL_LIGHT_VEC_GL | |
R200_LM0_SOURCE_MATERIAL_0 << R200_FRONT_SHININESS_SOURCE_SHIFT | |
R200_LM0_SOURCE_MATERIAL_1 << R200_BACK_SHININESS_SOURCE_SHIFT); |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = |
((R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) | |
(R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT)); |
rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_0] = 0; /* filled in via callbacks */ |
rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_1] = 0; |
rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_2] = 0; |
rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_3] = 0; |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = |
(R200_UCP_IN_CLIP_SPACE | |
R200_CULL_FRONT_IS_CCW); |
/* Texgen/Texmat state */ |
rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] = 0x00ffffff; |
rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_3] = |
((0 << R200_TEXGEN_0_INPUT_TEX_SHIFT) | |
(1 << R200_TEXGEN_1_INPUT_TEX_SHIFT) | |
(2 << R200_TEXGEN_2_INPUT_TEX_SHIFT) | |
(3 << R200_TEXGEN_3_INPUT_TEX_SHIFT) | |
(4 << R200_TEXGEN_4_INPUT_TEX_SHIFT) | |
(5 << R200_TEXGEN_5_INPUT_TEX_SHIFT)); |
rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = 0; |
rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = |
((0 << R200_TEXGEN_0_INPUT_SHIFT) | |
(1 << R200_TEXGEN_1_INPUT_SHIFT) | |
(2 << R200_TEXGEN_2_INPUT_SHIFT) | |
(3 << R200_TEXGEN_3_INPUT_SHIFT) | |
(4 << R200_TEXGEN_4_INPUT_SHIFT) | |
(5 << R200_TEXGEN_5_INPUT_SHIFT)); |
rmesa->hw.tcg.cmd[TCG_TEX_CYL_WRAP_CTL] = 0; |
for (i = 0 ; i < 8; i++) { |
struct gl_light *l = &ctx->Light.Light[i]; |
GLenum p = GL_LIGHT0 + i; |
*(float *)&(rmesa->hw.lit[i].cmd[LIT_RANGE_CUTOFF]) = FLT_MAX; |
ctx->Driver.Lightfv( ctx, p, GL_AMBIENT, l->Ambient ); |
ctx->Driver.Lightfv( ctx, p, GL_DIFFUSE, l->Diffuse ); |
ctx->Driver.Lightfv( ctx, p, GL_SPECULAR, l->Specular ); |
ctx->Driver.Lightfv( ctx, p, GL_POSITION, NULL ); |
ctx->Driver.Lightfv( ctx, p, GL_SPOT_DIRECTION, NULL ); |
ctx->Driver.Lightfv( ctx, p, GL_SPOT_EXPONENT, &l->SpotExponent ); |
ctx->Driver.Lightfv( ctx, p, GL_SPOT_CUTOFF, &l->SpotCutoff ); |
ctx->Driver.Lightfv( ctx, p, GL_CONSTANT_ATTENUATION, |
&l->ConstantAttenuation ); |
ctx->Driver.Lightfv( ctx, p, GL_LINEAR_ATTENUATION, |
&l->LinearAttenuation ); |
ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION, |
&l->QuadraticAttenuation ); |
*(float *)&(rmesa->hw.lit[i].cmd[LIT_ATTEN_XXX]) = 0.0; |
} |
ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT, |
ctx->Light.Model.Ambient ); |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); |
for (i = 0 ; i < 6; i++) { |
ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, NULL ); |
} |
ctx->Driver.Fogfv( ctx, GL_FOG_MODE, NULL ); |
ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density ); |
ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start ); |
ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End ); |
ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color ); |
ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, NULL ); |
rmesa->hw.grd.cmd[GRD_VERT_GUARD_CLIP_ADJ] = IEEE_ONE; |
rmesa->hw.grd.cmd[GRD_VERT_GUARD_DISCARD_ADJ] = IEEE_ONE; |
rmesa->hw.grd.cmd[GRD_HORZ_GUARD_CLIP_ADJ] = IEEE_ONE; |
rmesa->hw.grd.cmd[GRD_HORZ_GUARD_DISCARD_ADJ] = IEEE_ONE; |
rmesa->hw.eye.cmd[EYE_X] = 0; |
rmesa->hw.eye.cmd[EYE_Y] = 0; |
rmesa->hw.eye.cmd[EYE_Z] = IEEE_ONE; |
rmesa->hw.eye.cmd[EYE_RESCALE_FACTOR] = IEEE_ONE; |
rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] = |
R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST; |
/* ptp_eye is presumably used to calculate the attenuation wrt a different |
location? In any case, since point attenuation triggers _needeyecoords, |
it is constant. Probably ignored as long as R200_PS_USE_MODEL_EYE_VEC |
isn't set */ |
rmesa->hw.ptp.cmd[PTP_EYE_X] = 0; |
rmesa->hw.ptp.cmd[PTP_EYE_Y] = 0; |
rmesa->hw.ptp.cmd[PTP_EYE_Z] = IEEE_ONE | 0x80000000; /* -1.0 */ |
rmesa->hw.ptp.cmd[PTP_EYE_3] = 0; |
/* no idea what the ptp_vport_scale values are good for, except the |
PTSIZE one - hopefully doesn't matter */ |
rmesa->hw.ptp.cmd[PTP_VPORT_SCALE_0] = IEEE_ONE; |
rmesa->hw.ptp.cmd[PTP_VPORT_SCALE_1] = IEEE_ONE; |
rmesa->hw.ptp.cmd[PTP_VPORT_SCALE_PTSIZE] = IEEE_ONE; |
rmesa->hw.ptp.cmd[PTP_VPORT_SCALE_3] = IEEE_ONE; |
rmesa->hw.ptp.cmd[PTP_ATT_CONST_QUAD] = 0; |
rmesa->hw.ptp.cmd[PTP_ATT_CONST_LIN] = 0; |
rmesa->hw.ptp.cmd[PTP_ATT_CONST_CON] = IEEE_ONE; |
rmesa->hw.ptp.cmd[PTP_ATT_CONST_3] = 0; |
rmesa->hw.ptp.cmd[PTP_CLAMP_MIN] = IEEE_ONE; |
rmesa->hw.ptp.cmd[PTP_CLAMP_MAX] = 0x44ffe000; /* 2047 */ |
rmesa->hw.ptp.cmd[PTP_CLAMP_2] = 0; |
rmesa->hw.ptp.cmd[PTP_CLAMP_3] = 0; |
r200LightingSpaceChange( ctx ); |
radeon_init_query_stateobj(&rmesa->radeon, R200_QUERYOBJ_CMDSIZE); |
rmesa->radeon.query.queryobj.cmd[R200_QUERYOBJ_CMD_0] = CP_PACKET0(RADEON_RB3D_ZPASS_DATA, 0); |
rmesa->radeon.query.queryobj.cmd[R200_QUERYOBJ_DATA_0] = 0; |
rmesa->radeon.hw.all_dirty = GL_TRUE; |
rcommonInitCmdBuf(&rmesa->radeon); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_swtcl.c |
---|
0,0 → 1,957 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/mtypes.h" |
#include "main/colormac.h" |
#include "main/enums.h" |
#include "main/image.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "main/simple_list.h" |
#include "swrast/s_context.h" |
#include "swrast/s_fog.h" |
#include "swrast_setup/swrast_setup.h" |
#include "tnl/tnl.h" |
#include "tnl/t_context.h" |
#include "tnl/t_pipeline.h" |
#include "r200_context.h" |
#include "r200_ioctl.h" |
#include "r200_state.h" |
#include "r200_swtcl.h" |
#include "r200_tcl.h" |
/*********************************************************************** |
* Initialization |
***********************************************************************/ |
#define EMIT_ATTR( ATTR, STYLE, F0 ) \ |
do { \ |
rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = (ATTR); \ |
rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = (STYLE); \ |
rmesa->radeon.swtcl.vertex_attr_count++; \ |
fmt_0 |= F0; \ |
} while (0) |
#define EMIT_PAD( N ) \ |
do { \ |
rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = 0; \ |
rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = EMIT_PAD; \ |
rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].offset = (N); \ |
rmesa->radeon.swtcl.vertex_attr_count++; \ |
} while (0) |
static void r200SetVertexFormat( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT( ctx ); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLbitfield64 index_bitset = tnl->render_inputs_bitset; |
int fmt_0 = 0; |
int fmt_1 = 0; |
int offset = 0; |
/* Important: |
*/ |
if ( VB->NdcPtr != NULL ) { |
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; |
} |
else { |
VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr; |
} |
assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL ); |
rmesa->radeon.swtcl.vertex_attr_count = 0; |
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to |
* build up a hardware vertex. |
*/ |
if ( !rmesa->swtcl.needproj || |
(index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) ) { |
/* need w coord for projected textures */ |
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 ); |
offset = 4; |
} |
else { |
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F, R200_VTX_XY | R200_VTX_Z0 ); |
offset = 3; |
} |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE)) { |
EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, R200_VTX_POINT_SIZE ); |
offset += 1; |
} |
rmesa->swtcl.coloroffset = offset; |
#if MESA_LITTLE_ENDIAN |
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) ); |
#else |
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ABGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) ); |
#endif |
offset += 1; |
rmesa->swtcl.specoffset = 0; |
if (index_bitset & |
(BITFIELD64_BIT(_TNL_ATTRIB_COLOR1) | BITFIELD64_BIT(_TNL_ATTRIB_FOG))) { |
#if MESA_LITTLE_ENDIAN |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) { |
rmesa->swtcl.specoffset = offset; |
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); |
} |
else { |
EMIT_PAD( 3 ); |
} |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) { |
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); |
} |
else { |
EMIT_PAD( 1 ); |
} |
#else |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) { |
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); |
} |
else { |
EMIT_PAD( 1 ); |
} |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) { |
rmesa->swtcl.specoffset = offset; |
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); |
} |
else { |
EMIT_PAD( 3 ); |
} |
#endif |
} |
if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) { |
int i; |
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) { |
GLuint sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size; |
fmt_1 |= sz << (3 * i); |
EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_1F + sz - 1, 0 ); |
} |
} |
} |
if ( (rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK) |
!= R200_FOG_USE_SPEC_ALPHA ) { |
R200_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK; |
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_SPEC_ALPHA; |
} |
if (rmesa->radeon.tnl_index_bitset != index_bitset || |
(rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) || |
(rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) { |
R200_NEWPRIM(rmesa); |
R200_STATECHANGE( rmesa, vtx ); |
rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0; |
rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1; |
rmesa->radeon.swtcl.vertex_size = |
_tnl_install_attrs( ctx, |
rmesa->radeon.swtcl.vertex_attrs, |
rmesa->radeon.swtcl.vertex_attr_count, |
NULL, 0 ); |
rmesa->radeon.swtcl.vertex_size /= 4; |
rmesa->radeon.tnl_index_bitset = index_bitset; |
} |
} |
static void r200_predict_emit_size( r200ContextPtr rmesa ) |
{ |
if (RADEON_DEBUG & RADEON_VERTS) |
fprintf(stderr, "%s\n", __func__); |
const int vertex_array_size = 7; |
const int prim_size = 3; |
if (!rmesa->radeon.swtcl.emit_prediction) { |
const int state_size = radeonCountStateEmitSize(&rmesa->radeon); |
if (rcommonEnsureCmdBufSpace(&rmesa->radeon, |
state_size + |
vertex_array_size + prim_size, |
__FUNCTION__)) |
rmesa->radeon.swtcl.emit_prediction = radeonCountStateEmitSize(&rmesa->radeon); |
else |
rmesa->radeon.swtcl.emit_prediction = state_size; |
rmesa->radeon.swtcl.emit_prediction += vertex_array_size + prim_size |
+ rmesa->radeon.cmdbuf.cs->cdw; |
} |
} |
static void r200RenderStart( struct gl_context *ctx ) |
{ |
r200SetVertexFormat( ctx ); |
if (RADEON_DEBUG & RADEON_VERTS) |
fprintf(stderr, "%s\n", __func__); |
} |
/** |
* Set vertex state for SW TCL. The primary purpose of this function is to |
* determine in advance whether or not the hardware can / should do the |
* projection divide or Mesa should do it. |
*/ |
void r200ChooseVertexState( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT( ctx ); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint vte; |
GLuint vap; |
GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL); |
GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide; |
/* We must ensure that we don't do _tnl_need_projected_coords while in a |
* rasterization fallback. As this function will be called again when we |
* leave a rasterization fallback, we can just skip it for now. |
*/ |
if (rmesa->radeon.Fallback != 0) |
return; |
vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]; |
vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]; |
/* HW perspective divide is a win, but tiny vertex formats are a |
* bigger one. |
*/ |
if ((0 == (tnl->render_inputs_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX))) |
|| twosided |
|| unfilled) { |
rmesa->swtcl.needproj = GL_TRUE; |
vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT; |
vte &= ~R200_VTX_W0_FMT; |
if (tnl->render_inputs_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) { |
vap &= ~R200_VAP_FORCE_W_TO_ONE; |
} |
else { |
vap |= R200_VAP_FORCE_W_TO_ONE; |
} |
} |
else { |
rmesa->swtcl.needproj = GL_FALSE; |
vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT); |
vte |= R200_VTX_W0_FMT; |
vap &= ~R200_VAP_FORCE_W_TO_ONE; |
} |
_tnl_need_projected_coords( ctx, rmesa->swtcl.needproj ); |
if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) { |
R200_STATECHANGE( rmesa, vte ); |
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte; |
} |
if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) { |
R200_STATECHANGE( rmesa, vap ); |
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap; |
} |
} |
void r200_swtcl_flush(struct gl_context *ctx, uint32_t current_offset) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
if (RADEON_DEBUG & RADEON_VERTS) |
fprintf(stderr, "%s\n", __func__); |
radeonEmitState(&rmesa->radeon); |
r200EmitVertexAOS( rmesa, |
rmesa->radeon.swtcl.vertex_size, |
rmesa->radeon.swtcl.bo, |
current_offset); |
r200EmitVbufPrim( rmesa, |
rmesa->radeon.swtcl.hw_primitive, |
rmesa->radeon.swtcl.numverts); |
if ( rmesa->radeon.swtcl.emit_prediction < rmesa->radeon.cmdbuf.cs->cdw ) |
WARN_ONCE("Rendering was %d commands larger than predicted size." |
" We might overflow command buffer.\n", |
rmesa->radeon.cmdbuf.cs->cdw - rmesa->radeon.swtcl.emit_prediction ); |
rmesa->radeon.swtcl.emit_prediction = 0; |
} |
/**************************************************************************/ |
static INLINE GLuint reduced_hw_prim( struct gl_context *ctx, GLuint prim) |
{ |
switch (prim) { |
case GL_POINTS: |
return ((!ctx->Point.SmoothFlag) ? |
R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS); |
case GL_LINES: |
/* fallthrough */ |
case GL_LINE_LOOP: |
/* fallthrough */ |
case GL_LINE_STRIP: |
return R200_VF_PRIM_LINES; |
default: |
/* all others reduced to triangles */ |
return R200_VF_PRIM_TRIANGLES; |
} |
} |
static void r200RasterPrimitive( struct gl_context *ctx, GLuint hwprim ); |
static void r200RenderPrimitive( struct gl_context *ctx, GLenum prim ); |
static void r200ResetLineStipple( struct gl_context *ctx ); |
/*********************************************************************** |
* Emit primitives as inline vertices * |
***********************************************************************/ |
#define HAVE_POINTS 1 |
#define HAVE_LINES 1 |
#define HAVE_LINE_STRIPS 1 |
#define HAVE_TRIANGLES 1 |
#define HAVE_TRI_STRIPS 1 |
#define HAVE_TRI_STRIP_1 0 |
#define HAVE_TRI_FANS 1 |
#define HAVE_QUADS 0 |
#define HAVE_QUAD_STRIPS 0 |
#define HAVE_POLYGONS 1 |
#define HAVE_ELTS 0 |
static void* r200_alloc_verts( r200ContextPtr rmesa, GLuint n, GLuint size) |
{ |
void *rv; |
do { |
r200_predict_emit_size( rmesa ); |
rv = rcommonAllocDmaLowVerts( &rmesa->radeon, n, size * 4 ); |
} while(!rv); |
return rv; |
} |
#undef LOCAL_VARS |
#undef ALLOC_VERTS |
#define CTX_ARG r200ContextPtr rmesa |
#define GET_VERTEX_DWORDS() rmesa->radeon.swtcl.vertex_size |
#define ALLOC_VERTS( n, size ) r200_alloc_verts(rmesa, n, size) |
#define LOCAL_VARS \ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); \ |
const char *r200verts = (char *)rmesa->radeon.swtcl.verts; |
#define VERT(x) (radeonVertex *)(r200verts + ((x) * vertsize * sizeof(int))) |
#define VERTEX radeonVertex |
#define DO_DEBUG_VERTS (1 && (R200_DEBUG & RADEON_VERTS)) |
#undef TAG |
#define TAG(x) r200_##x |
#include "tnl_dd/t_dd_triemit.h" |
/*********************************************************************** |
* Macros for t_dd_tritmp.h to draw basic primitives * |
***********************************************************************/ |
#define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d ) |
#define TRI( a, b, c ) r200_triangle( rmesa, a, b, c ) |
#define LINE( a, b ) r200_line( rmesa, a, b ) |
#define POINT( a ) r200_point( rmesa, a ) |
/*********************************************************************** |
* Build render functions from dd templates * |
***********************************************************************/ |
#define R200_TWOSIDE_BIT 0x01 |
#define R200_UNFILLED_BIT 0x02 |
#define R200_MAX_TRIFUNC 0x04 |
static struct { |
tnl_points_func points; |
tnl_line_func line; |
tnl_triangle_func triangle; |
tnl_quad_func quad; |
} rast_tab[R200_MAX_TRIFUNC]; |
#define DO_FALLBACK 0 |
#define DO_UNFILLED (IND & R200_UNFILLED_BIT) |
#define DO_TWOSIDE (IND & R200_TWOSIDE_BIT) |
#define DO_FLAT 0 |
#define DO_OFFSET 0 |
#define DO_TRI 1 |
#define DO_QUAD 1 |
#define DO_LINE 1 |
#define DO_POINTS 1 |
#define DO_FULL_QUAD 1 |
#define HAVE_SPEC 1 |
#define HAVE_BACK_COLORS 0 |
#define HAVE_HW_FLATSHADE 1 |
#define TAB rast_tab |
#define DEPTH_SCALE 1.0 |
#define UNFILLED_TRI unfilled_tri |
#define UNFILLED_QUAD unfilled_quad |
#define VERT_X(_v) _v->v.x |
#define VERT_Y(_v) _v->v.y |
#define VERT_Z(_v) _v->v.z |
#define AREA_IS_CCW( a ) (a < 0) |
#define GET_VERTEX(e) (rmesa->radeon.swtcl.verts + (e*rmesa->radeon.swtcl.vertex_size*sizeof(int))) |
#define VERT_SET_RGBA( v, c ) \ |
do { \ |
radeon_color_t *color = (radeon_color_t *)&((v)->ui[coloroffset]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \ |
} while (0) |
#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset] |
#define VERT_SET_SPEC( v, c ) \ |
do { \ |
if (specoffset) { \ |
radeon_color_t *spec = (radeon_color_t *)&((v)->ui[specoffset]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \ |
} \ |
} while (0) |
#define VERT_COPY_SPEC( v0, v1 ) \ |
do { \ |
if (specoffset) { \ |
radeon_color_t *spec0 = (radeon_color_t *)&((v0)->ui[specoffset]); \ |
radeon_color_t *spec1 = (radeon_color_t *)&((v1)->ui[specoffset]); \ |
spec0->red = spec1->red; \ |
spec0->green = spec1->green; \ |
spec0->blue = spec1->blue; \ |
} \ |
} while (0) |
/* These don't need LE32_TO_CPU() as they used to save and restore |
* colors which are already in the correct format. |
*/ |
#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset] |
#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx] |
#define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset] |
#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] |
#undef LOCAL_VARS |
#undef TAG |
#undef INIT |
#define LOCAL_VARS(n) \ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); \ |
GLuint color[n] = {0}, spec[n] = {0}; \ |
GLuint coloroffset = rmesa->swtcl.coloroffset; \ |
GLuint specoffset = rmesa->swtcl.specoffset; \ |
(void) color; (void) spec; (void) coloroffset; (void) specoffset; |
/*********************************************************************** |
* Helpers for rendering unfilled primitives * |
***********************************************************************/ |
#define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim(ctx, x) ) |
#define RENDER_PRIMITIVE rmesa->radeon.swtcl.render_primitive |
#undef TAG |
#define TAG(x) x |
#include "tnl_dd/t_dd_unfilled.h" |
#undef IND |
/*********************************************************************** |
* Generate GL render functions * |
***********************************************************************/ |
#define IND (0) |
#define TAG(x) x |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (R200_TWOSIDE_BIT) |
#define TAG(x) x##_twoside |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (R200_UNFILLED_BIT) |
#define TAG(x) x##_unfilled |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT) |
#define TAG(x) x##_twoside_unfilled |
#include "tnl_dd/t_dd_tritmp.h" |
static void init_rast_tab( void ) |
{ |
init(); |
init_twoside(); |
init_unfilled(); |
init_twoside_unfilled(); |
} |
/**********************************************************************/ |
/* Render unclipped begin/end objects */ |
/**********************************************************************/ |
#define RENDER_POINTS( start, count ) \ |
for ( ; start < count ; start++) \ |
r200_point( rmesa, VERT(start) ) |
#define RENDER_LINE( v0, v1 ) \ |
r200_line( rmesa, VERT(v0), VERT(v1) ) |
#define RENDER_TRI( v0, v1, v2 ) \ |
r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) ) |
#define RENDER_QUAD( v0, v1, v2, v3 ) \ |
r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) ) |
#define INIT(x) do { \ |
r200RenderPrimitive( ctx, x ); \ |
} while (0) |
#undef LOCAL_VARS |
#define LOCAL_VARS \ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); \ |
const GLuint vertsize = rmesa->radeon.swtcl.vertex_size; \ |
const char *r200verts = (char *)rmesa->radeon.swtcl.verts; \ |
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ |
const GLboolean stipple = ctx->Line.StippleFlag; \ |
(void) elt; (void) stipple; |
#define RESET_STIPPLE if ( stipple ) r200ResetLineStipple( ctx ); |
#define RESET_OCCLUSION |
#define PRESERVE_VB_DEFS |
#define ELT(x) (x) |
#define TAG(x) r200_##x##_verts |
#include "tnl/t_vb_rendertmp.h" |
#undef ELT |
#undef TAG |
#define TAG(x) r200_##x##_elts |
#define ELT(x) elt[x] |
#include "tnl/t_vb_rendertmp.h" |
/**********************************************************************/ |
/* Choose render functions */ |
/**********************************************************************/ |
void r200ChooseRenderState( struct gl_context *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint index = 0; |
GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL); |
GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide; |
if (!rmesa->radeon.TclFallback || rmesa->radeon.Fallback) |
return; |
if (twosided) |
index |= R200_TWOSIDE_BIT; |
if (unfilled) |
index |= R200_UNFILLED_BIT; |
if (index != rmesa->radeon.swtcl.RenderIndex) { |
tnl->Driver.Render.Points = rast_tab[index].points; |
tnl->Driver.Render.Line = rast_tab[index].line; |
tnl->Driver.Render.ClippedLine = rast_tab[index].line; |
tnl->Driver.Render.Triangle = rast_tab[index].triangle; |
tnl->Driver.Render.Quad = rast_tab[index].quad; |
if (index == 0) { |
tnl->Driver.Render.PrimTabVerts = r200_render_tab_verts; |
tnl->Driver.Render.PrimTabElts = r200_render_tab_elts; |
tnl->Driver.Render.ClippedPolygon = r200_fast_clipped_poly; |
} else { |
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; |
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; |
tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; |
} |
rmesa->radeon.swtcl.RenderIndex = index; |
} |
} |
/**********************************************************************/ |
/* High level hooks for t_vb_render.c */ |
/**********************************************************************/ |
static void r200RasterPrimitive( struct gl_context *ctx, GLuint hwprim ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
radeon_prepare_render(&rmesa->radeon); |
if (rmesa->radeon.NewGLState) |
r200ValidateState( ctx ); |
if (rmesa->radeon.swtcl.hw_primitive != hwprim) { |
/* need to disable perspective-correct texturing for point sprites */ |
if ((hwprim & 0xf) == R200_VF_PRIM_POINT_SPRITES && ctx->Point.PointSprite) { |
if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) { |
R200_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE; |
} |
} |
else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) { |
R200_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE; |
} |
R200_NEWPRIM( rmesa ); |
rmesa->radeon.swtcl.hw_primitive = hwprim; |
} |
} |
static void r200RenderPrimitive( struct gl_context *ctx, GLenum prim ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL); |
rmesa->radeon.swtcl.render_primitive = prim; |
if (prim < GL_TRIANGLES || !unfilled) |
r200RasterPrimitive( ctx, reduced_hw_prim(ctx, prim) ); |
} |
static void r200RenderFinish( struct gl_context *ctx ) |
{ |
} |
static void r200ResetLineStipple( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
R200_STATECHANGE( rmesa, lin ); |
} |
/**********************************************************************/ |
/* Transition to/from hardware rasterization. */ |
/**********************************************************************/ |
static const char * const fallbackStrings[] = { |
"Texture mode", |
"glDrawBuffer(GL_FRONT_AND_BACK)", |
"glEnable(GL_STENCIL) without hw stencil buffer", |
"glRenderMode(selection or feedback)", |
"R200_NO_RAST", |
"Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)" |
}; |
static const char *getFallbackString(GLuint bit) |
{ |
int i = 0; |
while (bit > 1) { |
i++; |
bit >>= 1; |
} |
return fallbackStrings[i]; |
} |
void r200Fallback( struct gl_context *ctx, GLuint bit, GLboolean mode ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint oldfallback = rmesa->radeon.Fallback; |
if (mode) { |
rmesa->radeon.Fallback |= bit; |
if (oldfallback == 0) { |
radeon_firevertices(&rmesa->radeon); |
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_TRUE ); |
_swsetup_Wakeup( ctx ); |
rmesa->radeon.swtcl.RenderIndex = ~0; |
if (R200_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "R200 begin rasterization fallback: 0x%x %s\n", |
bit, getFallbackString(bit)); |
} |
} |
} |
else { |
rmesa->radeon.Fallback &= ~bit; |
if (oldfallback == bit) { |
_swrast_flush( ctx ); |
tnl->Driver.Render.Start = r200RenderStart; |
tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive; |
tnl->Driver.Render.Finish = r200RenderFinish; |
tnl->Driver.Render.BuildVertices = _tnl_build_vertices; |
tnl->Driver.Render.CopyPV = _tnl_copy_pv; |
tnl->Driver.Render.Interp = _tnl_interp; |
tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple; |
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_FALSE ); |
if (rmesa->radeon.TclFallback) { |
/* These are already done if rmesa->radeon.TclFallback goes to |
* zero above. But not if it doesn't (R200_NO_TCL for |
* example?) |
*/ |
_tnl_invalidate_vertex_state( ctx, ~0 ); |
_tnl_invalidate_vertices( ctx, ~0 ); |
rmesa->radeon.tnl_index_bitset = 0; |
r200ChooseVertexState( ctx ); |
r200ChooseRenderState( ctx ); |
} |
if (R200_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "R200 end rasterization fallback: 0x%x %s\n", |
bit, getFallbackString(bit)); |
} |
} |
} |
} |
/** |
* Cope with depth operations by drawing individual pixels as points. |
* |
* \todo |
* The way the vertex state is set in this routine is hokey. It seems to |
* work, but it's very hackish. This whole routine is pretty hackish. If |
* the bitmap is small enough, it seems like it would be faster to copy it |
* to AGP memory and use it as a non-power-of-two texture (i.e., |
* NV_texture_rectangle). |
*/ |
void |
r200PointsBitmap( struct gl_context *ctx, GLint px, GLint py, |
GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte *bitmap ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
const GLfloat *rc = ctx->Current.RasterColor; |
GLint row, col; |
radeonVertex vert; |
GLuint orig_vte; |
GLuint h; |
/* Turn off tcl. |
*/ |
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 1 ); |
/* Choose tiny vertex format |
*/ |
{ |
const GLuint fmt_0 = R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 |
| (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT); |
const GLuint fmt_1 = 0; |
GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]; |
GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]; |
vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT); |
vte |= R200_VTX_W0_FMT; |
vap &= ~R200_VAP_FORCE_W_TO_ONE; |
rmesa->radeon.swtcl.vertex_size = 5; |
if ( (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) |
|| (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) { |
R200_NEWPRIM(rmesa); |
R200_STATECHANGE( rmesa, vtx ); |
rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0; |
rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1; |
} |
if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) { |
R200_STATECHANGE( rmesa, vte ); |
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte; |
} |
if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) { |
R200_STATECHANGE( rmesa, vap ); |
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap; |
} |
} |
/* Ready for point primitives: |
*/ |
r200RenderPrimitive( ctx, GL_POINTS ); |
/* Turn off the hw viewport transformation: |
*/ |
R200_STATECHANGE( rmesa, vte ); |
orig_vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]; |
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VPORT_X_SCALE_ENA | |
R200_VPORT_Y_SCALE_ENA | |
R200_VPORT_Z_SCALE_ENA | |
R200_VPORT_X_OFFSET_ENA | |
R200_VPORT_Y_OFFSET_ENA | |
R200_VPORT_Z_OFFSET_ENA); |
/* Turn off other stuff: Stipple?, texture?, blending?, etc. |
*/ |
/* Populate the vertex |
* |
* Incorporate FOG into RGBA |
*/ |
if (ctx->Fog.Enabled) { |
const GLfloat *fc = ctx->Fog.Color; |
GLfloat color[4]; |
GLfloat f; |
if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) |
f = _swrast_z_to_fogfactor(ctx, ctx->Current.Attrib[VERT_ATTRIB_FOG][0]); |
else |
f = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance); |
color[0] = f * rc[0] + (1.F - f) * fc[0]; |
color[1] = f * rc[1] + (1.F - f) * fc[1]; |
color[2] = f * rc[2] + (1.F - f) * fc[2]; |
color[3] = rc[3]; |
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red, color[0]); |
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, color[1]); |
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue, color[2]); |
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, color[3]); |
} |
else { |
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red, rc[0]); |
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, rc[1]); |
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue, rc[2]); |
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, rc[3]); |
} |
vert.tv.z = ctx->Current.RasterPos[2]; |
/* Update window height |
*/ |
h = radeon_get_drawable(&rmesa->radeon)->h; |
/* Clipping handled by existing mechansims in r200_ioctl.c? |
*/ |
for (row=0; row<height; row++) { |
const GLubyte *src = (const GLubyte *) |
_mesa_image_address2d(unpack, bitmap, width, height, |
GL_COLOR_INDEX, GL_BITMAP, row, 0 ); |
if (unpack->LsbFirst) { |
/* Lsb first */ |
GLubyte mask = 1U << (unpack->SkipPixels & 0x7); |
for (col=0; col<width; col++) { |
if (*src & mask) { |
vert.tv.x = px+col; |
vert.tv.y = h - (py+row) - 1; |
r200_point( rmesa, &vert ); |
} |
src += (mask >> 7); |
mask = ((mask << 1) & 0xff) | (mask >> 7); |
} |
/* get ready for next row */ |
if (mask != 1) |
src++; |
} |
else { |
/* Msb first */ |
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); |
for (col=0; col<width; col++) { |
if (*src & mask) { |
vert.tv.x = px+col; |
vert.tv.y = h - (py+row) - 1; |
r200_point( rmesa, &vert ); |
} |
src += mask & 1; |
mask = ((mask << 7) & 0xff) | (mask >> 1); |
} |
/* get ready for next row */ |
if (mask != 128) |
src++; |
} |
} |
/* Fire outstanding vertices, restore state |
*/ |
R200_STATECHANGE( rmesa, vte ); |
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = orig_vte; |
/* Unfallback |
*/ |
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 0 ); |
/* Need to restore vertexformat? |
*/ |
if (rmesa->radeon.TclFallback) |
r200ChooseVertexState( ctx ); |
} |
/**********************************************************************/ |
/* Initialization. */ |
/**********************************************************************/ |
void r200InitSwtcl( struct gl_context *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
static int firsttime = 1; |
if (firsttime) { |
init_rast_tab(); |
firsttime = 0; |
} |
rmesa->radeon.swtcl.emit_prediction = 0; |
tnl->Driver.Render.Start = r200RenderStart; |
tnl->Driver.Render.Finish = r200RenderFinish; |
tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive; |
tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple; |
tnl->Driver.Render.BuildVertices = _tnl_build_vertices; |
tnl->Driver.Render.CopyPV = _tnl_copy_pv; |
tnl->Driver.Render.Interp = _tnl_interp; |
/* FIXME: what are these numbers? */ |
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, |
36 * sizeof(GLfloat) ); |
rmesa->radeon.swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf; |
rmesa->radeon.swtcl.RenderIndex = ~0; |
rmesa->radeon.swtcl.render_primitive = GL_TRIANGLES; |
rmesa->radeon.swtcl.hw_primitive = 0; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_swtcl.h |
---|
0,0 → 1,69 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 __R200_SWTCL_H__ |
#define __R200_SWTCL_H__ |
#include "main/mtypes.h" |
#include "swrast/swrast.h" |
#include "r200_context.h" |
extern void r200InitSwtcl( struct gl_context *ctx ); |
extern void r200ChooseRenderState( struct gl_context *ctx ); |
extern void r200ChooseVertexState( struct gl_context *ctx ); |
extern void r200CheckTexSizes( struct gl_context *ctx ); |
extern void r200BuildVertices( struct gl_context *ctx, GLuint start, GLuint count, |
GLuint newinputs ); |
extern void r200PrintSetupFlags(char *msg, GLuint flags ); |
extern void r200_translate_vertex( struct gl_context *ctx, |
const radeonVertex *src, |
SWvertex *dst ); |
extern void r200_print_vertex( struct gl_context *ctx, const radeonVertex *v ); |
extern void r200_import_float_colors( struct gl_context *ctx ); |
extern void r200_import_float_spec_colors( struct gl_context *ctx ); |
extern void r200PointsBitmap( struct gl_context *ctx, GLint px, GLint py, |
GLsizei width, GLsizei height, |
const struct gl_pixelstore_attrib *unpack, |
const GLubyte *bitmap ); |
void r200_swtcl_flush(struct gl_context *ctx, uint32_t current_offset); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_tcl.c |
---|
0,0 → 1,640 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/imports.h" |
#include "main/mtypes.h" |
#include "main/enums.h" |
#include "main/colormac.h" |
#include "main/light.h" |
#include "main/state.h" |
#include "vbo/vbo.h" |
#include "tnl/tnl.h" |
#include "tnl/t_pipeline.h" |
#include "r200_context.h" |
#include "r200_state.h" |
#include "r200_ioctl.h" |
#include "r200_tcl.h" |
#include "r200_swtcl.h" |
#include "r200_maos.h" |
#include "radeon_common_context.h" |
#define HAVE_POINTS 1 |
#define HAVE_LINES 1 |
#define HAVE_LINE_LOOP 0 |
#define HAVE_LINE_STRIPS 1 |
#define HAVE_TRIANGLES 1 |
#define HAVE_TRI_STRIPS 1 |
#define HAVE_TRI_STRIP_1 0 |
#define HAVE_TRI_FANS 1 |
#define HAVE_QUADS 1 |
#define HAVE_QUAD_STRIPS 1 |
#define HAVE_POLYGONS 1 |
#define HAVE_ELTS 1 |
#define HW_POINTS ((!ctx->Point.SmoothFlag) ? \ |
R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS) |
#define HW_LINES R200_VF_PRIM_LINES |
#define HW_LINE_LOOP 0 |
#define HW_LINE_STRIP R200_VF_PRIM_LINE_STRIP |
#define HW_TRIANGLES R200_VF_PRIM_TRIANGLES |
#define HW_TRIANGLE_STRIP_0 R200_VF_PRIM_TRIANGLE_STRIP |
#define HW_TRIANGLE_STRIP_1 0 |
#define HW_TRIANGLE_FAN R200_VF_PRIM_TRIANGLE_FAN |
#define HW_QUADS R200_VF_PRIM_QUADS |
#define HW_QUAD_STRIP R200_VF_PRIM_QUAD_STRIP |
#define HW_POLYGON R200_VF_PRIM_POLYGON |
static GLboolean discrete_prim[0x10] = { |
0, /* 0 none */ |
1, /* 1 points */ |
1, /* 2 lines */ |
0, /* 3 line_strip */ |
1, /* 4 tri_list */ |
0, /* 5 tri_fan */ |
0, /* 6 tri_strip */ |
0, /* 7 tri_w_flags */ |
1, /* 8 rect list (unused) */ |
1, /* 9 3vert point */ |
1, /* a 3vert line */ |
0, /* b point sprite */ |
0, /* c line loop */ |
1, /* d quads */ |
0, /* e quad strip */ |
0, /* f polygon */ |
}; |
#define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx) |
#define ELT_TYPE GLushort |
#define ELT_INIT(prim, hw_prim) \ |
r200TclPrimitive( ctx, prim, hw_prim | R200_VF_PRIM_WALK_IND ) |
#define GET_MESA_ELTS() TNL_CONTEXT(ctx)->vb.Elts |
/* Don't really know how many elts will fit in what's left of cmdbuf, |
* as there is state to emit, etc: |
*/ |
/* Testing on isosurf shows a maximum around here. Don't know if it's |
* the card or driver or kernel module that is causing the behaviour. |
*/ |
#define GET_MAX_HW_ELTS() 300 |
#define RESET_STIPPLE() do { \ |
R200_STATECHANGE( rmesa, lin ); \ |
radeonEmitState(&rmesa->radeon); \ |
} while (0) |
#define AUTO_STIPPLE( mode ) do { \ |
R200_STATECHANGE( rmesa, lin ); \ |
if (mode) \ |
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \ |
R200_LINE_PATTERN_AUTO_RESET; \ |
else \ |
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \ |
~R200_LINE_PATTERN_AUTO_RESET; \ |
radeonEmitState(&rmesa->radeon); \ |
} while (0) |
#define ALLOC_ELTS(nr) r200AllocElts( rmesa, nr ) |
static GLushort *r200AllocElts( r200ContextPtr rmesa, GLuint nr ) |
{ |
if (rmesa->radeon.dma.flush == r200FlushElts && |
rmesa->tcl.elt_used + nr*2 < R200_ELT_BUF_SZ) { |
GLushort *dest = (GLushort *)(rmesa->radeon.tcl.elt_dma_bo->ptr + |
rmesa->radeon.tcl.elt_dma_offset + rmesa->tcl.elt_used); |
rmesa->tcl.elt_used += nr*2; |
return dest; |
} |
else { |
if (rmesa->radeon.dma.flush) |
rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); |
r200EmitAOS( rmesa, |
rmesa->radeon.tcl.aos_count, 0 ); |
r200EmitMaxVtxIndex(rmesa, rmesa->radeon.tcl.aos[0].count); |
return r200AllocEltsOpenEnded( rmesa, rmesa->tcl.hw_primitive, nr ); |
} |
} |
#define CLOSE_ELTS() \ |
do { \ |
if (0) R200_NEWPRIM( rmesa ); \ |
} \ |
while (0) |
/* TODO: Try to extend existing primitive if both are identical, |
* discrete and there are no intervening state changes. (Somewhat |
* duplicates changes to DrawArrays code) |
*/ |
static void r200EmitPrim( struct gl_context *ctx, |
GLenum prim, |
GLuint hwprim, |
GLuint start, |
GLuint count) |
{ |
r200ContextPtr rmesa = R200_CONTEXT( ctx ); |
r200TclPrimitive( ctx, prim, hwprim ); |
// fprintf(stderr,"Emit prim %d\n", rmesa->radeon.tcl.aos_count); |
r200EmitAOS( rmesa, |
rmesa->radeon.tcl.aos_count, |
start ); |
/* Why couldn't this packet have taken an offset param? |
*/ |
r200EmitVbufPrim( rmesa, |
rmesa->tcl.hw_primitive, |
count - start ); |
} |
#define EMIT_PRIM(ctx, prim, hwprim, start, count) do { \ |
r200EmitPrim( ctx, prim, hwprim, start, count ); \ |
(void) rmesa; } while (0) |
#define MAX_CONVERSION_SIZE 40 |
/* Try & join small primitives |
*/ |
#if 0 |
#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) 0 |
#else |
#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) \ |
((NR) < 20 || \ |
((NR) < 40 && \ |
rmesa->tcl.hw_primitive == (PRIM| \ |
R200_VF_TCL_OUTPUT_VTX_ENABLE| \ |
R200_VF_PRIM_WALK_IND))) |
#endif |
#ifdef MESA_BIG_ENDIAN |
/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */ |
#define EMIT_ELT(dest, offset, x) do { \ |
int off = offset + ( ( (uintptr_t)dest & 0x2 ) >> 1 ); \ |
GLushort *des = (GLushort *)( (uintptr_t)dest & ~0x2 ); \ |
(des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); \ |
(void)rmesa; } while (0) |
#else |
#define EMIT_ELT(dest, offset, x) do { \ |
(dest)[offset] = (GLushort) (x); \ |
(void)rmesa; } while (0) |
#endif |
#define EMIT_TWO_ELTS(dest, offset, x, y) *(GLuint *)((dest)+offset) = ((y)<<16)|(x); |
#define TAG(x) tcl_##x |
#include "tnl_dd/t_dd_dmatmp2.h" |
/**********************************************************************/ |
/* External entrypoints */ |
/**********************************************************************/ |
void r200EmitPrimitive( struct gl_context *ctx, |
GLuint first, |
GLuint last, |
GLuint flags ) |
{ |
tcl_render_tab_verts[flags&PRIM_MODE_MASK]( ctx, first, last, flags ); |
} |
void r200EmitEltPrimitive( struct gl_context *ctx, |
GLuint first, |
GLuint last, |
GLuint flags ) |
{ |
tcl_render_tab_elts[flags&PRIM_MODE_MASK]( ctx, first, last, flags ); |
} |
void r200TclPrimitive( struct gl_context *ctx, |
GLenum prim, |
int hw_prim ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint newprim = hw_prim | R200_VF_TCL_OUTPUT_VTX_ENABLE; |
radeon_prepare_render(&rmesa->radeon); |
if (rmesa->radeon.NewGLState) |
r200ValidateState( ctx ); |
if (newprim != rmesa->tcl.hw_primitive || |
!discrete_prim[hw_prim&0xf]) { |
/* need to disable perspective-correct texturing for point sprites */ |
if ((prim & PRIM_MODE_MASK) == GL_POINTS && ctx->Point.PointSprite) { |
if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) { |
R200_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE; |
} |
} |
else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) { |
R200_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE; |
} |
R200_NEWPRIM( rmesa ); |
rmesa->tcl.hw_primitive = newprim; |
} |
} |
/** |
* Predict total emit size for next rendering operation so there is no flush in middle of rendering |
* Prediction has to aim towards the best possible value that is worse than worst case scenario |
*/ |
static GLuint r200EnsureEmitSize( struct gl_context * ctx , GLubyte* vimap_rev ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLuint space_required; |
GLuint state_size; |
GLuint nr_aos = 0; |
int i; |
/* predict number of aos to emit */ |
for (i = 0; i < 15; ++i) |
{ |
if (vimap_rev[i] != 255) |
{ |
++nr_aos; |
} |
} |
{ |
/* count the prediction for state size */ |
space_required = 0; |
state_size = radeonCountStateEmitSize( &rmesa->radeon ); |
/* vtx may be changed in r200EmitArrays so account for it if not dirty */ |
if (!rmesa->hw.vtx.dirty) |
state_size += rmesa->hw.vtx.check(&rmesa->radeon.glCtx, &rmesa->hw.vtx); |
/* predict size for elements */ |
for (i = 0; i < VB->PrimitiveCount; ++i) |
{ |
if (!VB->Primitive[i].count) |
continue; |
/* If primitive.count is less than MAX_CONVERSION_SIZE |
rendering code may decide convert to elts. |
In that case we have to make pessimistic prediction. |
and use larger of 2 paths. */ |
const GLuint elt_count =(VB->Primitive[i].count/GET_MAX_HW_ELTS() + 1); |
const GLuint elts = ELTS_BUFSZ(nr_aos) * elt_count; |
const GLuint index = INDEX_BUFSZ * elt_count; |
const GLuint vbuf = VBUF_BUFSZ; |
if ( (!VB->Elts && VB->Primitive[i].count >= MAX_CONVERSION_SIZE) |
|| vbuf > index + elts) |
space_required += vbuf; |
else |
space_required += index + elts; |
space_required += AOS_BUFSZ(nr_aos); |
} |
} |
radeon_print(RADEON_RENDER,RADEON_VERBOSE, |
"%s space %u, aos %d\n", |
__func__, space_required, AOS_BUFSZ(nr_aos) ); |
/* flush the buffer in case we need more than is left. */ |
if (rcommonEnsureCmdBufSpace(&rmesa->radeon, space_required + state_size, __FUNCTION__)) |
return space_required + radeonCountStateEmitSize( &rmesa->radeon ); |
else |
return space_required + state_size; |
} |
/**********************************************************************/ |
/* Render pipeline stage */ |
/**********************************************************************/ |
/* TCL render. |
*/ |
static GLboolean r200_run_tcl_render( struct gl_context *ctx, |
struct tnl_pipeline_stage *stage ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLuint i; |
GLubyte *vimap_rev; |
/* use hw fixed order for simplicity, pos 0, weight 1, normal 2, fog 3, |
color0 - color3 4-7, texcoord0 - texcoord5 8-13, pos 1 14. Must not use |
more than 12 of those at the same time. */ |
GLubyte map_rev_fixed[15] = {255, 255, 255, 255, 255, 255, 255, 255, |
255, 255, 255, 255, 255, 255, 255}; |
/* TODO: separate this from the swtnl pipeline |
*/ |
if (rmesa->radeon.TclFallback) |
return GL_TRUE; /* fallback to software t&l */ |
radeon_print(RADEON_RENDER, RADEON_NORMAL, "%s\n", __FUNCTION__); |
if (VB->Count == 0) |
return GL_FALSE; |
/* Validate state: |
*/ |
if (rmesa->radeon.NewGLState) |
if (!r200ValidateState( ctx )) |
return GL_TRUE; /* fallback to sw t&l */ |
if (!ctx->VertexProgram._Enabled) { |
/* NOTE: inputs != tnl->render_inputs - these are the untransformed |
* inputs. |
*/ |
map_rev_fixed[0] = VERT_ATTRIB_POS; |
/* technically there is no reason we always need VA_COLOR0. In theory |
could disable it depending on lighting, color materials, texturing... */ |
map_rev_fixed[4] = VERT_ATTRIB_COLOR0; |
if (ctx->Light.Enabled) { |
map_rev_fixed[2] = VERT_ATTRIB_NORMAL; |
} |
/* this also enables VA_COLOR1 when using separate specular |
lighting model, which is unnecessary. |
FIXME: OTOH, we're missing the case where a ATI_fragment_shader accesses |
the secondary color (if lighting is disabled). The chip seems |
misconfigured for that though elsewhere (tcl output, might lock up) */ |
if (_mesa_need_secondary_color(ctx)) { |
map_rev_fixed[5] = VERT_ATTRIB_COLOR1; |
} |
if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) { |
map_rev_fixed[3] = VERT_ATTRIB_FOG; |
} |
for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) { |
if (ctx->Texture.Unit[i]._ReallyEnabled) { |
if (rmesa->TexGenNeedNormals[i]) { |
map_rev_fixed[2] = VERT_ATTRIB_NORMAL; |
} |
map_rev_fixed[8 + i] = VERT_ATTRIB_TEX0 + i; |
} |
} |
vimap_rev = &map_rev_fixed[0]; |
} |
else { |
/* vtx_tcl_output_vtxfmt_0/1 need to match configuration of "fragment |
part", since using some vertex interpolator later which is not in |
out_vtxfmt0/1 will lock up. It seems to be ok to write in vertex |
prog to a not enabled output however, so just don't mess with it. |
We only need to change compsel. */ |
GLuint out_compsel = 0; |
const GLbitfield64 vp_out = |
rmesa->curr_vp_hw->mesa_program.Base.OutputsWritten; |
vimap_rev = &rmesa->curr_vp_hw->inputmap_rev[0]; |
assert(vp_out & BITFIELD64_BIT(VARYING_SLOT_POS)); |
out_compsel = R200_OUTPUT_XYZW; |
if (vp_out & BITFIELD64_BIT(VARYING_SLOT_COL0)) { |
out_compsel |= R200_OUTPUT_COLOR_0; |
} |
if (vp_out & BITFIELD64_BIT(VARYING_SLOT_COL1)) { |
out_compsel |= R200_OUTPUT_COLOR_1; |
} |
if (vp_out & BITFIELD64_BIT(VARYING_SLOT_FOGC)) { |
out_compsel |= R200_OUTPUT_DISCRETE_FOG; |
} |
if (vp_out & BITFIELD64_BIT(VARYING_SLOT_PSIZ)) { |
out_compsel |= R200_OUTPUT_PT_SIZE; |
} |
for (i = VARYING_SLOT_TEX0; i < VARYING_SLOT_TEX6; i++) { |
if (vp_out & BITFIELD64_BIT(i)) { |
out_compsel |= R200_OUTPUT_TEX_0 << (i - VARYING_SLOT_TEX0); |
} |
} |
if (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] != out_compsel) { |
R200_STATECHANGE( rmesa, vtx ); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = out_compsel; |
} |
} |
/* Do the actual work: |
*/ |
radeonReleaseArrays( ctx, ~0 /* stage->changed_inputs */ ); |
GLuint emit_end = r200EnsureEmitSize( ctx, vimap_rev ) |
+ rmesa->radeon.cmdbuf.cs->cdw; |
r200EmitArrays( ctx, vimap_rev ); |
for (i = 0 ; i < VB->PrimitiveCount ; i++) |
{ |
GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); |
GLuint start = VB->Primitive[i].start; |
GLuint length = VB->Primitive[i].count; |
if (!length) |
continue; |
if (VB->Elts) |
r200EmitEltPrimitive( ctx, start, start+length, prim ); |
else |
r200EmitPrimitive( ctx, start, start+length, prim ); |
} |
if ( emit_end < rmesa->radeon.cmdbuf.cs->cdw ) |
WARN_ONCE("Rendering was %d commands larger than predicted size." |
" We might overflow command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end); |
return GL_FALSE; /* finished the pipe */ |
} |
/* Initial state for tcl stage. |
*/ |
const struct tnl_pipeline_stage _r200_tcl_stage = |
{ |
"r200 render", |
NULL, /* private */ |
NULL, |
NULL, |
NULL, |
r200_run_tcl_render /* run */ |
}; |
/**********************************************************************/ |
/* Validate state at pipeline start */ |
/**********************************************************************/ |
/*----------------------------------------------------------------------- |
* Manage TCL fallbacks |
*/ |
static void transition_to_swtnl( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
R200_NEWPRIM( rmesa ); |
r200ChooseVertexState( ctx ); |
r200ChooseRenderState( ctx ); |
_tnl_validate_shine_tables( ctx ); |
tnl->Driver.NotifyMaterialChange = |
_tnl_validate_shine_tables; |
radeonReleaseArrays( ctx, ~0 ); |
/* Still using the D3D based hardware-rasterizer from the radeon; |
* need to put the card into D3D mode to make it work: |
*/ |
R200_STATECHANGE( rmesa, vap ); |
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~(R200_VAP_TCL_ENABLE|R200_VAP_PROG_VTX_SHADER_ENABLE); |
} |
static void transition_to_hwtnl( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
_tnl_need_projected_coords( ctx, GL_FALSE ); |
r200UpdateMaterial( ctx ); |
tnl->Driver.NotifyMaterialChange = r200UpdateMaterial; |
if ( rmesa->radeon.dma.flush ) |
rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); |
rmesa->radeon.dma.flush = NULL; |
R200_STATECHANGE( rmesa, vap ); |
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_TCL_ENABLE; |
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_FORCE_W_TO_ONE; |
if (ctx->VertexProgram._Enabled) { |
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_PROG_VTX_SHADER_ENABLE; |
} |
if ( ((rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK) |
== R200_FOG_USE_SPEC_ALPHA) && |
(ctx->Fog.FogCoordinateSource == GL_FOG_COORD )) { |
R200_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK; |
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_VTX_FOG; |
} |
R200_STATECHANGE( rmesa, vte ); |
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VTX_XY_FMT|R200_VTX_Z_FMT); |
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] |= R200_VTX_W0_FMT; |
if (R200_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "R200 end tcl fallback\n"); |
} |
static char *fallbackStrings[] = { |
"Rasterization fallback", |
"Unfilled triangles", |
"Twosided lighting, differing materials", |
"Materials in VB (maybe between begin/end)", |
"Texgen unit 0", |
"Texgen unit 1", |
"Texgen unit 2", |
"Texgen unit 3", |
"Texgen unit 4", |
"Texgen unit 5", |
"User disable", |
"Bitmap as points", |
"Vertex program" |
}; |
static char *getFallbackString(GLuint bit) |
{ |
int i = 0; |
while (bit > 1) { |
i++; |
bit >>= 1; |
} |
return fallbackStrings[i]; |
} |
void r200TclFallback( struct gl_context *ctx, GLuint bit, GLboolean mode ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint oldfallback = rmesa->radeon.TclFallback; |
if (mode) { |
if (oldfallback == 0) { |
/* We have to flush before transition */ |
if ( rmesa->radeon.dma.flush ) |
rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); |
if (R200_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "R200 begin tcl fallback %s\n", |
getFallbackString( bit )); |
rmesa->radeon.TclFallback |= bit; |
transition_to_swtnl( ctx ); |
} else |
rmesa->radeon.TclFallback |= bit; |
} else { |
if (oldfallback == bit) { |
/* We have to flush before transition */ |
if ( rmesa->radeon.dma.flush ) |
rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); |
if (R200_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "R200 end tcl fallback %s\n", |
getFallbackString( bit )); |
rmesa->radeon.TclFallback &= ~bit; |
transition_to_hwtnl( ctx ); |
} else |
rmesa->radeon.TclFallback &= ~bit; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_tcl.h |
---|
0,0 → 1,64 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 __R200_TCL_H__ |
#define __R200_TCL_H__ |
#include "r200_context.h" |
extern void r200TclPrimitive( struct gl_context *ctx, GLenum prim, int hw_prim ); |
extern void r200EmitEltPrimitive( struct gl_context *ctx, GLuint first, GLuint last, |
GLuint flags ); |
extern void r200EmitPrimitive( struct gl_context *ctx, GLuint first, GLuint last, |
GLuint flags ); |
extern void r200TclFallback( struct gl_context *ctx, GLuint bit, GLboolean mode ); |
#define R200_TCL_FALLBACK_RASTER 0x1 /* rasterization */ |
#define R200_TCL_FALLBACK_UNFILLED 0x2 /* unfilled tris */ |
#define R200_TCL_FALLBACK_LIGHT_TWOSIDE 0x4 /* twoside tris */ |
#define R200_TCL_FALLBACK_MATERIAL 0x8 /* material in vb */ |
#define R200_TCL_FALLBACK_TEXGEN_0 0x10 /* texgen, unit 0 */ |
#define R200_TCL_FALLBACK_TEXGEN_1 0x20 /* texgen, unit 1 */ |
#define R200_TCL_FALLBACK_TEXGEN_2 0x40 /* texgen, unit 2 */ |
#define R200_TCL_FALLBACK_TEXGEN_3 0x80 /* texgen, unit 3 */ |
#define R200_TCL_FALLBACK_TEXGEN_4 0x100 /* texgen, unit 4 */ |
#define R200_TCL_FALLBACK_TEXGEN_5 0x200 /* texgen, unit 5 */ |
#define R200_TCL_FALLBACK_TCL_DISABLE 0x400 /* user disable */ |
#define R200_TCL_FALLBACK_BITMAP 0x800 /* draw bitmap with points */ |
#define R200_TCL_FALLBACK_VERTEX_PROGRAM 0x1000/* vertex program active */ |
#define TCL_FALLBACK( ctx, bit, mode ) r200TclFallback( ctx, bit, mode ) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_tex.c |
---|
0,0 → 1,519 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/imports.h" |
#include "main/colormac.h" |
#include "main/context.h" |
#include "main/enums.h" |
#include "main/image.h" |
#include "main/simple_list.h" |
#include "main/teximage.h" |
#include "main/texobj.h" |
#include "main/samplerobj.h" |
#include "radeon_mipmap_tree.h" |
#include "r200_context.h" |
#include "r200_ioctl.h" |
#include "r200_tex.h" |
#include "xmlpool.h" |
/** |
* Set the texture wrap modes. |
* |
* \param t Texture object whose wrap modes are to be set |
* \param swrap Wrap mode for the \a s texture coordinate |
* \param twrap Wrap mode for the \a t texture coordinate |
*/ |
static void r200SetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap, GLenum rwrap ) |
{ |
GLboolean is_clamp = GL_FALSE; |
GLboolean is_clamp_to_border = GL_FALSE; |
struct gl_texture_object *tObj = &t->base; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(tex %p) sw %s, tw %s, rw %s\n", |
__func__, t, |
_mesa_lookup_enum_by_nr(swrap), |
_mesa_lookup_enum_by_nr(twrap), |
_mesa_lookup_enum_by_nr(rwrap)); |
t->pp_txfilter &= ~(R200_CLAMP_S_MASK | R200_CLAMP_T_MASK | R200_BORDER_MODE_D3D); |
switch ( swrap ) { |
case GL_REPEAT: |
t->pp_txfilter |= R200_CLAMP_S_WRAP; |
break; |
case GL_CLAMP: |
t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL; |
is_clamp = GL_TRUE; |
break; |
case GL_CLAMP_TO_EDGE: |
t->pp_txfilter |= R200_CLAMP_S_CLAMP_LAST; |
break; |
case GL_CLAMP_TO_BORDER: |
t->pp_txfilter |= R200_CLAMP_S_CLAMP_GL; |
is_clamp_to_border = GL_TRUE; |
break; |
case GL_MIRRORED_REPEAT: |
t->pp_txfilter |= R200_CLAMP_S_MIRROR; |
break; |
case GL_MIRROR_CLAMP_EXT: |
t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_GL; |
is_clamp = GL_TRUE; |
break; |
case GL_MIRROR_CLAMP_TO_EDGE_EXT: |
t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_LAST; |
break; |
case GL_MIRROR_CLAMP_TO_BORDER_EXT: |
t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_GL; |
is_clamp_to_border = GL_TRUE; |
break; |
default: |
_mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__); |
} |
if (tObj->Target != GL_TEXTURE_1D) { |
switch ( twrap ) { |
case GL_REPEAT: |
t->pp_txfilter |= R200_CLAMP_T_WRAP; |
break; |
case GL_CLAMP: |
t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL; |
is_clamp = GL_TRUE; |
break; |
case GL_CLAMP_TO_EDGE: |
t->pp_txfilter |= R200_CLAMP_T_CLAMP_LAST; |
break; |
case GL_CLAMP_TO_BORDER: |
t->pp_txfilter |= R200_CLAMP_T_CLAMP_GL; |
is_clamp_to_border = GL_TRUE; |
break; |
case GL_MIRRORED_REPEAT: |
t->pp_txfilter |= R200_CLAMP_T_MIRROR; |
break; |
case GL_MIRROR_CLAMP_EXT: |
t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_GL; |
is_clamp = GL_TRUE; |
break; |
case GL_MIRROR_CLAMP_TO_EDGE_EXT: |
t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_LAST; |
break; |
case GL_MIRROR_CLAMP_TO_BORDER_EXT: |
t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_GL; |
is_clamp_to_border = GL_TRUE; |
break; |
default: |
_mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__); |
} |
} |
t->pp_txformat_x &= ~R200_CLAMP_Q_MASK; |
switch ( rwrap ) { |
case GL_REPEAT: |
t->pp_txformat_x |= R200_CLAMP_Q_WRAP; |
break; |
case GL_CLAMP: |
t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL; |
is_clamp = GL_TRUE; |
break; |
case GL_CLAMP_TO_EDGE: |
t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_LAST; |
break; |
case GL_CLAMP_TO_BORDER: |
t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_GL; |
is_clamp_to_border = GL_TRUE; |
break; |
case GL_MIRRORED_REPEAT: |
t->pp_txformat_x |= R200_CLAMP_Q_MIRROR; |
break; |
case GL_MIRROR_CLAMP_EXT: |
t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_GL; |
is_clamp = GL_TRUE; |
break; |
case GL_MIRROR_CLAMP_TO_EDGE_EXT: |
t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_LAST; |
break; |
case GL_MIRROR_CLAMP_TO_BORDER_EXT: |
t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_GL; |
is_clamp_to_border = GL_TRUE; |
break; |
default: |
_mesa_problem(NULL, "bad R wrap mode in %s", __FUNCTION__); |
} |
if ( is_clamp_to_border ) { |
t->pp_txfilter |= R200_BORDER_MODE_D3D; |
} |
t->border_fallback = (is_clamp && is_clamp_to_border); |
} |
static void r200SetTexMaxAnisotropy( radeonTexObjPtr t, GLfloat max ) |
{ |
t->pp_txfilter &= ~R200_MAX_ANISO_MASK; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(tex %p) max %f.\n", |
__func__, t, max); |
if ( max <= 1.0 ) { |
t->pp_txfilter |= R200_MAX_ANISO_1_TO_1; |
} else if ( max <= 2.0 ) { |
t->pp_txfilter |= R200_MAX_ANISO_2_TO_1; |
} else if ( max <= 4.0 ) { |
t->pp_txfilter |= R200_MAX_ANISO_4_TO_1; |
} else if ( max <= 8.0 ) { |
t->pp_txfilter |= R200_MAX_ANISO_8_TO_1; |
} else { |
t->pp_txfilter |= R200_MAX_ANISO_16_TO_1; |
} |
} |
/** |
* Set the texture magnification and minification modes. |
* |
* \param t Texture whose filter modes are to be set |
* \param minf Texture minification mode |
* \param magf Texture magnification mode |
*/ |
static void r200SetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf ) |
{ |
GLuint anisotropy = (t->pp_txfilter & R200_MAX_ANISO_MASK); |
/* Force revalidation to account for switches from/to mipmapping. */ |
t->validated = GL_FALSE; |
t->pp_txfilter &= ~(R200_MIN_FILTER_MASK | R200_MAG_FILTER_MASK); |
t->pp_txformat_x &= ~R200_VOLUME_FILTER_MASK; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(tex %p) minf %s, maxf %s, anisotropy %d.\n", |
__func__, t, |
_mesa_lookup_enum_by_nr(minf), |
_mesa_lookup_enum_by_nr(magf), |
anisotropy); |
if ( anisotropy == R200_MAX_ANISO_1_TO_1 ) { |
switch ( minf ) { |
case GL_NEAREST: |
t->pp_txfilter |= R200_MIN_FILTER_NEAREST; |
break; |
case GL_LINEAR: |
t->pp_txfilter |= R200_MIN_FILTER_LINEAR; |
break; |
case GL_NEAREST_MIPMAP_NEAREST: |
t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_NEAREST; |
break; |
case GL_NEAREST_MIPMAP_LINEAR: |
t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_NEAREST; |
break; |
case GL_LINEAR_MIPMAP_NEAREST: |
t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_LINEAR; |
break; |
case GL_LINEAR_MIPMAP_LINEAR: |
t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_LINEAR; |
break; |
} |
} else { |
switch ( minf ) { |
case GL_NEAREST: |
t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST; |
break; |
case GL_LINEAR: |
t->pp_txfilter |= R200_MIN_FILTER_ANISO_LINEAR; |
break; |
case GL_NEAREST_MIPMAP_NEAREST: |
case GL_LINEAR_MIPMAP_NEAREST: |
t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST; |
break; |
case GL_NEAREST_MIPMAP_LINEAR: |
case GL_LINEAR_MIPMAP_LINEAR: |
t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR; |
break; |
} |
} |
/* Note we don't have 3D mipmaps so only use the mag filter setting |
* to set the 3D texture filter mode. |
*/ |
switch ( magf ) { |
case GL_NEAREST: |
t->pp_txfilter |= R200_MAG_FILTER_NEAREST; |
t->pp_txformat_x |= R200_VOLUME_FILTER_NEAREST; |
break; |
case GL_LINEAR: |
t->pp_txfilter |= R200_MAG_FILTER_LINEAR; |
t->pp_txformat_x |= R200_VOLUME_FILTER_LINEAR; |
break; |
} |
} |
static void r200SetTexBorderColor( radeonTexObjPtr t, const GLfloat color[4] ) |
{ |
GLubyte c[4]; |
CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); |
CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); |
CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); |
CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); |
t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] ); |
} |
static void r200TexEnv( struct gl_context *ctx, GLenum target, |
GLenum pname, const GLfloat *param ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint unit = ctx->Texture.CurrentUnit; |
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
radeon_print(RADEON_TEXTURE | RADEON_STATE, RADEON_VERBOSE, "%s( %s )\n", |
__FUNCTION__, _mesa_lookup_enum_by_nr( pname ) ); |
/* This is incorrect: Need to maintain this data for each of |
* GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch |
* between them according to _ReallyEnabled. |
*/ |
switch ( pname ) { |
case GL_TEXTURE_ENV_COLOR: { |
GLubyte c[4]; |
GLuint envColor; |
_mesa_unclamped_float_rgba_to_ubyte(c, texUnit->EnvColor); |
envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] ); |
if ( rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor ) { |
R200_STATECHANGE( rmesa, tf ); |
rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] = envColor; |
} |
break; |
} |
case GL_TEXTURE_LOD_BIAS_EXT: { |
GLfloat bias, min; |
GLuint b; |
const int fixed_one = R200_LOD_BIAS_FIXED_ONE; |
/* The R200's LOD bias is a signed 2's complement value with a |
* range of -16.0 <= bias < 16.0. |
* |
* NOTE: Add a small bias to the bias for conform mipsel.c test. |
*/ |
bias = *param; |
min = driQueryOptionb (&rmesa->radeon.optionCache, "no_neg_lod_bias") ? |
0.0 : -16.0; |
bias = CLAMP( bias, min, 16.0 ); |
b = ((int)(bias * fixed_one) |
+ R200_LOD_BIAS_CORRECTION) & R200_LOD_BIAS_MASK; |
if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] & R200_LOD_BIAS_MASK) != b ) { |
R200_STATECHANGE( rmesa, tex[unit] ); |
rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] &= ~R200_LOD_BIAS_MASK; |
rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] |= b; |
} |
break; |
} |
case GL_COORD_REPLACE_ARB: |
if (ctx->Point.PointSprite) { |
R200_STATECHANGE( rmesa, spr ); |
if ((GLenum)param[0]) { |
rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_GEN_TEX_0 << unit; |
} else { |
rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~(R200_PS_GEN_TEX_0 << unit); |
} |
} |
break; |
default: |
return; |
} |
} |
void r200TexUpdateParameters(struct gl_context *ctx, GLuint unit) |
{ |
struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit); |
radeonTexObj* t = radeon_tex_obj(ctx->Texture.Unit[unit]._Current); |
r200SetTexMaxAnisotropy(t , samp->MaxAnisotropy); |
r200SetTexFilter(t, samp->MinFilter, samp->MagFilter); |
r200SetTexWrap(t, samp->WrapS, samp->WrapT, samp->WrapR); |
r200SetTexBorderColor(t, samp->BorderColor.f); |
} |
/** |
* Changes variables and flags for a state update, which will happen at the |
* next UpdateTextureState |
*/ |
static void r200TexParameter( struct gl_context *ctx, GLenum target, |
struct gl_texture_object *texObj, |
GLenum pname, const GLfloat *params ) |
{ |
radeonTexObj* t = radeon_tex_obj(texObj); |
radeon_print(RADEON_TEXTURE | RADEON_STATE, RADEON_VERBOSE, |
"%s(%p, tex %p) target %s, pname %s\n", |
__FUNCTION__, ctx, texObj, |
_mesa_lookup_enum_by_nr( target ), |
_mesa_lookup_enum_by_nr( pname ) ); |
switch ( pname ) { |
case GL_TEXTURE_MIN_FILTER: |
case GL_TEXTURE_MAG_FILTER: |
case GL_TEXTURE_MAX_ANISOTROPY_EXT: |
case GL_TEXTURE_WRAP_S: |
case GL_TEXTURE_WRAP_T: |
case GL_TEXTURE_WRAP_R: |
case GL_TEXTURE_BORDER_COLOR: |
case GL_TEXTURE_BASE_LEVEL: |
case GL_TEXTURE_MAX_LEVEL: |
case GL_TEXTURE_MIN_LOD: |
case GL_TEXTURE_MAX_LOD: |
t->validated = GL_FALSE; |
break; |
default: |
return; |
} |
} |
static void r200DeleteTexture(struct gl_context * ctx, struct gl_texture_object *texObj) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
radeonTexObj* t = radeon_tex_obj(texObj); |
radeon_print(RADEON_TEXTURE | RADEON_STATE, RADEON_NORMAL, |
"%s( %p (target = %s) )\n", __FUNCTION__, |
(void *)texObj, |
_mesa_lookup_enum_by_nr(texObj->Target)); |
if (rmesa) { |
int i; |
radeon_firevertices(&rmesa->radeon); |
for ( i = 0 ; i < rmesa->radeon.glCtx.Const.MaxTextureUnits ; i++ ) { |
if ( t == rmesa->state.texture.unit[i].texobj ) { |
rmesa->state.texture.unit[i].texobj = NULL; |
rmesa->hw.tex[i].dirty = GL_FALSE; |
rmesa->hw.cube[i].dirty = GL_FALSE; |
} |
} |
} |
radeon_miptree_unreference(&t->mt); |
_mesa_delete_texture_object(ctx, texObj); |
} |
/* Need: |
* - Same GEN_MODE for all active bits |
* - Same EyePlane/ObjPlane for all active bits when using Eye/Obj |
* - STRQ presumably all supported (matrix means incoming R values |
* can end up in STQ, this has implications for vertex support, |
* presumably ok if maos is used, though?) |
* |
* Basically impossible to do this on the fly - just collect some |
* basic info & do the checks from ValidateState(). |
*/ |
static void r200TexGen( struct gl_context *ctx, |
GLenum coord, |
GLenum pname, |
const GLfloat *params ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint unit = ctx->Texture.CurrentUnit; |
rmesa->recheck_texgen[unit] = GL_TRUE; |
} |
/** |
* Allocate a new texture object. |
* Called via ctx->Driver.NewTextureObject. |
* Note: this function will be called during context creation to |
* allocate the default texture objects. |
* Fixup MaxAnisotropy according to user preference. |
*/ |
static struct gl_texture_object *r200NewTextureObject(struct gl_context * ctx, |
GLuint name, |
GLenum target) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
radeonTexObj* t = CALLOC_STRUCT(radeon_tex_obj); |
radeon_print(RADEON_STATE | RADEON_TEXTURE, RADEON_NORMAL, |
"%s(%p) target %s, new texture %p.\n", |
__FUNCTION__, ctx, |
_mesa_lookup_enum_by_nr(target), t); |
_mesa_initialize_texture_object(ctx, &t->base, name, target); |
t->base.Sampler.MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy; |
/* Initialize hardware state */ |
r200SetTexWrap( t, t->base.Sampler.WrapS, t->base.Sampler.WrapT, t->base.Sampler.WrapR ); |
r200SetTexMaxAnisotropy( t, t->base.Sampler.MaxAnisotropy ); |
r200SetTexFilter(t, t->base.Sampler.MinFilter, t->base.Sampler.MagFilter); |
r200SetTexBorderColor(t, t->base.Sampler.BorderColor.f); |
return &t->base; |
} |
static struct gl_sampler_object * |
r200NewSamplerObject(struct gl_context *ctx, GLuint name) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
struct gl_sampler_object *samp = _mesa_new_sampler_object(ctx, name); |
if (samp) |
samp->MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy; |
return samp; |
} |
void r200InitTextureFuncs( radeonContextPtr radeon, struct dd_function_table *functions ) |
{ |
/* Note: we only plug in the functions we implement in the driver |
* since _mesa_init_driver_functions() was already called. |
*/ |
radeon_init_common_texture_funcs(radeon, functions); |
functions->NewTextureObject = r200NewTextureObject; |
// functions->BindTexture = r200BindTexture; |
functions->DeleteTexture = r200DeleteTexture; |
functions->TexEnv = r200TexEnv; |
functions->TexParameter = r200TexParameter; |
functions->TexGen = r200TexGen; |
functions->NewSamplerObject = r200NewSamplerObject; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_tex.h |
---|
0,0 → 1,55 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 __R200_TEX_H__ |
#define __R200_TEX_H__ |
extern void r200SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv); |
extern void r200SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format, |
__DRIdrawable *dPriv); |
extern void r200UpdateTextureState( struct gl_context *ctx ); |
extern int r200UploadTexImages( r200ContextPtr rmesa, radeonTexObjPtr t, GLuint face ); |
extern void r200DestroyTexObj( r200ContextPtr rmesa, radeonTexObjPtr t ); |
extern void r200InitTextureFuncs( radeonContextPtr radeon, struct dd_function_table *functions ); |
extern void r200UpdateFragmentShader( struct gl_context *ctx ); |
extern void r200TexUpdateParameters(struct gl_context *ctx, GLuint unit); |
extern void set_re_cntl_d3d( struct gl_context *ctx, int unit, GLboolean use_d3d ); |
#endif /* __R200_TEX_H__ */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_texstate.c |
---|
0,0 → 1,1711 |
/* |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/imports.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/teximage.h" |
#include "main/texobj.h" |
#include "main/enums.h" |
#include "radeon_common.h" |
#include "radeon_mipmap_tree.h" |
#include "r200_context.h" |
#include "r200_state.h" |
#include "r200_ioctl.h" |
#include "r200_swtcl.h" |
#include "r200_tex.h" |
#include "r200_tcl.h" |
#define R200_TXFORMAT_A8 R200_TXFORMAT_I8 |
#define R200_TXFORMAT_L8 R200_TXFORMAT_I8 |
#define R200_TXFORMAT_AL88 R200_TXFORMAT_AI88 |
#define R200_TXFORMAT_YCBCR R200_TXFORMAT_YVYU422 |
#define R200_TXFORMAT_YCBCR_REV R200_TXFORMAT_VYUY422 |
#define R200_TXFORMAT_RGB_DXT1 R200_TXFORMAT_DXT1 |
#define R200_TXFORMAT_RGBA_DXT1 R200_TXFORMAT_DXT1 |
#define R200_TXFORMAT_RGBA_DXT3 R200_TXFORMAT_DXT23 |
#define R200_TXFORMAT_RGBA_DXT5 R200_TXFORMAT_DXT45 |
#define _COLOR(f) \ |
[ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 } |
#define _COLOR_REV(f) \ |
[ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f, 0 } |
#define _ALPHA(f) \ |
[ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 } |
#define _ALPHA_REV(f) \ |
[ MESA_FORMAT_ ## f ## _REV ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 } |
#define _YUV(f) \ |
[ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB } |
#define _INVALID(f) \ |
[ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 } |
#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \ |
&& (tx_table_be[f].format != 0xffffffff) ) |
struct tx_table { |
GLuint format, filter; |
}; |
static const struct tx_table tx_table_be[] = |
{ |
[ MESA_FORMAT_RGBA8888 ] = { R200_TXFORMAT_ABGR8888 | R200_TXFORMAT_ALPHA_IN_MAP, 0 }, |
_ALPHA_REV(RGBA8888), |
_ALPHA(ARGB8888), |
_ALPHA_REV(ARGB8888), |
_INVALID(RGB888), |
_COLOR(RGB565), |
_COLOR_REV(RGB565), |
_ALPHA(ARGB4444), |
_ALPHA_REV(ARGB4444), |
_ALPHA(ARGB1555), |
_ALPHA_REV(ARGB1555), |
_ALPHA(AL88), |
_ALPHA_REV(AL88), |
_ALPHA(A8), |
_COLOR(L8), |
_ALPHA(I8), |
_YUV(YCBCR), |
_YUV(YCBCR_REV), |
_INVALID(RGB_FXT1), |
_INVALID(RGBA_FXT1), |
_COLOR(RGB_DXT1), |
_ALPHA(RGBA_DXT1), |
_ALPHA(RGBA_DXT3), |
_ALPHA(RGBA_DXT5), |
}; |
static const struct tx_table tx_table_le[] = |
{ |
_ALPHA(RGBA8888), |
[ MESA_FORMAT_RGBA8888_REV ] = { R200_TXFORMAT_ABGR8888 | R200_TXFORMAT_ALPHA_IN_MAP, 0 }, |
_ALPHA(ARGB8888), |
_ALPHA_REV(ARGB8888), |
[ MESA_FORMAT_RGB888 ] = { R200_TXFORMAT_ARGB8888, 0 }, |
_COLOR(RGB565), |
_COLOR_REV(RGB565), |
_ALPHA(ARGB4444), |
_ALPHA_REV(ARGB4444), |
_ALPHA(ARGB1555), |
_ALPHA_REV(ARGB1555), |
_ALPHA(AL88), |
_ALPHA_REV(AL88), |
_ALPHA(A8), |
_COLOR(L8), |
_ALPHA(I8), |
_YUV(YCBCR), |
_YUV(YCBCR_REV), |
_INVALID(RGB_FXT1), |
_INVALID(RGBA_FXT1), |
_COLOR(RGB_DXT1), |
_ALPHA(RGBA_DXT1), |
_ALPHA(RGBA_DXT3), |
_ALPHA(RGBA_DXT5), |
}; |
#undef _COLOR |
#undef _ALPHA |
#undef _INVALID |
/* ================================================================ |
* Texture combine functions |
*/ |
/* GL_ARB_texture_env_combine support |
*/ |
/* The color tables have combine functions for GL_SRC_COLOR, |
* GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA. |
*/ |
static GLuint r200_register_color[][R200_MAX_TEXTURE_UNITS] = |
{ |
{ |
R200_TXC_ARG_A_R0_COLOR, |
R200_TXC_ARG_A_R1_COLOR, |
R200_TXC_ARG_A_R2_COLOR, |
R200_TXC_ARG_A_R3_COLOR, |
R200_TXC_ARG_A_R4_COLOR, |
R200_TXC_ARG_A_R5_COLOR |
}, |
{ |
R200_TXC_ARG_A_R0_COLOR | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_R1_COLOR | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_R2_COLOR | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_R3_COLOR | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_R4_COLOR | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_R5_COLOR | R200_TXC_COMP_ARG_A |
}, |
{ |
R200_TXC_ARG_A_R0_ALPHA, |
R200_TXC_ARG_A_R1_ALPHA, |
R200_TXC_ARG_A_R2_ALPHA, |
R200_TXC_ARG_A_R3_ALPHA, |
R200_TXC_ARG_A_R4_ALPHA, |
R200_TXC_ARG_A_R5_ALPHA |
}, |
{ |
R200_TXC_ARG_A_R0_ALPHA | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_R1_ALPHA | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_R2_ALPHA | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_R3_ALPHA | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_R4_ALPHA | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_R5_ALPHA | R200_TXC_COMP_ARG_A |
}, |
}; |
static GLuint r200_tfactor_color[] = |
{ |
R200_TXC_ARG_A_TFACTOR_COLOR, |
R200_TXC_ARG_A_TFACTOR_COLOR | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_TFACTOR_ALPHA, |
R200_TXC_ARG_A_TFACTOR_ALPHA | R200_TXC_COMP_ARG_A |
}; |
static GLuint r200_tfactor1_color[] = |
{ |
R200_TXC_ARG_A_TFACTOR1_COLOR, |
R200_TXC_ARG_A_TFACTOR1_COLOR | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_TFACTOR1_ALPHA, |
R200_TXC_ARG_A_TFACTOR1_ALPHA | R200_TXC_COMP_ARG_A |
}; |
static GLuint r200_primary_color[] = |
{ |
R200_TXC_ARG_A_DIFFUSE_COLOR, |
R200_TXC_ARG_A_DIFFUSE_COLOR | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_DIFFUSE_ALPHA, |
R200_TXC_ARG_A_DIFFUSE_ALPHA | R200_TXC_COMP_ARG_A |
}; |
/* GL_ZERO table - indices 0-3 |
* GL_ONE table - indices 1-4 |
*/ |
static GLuint r200_zero_color[] = |
{ |
R200_TXC_ARG_A_ZERO, |
R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_ZERO, |
R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A, |
R200_TXC_ARG_A_ZERO |
}; |
/* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA. |
*/ |
static GLuint r200_register_alpha[][R200_MAX_TEXTURE_UNITS] = |
{ |
{ |
R200_TXA_ARG_A_R0_ALPHA, |
R200_TXA_ARG_A_R1_ALPHA, |
R200_TXA_ARG_A_R2_ALPHA, |
R200_TXA_ARG_A_R3_ALPHA, |
R200_TXA_ARG_A_R4_ALPHA, |
R200_TXA_ARG_A_R5_ALPHA |
}, |
{ |
R200_TXA_ARG_A_R0_ALPHA | R200_TXA_COMP_ARG_A, |
R200_TXA_ARG_A_R1_ALPHA | R200_TXA_COMP_ARG_A, |
R200_TXA_ARG_A_R2_ALPHA | R200_TXA_COMP_ARG_A, |
R200_TXA_ARG_A_R3_ALPHA | R200_TXA_COMP_ARG_A, |
R200_TXA_ARG_A_R4_ALPHA | R200_TXA_COMP_ARG_A, |
R200_TXA_ARG_A_R5_ALPHA | R200_TXA_COMP_ARG_A |
}, |
}; |
static GLuint r200_tfactor_alpha[] = |
{ |
R200_TXA_ARG_A_TFACTOR_ALPHA, |
R200_TXA_ARG_A_TFACTOR_ALPHA | R200_TXA_COMP_ARG_A |
}; |
static GLuint r200_tfactor1_alpha[] = |
{ |
R200_TXA_ARG_A_TFACTOR1_ALPHA, |
R200_TXA_ARG_A_TFACTOR1_ALPHA | R200_TXA_COMP_ARG_A |
}; |
static GLuint r200_primary_alpha[] = |
{ |
R200_TXA_ARG_A_DIFFUSE_ALPHA, |
R200_TXA_ARG_A_DIFFUSE_ALPHA | R200_TXA_COMP_ARG_A |
}; |
/* GL_ZERO table - indices 0-1 |
* GL_ONE table - indices 1-2 |
*/ |
static GLuint r200_zero_alpha[] = |
{ |
R200_TXA_ARG_A_ZERO, |
R200_TXA_ARG_A_ZERO | R200_TXA_COMP_ARG_A, |
R200_TXA_ARG_A_ZERO, |
}; |
/* Extract the arg from slot A, shift it into the correct argument slot |
* and set the corresponding complement bit. |
*/ |
#define R200_COLOR_ARG( n, arg ) \ |
do { \ |
color_combine |= \ |
((color_arg[n] & R200_TXC_ARG_A_MASK) \ |
<< R200_TXC_ARG_##arg##_SHIFT); \ |
color_combine |= \ |
((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT) \ |
<< R200_TXC_COMP_ARG_##arg##_SHIFT); \ |
} while (0) |
#define R200_ALPHA_ARG( n, arg ) \ |
do { \ |
alpha_combine |= \ |
((alpha_arg[n] & R200_TXA_ARG_A_MASK) \ |
<< R200_TXA_ARG_##arg##_SHIFT); \ |
alpha_combine |= \ |
((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT) \ |
<< R200_TXA_COMP_ARG_##arg##_SHIFT); \ |
} while (0) |
/* ================================================================ |
* Texture unit state management |
*/ |
static GLboolean r200UpdateTextureEnv( struct gl_context *ctx, int unit, int slot, GLuint replaceargs ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
GLuint color_combine, alpha_combine; |
GLuint color_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] & |
~(R200_TXC_SCALE_MASK | R200_TXC_OUTPUT_REG_MASK | R200_TXC_TFACTOR_SEL_MASK | |
R200_TXC_TFACTOR1_SEL_MASK); |
GLuint alpha_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] & |
~(R200_TXA_DOT_ALPHA | R200_TXA_SCALE_MASK | R200_TXA_OUTPUT_REG_MASK | |
R200_TXA_TFACTOR_SEL_MASK | R200_TXA_TFACTOR1_SEL_MASK); |
/* texUnit->_Current can be NULL if and only if the texture unit is |
* not actually enabled. |
*/ |
assert( (texUnit->_ReallyEnabled == 0) |
|| (texUnit->_Current != NULL) ); |
if ( R200_DEBUG & RADEON_TEXTURE ) { |
fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, (void *)ctx, unit ); |
} |
/* Set the texture environment state. Isn't this nice and clean? |
* The chip will automagically set the texture alpha to 0xff when |
* the texture format does not include an alpha component. This |
* reduces the amount of special-casing we have to do, alpha-only |
* textures being a notable exception. |
*/ |
color_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXC_OUTPUT_REG_SHIFT) | |
(unit << R200_TXC_TFACTOR_SEL_SHIFT) | |
(replaceargs << R200_TXC_TFACTOR1_SEL_SHIFT); |
alpha_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXA_OUTPUT_REG_SHIFT) | |
(unit << R200_TXA_TFACTOR_SEL_SHIFT) | |
(replaceargs << R200_TXA_TFACTOR1_SEL_SHIFT); |
if ( !texUnit->_ReallyEnabled ) { |
assert( unit == 0); |
color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO |
| R200_TXC_ARG_C_DIFFUSE_COLOR | R200_TXC_OP_MADD; |
alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO |
| R200_TXA_ARG_C_DIFFUSE_ALPHA | R200_TXA_OP_MADD; |
} |
else { |
GLuint color_arg[3], alpha_arg[3]; |
GLuint i; |
const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB; |
const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA; |
GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB; |
GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA; |
const GLint replaceoprgb = |
ctx->Texture.Unit[replaceargs]._CurrentCombine->OperandRGB[0] - GL_SRC_COLOR; |
const GLint replaceopa = |
ctx->Texture.Unit[replaceargs]._CurrentCombine->OperandA[0] - GL_SRC_ALPHA; |
/* Step 1: |
* Extract the color and alpha combine function arguments. |
*/ |
for ( i = 0 ; i < numColorArgs ; i++ ) { |
GLint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR; |
const GLint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i]; |
assert(op >= 0); |
assert(op <= 3); |
switch ( srcRGBi ) { |
case GL_TEXTURE: |
color_arg[i] = r200_register_color[op][unit]; |
break; |
case GL_CONSTANT: |
color_arg[i] = r200_tfactor_color[op]; |
break; |
case GL_PRIMARY_COLOR: |
color_arg[i] = r200_primary_color[op]; |
break; |
case GL_PREVIOUS: |
if (replaceargs != unit) { |
const GLint srcRGBreplace = |
ctx->Texture.Unit[replaceargs]._CurrentCombine->SourceRGB[0]; |
if (op >= 2) { |
op = op ^ replaceopa; |
} |
else { |
op = op ^ replaceoprgb; |
} |
switch (srcRGBreplace) { |
case GL_TEXTURE: |
color_arg[i] = r200_register_color[op][replaceargs]; |
break; |
case GL_CONSTANT: |
color_arg[i] = r200_tfactor1_color[op]; |
break; |
case GL_PRIMARY_COLOR: |
color_arg[i] = r200_primary_color[op]; |
break; |
case GL_PREVIOUS: |
if (slot == 0) |
color_arg[i] = r200_primary_color[op]; |
else |
color_arg[i] = r200_register_color[op] |
[rmesa->state.texture.unit[replaceargs - 1].outputreg]; |
break; |
case GL_ZERO: |
color_arg[i] = r200_zero_color[op]; |
break; |
case GL_ONE: |
color_arg[i] = r200_zero_color[op+1]; |
break; |
case GL_TEXTURE0: |
case GL_TEXTURE1: |
case GL_TEXTURE2: |
case GL_TEXTURE3: |
case GL_TEXTURE4: |
case GL_TEXTURE5: |
color_arg[i] = r200_register_color[op][srcRGBreplace - GL_TEXTURE0]; |
break; |
default: |
return GL_FALSE; |
} |
} |
else { |
if (slot == 0) |
color_arg[i] = r200_primary_color[op]; |
else |
color_arg[i] = r200_register_color[op] |
[rmesa->state.texture.unit[unit - 1].outputreg]; |
} |
break; |
case GL_ZERO: |
color_arg[i] = r200_zero_color[op]; |
break; |
case GL_ONE: |
color_arg[i] = r200_zero_color[op+1]; |
break; |
case GL_TEXTURE0: |
case GL_TEXTURE1: |
case GL_TEXTURE2: |
case GL_TEXTURE3: |
case GL_TEXTURE4: |
case GL_TEXTURE5: |
color_arg[i] = r200_register_color[op][srcRGBi - GL_TEXTURE0]; |
break; |
default: |
return GL_FALSE; |
} |
} |
for ( i = 0 ; i < numAlphaArgs ; i++ ) { |
GLint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA; |
const GLint srcAi = texUnit->_CurrentCombine->SourceA[i]; |
assert(op >= 0); |
assert(op <= 1); |
switch ( srcAi ) { |
case GL_TEXTURE: |
alpha_arg[i] = r200_register_alpha[op][unit]; |
break; |
case GL_CONSTANT: |
alpha_arg[i] = r200_tfactor_alpha[op]; |
break; |
case GL_PRIMARY_COLOR: |
alpha_arg[i] = r200_primary_alpha[op]; |
break; |
case GL_PREVIOUS: |
if (replaceargs != unit) { |
const GLint srcAreplace = |
ctx->Texture.Unit[replaceargs]._CurrentCombine->SourceA[0]; |
op = op ^ replaceopa; |
switch (srcAreplace) { |
case GL_TEXTURE: |
alpha_arg[i] = r200_register_alpha[op][replaceargs]; |
break; |
case GL_CONSTANT: |
alpha_arg[i] = r200_tfactor1_alpha[op]; |
break; |
case GL_PRIMARY_COLOR: |
alpha_arg[i] = r200_primary_alpha[op]; |
break; |
case GL_PREVIOUS: |
if (slot == 0) |
alpha_arg[i] = r200_primary_alpha[op]; |
else |
alpha_arg[i] = r200_register_alpha[op] |
[rmesa->state.texture.unit[replaceargs - 1].outputreg]; |
break; |
case GL_ZERO: |
alpha_arg[i] = r200_zero_alpha[op]; |
break; |
case GL_ONE: |
alpha_arg[i] = r200_zero_alpha[op+1]; |
break; |
case GL_TEXTURE0: |
case GL_TEXTURE1: |
case GL_TEXTURE2: |
case GL_TEXTURE3: |
case GL_TEXTURE4: |
case GL_TEXTURE5: |
alpha_arg[i] = r200_register_alpha[op][srcAreplace - GL_TEXTURE0]; |
break; |
default: |
return GL_FALSE; |
} |
} |
else { |
if (slot == 0) |
alpha_arg[i] = r200_primary_alpha[op]; |
else |
alpha_arg[i] = r200_register_alpha[op] |
[rmesa->state.texture.unit[unit - 1].outputreg]; |
} |
break; |
case GL_ZERO: |
alpha_arg[i] = r200_zero_alpha[op]; |
break; |
case GL_ONE: |
alpha_arg[i] = r200_zero_alpha[op+1]; |
break; |
case GL_TEXTURE0: |
case GL_TEXTURE1: |
case GL_TEXTURE2: |
case GL_TEXTURE3: |
case GL_TEXTURE4: |
case GL_TEXTURE5: |
alpha_arg[i] = r200_register_alpha[op][srcAi - GL_TEXTURE0]; |
break; |
default: |
return GL_FALSE; |
} |
} |
/* Step 2: |
* Build up the color and alpha combine functions. |
*/ |
switch ( texUnit->_CurrentCombine->ModeRGB ) { |
case GL_REPLACE: |
color_combine = (R200_TXC_ARG_A_ZERO | |
R200_TXC_ARG_B_ZERO | |
R200_TXC_OP_MADD); |
R200_COLOR_ARG( 0, C ); |
break; |
case GL_MODULATE: |
color_combine = (R200_TXC_ARG_C_ZERO | |
R200_TXC_OP_MADD); |
R200_COLOR_ARG( 0, A ); |
R200_COLOR_ARG( 1, B ); |
break; |
case GL_ADD: |
color_combine = (R200_TXC_ARG_B_ZERO | |
R200_TXC_COMP_ARG_B | |
R200_TXC_OP_MADD); |
R200_COLOR_ARG( 0, A ); |
R200_COLOR_ARG( 1, C ); |
break; |
case GL_ADD_SIGNED: |
color_combine = (R200_TXC_ARG_B_ZERO | |
R200_TXC_COMP_ARG_B | |
R200_TXC_BIAS_ARG_C | /* new */ |
R200_TXC_OP_MADD); /* was ADDSIGNED */ |
R200_COLOR_ARG( 0, A ); |
R200_COLOR_ARG( 1, C ); |
break; |
case GL_SUBTRACT: |
color_combine = (R200_TXC_ARG_B_ZERO | |
R200_TXC_COMP_ARG_B | |
R200_TXC_NEG_ARG_C | |
R200_TXC_OP_MADD); |
R200_COLOR_ARG( 0, A ); |
R200_COLOR_ARG( 1, C ); |
break; |
case GL_INTERPOLATE: |
color_combine = (R200_TXC_OP_LERP); |
R200_COLOR_ARG( 0, B ); |
R200_COLOR_ARG( 1, A ); |
R200_COLOR_ARG( 2, C ); |
break; |
case GL_DOT3_RGB_EXT: |
case GL_DOT3_RGBA_EXT: |
/* The EXT version of the DOT3 extension does not support the |
* scale factor, but the ARB version (and the version in OpenGL |
* 1.3) does. |
*/ |
RGBshift = 0; |
/* FALLTHROUGH */ |
case GL_DOT3_RGB: |
case GL_DOT3_RGBA: |
/* DOT3 works differently on R200 than on R100. On R100, just |
* setting the DOT3 mode did everything for you. On R200, the |
* driver has to enable the biasing and scale in the inputs to |
* put them in the proper [-1,1] range. This is what the 4x and |
* the -0.5 in the DOT3 spec do. The post-scale is then set |
* normally. |
*/ |
color_combine = (R200_TXC_ARG_C_ZERO | |
R200_TXC_OP_DOT3 | |
R200_TXC_BIAS_ARG_A | |
R200_TXC_BIAS_ARG_B | |
R200_TXC_SCALE_ARG_A | |
R200_TXC_SCALE_ARG_B); |
R200_COLOR_ARG( 0, A ); |
R200_COLOR_ARG( 1, B ); |
break; |
case GL_MODULATE_ADD_ATI: |
color_combine = (R200_TXC_OP_MADD); |
R200_COLOR_ARG( 0, A ); |
R200_COLOR_ARG( 1, C ); |
R200_COLOR_ARG( 2, B ); |
break; |
case GL_MODULATE_SIGNED_ADD_ATI: |
color_combine = (R200_TXC_BIAS_ARG_C | /* new */ |
R200_TXC_OP_MADD); /* was ADDSIGNED */ |
R200_COLOR_ARG( 0, A ); |
R200_COLOR_ARG( 1, C ); |
R200_COLOR_ARG( 2, B ); |
break; |
case GL_MODULATE_SUBTRACT_ATI: |
color_combine = (R200_TXC_NEG_ARG_C | |
R200_TXC_OP_MADD); |
R200_COLOR_ARG( 0, A ); |
R200_COLOR_ARG( 1, C ); |
R200_COLOR_ARG( 2, B ); |
break; |
default: |
return GL_FALSE; |
} |
switch ( texUnit->_CurrentCombine->ModeA ) { |
case GL_REPLACE: |
alpha_combine = (R200_TXA_ARG_A_ZERO | |
R200_TXA_ARG_B_ZERO | |
R200_TXA_OP_MADD); |
R200_ALPHA_ARG( 0, C ); |
break; |
case GL_MODULATE: |
alpha_combine = (R200_TXA_ARG_C_ZERO | |
R200_TXA_OP_MADD); |
R200_ALPHA_ARG( 0, A ); |
R200_ALPHA_ARG( 1, B ); |
break; |
case GL_ADD: |
alpha_combine = (R200_TXA_ARG_B_ZERO | |
R200_TXA_COMP_ARG_B | |
R200_TXA_OP_MADD); |
R200_ALPHA_ARG( 0, A ); |
R200_ALPHA_ARG( 1, C ); |
break; |
case GL_ADD_SIGNED: |
alpha_combine = (R200_TXA_ARG_B_ZERO | |
R200_TXA_COMP_ARG_B | |
R200_TXA_BIAS_ARG_C | /* new */ |
R200_TXA_OP_MADD); /* was ADDSIGNED */ |
R200_ALPHA_ARG( 0, A ); |
R200_ALPHA_ARG( 1, C ); |
break; |
case GL_SUBTRACT: |
alpha_combine = (R200_TXA_ARG_B_ZERO | |
R200_TXA_COMP_ARG_B | |
R200_TXA_NEG_ARG_C | |
R200_TXA_OP_MADD); |
R200_ALPHA_ARG( 0, A ); |
R200_ALPHA_ARG( 1, C ); |
break; |
case GL_INTERPOLATE: |
alpha_combine = (R200_TXA_OP_LERP); |
R200_ALPHA_ARG( 0, B ); |
R200_ALPHA_ARG( 1, A ); |
R200_ALPHA_ARG( 2, C ); |
break; |
case GL_MODULATE_ADD_ATI: |
alpha_combine = (R200_TXA_OP_MADD); |
R200_ALPHA_ARG( 0, A ); |
R200_ALPHA_ARG( 1, C ); |
R200_ALPHA_ARG( 2, B ); |
break; |
case GL_MODULATE_SIGNED_ADD_ATI: |
alpha_combine = (R200_TXA_BIAS_ARG_C | /* new */ |
R200_TXA_OP_MADD); /* was ADDSIGNED */ |
R200_ALPHA_ARG( 0, A ); |
R200_ALPHA_ARG( 1, C ); |
R200_ALPHA_ARG( 2, B ); |
break; |
case GL_MODULATE_SUBTRACT_ATI: |
alpha_combine = (R200_TXA_NEG_ARG_C | |
R200_TXA_OP_MADD); |
R200_ALPHA_ARG( 0, A ); |
R200_ALPHA_ARG( 1, C ); |
R200_ALPHA_ARG( 2, B ); |
break; |
default: |
return GL_FALSE; |
} |
if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT) |
|| (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) { |
alpha_scale |= R200_TXA_DOT_ALPHA; |
Ashift = RGBshift; |
} |
/* Step 3: |
* Apply the scale factor. |
*/ |
color_scale |= (RGBshift << R200_TXC_SCALE_SHIFT); |
alpha_scale |= (Ashift << R200_TXA_SCALE_SHIFT); |
/* All done! |
*/ |
} |
if ( rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] != color_combine || |
rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] != alpha_combine || |
rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] != color_scale || |
rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] != alpha_scale) { |
R200_STATECHANGE( rmesa, pix[slot] ); |
rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] = color_combine; |
rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] = alpha_combine; |
rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] = color_scale; |
rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] = alpha_scale; |
} |
return GL_TRUE; |
} |
void r200SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint texture_format, |
__DRIdrawable *dPriv) |
{ |
struct gl_texture_unit *texUnit; |
struct gl_texture_object *texObj; |
struct gl_texture_image *texImage; |
struct radeon_renderbuffer *rb; |
radeon_texture_image *rImage; |
radeonContextPtr radeon; |
struct radeon_framebuffer *rfb; |
radeonTexObjPtr t; |
uint32_t pitch_val; |
gl_format texFormat; |
radeon = pDRICtx->driverPrivate; |
rfb = dPriv->driverPrivate; |
texUnit = &radeon->glCtx.Texture.Unit[radeon->glCtx.Texture.CurrentUnit]; |
texObj = _mesa_select_tex_object(&radeon->glCtx, texUnit, target); |
texImage = _mesa_get_tex_image(&radeon->glCtx, texObj, target, 0); |
rImage = get_radeon_texture_image(texImage); |
t = radeon_tex_obj(texObj); |
if (t == NULL) { |
return; |
} |
radeon_update_renderbuffers(pDRICtx, dPriv, GL_TRUE); |
rb = rfb->color_rb[0]; |
if (rb->bo == NULL) { |
/* Failed to BO for the buffer */ |
return; |
} |
_mesa_lock_texture(&radeon->glCtx, texObj); |
if (t->bo) { |
radeon_bo_unref(t->bo); |
t->bo = NULL; |
} |
if (rImage->bo) { |
radeon_bo_unref(rImage->bo); |
rImage->bo = NULL; |
} |
radeon_miptree_unreference(&t->mt); |
radeon_miptree_unreference(&rImage->mt); |
rImage->bo = rb->bo; |
radeon_bo_ref(rImage->bo); |
t->bo = rb->bo; |
radeon_bo_ref(t->bo); |
t->tile_bits = 0; |
t->image_override = GL_TRUE; |
t->override_offset = 0; |
t->pp_txpitch &= (1 << 13) -1; |
pitch_val = rb->pitch; |
switch (rb->cpp) { |
case 4: |
if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { |
texFormat = MESA_FORMAT_RGB888; |
t->pp_txformat = tx_table_le[MESA_FORMAT_RGB888].format; |
} |
else { |
texFormat = MESA_FORMAT_ARGB8888; |
t->pp_txformat = tx_table_le[MESA_FORMAT_ARGB8888].format; |
} |
t->pp_txfilter |= tx_table_le[MESA_FORMAT_ARGB8888].filter; |
break; |
case 3: |
default: |
texFormat = MESA_FORMAT_RGB888; |
t->pp_txformat = tx_table_le[MESA_FORMAT_RGB888].format; |
t->pp_txfilter |= tx_table_le[MESA_FORMAT_RGB888].filter; |
break; |
case 2: |
texFormat = MESA_FORMAT_RGB565; |
t->pp_txformat = tx_table_le[MESA_FORMAT_RGB565].format; |
t->pp_txfilter |= tx_table_le[MESA_FORMAT_RGB565].filter; |
break; |
} |
_mesa_init_teximage_fields(&radeon->glCtx, texImage, |
rb->base.Base.Width, rb->base.Base.Height, |
1, 0, |
rb->cpp, texFormat); |
rImage->base.RowStride = rb->pitch / rb->cpp; |
t->pp_txsize = ((rb->base.Base.Width - 1) << RADEON_TEX_USIZE_SHIFT) |
| ((rb->base.Base.Height - 1) << RADEON_TEX_VSIZE_SHIFT); |
if (target == GL_TEXTURE_RECTANGLE_NV) { |
t->pp_txformat |= R200_TXFORMAT_NON_POWER2; |
t->pp_txpitch = pitch_val; |
t->pp_txpitch -= 32; |
} else { |
t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK | |
R200_TXFORMAT_HEIGHT_MASK | |
R200_TXFORMAT_CUBIC_MAP_ENABLE | |
R200_TXFORMAT_F5_WIDTH_MASK | |
R200_TXFORMAT_F5_HEIGHT_MASK); |
t->pp_txformat |= ((texImage->WidthLog2 << R200_TXFORMAT_WIDTH_SHIFT) | |
(texImage->HeightLog2 << R200_TXFORMAT_HEIGHT_SHIFT)); |
} |
t->validated = GL_TRUE; |
_mesa_unlock_texture(&radeon->glCtx, texObj); |
return; |
} |
void r200SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv) |
{ |
r200SetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); |
} |
#define REF_COLOR 1 |
#define REF_ALPHA 2 |
static GLboolean r200UpdateAllTexEnv( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLint i, j, currslot; |
GLint maxunitused = -1; |
GLboolean texregfree[6] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}; |
GLubyte stageref[7] = {0, 0, 0, 0, 0, 0, 0}; |
GLint nextunit[R200_MAX_TEXTURE_UNITS] = {0, 0, 0, 0, 0, 0}; |
GLint currentnext = -1; |
GLboolean ok; |
/* find highest used unit */ |
for ( j = 0; j < R200_MAX_TEXTURE_UNITS; j++) { |
if (ctx->Texture.Unit[j]._ReallyEnabled) { |
maxunitused = j; |
} |
} |
stageref[maxunitused + 1] = REF_COLOR | REF_ALPHA; |
for ( j = maxunitused; j >= 0; j-- ) { |
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[j]; |
rmesa->state.texture.unit[j].outputreg = -1; |
if (stageref[j + 1]) { |
/* use the lowest available reg. That gets us automatically reg0 for the last stage. |
need this even for disabled units, as it may get referenced due to the replace |
optimization */ |
for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS; i++ ) { |
if (texregfree[i]) { |
rmesa->state.texture.unit[j].outputreg = i; |
break; |
} |
} |
if (rmesa->state.texture.unit[j].outputreg == -1) { |
/* no more free regs we can use. Need a fallback :-( */ |
return GL_FALSE; |
} |
nextunit[j] = currentnext; |
if (!texUnit->_ReallyEnabled) { |
/* the not enabled stages are referenced "indirectly", |
must not cut off the lower stages */ |
stageref[j] = REF_COLOR | REF_ALPHA; |
continue; |
} |
currentnext = j; |
const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB; |
const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA; |
const GLboolean isdot3rgba = (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) || |
(texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT); |
/* check if we need the color part, special case for dot3_rgba |
as if only the alpha part is referenced later on it still is using the color part */ |
if ((stageref[j + 1] & REF_COLOR) || isdot3rgba) { |
for ( i = 0 ; i < numColorArgs ; i++ ) { |
const GLuint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i]; |
const GLuint op = texUnit->_CurrentCombine->OperandRGB[i]; |
switch ( srcRGBi ) { |
case GL_PREVIOUS: |
/* op 0/1 are referencing color, op 2/3 alpha */ |
stageref[j] |= (op >> 1) + 1; |
break; |
case GL_TEXTURE: |
texregfree[j] = GL_FALSE; |
break; |
case GL_TEXTURE0: |
case GL_TEXTURE1: |
case GL_TEXTURE2: |
case GL_TEXTURE3: |
case GL_TEXTURE4: |
case GL_TEXTURE5: |
texregfree[srcRGBi - GL_TEXTURE0] = GL_FALSE; |
break; |
default: /* don't care about other sources here */ |
break; |
} |
} |
} |
/* alpha args are ignored for dot3_rgba */ |
if ((stageref[j + 1] & REF_ALPHA) && !isdot3rgba) { |
for ( i = 0 ; i < numAlphaArgs ; i++ ) { |
const GLuint srcAi = texUnit->_CurrentCombine->SourceA[i]; |
switch ( srcAi ) { |
case GL_PREVIOUS: |
stageref[j] |= REF_ALPHA; |
break; |
case GL_TEXTURE: |
texregfree[j] = GL_FALSE; |
break; |
case GL_TEXTURE0: |
case GL_TEXTURE1: |
case GL_TEXTURE2: |
case GL_TEXTURE3: |
case GL_TEXTURE4: |
case GL_TEXTURE5: |
texregfree[srcAi - GL_TEXTURE0] = GL_FALSE; |
break; |
default: /* don't care about other sources here */ |
break; |
} |
} |
} |
} |
} |
/* don't enable texture sampling for units if the result is not used */ |
for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) { |
if (ctx->Texture.Unit[i]._ReallyEnabled && !texregfree[i]) |
rmesa->state.texture.unit[i].unitneeded = ctx->Texture.Unit[i]._ReallyEnabled; |
else rmesa->state.texture.unit[i].unitneeded = 0; |
} |
ok = GL_TRUE; |
currslot = 0; |
rmesa->state.envneeded = 1; |
i = 0; |
while ((i <= maxunitused) && (i >= 0)) { |
/* only output instruction if the results are referenced */ |
if (ctx->Texture.Unit[i]._ReallyEnabled && stageref[i+1]) { |
GLuint replaceunit = i; |
/* try to optimize GL_REPLACE away (only one level deep though) */ |
if ( (ctx->Texture.Unit[i]._CurrentCombine->ModeRGB == GL_REPLACE) && |
(ctx->Texture.Unit[i]._CurrentCombine->ModeA == GL_REPLACE) && |
(ctx->Texture.Unit[i]._CurrentCombine->ScaleShiftRGB == 0) && |
(ctx->Texture.Unit[i]._CurrentCombine->ScaleShiftA == 0) && |
(nextunit[i] > 0) ) { |
/* yippie! can optimize it away! */ |
replaceunit = i; |
i = nextunit[i]; |
} |
/* need env instruction slot */ |
rmesa->state.envneeded |= 1 << currslot; |
ok = r200UpdateTextureEnv( ctx, i, currslot, replaceunit ); |
if (!ok) return GL_FALSE; |
currslot++; |
} |
i = i + 1; |
} |
if (currslot == 0) { |
/* need one stage at least */ |
rmesa->state.texture.unit[0].outputreg = 0; |
ok = r200UpdateTextureEnv( ctx, 0, 0, 0 ); |
} |
R200_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_BLEND_ENABLE_MASK | R200_MULTI_PASS_ENABLE); |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= rmesa->state.envneeded << R200_TEX_BLEND_0_ENABLE_SHIFT; |
return ok; |
} |
#undef REF_COLOR |
#undef REF_ALPHA |
#define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK | \ |
R200_MIN_FILTER_MASK | \ |
R200_MAG_FILTER_MASK | \ |
R200_MAX_ANISO_MASK | \ |
R200_YUV_TO_RGB | \ |
R200_YUV_TEMPERATURE_MASK | \ |
R200_CLAMP_S_MASK | \ |
R200_CLAMP_T_MASK | \ |
R200_BORDER_MODE_D3D ) |
#define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK | \ |
R200_TXFORMAT_HEIGHT_MASK | \ |
R200_TXFORMAT_FORMAT_MASK | \ |
R200_TXFORMAT_F5_WIDTH_MASK | \ |
R200_TXFORMAT_F5_HEIGHT_MASK | \ |
R200_TXFORMAT_ALPHA_IN_MAP | \ |
R200_TXFORMAT_CUBIC_MAP_ENABLE | \ |
R200_TXFORMAT_NON_POWER2) |
#define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK | \ |
R200_TEXCOORD_MASK | \ |
R200_MIN_MIP_LEVEL_MASK | \ |
R200_CLAMP_Q_MASK | \ |
R200_VOLUME_FILTER_MASK) |
static void disable_tex_obj_state( r200ContextPtr rmesa, |
int unit ) |
{ |
R200_STATECHANGE( rmesa, vtx ); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3)); |
R200_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_0_ENABLE << unit); |
if (rmesa->radeon.TclFallback & (R200_TCL_FALLBACK_TEXGEN_0<<unit)) { |
TCL_FALLBACK( &rmesa->radeon.glCtx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE); |
} |
/* Actually want to keep all units less than max active texture |
* enabled, right? Fix this for >2 texunits. |
*/ |
{ |
GLuint tmp = rmesa->TexGenEnabled; |
rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit); |
rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit); |
rmesa->TexGenNeedNormals[unit] = GL_FALSE; |
rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit); |
if (tmp != rmesa->TexGenEnabled) { |
rmesa->recheck_texgen[unit] = GL_TRUE; |
rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX; |
} |
} |
} |
static void import_tex_obj_state( r200ContextPtr rmesa, |
int unit, |
radeonTexObjPtr texobj ) |
{ |
/* do not use RADEON_DB_STATE to avoid stale texture caches */ |
GLuint *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0]; |
R200_STATECHANGE( rmesa, tex[unit] ); |
cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK; |
cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK; |
cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; |
cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK; |
cmd[TEX_PP_TXFORMAT_X] &= ~TEXOBJ_TXFORMAT_X_MASK; |
cmd[TEX_PP_TXFORMAT_X] |= texobj->pp_txformat_x & TEXOBJ_TXFORMAT_X_MASK; |
cmd[TEX_PP_TXSIZE] = texobj->pp_txsize; /* NPOT only! */ |
cmd[TEX_PP_TXPITCH] = texobj->pp_txpitch; /* NPOT only! */ |
cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color; |
if (texobj->base.Target == GL_TEXTURE_CUBE_MAP) { |
GLuint *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0]; |
R200_STATECHANGE( rmesa, cube[unit] ); |
cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces; |
/* that value is submitted twice. could change cube atom |
to not include that command when new drm is used */ |
cmd[TEX_PP_CUBIC_FACES] = texobj->pp_cubic_faces; |
} |
} |
static void set_texgen_matrix( r200ContextPtr rmesa, |
GLuint unit, |
const GLfloat *s_plane, |
const GLfloat *t_plane, |
const GLfloat *r_plane, |
const GLfloat *q_plane ) |
{ |
GLfloat m[16]; |
m[0] = s_plane[0]; |
m[4] = s_plane[1]; |
m[8] = s_plane[2]; |
m[12] = s_plane[3]; |
m[1] = t_plane[0]; |
m[5] = t_plane[1]; |
m[9] = t_plane[2]; |
m[13] = t_plane[3]; |
m[2] = r_plane[0]; |
m[6] = r_plane[1]; |
m[10] = r_plane[2]; |
m[14] = r_plane[3]; |
m[3] = q_plane[0]; |
m[7] = q_plane[1]; |
m[11] = q_plane[2]; |
m[15] = q_plane[3]; |
_math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m); |
_math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) ); |
rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit; |
} |
static GLuint r200_need_dis_texgen(const GLbitfield texGenEnabled, |
const GLfloat *planeS, |
const GLfloat *planeT, |
const GLfloat *planeR, |
const GLfloat *planeQ) |
{ |
GLuint needtgenable = 0; |
if (!(texGenEnabled & S_BIT)) { |
if (((texGenEnabled & T_BIT) && planeT[0] != 0.0) || |
((texGenEnabled & R_BIT) && planeR[0] != 0.0) || |
((texGenEnabled & Q_BIT) && planeQ[0] != 0.0)) { |
needtgenable |= S_BIT; |
} |
} |
if (!(texGenEnabled & T_BIT)) { |
if (((texGenEnabled & S_BIT) && planeS[1] != 0.0) || |
((texGenEnabled & R_BIT) && planeR[1] != 0.0) || |
((texGenEnabled & Q_BIT) && planeQ[1] != 0.0)) { |
needtgenable |= T_BIT; |
} |
} |
if (!(texGenEnabled & R_BIT)) { |
if (((texGenEnabled & S_BIT) && planeS[2] != 0.0) || |
((texGenEnabled & T_BIT) && planeT[2] != 0.0) || |
((texGenEnabled & Q_BIT) && planeQ[2] != 0.0)) { |
needtgenable |= R_BIT; |
} |
} |
if (!(texGenEnabled & Q_BIT)) { |
if (((texGenEnabled & S_BIT) && planeS[3] != 0.0) || |
((texGenEnabled & T_BIT) && planeT[3] != 0.0) || |
((texGenEnabled & R_BIT) && planeR[3] != 0.0)) { |
needtgenable |= Q_BIT; |
} |
} |
return needtgenable; |
} |
/* |
* Returns GL_FALSE if fallback required. |
*/ |
static GLboolean r200_validate_texgen( struct gl_context *ctx, GLuint unit ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4; |
GLuint tgi, tgcm; |
GLuint mode = 0; |
GLboolean mixed_fallback = GL_FALSE; |
static const GLfloat I[16] = { |
1, 0, 0, 0, |
0, 1, 0, 0, |
0, 0, 1, 0, |
0, 0, 0, 1 }; |
static const GLfloat reflect[16] = { |
-1, 0, 0, 0, |
0, -1, 0, 0, |
0, 0, -1, 0, |
0, 0, 0, 1 }; |
rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit); |
rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit); |
rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit); |
rmesa->TexGenNeedNormals[unit] = GL_FALSE; |
tgi = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] & ~(R200_TEXGEN_INPUT_MASK << |
inputshift); |
tgcm = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] & ~(R200_TEXGEN_COMP_MASK << |
(unit * 4)); |
if (0) |
fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit); |
if (texUnit->TexGenEnabled & S_BIT) { |
mode = texUnit->GenS.Mode; |
} else { |
tgcm |= R200_TEXGEN_COMP_S << (unit * 4); |
} |
if (texUnit->TexGenEnabled & T_BIT) { |
if (texUnit->GenT.Mode != mode) |
mixed_fallback = GL_TRUE; |
} else { |
tgcm |= R200_TEXGEN_COMP_T << (unit * 4); |
} |
if (texUnit->TexGenEnabled & R_BIT) { |
if (texUnit->GenR.Mode != mode) |
mixed_fallback = GL_TRUE; |
} else { |
tgcm |= R200_TEXGEN_COMP_R << (unit * 4); |
} |
if (texUnit->TexGenEnabled & Q_BIT) { |
if (texUnit->GenQ.Mode != mode) |
mixed_fallback = GL_TRUE; |
} else { |
tgcm |= R200_TEXGEN_COMP_Q << (unit * 4); |
} |
if (mixed_fallback) { |
if (R200_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n", |
texUnit->TexGenEnabled, texUnit->GenS.Mode, texUnit->GenT.Mode, |
texUnit->GenR.Mode, texUnit->GenQ.Mode); |
return GL_FALSE; |
} |
/* we CANNOT do mixed mode if the texgen mode requires a plane where the input |
is not enabled for texgen, since the planes are concatenated into texmat, |
and thus the input will come from texcoord rather than tex gen equation! |
Either fallback or just hope that those texcoords aren't really needed... |
Assuming the former will cause lots of unnecessary fallbacks, the latter will |
generate bogus results sometimes - it's pretty much impossible to really know |
when a fallback is needed, depends on texmat and what sort of texture is bound |
etc, - for now fallback if we're missing either S or T bits, there's a high |
probability we need the texcoords in that case. |
That's a lot of work for some obscure texgen mixed mode fixup - why oh why |
doesn't the chip just directly accept the plane parameters :-(. */ |
switch (mode) { |
case GL_OBJECT_LINEAR: { |
GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled, |
texUnit->GenS.ObjectPlane, |
texUnit->GenT.ObjectPlane, |
texUnit->GenR.ObjectPlane, |
texUnit->GenQ.ObjectPlane ); |
if (needtgenable & (S_BIT | T_BIT)) { |
if (R200_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "fallback mixed texgen / obj plane, 0x%x\n", |
texUnit->TexGenEnabled); |
return GL_FALSE; |
} |
if (needtgenable & (R_BIT)) { |
tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4)); |
} |
if (needtgenable & (Q_BIT)) { |
tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4)); |
} |
tgi |= R200_TEXGEN_INPUT_OBJ << inputshift; |
set_texgen_matrix( rmesa, unit, |
(texUnit->TexGenEnabled & S_BIT) ? texUnit->GenS.ObjectPlane : I, |
(texUnit->TexGenEnabled & T_BIT) ? texUnit->GenT.ObjectPlane : I + 4, |
(texUnit->TexGenEnabled & R_BIT) ? texUnit->GenR.ObjectPlane : I + 8, |
(texUnit->TexGenEnabled & Q_BIT) ? texUnit->GenQ.ObjectPlane : I + 12); |
} |
break; |
case GL_EYE_LINEAR: { |
GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled, |
texUnit->GenS.EyePlane, |
texUnit->GenT.EyePlane, |
texUnit->GenR.EyePlane, |
texUnit->GenQ.EyePlane ); |
if (needtgenable & (S_BIT | T_BIT)) { |
if (R200_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "fallback mixed texgen / eye plane, 0x%x\n", |
texUnit->TexGenEnabled); |
return GL_FALSE; |
} |
if (needtgenable & (R_BIT)) { |
tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4)); |
} |
if (needtgenable & (Q_BIT)) { |
tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4)); |
} |
tgi |= R200_TEXGEN_INPUT_EYE << inputshift; |
set_texgen_matrix( rmesa, unit, |
(texUnit->TexGenEnabled & S_BIT) ? texUnit->GenS.EyePlane : I, |
(texUnit->TexGenEnabled & T_BIT) ? texUnit->GenT.EyePlane : I + 4, |
(texUnit->TexGenEnabled & R_BIT) ? texUnit->GenR.EyePlane : I + 8, |
(texUnit->TexGenEnabled & Q_BIT) ? texUnit->GenQ.EyePlane : I + 12); |
} |
break; |
case GL_REFLECTION_MAP_NV: |
rmesa->TexGenNeedNormals[unit] = GL_TRUE; |
tgi |= R200_TEXGEN_INPUT_EYE_REFLECT << inputshift; |
/* pretty weird, must only negate when lighting is enabled? */ |
if (ctx->Light.Enabled) |
set_texgen_matrix( rmesa, unit, |
(texUnit->TexGenEnabled & S_BIT) ? reflect : I, |
(texUnit->TexGenEnabled & T_BIT) ? reflect + 4 : I + 4, |
(texUnit->TexGenEnabled & R_BIT) ? reflect + 8 : I + 8, |
I + 12); |
break; |
case GL_NORMAL_MAP_NV: |
rmesa->TexGenNeedNormals[unit] = GL_TRUE; |
tgi |= R200_TEXGEN_INPUT_EYE_NORMAL<<inputshift; |
break; |
case GL_SPHERE_MAP: |
rmesa->TexGenNeedNormals[unit] = GL_TRUE; |
tgi |= R200_TEXGEN_INPUT_SPHERE<<inputshift; |
break; |
case 0: |
/* All texgen units were disabled, so just pass coords through. */ |
tgi |= unit << inputshift; |
break; |
default: |
/* Unsupported mode, fallback: |
*/ |
if (R200_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "fallback unsupported texgen, %d\n", |
texUnit->GenS.Mode); |
return GL_FALSE; |
} |
rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit; |
rmesa->TexGenCompSel |= R200_OUTPUT_TEX_0 << unit; |
if (tgi != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] || |
tgcm != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2]) |
{ |
R200_STATECHANGE(rmesa, tcg); |
rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = tgi; |
rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] = tgcm; |
} |
return GL_TRUE; |
} |
void set_re_cntl_d3d( struct gl_context *ctx, int unit, GLboolean use_d3d ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint re_cntl; |
re_cntl = rmesa->hw.set.cmd[SET_RE_CNTL] & ~(R200_VTX_STQ0_D3D << (2 * unit)); |
if (use_d3d) |
re_cntl |= R200_VTX_STQ0_D3D << (2 * unit); |
if ( re_cntl != rmesa->hw.set.cmd[SET_RE_CNTL] ) { |
R200_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_RE_CNTL] = re_cntl; |
} |
} |
/** |
* Compute the cached hardware register values for the given texture object. |
* |
* \param rmesa Context pointer |
* \param t the r300 texture object |
*/ |
static void setup_hardware_state(r200ContextPtr rmesa, radeonTexObj *t) |
{ |
const struct gl_texture_image *firstImage = t->base.Image[0][t->minLod]; |
GLint log2Width, log2Height, log2Depth, texelBytes; |
uint extra_size = 0; |
if ( t->bo ) { |
return; |
} |
log2Width = firstImage->WidthLog2; |
log2Height = firstImage->HeightLog2; |
log2Depth = firstImage->DepthLog2; |
texelBytes = _mesa_get_format_bytes(firstImage->TexFormat); |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(%p, tex %p) log2(w %d, h %d, d %d), texelBytes %d. format %d\n", |
__func__, rmesa, t, log2Width, log2Height, |
log2Depth, texelBytes, firstImage->TexFormat); |
if (!t->image_override) { |
if (VALID_FORMAT(firstImage->TexFormat)) { |
const struct tx_table *table = _mesa_little_endian() ? tx_table_le : |
tx_table_be; |
t->pp_txformat &= ~(R200_TXFORMAT_FORMAT_MASK | |
R200_TXFORMAT_ALPHA_IN_MAP); |
t->pp_txfilter &= ~R200_YUV_TO_RGB; |
t->pp_txformat |= table[ firstImage->TexFormat ].format; |
t->pp_txfilter |= table[ firstImage->TexFormat ].filter; |
} else { |
_mesa_problem(NULL, "unexpected texture format in %s", |
__FUNCTION__); |
return; |
} |
} |
t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK; |
t->pp_txfilter |= ((t->maxLod) << R200_MAX_MIP_LEVEL_SHIFT) |
& R200_MAX_MIP_LEVEL_MASK; |
if ( t->pp_txfilter & |
(R200_MIN_FILTER_NEAREST_MIP_NEAREST |
| R200_MIN_FILTER_NEAREST_MIP_LINEAR |
| R200_MIN_FILTER_LINEAR_MIP_NEAREST |
| R200_MIN_FILTER_LINEAR_MIP_LINEAR |
| R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST |
| R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR)) |
extra_size = t->minLod; |
t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK | |
R200_TXFORMAT_HEIGHT_MASK | |
R200_TXFORMAT_CUBIC_MAP_ENABLE | |
R200_TXFORMAT_F5_WIDTH_MASK | |
R200_TXFORMAT_F5_HEIGHT_MASK); |
t->pp_txformat |= (((log2Width + extra_size) << R200_TXFORMAT_WIDTH_SHIFT) | |
((log2Height + extra_size)<< R200_TXFORMAT_HEIGHT_SHIFT)); |
t->tile_bits = 0; |
t->pp_txformat_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK |
| R200_MIN_MIP_LEVEL_MASK); |
t->pp_txformat_x |= (t->minLod << R200_MIN_MIP_LEVEL_SHIFT) |
& R200_MIN_MIP_LEVEL_MASK; |
if (t->base.Target == GL_TEXTURE_3D) { |
t->pp_txformat_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT); |
t->pp_txformat_x |= R200_TEXCOORD_VOLUME; |
} |
else if (t->base.Target == GL_TEXTURE_CUBE_MAP) { |
ASSERT(log2Width == log2Height); |
t->pp_txformat |= ((log2Width << R200_TXFORMAT_F5_WIDTH_SHIFT) | |
(log2Height << R200_TXFORMAT_F5_HEIGHT_SHIFT) | |
/* don't think we need this bit, if it exists at all - fglrx does not set it */ |
(R200_TXFORMAT_CUBIC_MAP_ENABLE)); |
t->pp_txformat_x |= R200_TEXCOORD_CUBIC_ENV; |
t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) | |
(log2Height << R200_FACE_HEIGHT_1_SHIFT) | |
(log2Width << R200_FACE_WIDTH_2_SHIFT) | |
(log2Height << R200_FACE_HEIGHT_2_SHIFT) | |
(log2Width << R200_FACE_WIDTH_3_SHIFT) | |
(log2Height << R200_FACE_HEIGHT_3_SHIFT) | |
(log2Width << R200_FACE_WIDTH_4_SHIFT) | |
(log2Height << R200_FACE_HEIGHT_4_SHIFT)); |
} |
else { |
/* If we don't in fact send enough texture coordinates, q will be 1, |
* making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?) |
*/ |
t->pp_txformat_x |= R200_TEXCOORD_PROJ; |
} |
/* FIXME: NPOT sizes, Is it correct realy? */ |
t->pp_txsize = (((firstImage->Width - 1) << R200_PP_TX_WIDTHMASK_SHIFT) |
| ((firstImage->Height - 1) << R200_PP_TX_HEIGHTMASK_SHIFT)); |
if ( !t->image_override ) { |
if (_mesa_is_format_compressed(firstImage->TexFormat)) |
t->pp_txpitch = (firstImage->Width + 63) & ~(63); |
else |
t->pp_txpitch = ((firstImage->Width * texelBytes) + 63) & ~(63); |
t->pp_txpitch -= 32; |
} |
if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) { |
t->pp_txformat |= R200_TXFORMAT_NON_POWER2; |
} |
} |
static GLboolean r200_validate_texture(struct gl_context *ctx, struct gl_texture_object *texObj, int unit) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
radeonTexObj *t = radeon_tex_obj(texObj); |
if (!radeon_validate_texture_miptree(ctx, _mesa_get_samplerobj(ctx, unit), texObj)) |
return GL_FALSE; |
r200_validate_texgen(ctx, unit); |
/* Configure the hardware registers (more precisely, the cached version |
* of the hardware registers). */ |
setup_hardware_state(rmesa, t); |
if (texObj->Target == GL_TEXTURE_RECTANGLE_NV || |
texObj->Target == GL_TEXTURE_2D || |
texObj->Target == GL_TEXTURE_1D) |
set_re_cntl_d3d( ctx, unit, GL_FALSE ); |
else |
set_re_cntl_d3d( ctx, unit, GL_TRUE ); |
R200_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << unit; |
R200_STATECHANGE( rmesa, vtx ); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3)); |
rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3); |
rmesa->recheck_texgen[unit] = GL_TRUE; |
r200TexUpdateParameters(ctx, unit); |
import_tex_obj_state( rmesa, unit, t ); |
if (rmesa->recheck_texgen[unit]) { |
GLboolean fallback = !r200_validate_texgen( ctx, unit ); |
TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), fallback); |
rmesa->recheck_texgen[unit] = 0; |
rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX; |
} |
t->validated = GL_TRUE; |
FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback ); |
return !t->border_fallback; |
} |
static GLboolean r200UpdateTextureUnit(struct gl_context *ctx, int unit) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLuint unitneeded = rmesa->state.texture.unit[unit].unitneeded; |
if (!unitneeded) { |
/* disable the unit */ |
disable_tex_obj_state(rmesa, unit); |
return GL_TRUE; |
} |
if (!r200_validate_texture(ctx, ctx->Texture.Unit[unit]._Current, unit)) { |
_mesa_warning(ctx, |
"failed to validate texture for unit %d.\n", |
unit); |
rmesa->state.texture.unit[unit].texobj = NULL; |
return GL_FALSE; |
} |
rmesa->state.texture.unit[unit].texobj = radeon_tex_obj(ctx->Texture.Unit[unit]._Current); |
return GL_TRUE; |
} |
void r200UpdateTextureState( struct gl_context *ctx ) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
GLboolean ok; |
GLuint dbg; |
/* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or |
rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since |
we use these to determine if we want to emit the corresponding state |
atoms. */ |
R200_NEWPRIM( rmesa ); |
if (ctx->ATIFragmentShader._Enabled) { |
GLuint i; |
for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) { |
rmesa->state.texture.unit[i].unitneeded = ctx->Texture.Unit[i]._ReallyEnabled; |
} |
ok = GL_TRUE; |
} |
else { |
ok = r200UpdateAllTexEnv( ctx ); |
} |
if (ok) { |
ok = (r200UpdateTextureUnit( ctx, 0 ) && |
r200UpdateTextureUnit( ctx, 1 ) && |
r200UpdateTextureUnit( ctx, 2 ) && |
r200UpdateTextureUnit( ctx, 3 ) && |
r200UpdateTextureUnit( ctx, 4 ) && |
r200UpdateTextureUnit( ctx, 5 )); |
} |
if (ok && ctx->ATIFragmentShader._Enabled) { |
r200UpdateFragmentShader(ctx); |
} |
FALLBACK( rmesa, R200_FALLBACK_TEXTURE, !ok ); |
if (rmesa->radeon.TclFallback) |
r200ChooseVertexState( ctx ); |
if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200) { |
/* |
* T0 hang workaround ------------- |
* not needed for r200 derivatives |
*/ |
if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_ENABLE_MASK) == R200_TEX_0_ENABLE && |
(rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) { |
R200_STATECHANGE(rmesa, ctx); |
R200_STATECHANGE(rmesa, tex[1]); |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE; |
if (!(rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_1_ENABLE)) |
rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; |
rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= R200_TXFORMAT_LOOKUP_DISABLE; |
} |
else if (!ctx->ATIFragmentShader._Enabled) { |
if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) && |
(rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] & R200_TXFORMAT_LOOKUP_DISABLE)) { |
R200_STATECHANGE(rmesa, tex[1]); |
rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~R200_TXFORMAT_LOOKUP_DISABLE; |
} |
} |
/* do the same workaround for the first pass of a fragment shader. |
* completely unknown if necessary / sufficient. |
*/ |
if ((rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_ENABLE_MASK) == R200_PPX_TEX_0_ENABLE && |
(rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) { |
R200_STATECHANGE(rmesa, cst); |
R200_STATECHANGE(rmesa, tex[1]); |
rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_1_ENABLE; |
if (!(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE)) |
rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; |
rmesa->hw.tex[1].cmd[TEX_PP_TXMULTI_CTL] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE; |
} |
/* maybe needs to be done pairwise due to 2 parallel (physical) tex units ? |
looks like that's not the case, if 8500/9100 owners don't complain remove this... |
for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) { |
if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE | |
R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) && |
((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > |
R200_MIN_FILTER_LINEAR)) { |
R200_STATECHANGE(rmesa, ctx); |
R200_STATECHANGE(rmesa, tex[i+1]); |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i); |
rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; |
rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000; |
} |
else { |
if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) && |
(rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) { |
R200_STATECHANGE(rmesa, tex[i+1]); |
rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000; |
} |
} |
} */ |
/* |
* Texture cache LRU hang workaround ------------- |
* not needed for r200 derivatives |
* hopefully this covers first pass of a shader as well |
*/ |
/* While the cases below attempt to only enable the workaround in the |
* specific cases necessary, they were insufficient. See bugzilla #1519, |
* #729, #814. Tests with quake3 showed no impact on performance. |
*/ |
dbg = 0x6; |
/* |
if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) && |
((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & |
0x04) == 0)) || |
((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) && |
((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & |
0x04) == 0)) || |
((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) && |
((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & |
0x04) == 0))) |
{ |
dbg |= 0x02; |
} |
if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) && |
((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & |
0x04) == 0)) || |
((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) && |
((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & |
0x04) == 0)) || |
((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) && |
((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & |
0x04) == 0))) |
{ |
dbg |= 0x04; |
}*/ |
if (dbg != rmesa->hw.tam.cmd[TAM_DEBUG3]) { |
R200_STATECHANGE( rmesa, tam ); |
rmesa->hw.tam.cmd[TAM_DEBUG3] = dbg; |
if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg); |
} |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_vertprog.c |
---|
0,0 → 1,1276 |
/************************************************************************** |
Copyright (C) 2005 Aapo Tahkola. |
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 |
on 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 COPYRIGHT OWNER(S) 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: |
* Aapo Tahkola <aet@rasterburn.org> |
* Roland Scheidegger <rscheidegger_lists@hispeed.ch> |
*/ |
#include "main/glheader.h" |
#include "main/macros.h" |
#include "main/enums.h" |
#include "program/program.h" |
#include "program/prog_instruction.h" |
#include "program/prog_parameter.h" |
#include "program/prog_statevars.h" |
#include "program/programopt.h" |
#include "tnl/tnl.h" |
#include "r200_context.h" |
#include "r200_vertprog.h" |
#include "r200_ioctl.h" |
#include "r200_tcl.h" |
#if SWIZZLE_X != VSF_IN_COMPONENT_X || \ |
SWIZZLE_Y != VSF_IN_COMPONENT_Y || \ |
SWIZZLE_Z != VSF_IN_COMPONENT_Z || \ |
SWIZZLE_W != VSF_IN_COMPONENT_W || \ |
SWIZZLE_ZERO != VSF_IN_COMPONENT_ZERO || \ |
SWIZZLE_ONE != VSF_IN_COMPONENT_ONE || \ |
WRITEMASK_X != VSF_FLAG_X || \ |
WRITEMASK_Y != VSF_FLAG_Y || \ |
WRITEMASK_Z != VSF_FLAG_Z || \ |
WRITEMASK_W != VSF_FLAG_W |
#error Cannot change these! |
#endif |
#define SCALAR_FLAG (1<<31) |
#define FLAG_MASK (1<<31) |
#define OP_MASK (0xf) /* we are unlikely to have more than 15 */ |
#define OPN(operator, ip) {#operator, OPCODE_##operator, ip} |
static struct{ |
char *name; |
int opcode; |
unsigned long ip; /* number of input operands and flags */ |
}op_names[]={ |
OPN(ABS, 1), |
OPN(ADD, 2), |
OPN(ARL, 1|SCALAR_FLAG), |
OPN(DP3, 2), |
OPN(DP4, 2), |
OPN(DPH, 2), |
OPN(DST, 2), |
OPN(EX2, 1|SCALAR_FLAG), |
OPN(EXP, 1|SCALAR_FLAG), |
OPN(FLR, 1), |
OPN(FRC, 1), |
OPN(LG2, 1|SCALAR_FLAG), |
OPN(LIT, 1), |
OPN(LOG, 1|SCALAR_FLAG), |
OPN(MAD, 3), |
OPN(MAX, 2), |
OPN(MIN, 2), |
OPN(MOV, 1), |
OPN(MUL, 2), |
OPN(POW, 2|SCALAR_FLAG), |
OPN(RCP, 1|SCALAR_FLAG), |
OPN(RSQ, 1|SCALAR_FLAG), |
OPN(SGE, 2), |
OPN(SLT, 2), |
OPN(SUB, 2), |
OPN(SWZ, 1), |
OPN(XPD, 2), |
OPN(END, 0), |
}; |
#undef OPN |
static GLboolean r200VertexProgUpdateParams(struct gl_context *ctx, struct r200_vertex_program *vp) |
{ |
r200ContextPtr rmesa = R200_CONTEXT( ctx ); |
GLfloat *fcmd = (GLfloat *)&rmesa->hw.vpp[0].cmd[VPP_CMD_0 + 1]; |
int pi; |
struct gl_vertex_program *mesa_vp = &vp->mesa_program; |
struct gl_program_parameter_list *paramList; |
drm_radeon_cmd_header_t tmp; |
R200_STATECHANGE( rmesa, vpp[0] ); |
R200_STATECHANGE( rmesa, vpp[1] ); |
assert(mesa_vp->Base.Parameters); |
_mesa_load_state_parameters(ctx, mesa_vp->Base.Parameters); |
paramList = mesa_vp->Base.Parameters; |
if(paramList->NumParameters > R200_VSF_MAX_PARAM){ |
fprintf(stderr, "%s:Params exhausted\n", __FUNCTION__); |
return GL_FALSE; |
} |
for(pi = 0; pi < paramList->NumParameters; pi++) { |
switch(paramList->Parameters[pi].Type) { |
case PROGRAM_STATE_VAR: |
//fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name); |
case PROGRAM_CONSTANT: |
*fcmd++ = paramList->ParameterValues[pi][0].f; |
*fcmd++ = paramList->ParameterValues[pi][1].f; |
*fcmd++ = paramList->ParameterValues[pi][2].f; |
*fcmd++ = paramList->ParameterValues[pi][3].f; |
break; |
default: |
_mesa_problem(NULL, "Bad param type in %s", __FUNCTION__); |
break; |
} |
if (pi == 95) { |
fcmd = (GLfloat *)&rmesa->hw.vpp[1].cmd[VPP_CMD_0 + 1]; |
} |
} |
/* hack up the cmd_size so not the whole state atom is emitted always. */ |
rmesa->hw.vpp[0].cmd_size = |
1 + 4 * ((paramList->NumParameters > 96) ? 96 : paramList->NumParameters); |
tmp.i = rmesa->hw.vpp[0].cmd[VPP_CMD_0]; |
tmp.veclinear.count = (paramList->NumParameters > 96) ? 96 : paramList->NumParameters; |
rmesa->hw.vpp[0].cmd[VPP_CMD_0] = tmp.i; |
if (paramList->NumParameters > 96) { |
rmesa->hw.vpp[1].cmd_size = 1 + 4 * (paramList->NumParameters - 96); |
tmp.i = rmesa->hw.vpp[1].cmd[VPP_CMD_0]; |
tmp.veclinear.count = paramList->NumParameters - 96; |
rmesa->hw.vpp[1].cmd[VPP_CMD_0] = tmp.i; |
} |
return GL_TRUE; |
} |
static INLINE unsigned long t_dst_mask(GLuint mask) |
{ |
/* WRITEMASK_* is equivalent to VSF_FLAG_* */ |
return mask & VSF_FLAG_ALL; |
} |
static unsigned long t_dst(struct prog_dst_register *dst) |
{ |
switch(dst->File) { |
case PROGRAM_TEMPORARY: |
return ((dst->Index << R200_VPI_OUT_REG_INDEX_SHIFT) |
| R200_VSF_OUT_CLASS_TMP); |
case PROGRAM_OUTPUT: |
switch (dst->Index) { |
case VARYING_SLOT_POS: |
return R200_VSF_OUT_CLASS_RESULT_POS; |
case VARYING_SLOT_COL0: |
return R200_VSF_OUT_CLASS_RESULT_COLOR; |
case VARYING_SLOT_COL1: |
return ((1 << R200_VPI_OUT_REG_INDEX_SHIFT) |
| R200_VSF_OUT_CLASS_RESULT_COLOR); |
case VARYING_SLOT_FOGC: |
return R200_VSF_OUT_CLASS_RESULT_FOGC; |
case VARYING_SLOT_TEX0: |
case VARYING_SLOT_TEX1: |
case VARYING_SLOT_TEX2: |
case VARYING_SLOT_TEX3: |
case VARYING_SLOT_TEX4: |
case VARYING_SLOT_TEX5: |
return (((dst->Index - VARYING_SLOT_TEX0) << R200_VPI_OUT_REG_INDEX_SHIFT) |
| R200_VSF_OUT_CLASS_RESULT_TEXC); |
case VARYING_SLOT_PSIZ: |
return R200_VSF_OUT_CLASS_RESULT_POINTSIZE; |
default: |
fprintf(stderr, "problem in %s, unknown dst output reg %d\n", __FUNCTION__, dst->Index); |
exit(0); |
return 0; |
} |
case PROGRAM_ADDRESS: |
assert (dst->Index == 0); |
return R200_VSF_OUT_CLASS_ADDR; |
default: |
fprintf(stderr, "problem in %s, unknown register type %d\n", __FUNCTION__, dst->File); |
exit(0); |
return 0; |
} |
} |
static unsigned long t_src_class(gl_register_file file) |
{ |
switch(file){ |
case PROGRAM_TEMPORARY: |
return VSF_IN_CLASS_TMP; |
case PROGRAM_INPUT: |
return VSF_IN_CLASS_ATTR; |
case PROGRAM_LOCAL_PARAM: |
case PROGRAM_ENV_PARAM: |
case PROGRAM_CONSTANT: |
case PROGRAM_STATE_VAR: |
return VSF_IN_CLASS_PARAM; |
/* |
case PROGRAM_OUTPUT: |
case PROGRAM_ADDRESS: |
*/ |
default: |
fprintf(stderr, "problem in %s", __FUNCTION__); |
exit(0); |
} |
} |
static INLINE unsigned long t_swizzle(GLubyte swizzle) |
{ |
/* this is in fact a NOP as the Mesa SWIZZLE_* are all identical to VSF_IN_COMPONENT_* */ |
return swizzle; |
} |
#if 0 |
static void vp_dump_inputs(struct r200_vertex_program *vp, char *caller) |
{ |
int i; |
if(vp == NULL){ |
fprintf(stderr, "vp null in call to %s from %s\n", __FUNCTION__, caller); |
return ; |
} |
fprintf(stderr, "%s:<", caller); |
for(i=0; i < VERT_ATTRIB_MAX; i++) |
fprintf(stderr, "%d ", vp->inputs[i]); |
fprintf(stderr, ">\n"); |
} |
#endif |
static unsigned long t_src_index(struct r200_vertex_program *vp, struct prog_src_register *src) |
{ |
/* |
int i; |
int max_reg = -1; |
*/ |
if(src->File == PROGRAM_INPUT){ |
/* if(vp->inputs[src->Index] != -1) |
return vp->inputs[src->Index]; |
for(i=0; i < VERT_ATTRIB_MAX; i++) |
if(vp->inputs[i] > max_reg) |
max_reg = vp->inputs[i]; |
vp->inputs[src->Index] = max_reg+1;*/ |
//vp_dump_inputs(vp, __FUNCTION__); |
assert(vp->inputs[src->Index] != -1); |
return vp->inputs[src->Index]; |
} else { |
if (src->Index < 0) { |
fprintf(stderr, "WARNING negative offsets for indirect addressing do not work\n"); |
return 0; |
} |
return src->Index; |
} |
} |
static unsigned long t_src(struct r200_vertex_program *vp, struct prog_src_register *src) |
{ |
return MAKE_VSF_SOURCE(t_src_index(vp, src), |
t_swizzle(GET_SWZ(src->Swizzle, 0)), |
t_swizzle(GET_SWZ(src->Swizzle, 1)), |
t_swizzle(GET_SWZ(src->Swizzle, 2)), |
t_swizzle(GET_SWZ(src->Swizzle, 3)), |
t_src_class(src->File), |
src->Negate) | (src->RelAddr << 4); |
} |
static unsigned long t_src_scalar(struct r200_vertex_program *vp, struct prog_src_register *src) |
{ |
return MAKE_VSF_SOURCE(t_src_index(vp, src), |
t_swizzle(GET_SWZ(src->Swizzle, 0)), |
t_swizzle(GET_SWZ(src->Swizzle, 0)), |
t_swizzle(GET_SWZ(src->Swizzle, 0)), |
t_swizzle(GET_SWZ(src->Swizzle, 0)), |
t_src_class(src->File), |
src->Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src->RelAddr << 4); |
} |
static unsigned long t_opcode(enum prog_opcode opcode) |
{ |
switch(opcode){ |
case OPCODE_ADD: return R200_VPI_OUT_OP_ADD; |
/* FIXME: ARL works fine, but negative offsets won't work - fglrx just |
* seems to ignore neg offsets which isn't quite correct... |
*/ |
case OPCODE_ARL: return R200_VPI_OUT_OP_ARL; |
case OPCODE_DP4: return R200_VPI_OUT_OP_DOT; |
case OPCODE_DST: return R200_VPI_OUT_OP_DST; |
case OPCODE_EX2: return R200_VPI_OUT_OP_EX2; |
case OPCODE_EXP: return R200_VPI_OUT_OP_EXP; |
case OPCODE_FRC: return R200_VPI_OUT_OP_FRC; |
case OPCODE_LG2: return R200_VPI_OUT_OP_LG2; |
case OPCODE_LIT: return R200_VPI_OUT_OP_LIT; |
case OPCODE_LOG: return R200_VPI_OUT_OP_LOG; |
case OPCODE_MAX: return R200_VPI_OUT_OP_MAX; |
case OPCODE_MIN: return R200_VPI_OUT_OP_MIN; |
case OPCODE_MUL: return R200_VPI_OUT_OP_MUL; |
case OPCODE_RCP: return R200_VPI_OUT_OP_RCP; |
case OPCODE_RSQ: return R200_VPI_OUT_OP_RSQ; |
case OPCODE_SGE: return R200_VPI_OUT_OP_SGE; |
case OPCODE_SLT: return R200_VPI_OUT_OP_SLT; |
default: |
fprintf(stderr, "%s: Should not be called with opcode %d!", __FUNCTION__, opcode); |
} |
exit(-1); |
return 0; |
} |
static unsigned long op_operands(enum prog_opcode opcode) |
{ |
int i; |
/* Can we trust mesas opcodes to be in order ? */ |
for(i=0; i < sizeof(op_names) / sizeof(*op_names); i++) |
if(op_names[i].opcode == opcode) |
return op_names[i].ip; |
fprintf(stderr, "op %d not found in op_names\n", opcode); |
exit(-1); |
return 0; |
} |
/* TODO: Get rid of t_src_class call */ |
#define CMP_SRCS(a, b) (((a.RelAddr != b.RelAddr) || (a.Index != b.Index)) && \ |
((t_src_class(a.File) == VSF_IN_CLASS_PARAM && \ |
t_src_class(b.File) == VSF_IN_CLASS_PARAM) || \ |
(t_src_class(a.File) == VSF_IN_CLASS_ATTR && \ |
t_src_class(b.File) == VSF_IN_CLASS_ATTR))) \ |
/* fglrx on rv250 codes up unused sources as follows: |
unused but necessary sources are same as previous source, zero-ed out. |
unnecessary sources are same as previous source but with VSF_IN_CLASS_NONE set. |
i.e. an add (2 args) has its 2nd arg (if you use it as mov) zero-ed out, and 3rd arg |
set to VSF_IN_CLASS_NONE. Not sure if strictly necessary. */ |
/* use these simpler definitions. Must obviously not be used with not yet set up regs. |
Those are NOT semantically equivalent to the r300 ones, requires code changes */ |
#define ZERO_SRC_0 (((o_inst->src0 & ~(0xfff << R200_VPI_IN_X_SHIFT)) \ |
| ((R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_X_SHIFT) \ |
| (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Y_SHIFT) \ |
| (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Z_SHIFT) \ |
| (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_W_SHIFT)))) |
#define ZERO_SRC_1 (((o_inst->src1 & ~(0xfff << R200_VPI_IN_X_SHIFT)) \ |
| ((R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_X_SHIFT) \ |
| (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Y_SHIFT) \ |
| (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Z_SHIFT) \ |
| (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_W_SHIFT)))) |
#define ZERO_SRC_2 (((o_inst->src2 & ~(0xfff << R200_VPI_IN_X_SHIFT)) \ |
| ((R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_X_SHIFT) \ |
| (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Y_SHIFT) \ |
| (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_Z_SHIFT) \ |
| (R200_VPI_IN_SELECT_ZERO << R200_VPI_IN_W_SHIFT)))) |
#define UNUSED_SRC_0 ((o_inst->src0 & ~15) | 9) |
#define UNUSED_SRC_1 ((o_inst->src1 & ~15) | 9) |
#define UNUSED_SRC_2 ((o_inst->src2 & ~15) | 9) |
/** |
* Generate an R200 vertex program from Mesa's internal representation. |
* |
* \return GL_TRUE for success, GL_FALSE for failure. |
*/ |
static GLboolean r200_translate_vertex_program(struct gl_context *ctx, struct r200_vertex_program *vp) |
{ |
struct gl_vertex_program *mesa_vp = &vp->mesa_program; |
struct prog_instruction *vpi; |
int i; |
VERTEX_SHADER_INSTRUCTION *o_inst; |
unsigned long operands; |
int are_srcs_scalar; |
unsigned long hw_op; |
int dofogfix = 0; |
int fog_temp_i = 0; |
int free_inputs; |
int array_count = 0; |
int u_temp_used; |
vp->native = GL_FALSE; |
vp->translated = GL_TRUE; |
vp->fogmode = ctx->Fog.Mode; |
if (mesa_vp->Base.NumInstructions == 0) |
return GL_FALSE; |
#if 0 |
if ((mesa_vp->Base.InputsRead & |
~(VERT_BIT_POS | VERT_BIT_NORMAL | VERT_BIT_COLOR0 | VERT_BIT_COLOR1 | |
VERT_BIT_FOG | VERT_BIT_TEX0 | VERT_BIT_TEX1 | VERT_BIT_TEX2 | |
VERT_BIT_TEX3 | VERT_BIT_TEX4 | VERT_BIT_TEX5)) != 0) { |
if (R200_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "can't handle vert prog inputs 0x%x\n", |
mesa_vp->Base.InputsRead); |
} |
return GL_FALSE; |
} |
#endif |
if ((mesa_vp->Base.OutputsWritten & |
~((1 << VARYING_SLOT_POS) | (1 << VARYING_SLOT_COL0) | (1 << VARYING_SLOT_COL1) | |
(1 << VARYING_SLOT_FOGC) | (1 << VARYING_SLOT_TEX0) | (1 << VARYING_SLOT_TEX1) | |
(1 << VARYING_SLOT_TEX2) | (1 << VARYING_SLOT_TEX3) | (1 << VARYING_SLOT_TEX4) | |
(1 << VARYING_SLOT_TEX5) | (1 << VARYING_SLOT_PSIZ))) != 0) { |
if (R200_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "can't handle vert prog outputs 0x%llx\n", |
(unsigned long long) mesa_vp->Base.OutputsWritten); |
} |
return GL_FALSE; |
} |
/* Initial value should be last tmp reg that hw supports. |
Strangely enough r300 doesnt mind even though these would be out of range. |
Smart enough to realize that it doesnt need it? */ |
int u_temp_i = R200_VSF_MAX_TEMPS - 1; |
struct prog_src_register src[3]; |
struct prog_dst_register dst; |
/* FIXME: is changing the prog safe to do here? */ |
if (mesa_vp->IsPositionInvariant && |
/* make sure we only do this once */ |
!(mesa_vp->Base.OutputsWritten & (1 << VARYING_SLOT_POS))) { |
_mesa_insert_mvp_code(ctx, mesa_vp); |
} |
/* for fogc, can't change mesa_vp, as it would hose swtnl, and exp with |
base e isn't directly available neither. */ |
if ((mesa_vp->Base.OutputsWritten & (1 << VARYING_SLOT_FOGC)) && !vp->fogpidx) { |
struct gl_program_parameter_list *paramList; |
gl_state_index tokens[STATE_LENGTH] = { STATE_FOG_PARAMS, 0, 0, 0, 0 }; |
paramList = mesa_vp->Base.Parameters; |
vp->fogpidx = _mesa_add_state_reference(paramList, tokens); |
} |
vp->pos_end = 0; |
mesa_vp->Base.NumNativeInstructions = 0; |
if (mesa_vp->Base.Parameters) |
mesa_vp->Base.NumNativeParameters = mesa_vp->Base.Parameters->NumParameters; |
else |
mesa_vp->Base.NumNativeParameters = 0; |
for(i = 0; i < VERT_ATTRIB_MAX; i++) |
vp->inputs[i] = -1; |
for(i = 0; i < 15; i++) |
vp->inputmap_rev[i] = 255; |
free_inputs = 0x2ffd; |
/* fglrx uses fixed inputs as follows for conventional attribs. |
generic attribs use non-fixed assignment, fglrx will always use the |
lowest attrib values available. We'll just do the same. |
There are 12 generic attribs possible, corresponding to attrib 0, 2-11 |
and 13 in a hw vertex prog. |
attr 1 and 12 aren't used for generic attribs as those cannot be made vec4 |
(correspond to vertex normal/weight - maybe weight actually could be made vec4). |
Additionally, not more than 12 arrays in total are possible I think. |
attr 0 is pos, R200_VTX_XY1|R200_VTX_Z1|R200_VTX_W1 in R200_SE_VTX_FMT_0 |
attr 2-5 use colors 0-3 (R200_VTX_FP_RGBA << R200_VTX_COLOR_0/1/2/3_SHIFT in R200_SE_VTX_FMT_0) |
attr 6-11 use tex 0-5 (4 << R200_VTX_TEX0/1/2/3/4/5_COMP_CNT_SHIFT in R200_SE_VTX_FMT_1) |
attr 13 uses vtx1 pos (R200_VTX_XY1|R200_VTX_Z1|R200_VTX_W1 in R200_SE_VTX_FMT_0) |
*/ |
/* attr 4,5 and 13 are only used with generic attribs. |
Haven't seen attr 14 used, maybe that's for the hw pointsize vec1 (which is |
not possibe to use with vertex progs as it is lacking in vert prog specification) */ |
/* may look different when using idx buf / input_route instead of se_vtx_fmt? */ |
if (mesa_vp->Base.InputsRead & VERT_BIT_POS) { |
vp->inputs[VERT_ATTRIB_POS] = 0; |
vp->inputmap_rev[0] = VERT_ATTRIB_POS; |
free_inputs &= ~(1 << 0); |
array_count++; |
} |
if (mesa_vp->Base.InputsRead & VERT_BIT_WEIGHT) { |
vp->inputs[VERT_ATTRIB_WEIGHT] = 12; |
vp->inputmap_rev[1] = VERT_ATTRIB_WEIGHT; |
array_count++; |
} |
if (mesa_vp->Base.InputsRead & VERT_BIT_NORMAL) { |
vp->inputs[VERT_ATTRIB_NORMAL] = 1; |
vp->inputmap_rev[2] = VERT_ATTRIB_NORMAL; |
array_count++; |
} |
if (mesa_vp->Base.InputsRead & VERT_BIT_COLOR0) { |
vp->inputs[VERT_ATTRIB_COLOR0] = 2; |
vp->inputmap_rev[4] = VERT_ATTRIB_COLOR0; |
free_inputs &= ~(1 << 2); |
array_count++; |
} |
if (mesa_vp->Base.InputsRead & VERT_BIT_COLOR1) { |
vp->inputs[VERT_ATTRIB_COLOR1] = 3; |
vp->inputmap_rev[5] = VERT_ATTRIB_COLOR1; |
free_inputs &= ~(1 << 3); |
array_count++; |
} |
if (mesa_vp->Base.InputsRead & VERT_BIT_FOG) { |
vp->inputs[VERT_ATTRIB_FOG] = 15; array_count++; |
vp->inputmap_rev[3] = VERT_ATTRIB_FOG; |
array_count++; |
} |
/* VERT_ATTRIB_TEX0-5 */ |
for (i = 0; i <= 5; i++) { |
if (mesa_vp->Base.InputsRead & VERT_BIT_TEX(i)) { |
vp->inputs[VERT_ATTRIB_TEX(i)] = i + 6; |
vp->inputmap_rev[8 + i] = VERT_ATTRIB_TEX(i); |
free_inputs &= ~(1 << (i + 6)); |
array_count++; |
} |
} |
/* using VERT_ATTRIB_TEX6/7 would be illegal */ |
for (; i < VERT_ATTRIB_TEX_MAX; i++) { |
if (mesa_vp->Base.InputsRead & VERT_BIT_TEX(i)) { |
if (R200_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "texture attribute %d in vert prog\n", i); |
} |
return GL_FALSE; |
} |
} |
/* completely ignore aliasing? */ |
for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) { |
int j; |
/* completely ignore aliasing? */ |
if (mesa_vp->Base.InputsRead & VERT_BIT_GENERIC(i)) { |
array_count++; |
if (array_count > 12) { |
if (R200_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "more than 12 attribs used in vert prog\n"); |
} |
return GL_FALSE; |
} |
for (j = 0; j < 14; j++) { |
/* will always find one due to limited array_count */ |
if (free_inputs & (1 << j)) { |
free_inputs &= ~(1 << j); |
vp->inputs[VERT_ATTRIB_GENERIC(i)] = j; |
if (j == 0) { |
/* mapped to pos */ |
vp->inputmap_rev[j] = VERT_ATTRIB_GENERIC(i); |
} else if (j < 12) { |
/* mapped to col/tex */ |
vp->inputmap_rev[j + 2] = VERT_ATTRIB_GENERIC(i); |
} else { |
/* mapped to pos1 */ |
vp->inputmap_rev[j + 1] = VERT_ATTRIB_GENERIC(i); |
} |
break; |
} |
} |
} |
} |
if (!(mesa_vp->Base.OutputsWritten & (1 << VARYING_SLOT_POS))) { |
if (R200_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "can't handle vert prog without position output\n"); |
} |
return GL_FALSE; |
} |
if (free_inputs & 1) { |
if (R200_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "can't handle vert prog without position input\n"); |
} |
return GL_FALSE; |
} |
o_inst = vp->instr; |
for (vpi = mesa_vp->Base.Instructions; vpi->Opcode != OPCODE_END; vpi++, o_inst++){ |
operands = op_operands(vpi->Opcode); |
are_srcs_scalar = operands & SCALAR_FLAG; |
operands &= OP_MASK; |
for(i = 0; i < operands; i++) { |
src[i] = vpi->SrcReg[i]; |
/* hack up default attrib values as per spec as swizzling. |
normal, fog, secondary color. Crazy? |
May need more if we don't submit vec4 elements? */ |
if (src[i].File == PROGRAM_INPUT) { |
if (src[i].Index == VERT_ATTRIB_NORMAL) { |
int j; |
for (j = 0; j < 4; j++) { |
if (GET_SWZ(src[i].Swizzle, j) == SWIZZLE_W) { |
src[i].Swizzle &= ~(SWIZZLE_W << (j*3)); |
src[i].Swizzle |= SWIZZLE_ONE << (j*3); |
} |
} |
} |
else if (src[i].Index == VERT_ATTRIB_COLOR1) { |
int j; |
for (j = 0; j < 4; j++) { |
if (GET_SWZ(src[i].Swizzle, j) == SWIZZLE_W) { |
src[i].Swizzle &= ~(SWIZZLE_W << (j*3)); |
src[i].Swizzle |= SWIZZLE_ZERO << (j*3); |
} |
} |
} |
else if (src[i].Index == VERT_ATTRIB_FOG) { |
int j; |
for (j = 0; j < 4; j++) { |
if (GET_SWZ(src[i].Swizzle, j) == SWIZZLE_W) { |
src[i].Swizzle &= ~(SWIZZLE_W << (j*3)); |
src[i].Swizzle |= SWIZZLE_ONE << (j*3); |
} |
else if ((GET_SWZ(src[i].Swizzle, j) == SWIZZLE_Y) || |
GET_SWZ(src[i].Swizzle, j) == SWIZZLE_Z) { |
src[i].Swizzle &= ~(SWIZZLE_W << (j*3)); |
src[i].Swizzle |= SWIZZLE_ZERO << (j*3); |
} |
} |
} |
} |
} |
if(operands == 3){ |
if( CMP_SRCS(src[1], src[2]) || CMP_SRCS(src[0], src[2]) ){ |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, |
(u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, |
VSF_FLAG_ALL); |
o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[2]), |
SWIZZLE_X, SWIZZLE_Y, |
SWIZZLE_Z, SWIZZLE_W, |
t_src_class(src[2].File), VSF_FLAG_NONE) | (src[2].RelAddr << 4); |
o_inst->src1 = ZERO_SRC_0; |
o_inst->src2 = UNUSED_SRC_1; |
o_inst++; |
src[2].File = PROGRAM_TEMPORARY; |
src[2].Index = u_temp_i; |
src[2].RelAddr = 0; |
u_temp_i--; |
} |
} |
if(operands >= 2){ |
if( CMP_SRCS(src[1], src[0]) ){ |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, |
(u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, |
VSF_FLAG_ALL); |
o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), |
SWIZZLE_X, SWIZZLE_Y, |
SWIZZLE_Z, SWIZZLE_W, |
t_src_class(src[0].File), VSF_FLAG_NONE) | (src[0].RelAddr << 4); |
o_inst->src1 = ZERO_SRC_0; |
o_inst->src2 = UNUSED_SRC_1; |
o_inst++; |
src[0].File = PROGRAM_TEMPORARY; |
src[0].Index = u_temp_i; |
src[0].RelAddr = 0; |
u_temp_i--; |
} |
} |
dst = vpi->DstReg; |
if (dst.File == PROGRAM_OUTPUT && |
dst.Index == VARYING_SLOT_FOGC && |
dst.WriteMask & WRITEMASK_X) { |
fog_temp_i = u_temp_i; |
dst.File = PROGRAM_TEMPORARY; |
dst.Index = fog_temp_i; |
dofogfix = 1; |
u_temp_i--; |
} |
/* These ops need special handling. */ |
switch(vpi->Opcode){ |
case OPCODE_POW: |
/* pow takes only one argument, first scalar is in slot x, 2nd in slot z (other slots don't matter). |
So may need to insert additional instruction */ |
if ((src[0].File == src[1].File) && |
(src[0].Index == src[1].Index)) { |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_POW, t_dst(&dst), |
t_dst_mask(dst.WriteMask)); |
o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), |
t_swizzle(GET_SWZ(src[0].Swizzle, 0)), |
SWIZZLE_ZERO, |
t_swizzle(GET_SWZ(src[1].Swizzle, 0)), |
SWIZZLE_ZERO, |
t_src_class(src[0].File), |
src[0].Negate) | (src[0].RelAddr << 4); |
o_inst->src1 = UNUSED_SRC_0; |
o_inst->src2 = UNUSED_SRC_0; |
} |
else { |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, |
(u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, |
VSF_FLAG_ALL); |
o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), |
t_swizzle(GET_SWZ(src[0].Swizzle, 0)), |
SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO, |
t_src_class(src[0].File), |
src[0].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4); |
o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), |
SWIZZLE_ZERO, SWIZZLE_ZERO, |
t_swizzle(GET_SWZ(src[1].Swizzle, 0)), SWIZZLE_ZERO, |
t_src_class(src[1].File), |
src[1].Negate ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4); |
o_inst->src2 = UNUSED_SRC_1; |
o_inst++; |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_POW, t_dst(&dst), |
t_dst_mask(dst.WriteMask)); |
o_inst->src0 = MAKE_VSF_SOURCE(u_temp_i, |
VSF_IN_COMPONENT_X, |
VSF_IN_COMPONENT_Y, |
VSF_IN_COMPONENT_Z, |
VSF_IN_COMPONENT_W, |
VSF_IN_CLASS_TMP, |
VSF_FLAG_NONE); |
o_inst->src1 = UNUSED_SRC_0; |
o_inst->src2 = UNUSED_SRC_0; |
u_temp_i--; |
} |
goto next; |
case OPCODE_MOV://ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{} {ZERO ZERO ZERO ZERO} |
case OPCODE_SWZ: |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst), |
t_dst_mask(dst.WriteMask)); |
o_inst->src0 = t_src(vp, &src[0]); |
o_inst->src1 = ZERO_SRC_0; |
o_inst->src2 = UNUSED_SRC_1; |
goto next; |
case OPCODE_MAD: |
/* only 2 read ports into temp memory thus may need the macro op MAD_2 |
instead (requiring 2 clocks) if all inputs are in temp memory |
(and, only if they actually reference 3 distinct temps) */ |
hw_op=(src[0].File == PROGRAM_TEMPORARY && |
src[1].File == PROGRAM_TEMPORARY && |
src[2].File == PROGRAM_TEMPORARY && |
(((src[0].RelAddr << 8) | src[0].Index) != ((src[1].RelAddr << 8) | src[1].Index)) && |
(((src[0].RelAddr << 8) | src[0].Index) != ((src[2].RelAddr << 8) | src[2].Index)) && |
(((src[1].RelAddr << 8) | src[1].Index) != ((src[2].RelAddr << 8) | src[2].Index))) ? |
R200_VPI_OUT_OP_MAD_2 : R200_VPI_OUT_OP_MAD; |
o_inst->op = MAKE_VSF_OP(hw_op, t_dst(&dst), |
t_dst_mask(dst.WriteMask)); |
o_inst->src0 = t_src(vp, &src[0]); |
#if 0 |
if ((o_inst - vp->instr) == 31) { |
/* fix up the broken vertex program of quake4 demo... */ |
o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), |
SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, |
t_src_class(src[1].File), |
src[1].Negate) | (src[1].RelAddr << 4); |
o_inst->src2 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), |
SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, SWIZZLE_Y, |
t_src_class(src[1].File), |
src[1].Negate) | (src[1].RelAddr << 4); |
} |
else { |
o_inst->src1 = t_src(vp, &src[1]); |
o_inst->src2 = t_src(vp, &src[2]); |
} |
#else |
o_inst->src1 = t_src(vp, &src[1]); |
o_inst->src2 = t_src(vp, &src[2]); |
#endif |
goto next; |
case OPCODE_DP3://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ZERO} PARAM 0{} {X Y Z ZERO} |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_DOT, t_dst(&dst), |
t_dst_mask(dst.WriteMask)); |
o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), |
t_swizzle(GET_SWZ(src[0].Swizzle, 0)), |
t_swizzle(GET_SWZ(src[0].Swizzle, 1)), |
t_swizzle(GET_SWZ(src[0].Swizzle, 2)), |
SWIZZLE_ZERO, |
t_src_class(src[0].File), |
src[0].Negate) | (src[0].RelAddr << 4); |
o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), |
t_swizzle(GET_SWZ(src[1].Swizzle, 0)), |
t_swizzle(GET_SWZ(src[1].Swizzle, 1)), |
t_swizzle(GET_SWZ(src[1].Swizzle, 2)), |
SWIZZLE_ZERO, |
t_src_class(src[1].File), |
src[1].Negate) | (src[1].RelAddr << 4); |
o_inst->src2 = UNUSED_SRC_1; |
goto next; |
case OPCODE_DPH://DOT RESULT 1.X Y Z W PARAM 0{} {X Y Z ONE} PARAM 0{} {X Y Z W} |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_DOT, t_dst(&dst), |
t_dst_mask(dst.WriteMask)); |
o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), |
t_swizzle(GET_SWZ(src[0].Swizzle, 0)), |
t_swizzle(GET_SWZ(src[0].Swizzle, 1)), |
t_swizzle(GET_SWZ(src[0].Swizzle, 2)), |
VSF_IN_COMPONENT_ONE, |
t_src_class(src[0].File), |
src[0].Negate) | (src[0].RelAddr << 4); |
o_inst->src1 = t_src(vp, &src[1]); |
o_inst->src2 = UNUSED_SRC_1; |
goto next; |
case OPCODE_SUB://ADD RESULT 1.X Y Z W TMP 0{} {X Y Z W} PARAM 1{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst), |
t_dst_mask(dst.WriteMask)); |
o_inst->src0 = t_src(vp, &src[0]); |
o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), |
t_swizzle(GET_SWZ(src[1].Swizzle, 0)), |
t_swizzle(GET_SWZ(src[1].Swizzle, 1)), |
t_swizzle(GET_SWZ(src[1].Swizzle, 2)), |
t_swizzle(GET_SWZ(src[1].Swizzle, 3)), |
t_src_class(src[1].File), |
(!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4); |
o_inst->src2 = UNUSED_SRC_1; |
goto next; |
case OPCODE_ABS://MAX RESULT 1.X Y Z W PARAM 0{} {X Y Z W} PARAM 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W |
o_inst->op=MAKE_VSF_OP(R200_VPI_OUT_OP_MAX, t_dst(&dst), |
t_dst_mask(dst.WriteMask)); |
o_inst->src0=t_src(vp, &src[0]); |
o_inst->src1=MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), |
t_swizzle(GET_SWZ(src[0].Swizzle, 0)), |
t_swizzle(GET_SWZ(src[0].Swizzle, 1)), |
t_swizzle(GET_SWZ(src[0].Swizzle, 2)), |
t_swizzle(GET_SWZ(src[0].Swizzle, 3)), |
t_src_class(src[0].File), |
(!src[0].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[0].RelAddr << 4); |
o_inst->src2 = UNUSED_SRC_1; |
goto next; |
case OPCODE_FLR: |
/* FRC TMP 0.X Y Z W PARAM 0{} {X Y Z W} |
ADD RESULT 1.X Y Z W PARAM 0{} {X Y Z W} TMP 0{X Y Z W } {X Y Z W} neg Xneg Yneg Zneg W */ |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_FRC, |
(u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, |
t_dst_mask(dst.WriteMask)); |
o_inst->src0 = t_src(vp, &src[0]); |
o_inst->src1 = UNUSED_SRC_0; |
o_inst->src2 = UNUSED_SRC_1; |
o_inst++; |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, t_dst(&dst), |
t_dst_mask(dst.WriteMask)); |
o_inst->src0 = t_src(vp, &src[0]); |
o_inst->src1 = MAKE_VSF_SOURCE(u_temp_i, |
VSF_IN_COMPONENT_X, |
VSF_IN_COMPONENT_Y, |
VSF_IN_COMPONENT_Z, |
VSF_IN_COMPONENT_W, |
VSF_IN_CLASS_TMP, |
/* Not 100% sure about this */ |
(!src[0].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE/*VSF_FLAG_ALL*/); |
o_inst->src2 = UNUSED_SRC_0; |
u_temp_i--; |
goto next; |
case OPCODE_XPD: |
/* mul r0, r1.yzxw, r2.zxyw |
mad r0, -r2.yzxw, r1.zxyw, r0 |
*/ |
hw_op=(src[0].File == PROGRAM_TEMPORARY && |
src[1].File == PROGRAM_TEMPORARY && |
(((src[0].RelAddr << 8) | src[0].Index) != ((src[1].RelAddr << 8) | src[1].Index))) ? |
R200_VPI_OUT_OP_MAD_2 : R200_VPI_OUT_OP_MAD; |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, |
(u_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, |
t_dst_mask(dst.WriteMask)); |
o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), |
t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y |
t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z |
t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x |
t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w |
t_src_class(src[0].File), |
src[0].Negate) | (src[0].RelAddr << 4); |
o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), |
t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z |
t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x |
t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y |
t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w |
t_src_class(src[1].File), |
src[1].Negate) | (src[1].RelAddr << 4); |
o_inst->src2 = UNUSED_SRC_1; |
o_inst++; |
u_temp_i--; |
o_inst->op = MAKE_VSF_OP(hw_op, t_dst(&dst), |
t_dst_mask(dst.WriteMask)); |
o_inst->src0 = MAKE_VSF_SOURCE(t_src_index(vp, &src[1]), |
t_swizzle(GET_SWZ(src[1].Swizzle, 1)), // y |
t_swizzle(GET_SWZ(src[1].Swizzle, 2)), // z |
t_swizzle(GET_SWZ(src[1].Swizzle, 0)), // x |
t_swizzle(GET_SWZ(src[1].Swizzle, 3)), // w |
t_src_class(src[1].File), |
(!src[1].Negate) ? VSF_FLAG_ALL : VSF_FLAG_NONE) | (src[1].RelAddr << 4); |
o_inst->src1 = MAKE_VSF_SOURCE(t_src_index(vp, &src[0]), |
t_swizzle(GET_SWZ(src[0].Swizzle, 2)), // z |
t_swizzle(GET_SWZ(src[0].Swizzle, 0)), // x |
t_swizzle(GET_SWZ(src[0].Swizzle, 1)), // y |
t_swizzle(GET_SWZ(src[0].Swizzle, 3)), // w |
t_src_class(src[0].File), |
src[0].Negate) | (src[0].RelAddr << 4); |
o_inst->src2 = MAKE_VSF_SOURCE(u_temp_i+1, |
VSF_IN_COMPONENT_X, |
VSF_IN_COMPONENT_Y, |
VSF_IN_COMPONENT_Z, |
VSF_IN_COMPONENT_W, |
VSF_IN_CLASS_TMP, |
VSF_FLAG_NONE); |
goto next; |
case OPCODE_END: |
assert(0); |
default: |
break; |
} |
o_inst->op = MAKE_VSF_OP(t_opcode(vpi->Opcode), t_dst(&dst), |
t_dst_mask(dst.WriteMask)); |
if(are_srcs_scalar){ |
switch(operands){ |
case 1: |
o_inst->src0 = t_src_scalar(vp, &src[0]); |
o_inst->src1 = UNUSED_SRC_0; |
o_inst->src2 = UNUSED_SRC_1; |
break; |
case 2: |
o_inst->src0 = t_src_scalar(vp, &src[0]); |
o_inst->src1 = t_src_scalar(vp, &src[1]); |
o_inst->src2 = UNUSED_SRC_1; |
break; |
case 3: |
o_inst->src0 = t_src_scalar(vp, &src[0]); |
o_inst->src1 = t_src_scalar(vp, &src[1]); |
o_inst->src2 = t_src_scalar(vp, &src[2]); |
break; |
default: |
fprintf(stderr, "illegal number of operands %lu\n", operands); |
exit(-1); |
break; |
} |
} else { |
switch(operands){ |
case 1: |
o_inst->src0 = t_src(vp, &src[0]); |
o_inst->src1 = UNUSED_SRC_0; |
o_inst->src2 = UNUSED_SRC_1; |
break; |
case 2: |
o_inst->src0 = t_src(vp, &src[0]); |
o_inst->src1 = t_src(vp, &src[1]); |
o_inst->src2 = UNUSED_SRC_1; |
break; |
case 3: |
o_inst->src0 = t_src(vp, &src[0]); |
o_inst->src1 = t_src(vp, &src[1]); |
o_inst->src2 = t_src(vp, &src[2]); |
break; |
default: |
fprintf(stderr, "illegal number of operands %lu\n", operands); |
exit(-1); |
break; |
} |
} |
next: |
if (dofogfix) { |
o_inst++; |
if (vp->fogmode == GL_EXP) { |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, |
(fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, |
VSF_FLAG_X); |
o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); |
o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, X, X, X, X, PARAM, NONE); |
o_inst->src2 = UNUSED_SRC_1; |
o_inst++; |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_EXP_E, |
R200_VSF_OUT_CLASS_RESULT_FOGC, |
VSF_FLAG_X); |
o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL); |
o_inst->src1 = UNUSED_SRC_0; |
o_inst->src2 = UNUSED_SRC_1; |
} |
else if (vp->fogmode == GL_EXP2) { |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, |
(fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, |
VSF_FLAG_X); |
o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); |
o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, X, X, X, X, PARAM, NONE); |
o_inst->src2 = UNUSED_SRC_1; |
o_inst++; |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, |
(fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, |
VSF_FLAG_X); |
o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); |
o_inst->src1 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); |
o_inst->src2 = UNUSED_SRC_1; |
o_inst++; |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_EXP_E, |
R200_VSF_OUT_CLASS_RESULT_FOGC, |
VSF_FLAG_X); |
o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL); |
o_inst->src1 = UNUSED_SRC_0; |
o_inst->src2 = UNUSED_SRC_1; |
} |
else { /* fogmode == GL_LINEAR */ |
/* could do that with single op (dot) if using params like |
with fixed function pipeline fog */ |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_ADD, |
(fog_temp_i << R200_VPI_OUT_REG_INDEX_SHIFT) | R200_VSF_OUT_CLASS_TMP, |
VSF_FLAG_X); |
o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, ALL); |
o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, Z, Z, Z, Z, PARAM, NONE); |
o_inst->src2 = UNUSED_SRC_1; |
o_inst++; |
o_inst->op = MAKE_VSF_OP(R200_VPI_OUT_OP_MUL, |
R200_VSF_OUT_CLASS_RESULT_FOGC, |
VSF_FLAG_X); |
o_inst->src0 = EASY_VSF_SOURCE(fog_temp_i, X, X, X, X, TMP, NONE); |
o_inst->src1 = EASY_VSF_SOURCE(vp->fogpidx, W, W, W, W, PARAM, NONE); |
o_inst->src2 = UNUSED_SRC_1; |
} |
dofogfix = 0; |
} |
u_temp_used = (R200_VSF_MAX_TEMPS - 1) - u_temp_i; |
if (mesa_vp->Base.NumNativeTemporaries < |
(mesa_vp->Base.NumTemporaries + u_temp_used)) { |
mesa_vp->Base.NumNativeTemporaries = |
mesa_vp->Base.NumTemporaries + u_temp_used; |
} |
if ((mesa_vp->Base.NumTemporaries + u_temp_used) > R200_VSF_MAX_TEMPS) { |
if (R200_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "Ran out of temps, num temps %d, us %d\n", mesa_vp->Base.NumTemporaries, u_temp_used); |
} |
return GL_FALSE; |
} |
u_temp_i = R200_VSF_MAX_TEMPS - 1; |
if(o_inst - vp->instr >= R200_VSF_MAX_INST) { |
mesa_vp->Base.NumNativeInstructions = 129; |
if (R200_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "more than 128 native instructions\n"); |
} |
return GL_FALSE; |
} |
if ((o_inst->op & R200_VSF_OUT_CLASS_MASK) == R200_VSF_OUT_CLASS_RESULT_POS) { |
vp->pos_end = (o_inst - vp->instr); |
} |
} |
vp->native = GL_TRUE; |
mesa_vp->Base.NumNativeInstructions = (o_inst - vp->instr); |
#if 0 |
fprintf(stderr, "hw program:\n"); |
for(i=0; i < vp->program.length; i++) |
fprintf(stderr, "%08x\n", vp->instr[i]); |
#endif |
return GL_TRUE; |
} |
void r200SetupVertexProg( struct gl_context *ctx ) { |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
struct r200_vertex_program *vp = (struct r200_vertex_program *)ctx->VertexProgram.Current; |
GLboolean fallback; |
GLint i; |
if (!vp->translated || (ctx->Fog.Enabled && ctx->Fog.Mode != vp->fogmode)) { |
rmesa->curr_vp_hw = NULL; |
r200_translate_vertex_program(ctx, vp); |
} |
/* could optimize setting up vertex progs away for non-tcl hw */ |
fallback = !(vp->native && r200VertexProgUpdateParams(ctx, vp)); |
TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, fallback); |
if (rmesa->radeon.TclFallback) return; |
R200_STATECHANGE( rmesa, vap ); |
/* FIXME: fglrx sets R200_VAP_SINGLE_BUF_STATE_ENABLE too. Do we need it? |
maybe only when using more than 64 inst / 96 param? */ |
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_PROG_VTX_SHADER_ENABLE /*| R200_VAP_SINGLE_BUF_STATE_ENABLE*/; |
R200_STATECHANGE( rmesa, pvs ); |
rmesa->hw.pvs.cmd[PVS_CNTL_1] = (0 << R200_PVS_CNTL_1_PROGRAM_START_SHIFT) | |
((vp->mesa_program.Base.NumNativeInstructions - 1) << R200_PVS_CNTL_1_PROGRAM_END_SHIFT) | |
(vp->pos_end << R200_PVS_CNTL_1_POS_END_SHIFT); |
rmesa->hw.pvs.cmd[PVS_CNTL_2] = (0 << R200_PVS_CNTL_2_PARAM_OFFSET_SHIFT) | |
(vp->mesa_program.Base.NumNativeParameters << R200_PVS_CNTL_2_PARAM_COUNT_SHIFT); |
/* maybe user clip planes just work with vertex progs... untested */ |
if (ctx->Transform.ClipPlanesEnabled) { |
R200_STATECHANGE( rmesa, tcl ); |
if (vp->mesa_program.IsPositionInvariant) { |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (ctx->Transform.ClipPlanesEnabled << 2); |
} |
else { |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(0xfc); |
} |
} |
if (vp != rmesa->curr_vp_hw) { |
GLuint count = vp->mesa_program.Base.NumNativeInstructions; |
drm_radeon_cmd_header_t tmp; |
R200_STATECHANGE( rmesa, vpi[0] ); |
R200_STATECHANGE( rmesa, vpi[1] ); |
/* FIXME: what about using a memcopy... */ |
for (i = 0; (i < 64) && i < count; i++) { |
rmesa->hw.vpi[0].cmd[VPI_OPDST_0 + 4 * i] = vp->instr[i].op; |
rmesa->hw.vpi[0].cmd[VPI_SRC0_0 + 4 * i] = vp->instr[i].src0; |
rmesa->hw.vpi[0].cmd[VPI_SRC1_0 + 4 * i] = vp->instr[i].src1; |
rmesa->hw.vpi[0].cmd[VPI_SRC2_0 + 4 * i] = vp->instr[i].src2; |
} |
/* hack up the cmd_size so not the whole state atom is emitted always. |
This may require some more thought, we may emit half progs on lost state, but |
hopefully it won't matter? |
WARNING: must not use R200_DB_STATECHANGE, this will produce bogus (and rejected) |
packet emits (due to the mismatched cmd_size and count in cmd/last_cmd) */ |
rmesa->hw.vpi[0].cmd_size = 1 + 4 * ((count > 64) ? 64 : count); |
tmp.i = rmesa->hw.vpi[0].cmd[VPI_CMD_0]; |
tmp.veclinear.count = (count > 64) ? 64 : count; |
rmesa->hw.vpi[0].cmd[VPI_CMD_0] = tmp.i; |
if (count > 64) { |
for (i = 0; i < (count - 64); i++) { |
rmesa->hw.vpi[1].cmd[VPI_OPDST_0 + 4 * i] = vp->instr[i + 64].op; |
rmesa->hw.vpi[1].cmd[VPI_SRC0_0 + 4 * i] = vp->instr[i + 64].src0; |
rmesa->hw.vpi[1].cmd[VPI_SRC1_0 + 4 * i] = vp->instr[i + 64].src1; |
rmesa->hw.vpi[1].cmd[VPI_SRC2_0 + 4 * i] = vp->instr[i + 64].src2; |
} |
rmesa->hw.vpi[1].cmd_size = 1 + 4 * (count - 64); |
tmp.i = rmesa->hw.vpi[1].cmd[VPI_CMD_0]; |
tmp.veclinear.count = count - 64; |
rmesa->hw.vpi[1].cmd[VPI_CMD_0] = tmp.i; |
} |
rmesa->curr_vp_hw = vp; |
} |
} |
static void |
r200BindProgram(struct gl_context *ctx, GLenum target, struct gl_program *prog) |
{ |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
switch(target){ |
case GL_VERTEX_PROGRAM_ARB: |
rmesa->curr_vp_hw = NULL; |
break; |
default: |
_mesa_problem(ctx, "Target not supported yet!"); |
break; |
} |
} |
static struct gl_program * |
r200NewProgram(struct gl_context *ctx, GLenum target, GLuint id) |
{ |
struct r200_vertex_program *vp; |
switch(target){ |
case GL_VERTEX_PROGRAM_ARB: |
vp = CALLOC_STRUCT(r200_vertex_program); |
return _mesa_init_vertex_program(ctx, &vp->mesa_program, target, id); |
case GL_FRAGMENT_PROGRAM_ARB: |
return _mesa_init_fragment_program( ctx, CALLOC_STRUCT(gl_fragment_program), target, id ); |
default: |
_mesa_problem(ctx, "Bad target in r200NewProgram"); |
} |
return NULL; |
} |
static void |
r200DeleteProgram(struct gl_context *ctx, struct gl_program *prog) |
{ |
_mesa_delete_program(ctx, prog); |
} |
static GLboolean |
r200ProgramStringNotify(struct gl_context *ctx, GLenum target, struct gl_program *prog) |
{ |
struct r200_vertex_program *vp = (void *)prog; |
r200ContextPtr rmesa = R200_CONTEXT(ctx); |
switch(target) { |
case GL_VERTEX_PROGRAM_ARB: |
vp->translated = GL_FALSE; |
vp->fogpidx = 0; |
/* memset(&vp->translated, 0, sizeof(struct r200_vertex_program) - sizeof(struct gl_vertex_program));*/ |
r200_translate_vertex_program(ctx, vp); |
rmesa->curr_vp_hw = NULL; |
break; |
case GL_FRAGMENT_SHADER_ATI: |
rmesa->afs_loaded = NULL; |
break; |
} |
/* need this for tcl fallbacks */ |
(void) _tnl_program_string(ctx, target, prog); |
/* XXX check if program is legal, within limits */ |
return GL_TRUE; |
} |
static GLboolean |
r200IsProgramNative(struct gl_context *ctx, GLenum target, struct gl_program *prog) |
{ |
struct r200_vertex_program *vp = (void *)prog; |
switch(target){ |
case GL_VERTEX_PROGRAM_ARB: |
if (!vp->translated) { |
r200_translate_vertex_program(ctx, vp); |
} |
/* does not take parameters etc. into account */ |
return vp->native; |
default: |
_mesa_problem(ctx, "Bad target in r200NewProgram"); |
} |
return 0; |
} |
void r200InitShaderFuncs(struct dd_function_table *functions) |
{ |
functions->NewProgram = r200NewProgram; |
functions->BindProgram = r200BindProgram; |
functions->DeleteProgram = r200DeleteProgram; |
functions->ProgramStringNotify = r200ProgramStringNotify; |
functions->IsProgramNative = r200IsProgramNative; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/r200_vertprog.h |
---|
0,0 → 1,163 |
#ifndef __VERTEX_SHADER_H__ |
#define __VERTEX_SHADER_H__ |
#include "r200_reg.h" |
typedef struct { |
uint32_t op; |
uint32_t src0; |
uint32_t src1; |
uint32_t src2; |
} VERTEX_SHADER_INSTRUCTION; |
extern void r200InitShaderFuncs(struct dd_function_table *functions); |
extern void r200SetupVertexProg( struct gl_context *ctx ); |
#define VSF_FLAG_X 1 |
#define VSF_FLAG_Y 2 |
#define VSF_FLAG_Z 4 |
#define VSF_FLAG_W 8 |
#define VSF_FLAG_XYZ (VSF_FLAG_X | VSF_FLAG_Y | VSF_FLAG_Z) |
#define VSF_FLAG_ALL 0xf |
#define VSF_FLAG_NONE 0 |
#define R200_VSF_MAX_INST 128 |
#define R200_VSF_MAX_PARAM 192 |
#define R200_VSF_MAX_TEMPS 12 |
#define R200_VPI_OUT_REG_INDEX_SHIFT 13 |
#define R200_VPI_OUT_REG_INDEX_MASK (31 << 13) /* GUESS based on fglrx native limits */ |
#define R200_VPI_OUT_WRITE_X (1 << 20) |
#define R200_VPI_OUT_WRITE_Y (1 << 21) |
#define R200_VPI_OUT_WRITE_Z (1 << 22) |
#define R200_VPI_OUT_WRITE_W (1 << 23) |
#define R200_VPI_IN_REG_CLASS_TEMPORARY (0 << 0) |
#define R200_VPI_IN_REG_CLASS_ATTRIBUTE (1 << 0) |
#define R200_VPI_IN_REG_CLASS_PARAMETER (2 << 0) |
#define R200_VPI_IN_REG_CLASS_NONE (9 << 0) |
#define R200_VPI_IN_REG_CLASS_MASK (31 << 0) /* GUESS */ |
#define R200_VPI_IN_REG_INDEX_SHIFT 5 |
#define R200_VPI_IN_REG_INDEX_MASK (255 << 5) /* GUESS based on fglrx native limits */ |
/* The R200 can select components from the input register arbitrarily. |
// Use the following constants, shifted by the component shift you |
// want to select */ |
#define R200_VPI_IN_SELECT_X 0 |
#define R200_VPI_IN_SELECT_Y 1 |
#define R200_VPI_IN_SELECT_Z 2 |
#define R200_VPI_IN_SELECT_W 3 |
#define R200_VPI_IN_SELECT_ZERO 4 |
#define R200_VPI_IN_SELECT_ONE 5 |
#define R200_VPI_IN_SELECT_MASK 7 |
#define R200_VPI_IN_X_SHIFT 13 |
#define R200_VPI_IN_Y_SHIFT 16 |
#define R200_VPI_IN_Z_SHIFT 19 |
#define R200_VPI_IN_W_SHIFT 22 |
#define R200_VPI_IN_NEG_X (1 << 25) |
#define R200_VPI_IN_NEG_Y (1 << 26) |
#define R200_VPI_IN_NEG_Z (1 << 27) |
#define R200_VPI_IN_NEG_W (1 << 28) |
#define R200_VSF_OUT_CLASS_TMP (0 << 8) |
#define R200_VSF_OUT_CLASS_ADDR (3 << 8) |
#define R200_VSF_OUT_CLASS_RESULT_POS (4 << 8) |
#define R200_VSF_OUT_CLASS_RESULT_COLOR (5 << 8) |
#define R200_VSF_OUT_CLASS_RESULT_TEXC (6 << 8) |
#define R200_VSF_OUT_CLASS_RESULT_FOGC (7 << 8) |
#define R200_VSF_OUT_CLASS_RESULT_POINTSIZE (8 << 8) |
#define R200_VSF_OUT_CLASS_MASK (31 << 8) |
/* opcodes - they all are the same as on r300 it seems, however |
LIT and POW require different setup */ |
#define R200_VPI_OUT_OP_DOT (1 << 0) |
#define R200_VPI_OUT_OP_MUL (2 << 0) |
#define R200_VPI_OUT_OP_ADD (3 << 0) |
#define R200_VPI_OUT_OP_MAD (4 << 0) |
#define R200_VPI_OUT_OP_DST (5 << 0) |
#define R200_VPI_OUT_OP_FRC (6 << 0) |
#define R200_VPI_OUT_OP_MAX (7 << 0) |
#define R200_VPI_OUT_OP_MIN (8 << 0) |
#define R200_VPI_OUT_OP_SGE (9 << 0) |
#define R200_VPI_OUT_OP_SLT (10 << 0) |
#define R200_VPI_OUT_OP_ARL (13 << 0) |
#define R200_VPI_OUT_OP_EXP (65 << 0) |
#define R200_VPI_OUT_OP_LOG (66 << 0) |
/* base e exp. Useful for fog. */ |
#define R200_VPI_OUT_OP_EXP_E (67 << 0) |
#define R200_VPI_OUT_OP_LIT (68 << 0) |
#define R200_VPI_OUT_OP_POW (69 << 0) |
#define R200_VPI_OUT_OP_RCP (70 << 0) |
#define R200_VPI_OUT_OP_RSQ (72 << 0) |
#define R200_VPI_OUT_OP_EX2 (75 << 0) |
#define R200_VPI_OUT_OP_LG2 (76 << 0) |
#define R200_VPI_OUT_OP_MAD_2 (128 << 0) |
/* first CARD32 of an instruction */ |
/* possible operations: |
DOT, MUL, ADD, MAD, FRC, MAX, MIN, SGE, SLT, EXP, LOG, LIT, POW, RCP, RSQ, EX2, |
LG2, MAD_2, ARL */ |
#define MAKE_VSF_OP(op, out_reg, out_reg_fields) \ |
((op) | (out_reg) | ((out_reg_fields) << 20) ) |
#define VSF_IN_CLASS_TMP 0 |
#define VSF_IN_CLASS_ATTR 1 |
#define VSF_IN_CLASS_PARAM 2 |
#define VSF_IN_CLASS_NONE 9 |
#define VSF_IN_COMPONENT_X 0 |
#define VSF_IN_COMPONENT_Y 1 |
#define VSF_IN_COMPONENT_Z 2 |
#define VSF_IN_COMPONENT_W 3 |
#define VSF_IN_COMPONENT_ZERO 4 |
#define VSF_IN_COMPONENT_ONE 5 |
#define MAKE_VSF_SOURCE(in_reg_index, comp_x, comp_y, comp_z, comp_w, class, negate) \ |
( ((in_reg_index)<<R200_VPI_IN_REG_INDEX_SHIFT) \ |
| ((comp_x)<<R200_VPI_IN_X_SHIFT) \ |
| ((comp_y)<<R200_VPI_IN_Y_SHIFT) \ |
| ((comp_z)<<R200_VPI_IN_Z_SHIFT) \ |
| ((comp_w)<<R200_VPI_IN_W_SHIFT) \ |
| ((negate)<<25) | ((class))) |
#define EASY_VSF_SOURCE(in_reg_index, comp_x, comp_y, comp_z, comp_w, class, negate) \ |
MAKE_VSF_SOURCE(in_reg_index, \ |
VSF_IN_COMPONENT_##comp_x, \ |
VSF_IN_COMPONENT_##comp_y, \ |
VSF_IN_COMPONENT_##comp_z, \ |
VSF_IN_COMPONENT_##comp_w, \ |
VSF_IN_CLASS_##class, VSF_FLAG_##negate) |
/* special sources: */ |
/* (1.0,1.0,1.0,1.0) vector (ATTR, plain ) */ |
#define VSF_ATTR_UNITY(reg) EASY_VSF_SOURCE(reg, ONE, ONE, ONE, ONE, ATTR, NONE) |
#define VSF_UNITY(reg) EASY_VSF_SOURCE(reg, ONE, ONE, ONE, ONE, NONE, NONE) |
/* contents of unmodified register */ |
#define VSF_REG(reg) EASY_VSF_SOURCE(reg, X, Y, Z, W, ATTR, NONE) |
/* contents of unmodified parameter */ |
#define VSF_PARAM(reg) EASY_VSF_SOURCE(reg, X, Y, Z, W, PARAM, NONE) |
/* contents of unmodified temporary register */ |
#define VSF_TMP(reg) EASY_VSF_SOURCE(reg, X, Y, Z, W, TMP, NONE) |
/* components of ATTR register */ |
#define VSF_ATTR_X(reg) EASY_VSF_SOURCE(reg, X, X, X, X, ATTR, NONE) |
#define VSF_ATTR_Y(reg) EASY_VSF_SOURCE(reg, Y, Y, Y, Y, ATTR, NONE) |
#define VSF_ATTR_Z(reg) EASY_VSF_SOURCE(reg, Z, Z, Z, Z, ATTR, NONE) |
#define VSF_ATTR_W(reg) EASY_VSF_SOURCE(reg, W, W, W, W, ATTR, NONE) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_buffer_objects.c |
---|
0,0 → 1,0 |
../radeon/radeon_buffer_objects.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_buffer_objects.h |
---|
0,0 → 1,0 |
../radeon/radeon_buffer_objects.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_chipset.h |
---|
0,0 → 1,0 |
../radeon/radeon_chipset.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_cmdbuf.h |
---|
0,0 → 1,0 |
../radeon/radeon_cmdbuf.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_common.c |
---|
0,0 → 1,0 |
../radeon/radeon_common.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_common.h |
---|
0,0 → 1,0 |
../radeon/radeon_common.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_common_context.c |
---|
0,0 → 1,0 |
../radeon/radeon_common_context.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_common_context.h |
---|
0,0 → 1,0 |
../radeon/radeon_common_context.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_debug.c |
---|
0,0 → 1,0 |
../radeon/radeon_debug.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_debug.h |
---|
0,0 → 1,0 |
../radeon/radeon_debug.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_dma.c |
---|
0,0 → 1,0 |
../radeon/radeon_dma.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_dma.h |
---|
0,0 → 1,0 |
../radeon/radeon_dma.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_fbo.c |
---|
0,0 → 1,0 |
../radeon/radeon_fbo.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_fog.c |
---|
0,0 → 1,0 |
../radeon/radeon_fog.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_fog.h |
---|
0,0 → 1,0 |
../radeon/radeon_fog.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_mipmap_tree.c |
---|
0,0 → 1,0 |
../radeon/radeon_mipmap_tree.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_mipmap_tree.h |
---|
0,0 → 1,0 |
../radeon/radeon_mipmap_tree.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_pixel_read.c |
---|
0,0 → 1,0 |
../radeon/radeon_pixel_read.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_queryobj.c |
---|
0,0 → 1,0 |
../radeon/radeon_queryobj.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_queryobj.h |
---|
0,0 → 1,0 |
../radeon/radeon_queryobj.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_screen.c |
---|
0,0 → 1,0 |
../radeon/radeon_screen.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_screen.h |
---|
0,0 → 1,0 |
../radeon/radeon_screen.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_span.c |
---|
0,0 → 1,0 |
../radeon/radeon_span.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_span.h |
---|
0,0 → 1,0 |
../radeon/radeon_span.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_tex_copy.c |
---|
0,0 → 1,0 |
../radeon/radeon_tex_copy.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_texture.c |
---|
0,0 → 1,0 |
../radeon/radeon_texture.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_texture.h |
---|
0,0 → 1,0 |
../radeon/radeon_texture.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_tile.c |
---|
0,0 → 1,0 |
../radeon/radeon_tile.c |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/radeon_tile.h |
---|
0,0 → 1,0 |
../radeon/radeon_tile.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/server/radeon_dri.h |
---|
0,0 → 1,0 |
../../radeon/server/radeon_dri.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/server/radeon_macros.h |
---|
0,0 → 1,0 |
../../radeon/server/radeon_macros.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/r200/server/radeon_reg.h |
---|
0,0 → 1,0 |
../../radeon/server/radeon_reg.h |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/Makefile.am |
---|
0,0 → 1,58 |
# Copyright © 2012 Matt Turner <mattst88@gmail.com> |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
# copy of this software and associated documentation files (the "Software"), |
# to deal in the Software without restriction, including without limitation |
# the rights to use, copy, modify, merge, publish, distribute, sublicense, |
# and/or sell copies of the Software, and to permit persons to whom the |
# Software is furnished to do so, subject to the following conditions: |
# |
# The above copyright notice and this permission notice (including the next |
# paragraph) shall be included in all copies or substantial portions of the |
# Software. |
# |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
# IN THE SOFTWARE. |
include Makefile.sources |
AM_CFLAGS = \ |
-DRADEON_R100 \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
-I$(top_srcdir)/src/mesa/drivers/dri/common \ |
-I$(top_srcdir)/src/mesa/drivers/dri/radeon/server \ |
-I$(top_builddir)/src/mesa/drivers/dri/common \ |
$(DEFINES) \ |
$(VISIBILITY_CFLAGS) \ |
$(RADEON_CFLAGS) |
dridir = $(DRI_DRIVER_INSTALL_DIR) |
if HAVE_RADEON_DRI |
dri_LTLIBRARIES = radeon_dri.la |
endif |
radeon_dri_la_SOURCES = \ |
$(RADEON_C_FILES) |
radeon_dri_la_LDFLAGS = -module -avoid-version -shared |
radeon_dri_la_LIBADD = \ |
../common/libdricommon.la \ |
$(DRI_LIB_DEPS) \ |
$(RADEON_LIBS) |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
all-local: radeon_dri.la |
$(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
ln -f .libs/radeon_dri.so $(top_builddir)/$(LIB_DIR)/radeon_dri.so; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/Makefile.in |
---|
0,0 → 1,924 |
# 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 Matt Turner <mattst88@gmail.com> |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
# copy of this software and associated documentation files (the "Software"), |
# to deal in the Software without restriction, including without limitation |
# the rights to use, copy, modify, merge, publish, distribute, 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 = $(srcdir)/Makefile.sources $(srcdir)/Makefile.in \ |
$(srcdir)/Makefile.am $(top_srcdir)/bin/depcomp |
subdir = src/mesa/drivers/dri/radeon |
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 = |
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; |
am__vpath_adj = case $$p in \ |
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |
*) f=$$p;; \ |
esac; |
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; |
am__install_max = 40 |
am__nobase_strip_setup = \ |
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` |
am__nobase_strip = \ |
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" |
am__nobase_list = $(am__nobase_strip_setup); \ |
for p in $$list; do echo "$$p $$p"; done | \ |
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ |
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ |
if (++n[$$2] == $(am__install_max)) \ |
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ |
END { for (dir in files) print dir, files[dir] }' |
am__base_list = \ |
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ |
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' |
am__uninstall_files_from_dir = { \ |
test -z "$$files" \ |
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ |
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \ |
$(am__cd) "$$dir" && rm -f $$files; }; \ |
} |
am__installdirs = "$(DESTDIR)$(dridir)" |
LTLIBRARIES = $(dri_LTLIBRARIES) |
am__DEPENDENCIES_1 = |
radeon_dri_la_DEPENDENCIES = ../common/libdricommon.la \ |
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) |
am__objects_1 = radeon_buffer_objects.lo radeon_common_context.lo \ |
radeon_common.lo radeon_dma.lo radeon_debug.lo radeon_fbo.lo \ |
radeon_fog.lo radeon_mipmap_tree.lo radeon_pixel_read.lo \ |
radeon_queryobj.lo radeon_span.lo radeon_texture.lo \ |
radeon_tex_copy.lo radeon_tile.lo |
am__objects_2 = radeon_context.lo radeon_ioctl.lo radeon_screen.lo \ |
radeon_state.lo radeon_state_init.lo radeon_tex.lo \ |
radeon_texstate.lo radeon_tcl.lo radeon_swtcl.lo \ |
radeon_maos.lo radeon_sanity.lo radeon_blit.lo |
am__objects_3 = $(am__objects_1) $(am__objects_2) |
am_radeon_dri_la_OBJECTS = $(am__objects_3) |
radeon_dri_la_OBJECTS = $(am_radeon_dri_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 = |
radeon_dri_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ |
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ |
$(radeon_dri_la_LDFLAGS) $(LDFLAGS) -o $@ |
@HAVE_RADEON_DRI_TRUE@am_radeon_dri_la_rpath = -rpath $(dridir) |
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 = $(radeon_dri_la_SOURCES) |
DIST_SOURCES = $(radeon_dri_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@ |
RADEON_COMMON_FILES = \ |
radeon_buffer_objects.c \ |
radeon_common_context.c \ |
radeon_common.c \ |
radeon_dma.c \ |
radeon_debug.c \ |
radeon_fbo.c \ |
radeon_fog.c \ |
radeon_mipmap_tree.c \ |
radeon_pixel_read.c \ |
radeon_queryobj.c \ |
radeon_span.c \ |
radeon_texture.c \ |
radeon_tex_copy.c \ |
radeon_tile.c |
DRIVER_FILES = \ |
radeon_context.c \ |
radeon_ioctl.c \ |
radeon_screen.c \ |
radeon_state.c \ |
radeon_state_init.c \ |
radeon_tex.c \ |
radeon_texstate.c \ |
radeon_tcl.c \ |
radeon_swtcl.c \ |
radeon_maos.c \ |
radeon_sanity.c \ |
radeon_blit.c |
RADEON_C_FILES = \ |
$(RADEON_COMMON_FILES) \ |
$(DRIVER_FILES) |
AM_CFLAGS = \ |
-DRADEON_R100 \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
-I$(top_srcdir)/src/mesa/drivers/dri/common \ |
-I$(top_srcdir)/src/mesa/drivers/dri/radeon/server \ |
-I$(top_builddir)/src/mesa/drivers/dri/common \ |
$(DEFINES) \ |
$(VISIBILITY_CFLAGS) \ |
$(RADEON_CFLAGS) |
dridir = $(DRI_DRIVER_INSTALL_DIR) |
@HAVE_RADEON_DRI_TRUE@dri_LTLIBRARIES = radeon_dri.la |
radeon_dri_la_SOURCES = \ |
$(RADEON_C_FILES) |
radeon_dri_la_LDFLAGS = -module -avoid-version -shared |
radeon_dri_la_LIBADD = \ |
../common/libdricommon.la \ |
$(DRI_LIB_DEPS) \ |
$(RADEON_LIBS) |
all: all-am |
.SUFFIXES: |
.SUFFIXES: .c .lo .o .obj |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(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/mesa/drivers/dri/radeon/Makefile'; \ |
$(am__cd) $(top_srcdir) && \ |
$(AUTOMAKE) --foreign src/mesa/drivers/dri/radeon/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; |
$(srcdir)/Makefile.sources: |
$(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): |
install-driLTLIBRARIES: $(dri_LTLIBRARIES) |
@$(NORMAL_INSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
list2=; for p in $$list; do \ |
if test -f $$p; then \ |
list2="$$list2 $$p"; \ |
else :; fi; \ |
done; \ |
test -z "$$list2" || { \ |
echo " $(MKDIR_P) '$(DESTDIR)$(dridir)'"; \ |
$(MKDIR_P) "$(DESTDIR)$(dridir)" || exit 1; \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(dridir)'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(dridir)"; \ |
} |
uninstall-driLTLIBRARIES: |
@$(NORMAL_UNINSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
for p in $$list; do \ |
$(am__strip_dir) \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(dridir)/$$f'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(dridir)/$$f"; \ |
done |
clean-driLTLIBRARIES: |
-test -z "$(dri_LTLIBRARIES)" || rm -f $(dri_LTLIBRARIES) |
@list='$(dri_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}; \ |
} |
radeon_dri.la: $(radeon_dri_la_OBJECTS) $(radeon_dri_la_DEPENDENCIES) $(EXTRA_radeon_dri_la_DEPENDENCIES) |
$(AM_V_CCLD)$(radeon_dri_la_LINK) $(am_radeon_dri_la_rpath) $(radeon_dri_la_OBJECTS) $(radeon_dri_la_LIBADD) $(LIBS) |
mostlyclean-compile: |
-rm -f *.$(OBJEXT) |
distclean-compile: |
-rm -f *.tab.c |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_blit.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_buffer_objects.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_common.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_common_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_context.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_debug.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_dma.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_fbo.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_fog.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_ioctl.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_maos.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_mipmap_tree.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_pixel_read.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_queryobj.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_sanity.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_screen.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_span.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_state.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_state_init.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_swtcl.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_tcl.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_tex.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_tex_copy.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_texstate.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_texture.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_tile.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) all-local |
installdirs: |
for dir in "$(DESTDIR)$(dridir)"; do \ |
test -z "$$dir" || $(MKDIR_P) "$$dir"; \ |
done |
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-driLTLIBRARIES clean-generic clean-libtool \ |
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-driLTLIBRARIES |
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: uninstall-driLTLIBRARIES |
.MAKE: install-am install-strip |
.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \ |
clean-driLTLIBRARIES clean-generic clean-libtool 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-driLTLIBRARIES 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 \ |
uninstall-driLTLIBRARIES |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
all-local: radeon_dri.la |
$(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
ln -f .libs/radeon_dri.so $(top_builddir)/$(LIB_DIR)/radeon_dri.so; |
# 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/src/mesa/drivers/dri/radeon/Makefile.sources |
---|
0,0 → 1,33 |
RADEON_COMMON_FILES = \ |
radeon_buffer_objects.c \ |
radeon_common_context.c \ |
radeon_common.c \ |
radeon_dma.c \ |
radeon_debug.c \ |
radeon_fbo.c \ |
radeon_fog.c \ |
radeon_mipmap_tree.c \ |
radeon_pixel_read.c \ |
radeon_queryobj.c \ |
radeon_span.c \ |
radeon_texture.c \ |
radeon_tex_copy.c \ |
radeon_tile.c |
DRIVER_FILES = \ |
radeon_context.c \ |
radeon_ioctl.c \ |
radeon_screen.c \ |
radeon_state.c \ |
radeon_state_init.c \ |
radeon_tex.c \ |
radeon_texstate.c \ |
radeon_tcl.c \ |
radeon_swtcl.c \ |
radeon_maos.c \ |
radeon_sanity.c \ |
radeon_blit.c |
RADEON_C_FILES = \ |
$(RADEON_COMMON_FILES) \ |
$(DRIVER_FILES) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_blit.c |
---|
0,0 → 1,429 |
/* |
* Copyright (C) 2010 Advanced Micro Devices, 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, 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 COPYRIGHT OWNER(S) 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 "radeon_common.h" |
#include "radeon_context.h" |
#include "radeon_blit.h" |
static inline uint32_t cmdpacket0(struct radeon_screen *rscrn, |
int reg, int count) |
{ |
if (count) |
return CP_PACKET0(reg, count - 1); |
return CP_PACKET2; |
} |
/* common formats supported as both textures and render targets */ |
unsigned r100_check_blit(gl_format mesa_format, uint32_t dst_pitch) |
{ |
/* XXX others? BE/LE? */ |
switch (mesa_format) { |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_XRGB8888: |
case MESA_FORMAT_RGB565: |
case MESA_FORMAT_ARGB4444: |
case MESA_FORMAT_ARGB1555: |
case MESA_FORMAT_A8: |
case MESA_FORMAT_L8: |
case MESA_FORMAT_I8: |
break; |
default: |
return 0; |
} |
/* Rendering to small buffer doesn't work. |
* Looks like a hw limitation. |
*/ |
if (dst_pitch < 32) |
return 0; |
/* ??? */ |
if (_mesa_get_format_bits(mesa_format, GL_DEPTH_BITS) > 0) |
return 0; |
return 1; |
} |
static inline void emit_vtx_state(struct r100_context *r100) |
{ |
BATCH_LOCALS(&r100->radeon); |
BEGIN_BATCH(8); |
if (r100->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) { |
OUT_BATCH_REGVAL(RADEON_SE_CNTL_STATUS, 0); |
} else { |
OUT_BATCH_REGVAL(RADEON_SE_CNTL_STATUS, RADEON_TCL_BYPASS); |
} |
OUT_BATCH_REGVAL(RADEON_SE_COORD_FMT, (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | |
RADEON_TEX1_W_ROUTING_USE_W0)); |
OUT_BATCH_REGVAL(RADEON_SE_VTX_FMT, RADEON_SE_VTX_FMT_XY | RADEON_SE_VTX_FMT_ST0); |
OUT_BATCH_REGVAL(RADEON_SE_CNTL, (RADEON_DIFFUSE_SHADE_GOURAUD | |
RADEON_BFACE_SOLID | |
RADEON_FFACE_SOLID | |
RADEON_VTX_PIX_CENTER_OGL | |
RADEON_ROUND_MODE_ROUND | |
RADEON_ROUND_PREC_4TH_PIX)); |
END_BATCH(); |
} |
static void inline emit_tx_setup(struct r100_context *r100, |
gl_format mesa_format, |
struct radeon_bo *bo, |
intptr_t offset, |
unsigned width, |
unsigned height, |
unsigned pitch) |
{ |
uint32_t txformat = RADEON_TXFORMAT_NON_POWER2; |
BATCH_LOCALS(&r100->radeon); |
assert(width <= 2048); |
assert(height <= 2048); |
assert(offset % 32 == 0); |
/* XXX others? BE/LE? */ |
switch (mesa_format) { |
case MESA_FORMAT_ARGB8888: |
txformat |= RADEON_TXFORMAT_ARGB8888 | RADEON_TXFORMAT_ALPHA_IN_MAP; |
break; |
case MESA_FORMAT_RGBA8888: |
txformat |= RADEON_TXFORMAT_RGBA8888 | RADEON_TXFORMAT_ALPHA_IN_MAP; |
break; |
case MESA_FORMAT_XRGB8888: |
txformat |= RADEON_TXFORMAT_ARGB8888; |
break; |
case MESA_FORMAT_RGB565: |
txformat |= RADEON_TXFORMAT_RGB565; |
break; |
case MESA_FORMAT_ARGB4444: |
txformat |= RADEON_TXFORMAT_ARGB4444 | RADEON_TXFORMAT_ALPHA_IN_MAP; |
break; |
case MESA_FORMAT_ARGB1555: |
txformat |= RADEON_TXFORMAT_ARGB1555 | RADEON_TXFORMAT_ALPHA_IN_MAP; |
break; |
case MESA_FORMAT_A8: |
case MESA_FORMAT_I8: |
txformat |= RADEON_TXFORMAT_I8 | RADEON_TXFORMAT_ALPHA_IN_MAP; |
break; |
case MESA_FORMAT_L8: |
txformat |= RADEON_TXFORMAT_I8; |
break; |
case MESA_FORMAT_AL88: |
txformat |= RADEON_TXFORMAT_AI88 | RADEON_TXFORMAT_ALPHA_IN_MAP; |
break; |
default: |
break; |
} |
if (bo->flags & RADEON_BO_FLAGS_MACRO_TILE) |
offset |= RADEON_TXO_MACRO_TILE; |
if (bo->flags & RADEON_BO_FLAGS_MICRO_TILE) |
offset |= RADEON_TXO_MICRO_TILE_X2; |
BEGIN_BATCH(18); |
OUT_BATCH_REGVAL(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE); |
OUT_BATCH_REGVAL(RADEON_PP_TXCBLEND_0, (RADEON_COLOR_ARG_A_ZERO | |
RADEON_COLOR_ARG_B_ZERO | |
RADEON_COLOR_ARG_C_T0_COLOR | |
RADEON_BLEND_CTL_ADD | |
RADEON_CLAMP_TX)); |
OUT_BATCH_REGVAL(RADEON_PP_TXABLEND_0, (RADEON_ALPHA_ARG_A_ZERO | |
RADEON_ALPHA_ARG_B_ZERO | |
RADEON_ALPHA_ARG_C_T0_ALPHA | |
RADEON_BLEND_CTL_ADD | |
RADEON_CLAMP_TX)); |
OUT_BATCH_REGVAL(RADEON_PP_TXFILTER_0, (RADEON_CLAMP_S_CLAMP_LAST | |
RADEON_CLAMP_T_CLAMP_LAST | |
RADEON_MAG_FILTER_NEAREST | |
RADEON_MIN_FILTER_NEAREST)); |
OUT_BATCH_REGVAL(RADEON_PP_TXFORMAT_0, txformat); |
OUT_BATCH_REGVAL(RADEON_PP_TEX_SIZE_0, ((width - 1) | |
((height - 1) << RADEON_TEX_VSIZE_SHIFT))); |
OUT_BATCH_REGVAL(RADEON_PP_TEX_PITCH_0, pitch * _mesa_get_format_bytes(mesa_format) - 32); |
OUT_BATCH_REGSEQ(RADEON_PP_TXOFFSET_0, 1); |
OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); |
END_BATCH(); |
} |
static inline void emit_cb_setup(struct r100_context *r100, |
struct radeon_bo *bo, |
intptr_t offset, |
gl_format mesa_format, |
unsigned pitch, |
unsigned width, |
unsigned height) |
{ |
uint32_t dst_pitch = pitch; |
uint32_t dst_format = 0; |
BATCH_LOCALS(&r100->radeon); |
/* XXX others? BE/LE? */ |
switch (mesa_format) { |
case MESA_FORMAT_ARGB8888: |
case MESA_FORMAT_XRGB8888: |
dst_format = RADEON_COLOR_FORMAT_ARGB8888; |
break; |
case MESA_FORMAT_RGB565: |
dst_format = RADEON_COLOR_FORMAT_RGB565; |
break; |
case MESA_FORMAT_ARGB4444: |
dst_format = RADEON_COLOR_FORMAT_ARGB4444; |
break; |
case MESA_FORMAT_ARGB1555: |
dst_format = RADEON_COLOR_FORMAT_ARGB1555; |
break; |
case MESA_FORMAT_A8: |
case MESA_FORMAT_L8: |
case MESA_FORMAT_I8: |
dst_format = RADEON_COLOR_FORMAT_RGB8; |
break; |
default: |
break; |
} |
if (bo->flags & RADEON_BO_FLAGS_MACRO_TILE) |
dst_pitch |= RADEON_COLOR_TILE_ENABLE; |
if (bo->flags & RADEON_BO_FLAGS_MICRO_TILE) |
dst_pitch |= RADEON_COLOR_MICROTILE_ENABLE; |
BEGIN_BATCH_NO_AUTOSTATE(18); |
OUT_BATCH_REGVAL(RADEON_RE_TOP_LEFT, 0); |
OUT_BATCH_REGVAL(RADEON_RE_WIDTH_HEIGHT, (((width - 1) << RADEON_RE_WIDTH_SHIFT) | |
((height - 1) << RADEON_RE_HEIGHT_SHIFT))); |
OUT_BATCH_REGVAL(RADEON_RB3D_PLANEMASK, 0xffffffff); |
OUT_BATCH_REGVAL(RADEON_RB3D_BLENDCNTL, RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO); |
OUT_BATCH_REGVAL(RADEON_RB3D_CNTL, dst_format); |
OUT_BATCH_REGSEQ(RADEON_RB3D_COLOROFFSET, 1); |
OUT_BATCH_RELOC(offset, bo, offset, 0, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); |
OUT_BATCH_REGSEQ(RADEON_RB3D_COLORPITCH, 1); |
OUT_BATCH_RELOC(dst_pitch, bo, dst_pitch, 0, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); |
END_BATCH(); |
} |
static GLboolean validate_buffers(struct r100_context *r100, |
struct radeon_bo *src_bo, |
struct radeon_bo *dst_bo) |
{ |
int ret; |
radeon_cs_space_reset_bos(r100->radeon.cmdbuf.cs); |
ret = radeon_cs_space_check_with_bo(r100->radeon.cmdbuf.cs, |
src_bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); |
if (ret) |
return GL_FALSE; |
ret = radeon_cs_space_check_with_bo(r100->radeon.cmdbuf.cs, |
dst_bo, 0, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT); |
if (ret) |
return GL_FALSE; |
return GL_TRUE; |
} |
/** |
* Calculate texcoords for given image region. |
* Output values are [minx, maxx, miny, maxy] |
*/ |
static inline void calc_tex_coords(float img_width, float img_height, |
float x, float y, |
float reg_width, float reg_height, |
unsigned flip_y, float *buf) |
{ |
buf[0] = x / img_width; |
buf[1] = buf[0] + reg_width / img_width; |
buf[2] = y / img_height; |
buf[3] = buf[2] + reg_height / img_height; |
if (flip_y) |
{ |
buf[2] = 1.0 - buf[2]; |
buf[3] = 1.0 - buf[3]; |
} |
} |
static inline void emit_draw_packet(struct r100_context *r100, |
unsigned src_width, unsigned src_height, |
unsigned src_x_offset, unsigned src_y_offset, |
unsigned dst_x_offset, unsigned dst_y_offset, |
unsigned reg_width, unsigned reg_height, |
unsigned flip_y) |
{ |
float texcoords[4]; |
float verts[12]; |
BATCH_LOCALS(&r100->radeon); |
calc_tex_coords(src_width, src_height, |
src_x_offset, src_y_offset, |
reg_width, reg_height, |
flip_y, texcoords); |
verts[0] = dst_x_offset; |
verts[1] = dst_y_offset + reg_height; |
verts[2] = texcoords[0]; |
verts[3] = texcoords[3]; |
verts[4] = dst_x_offset + reg_width; |
verts[5] = dst_y_offset + reg_height; |
verts[6] = texcoords[1]; |
verts[7] = texcoords[3]; |
verts[8] = dst_x_offset + reg_width; |
verts[9] = dst_y_offset; |
verts[10] = texcoords[1]; |
verts[11] = texcoords[2]; |
BEGIN_BATCH(15); |
OUT_BATCH(RADEON_CP_PACKET3_3D_DRAW_IMMD | (13 << 16)); |
OUT_BATCH(RADEON_CP_VC_FRMT_XY | RADEON_CP_VC_FRMT_ST0); |
OUT_BATCH(RADEON_CP_VC_CNTL_PRIM_WALK_RING | |
RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST | |
RADEON_CP_VC_CNTL_MAOS_ENABLE | |
RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | |
(3 << 16)); |
OUT_BATCH_TABLE(verts, 12); |
END_BATCH(); |
} |
/** |
* Copy a region of [@a width x @a height] pixels from source buffer |
* to destination buffer. |
* @param[in] r100 r100 context |
* @param[in] src_bo source radeon buffer object |
* @param[in] src_offset offset of the source image in the @a src_bo |
* @param[in] src_mesaformat source image format |
* @param[in] src_pitch aligned source image width |
* @param[in] src_width source image width |
* @param[in] src_height source image height |
* @param[in] src_x_offset x offset in the source image |
* @param[in] src_y_offset y offset in the source image |
* @param[in] dst_bo destination radeon buffer object |
* @param[in] dst_offset offset of the destination image in the @a dst_bo |
* @param[in] dst_mesaformat destination image format |
* @param[in] dst_pitch aligned destination image width |
* @param[in] dst_width destination image width |
* @param[in] dst_height destination image height |
* @param[in] dst_x_offset x offset in the destination image |
* @param[in] dst_y_offset y offset in the destination image |
* @param[in] width region width |
* @param[in] height region height |
* @param[in] flip_y set if y coords of the source image need to be flipped |
*/ |
unsigned r100_blit(struct gl_context *ctx, |
struct radeon_bo *src_bo, |
intptr_t src_offset, |
gl_format src_mesaformat, |
unsigned src_pitch, |
unsigned src_width, |
unsigned src_height, |
unsigned src_x_offset, |
unsigned src_y_offset, |
struct radeon_bo *dst_bo, |
intptr_t dst_offset, |
gl_format dst_mesaformat, |
unsigned dst_pitch, |
unsigned dst_width, |
unsigned dst_height, |
unsigned dst_x_offset, |
unsigned dst_y_offset, |
unsigned reg_width, |
unsigned reg_height, |
unsigned flip_y) |
{ |
struct r100_context *r100 = R100_CONTEXT(ctx); |
if (!r100_check_blit(dst_mesaformat, dst_pitch)) |
return GL_FALSE; |
/* Make sure that colorbuffer has even width - hw limitation */ |
if (dst_pitch % 2 > 0) |
++dst_pitch; |
/* Need to clamp the region size to make sure |
* we don't read outside of the source buffer |
* or write outside of the destination buffer. |
*/ |
if (reg_width + src_x_offset > src_width) |
reg_width = src_width - src_x_offset; |
if (reg_height + src_y_offset > src_height) |
reg_height = src_height - src_y_offset; |
if (reg_width + dst_x_offset > dst_width) |
reg_width = dst_width - dst_x_offset; |
if (reg_height + dst_y_offset > dst_height) |
reg_height = dst_height - dst_y_offset; |
if (src_bo == dst_bo) { |
return GL_FALSE; |
} |
if (src_offset % 32 || dst_offset % 32) { |
return GL_FALSE; |
} |
if (0) { |
fprintf(stderr, "src: size [%d x %d], pitch %d, offset %zd " |
"offset [%d x %d], format %s, bo %p\n", |
src_width, src_height, src_pitch, src_offset, |
src_x_offset, src_y_offset, |
_mesa_get_format_name(src_mesaformat), |
src_bo); |
fprintf(stderr, "dst: pitch %d offset %zd, offset[%d x %d], format %s, bo %p\n", |
dst_pitch, dst_offset, dst_x_offset, dst_y_offset, |
_mesa_get_format_name(dst_mesaformat), dst_bo); |
fprintf(stderr, "region: %d x %d\n", reg_width, reg_height); |
} |
/* Flush is needed to make sure that source buffer has correct data */ |
radeonFlush(ctx); |
rcommonEnsureCmdBufSpace(&r100->radeon, 59, __FUNCTION__); |
if (!validate_buffers(r100, src_bo, dst_bo)) |
return GL_FALSE; |
/* 8 */ |
emit_vtx_state(r100); |
/* 18 */ |
emit_tx_setup(r100, src_mesaformat, src_bo, src_offset, src_width, src_height, src_pitch); |
/* 18 */ |
emit_cb_setup(r100, dst_bo, dst_offset, dst_mesaformat, dst_pitch, dst_width, dst_height); |
/* 15 */ |
emit_draw_packet(r100, src_width, src_height, |
src_x_offset, src_y_offset, |
dst_x_offset, dst_y_offset, |
reg_width, reg_height, |
flip_y); |
radeonFlush(ctx); |
return GL_TRUE; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_blit.h |
---|
0,0 → 1,56 |
/* |
* Copyright (C) 2010 Advanced Micro Devices, 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, 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 COPYRIGHT OWNER(S) 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 RADEON_BLIT_H |
#define RADEON_BLIT_H |
void r100_blit_init(struct r100_context *r100); |
unsigned r100_check_blit(gl_format mesa_format, uint32_t dst_pitch); |
unsigned r100_blit(struct gl_context *ctx, |
struct radeon_bo *src_bo, |
intptr_t src_offset, |
gl_format src_mesaformat, |
unsigned src_pitch, |
unsigned src_width, |
unsigned src_height, |
unsigned src_x_offset, |
unsigned src_y_offset, |
struct radeon_bo *dst_bo, |
intptr_t dst_offset, |
gl_format dst_mesaformat, |
unsigned dst_pitch, |
unsigned dst_width, |
unsigned dst_height, |
unsigned dst_x_offset, |
unsigned dst_y_offset, |
unsigned width, |
unsigned height, |
unsigned flip_y); |
#endif // RADEON_BLIT_H |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_buffer_objects.c |
---|
0,0 → 1,233 |
/* |
* Copyright 2009 Maciej Cencora <m.cencora@gmail.com> |
* |
* 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, 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 COPYRIGHT OWNER(S) 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 "radeon_buffer_objects.h" |
#include "main/imports.h" |
#include "main/mtypes.h" |
#include "main/bufferobj.h" |
#include "radeon_common.h" |
struct radeon_buffer_object * |
get_radeon_buffer_object(struct gl_buffer_object *obj) |
{ |
return (struct radeon_buffer_object *) obj; |
} |
static struct gl_buffer_object * |
radeonNewBufferObject(struct gl_context * ctx, |
GLuint name, |
GLenum target) |
{ |
struct radeon_buffer_object *obj = CALLOC_STRUCT(radeon_buffer_object); |
_mesa_initialize_buffer_object(ctx, &obj->Base, name, target); |
obj->bo = NULL; |
return &obj->Base; |
} |
/** |
* Called via glDeleteBuffersARB(). |
*/ |
static void |
radeonDeleteBufferObject(struct gl_context * ctx, |
struct gl_buffer_object *obj) |
{ |
struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); |
if (obj->Pointer) { |
radeon_bo_unmap(radeon_obj->bo); |
} |
if (radeon_obj->bo) { |
radeon_bo_unref(radeon_obj->bo); |
} |
free(radeon_obj); |
} |
/** |
* Allocate space for and store data in a buffer object. Any data that was |
* previously stored in the buffer object is lost. If data is NULL, |
* memory will be allocated, but no copy will occur. |
* Called via ctx->Driver.BufferData(). |
* \return GL_TRUE for success, GL_FALSE if out of memory |
*/ |
static GLboolean |
radeonBufferData(struct gl_context * ctx, |
GLenum target, |
GLsizeiptrARB size, |
const GLvoid * data, |
GLenum usage, |
struct gl_buffer_object *obj) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); |
radeon_obj->Base.Size = size; |
radeon_obj->Base.Usage = usage; |
if (radeon_obj->bo != NULL) { |
radeon_bo_unref(radeon_obj->bo); |
radeon_obj->bo = NULL; |
} |
if (size != 0) { |
radeon_obj->bo = radeon_bo_open(radeon->radeonScreen->bom, |
0, |
size, |
32, |
RADEON_GEM_DOMAIN_GTT, |
0); |
if (!radeon_obj->bo) |
return GL_FALSE; |
if (data != NULL) { |
radeon_bo_map(radeon_obj->bo, GL_TRUE); |
memcpy(radeon_obj->bo->ptr, data, size); |
radeon_bo_unmap(radeon_obj->bo); |
} |
} |
return GL_TRUE; |
} |
/** |
* Replace data in a subrange of buffer object. If the data range |
* specified by size + offset extends beyond the end of the buffer or |
* if data is NULL, no copy is performed. |
* Called via glBufferSubDataARB(). |
*/ |
static void |
radeonBufferSubData(struct gl_context * ctx, |
GLintptrARB offset, |
GLsizeiptrARB size, |
const GLvoid * data, |
struct gl_buffer_object *obj) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); |
if (radeon_bo_is_referenced_by_cs(radeon_obj->bo, radeon->cmdbuf.cs)) { |
radeon_firevertices(radeon); |
} |
radeon_bo_map(radeon_obj->bo, GL_TRUE); |
memcpy(radeon_obj->bo->ptr + offset, data, size); |
radeon_bo_unmap(radeon_obj->bo); |
} |
/** |
* Called via glGetBufferSubDataARB() |
*/ |
static void |
radeonGetBufferSubData(struct gl_context * ctx, |
GLintptrARB offset, |
GLsizeiptrARB size, |
GLvoid * data, |
struct gl_buffer_object *obj) |
{ |
struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); |
radeon_bo_map(radeon_obj->bo, GL_FALSE); |
memcpy(data, radeon_obj->bo->ptr + offset, size); |
radeon_bo_unmap(radeon_obj->bo); |
} |
/** |
* Called via glMapBuffer() and glMapBufferRange() |
*/ |
static void * |
radeonMapBufferRange(struct gl_context * ctx, |
GLintptr offset, GLsizeiptr length, |
GLbitfield access, struct gl_buffer_object *obj) |
{ |
struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); |
const GLboolean write_only = |
(access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == GL_MAP_WRITE_BIT; |
if (write_only) { |
ctx->Driver.Flush(ctx); |
} |
if (radeon_obj->bo == NULL) { |
obj->Pointer = NULL; |
return NULL; |
} |
obj->Offset = offset; |
obj->Length = length; |
obj->AccessFlags = access; |
radeon_bo_map(radeon_obj->bo, write_only); |
obj->Pointer = radeon_obj->bo->ptr + offset; |
return obj->Pointer; |
} |
/** |
* Called via glUnmapBufferARB() |
*/ |
static GLboolean |
radeonUnmapBuffer(struct gl_context * ctx, |
struct gl_buffer_object *obj) |
{ |
struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); |
if (radeon_obj->bo != NULL) { |
radeon_bo_unmap(radeon_obj->bo); |
} |
obj->Pointer = NULL; |
obj->Offset = 0; |
obj->Length = 0; |
return GL_TRUE; |
} |
void |
radeonInitBufferObjectFuncs(struct dd_function_table *functions) |
{ |
functions->NewBufferObject = radeonNewBufferObject; |
functions->DeleteBuffer = radeonDeleteBufferObject; |
functions->BufferData = radeonBufferData; |
functions->BufferSubData = radeonBufferSubData; |
functions->GetBufferSubData = radeonGetBufferSubData; |
functions->MapBufferRange = radeonMapBufferRange; |
functions->UnmapBuffer = radeonUnmapBuffer; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_buffer_objects.h |
---|
0,0 → 1,52 |
/* |
* Copyright 2009 Maciej Cencora <m.cencora@gmail.com> |
* |
* 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, 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 COPYRIGHT OWNER(S) 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 RADEON_BUFFER_OBJECTS_H |
#define RADEON_BUFFER_OBJECTS_H |
#include "main/mtypes.h" |
struct radeon_bo; |
/** |
* Radeon vertex/pixel buffer object, derived from Mesa's gl_buffer_object. |
*/ |
struct radeon_buffer_object |
{ |
struct gl_buffer_object Base; |
struct radeon_bo *bo; |
}; |
struct radeon_buffer_object * |
get_radeon_buffer_object(struct gl_buffer_object *obj); |
/** |
* Hook the bufferobject implementation into mesa: |
*/ |
void radeonInitBufferObjectFuncs(struct dd_function_table *functions); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_chipset.h |
---|
0,0 → 1,41 |
#ifndef _RADEON_CHIPSET_H |
#define _RADEON_CHIPSET_H |
/* General chip classes: |
* r100 includes R100, RV100, RV200, RS100, RS200, RS250. |
* r200 includes R200, RV250, RV280, RS300. |
* (RS* denotes IGP) |
*/ |
enum { |
#define CHIPSET(id, name, family) PCI_CHIP_##name = id, |
#if defined(RADEON_R100) |
#include "pci_ids/radeon_pci_ids.h" |
#elif defined(RADEON_R200) |
#include "pci_ids/r200_pci_ids.h" |
#endif |
#undef CHIPSET |
}; |
enum { |
#if defined(RADEON_R100) |
CHIP_FAMILY_R100, |
CHIP_FAMILY_RV100, |
CHIP_FAMILY_RS100, |
CHIP_FAMILY_RV200, |
CHIP_FAMILY_RS200, |
#elif defined(RADEON_R200) |
CHIP_FAMILY_R200, |
CHIP_FAMILY_RV250, |
CHIP_FAMILY_RS300, |
CHIP_FAMILY_RV280, |
#endif |
CHIP_FAMILY_LAST |
}; |
#define RADEON_CHIPSET_TCL (1 << 0) /* tcl support - any radeon */ |
#define RADEON_CHIPSET_BROKEN_STENCIL (1 << 1) /* r100 stencil bug */ |
#define R200_CHIPSET_YCBCR_BROKEN (1 << 2) /* r200 ycbcr bug */ |
#define RADEON_CHIPSET_DEPTH_ALWAYS_TILED (1 << 3) /* M7 and R200s */ |
#endif /* _RADEON_CHIPSET_H */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_cmdbuf.h |
---|
0,0 → 1,113 |
#ifndef COMMON_CMDBUF_H |
#define COMMON_CMDBUF_H |
GLboolean rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller); |
int rcommonFlushCmdBuf(radeonContextPtr rmesa, const char *caller); |
int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller); |
void rcommonInitCmdBuf(radeonContextPtr rmesa); |
void rcommonDestroyCmdBuf(radeonContextPtr rmesa); |
void rcommonBeginBatch(radeonContextPtr rmesa, |
int n, |
int dostate, |
const char *file, |
const char *function, |
int line); |
/* +r6/r7 : code here moved */ |
#define CP_PACKET2 (2 << 30) |
#define CP_PACKET0(reg, n) (RADEON_CP_PACKET0 | ((n)<<16) | ((reg)>>2)) |
#define CP_PACKET0_ONE(reg, n) (RADEON_CP_PACKET0 | RADEON_CP_PACKET0_ONE_REG_WR | ((n)<<16) | ((reg)>>2)) |
#define CP_PACKET3(pkt, n) (RADEON_CP_PACKET3 | (pkt) | ((n) << 16)) |
/** |
* Every function writing to the command buffer needs to declare this |
* to get the necessary local variables. |
*/ |
#define BATCH_LOCALS(rmesa) \ |
const radeonContextPtr b_l_rmesa = rmesa |
/** |
* Prepare writing n dwords to the command buffer, |
* including producing any necessary state emits on buffer wraparound. |
*/ |
#define BEGIN_BATCH(n) rcommonBeginBatch(b_l_rmesa, n, 1, __FILE__, __FUNCTION__, __LINE__) |
/** |
* Same as BEGIN_BATCH, but do not cause automatic state emits. |
*/ |
#define BEGIN_BATCH_NO_AUTOSTATE(n) rcommonBeginBatch(b_l_rmesa, n, 0, __FILE__, __FUNCTION__, __LINE__) |
/** |
* Write one dword to the command buffer. |
*/ |
#define OUT_BATCH(data) \ |
do { \ |
radeon_cs_write_dword(b_l_rmesa->cmdbuf.cs, data);\ |
} while(0) |
/** |
* Write a relocated dword to the command buffer. |
*/ |
#define OUT_BATCH_RELOC(data, bo, offset, rd, wd, flags) \ |
do { \ |
int __offset = (offset); \ |
if (0 && __offset) { \ |
fprintf(stderr, "(%s:%s:%d) offset : %d\n", \ |
__FILE__, __FUNCTION__, __LINE__, __offset); \ |
} \ |
radeon_cs_write_dword(b_l_rmesa->cmdbuf.cs, __offset); \ |
radeon_cs_write_reloc(b_l_rmesa->cmdbuf.cs, \ |
bo, rd, wd, flags); \ |
} while(0) |
/** |
* Write n dwords from ptr to the command buffer. |
*/ |
#define OUT_BATCH_TABLE(ptr,n) \ |
do { \ |
radeon_cs_write_table(b_l_rmesa->cmdbuf.cs, (ptr), (n));\ |
} while(0) |
/** |
* Finish writing dwords to the command buffer. |
* The number of (direct or indirect) OUT_BATCH calls between the previous |
* BEGIN_BATCH and END_BATCH must match the number specified at BEGIN_BATCH time. |
*/ |
#define END_BATCH() \ |
do { \ |
radeon_cs_end(b_l_rmesa->cmdbuf.cs, __FILE__, __FUNCTION__, __LINE__);\ |
} while(0) |
/** |
* After the last END_BATCH() of rendering, this indicates that flushing |
* the command buffer now is okay. |
*/ |
#define COMMIT_BATCH() \ |
do { \ |
} while(0) |
/** Single register write to command buffer; requires 2 dwords. */ |
#define OUT_BATCH_REGVAL(reg, val) \ |
OUT_BATCH(cmdpacket0(b_l_rmesa->radeonScreen, (reg), 1)); \ |
OUT_BATCH((val)) |
/** Continuous register range write to command buffer; requires 1 dword, |
* expects count dwords afterwards for register contents. */ |
#define OUT_BATCH_REGSEQ(reg, count) \ |
OUT_BATCH(cmdpacket0(b_l_rmesa->radeonScreen, (reg), (count))) |
/* +r6/r7 : code here moved */ |
/* Fire the buffered vertices no matter what. |
*/ |
static INLINE void radeon_firevertices(radeonContextPtr radeon) |
{ |
if (radeon->cmdbuf.cs->cdw || radeon->dma.flush ) |
radeon->glCtx.Driver.Flush(&radeon->glCtx); /* +r6/r7 */ |
} |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_common.c |
---|
0,0 → 1,789 |
/************************************************************************** |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 COPYRIGHT OWNER(S) 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> |
*/ |
/* |
- Scissor implementation |
- buffer swap/copy ioctls |
- finish/flush |
- state emission |
- cmdbuffer management |
*/ |
#include <errno.h> |
#include "main/glheader.h" |
#include "main/imports.h" |
#include "main/context.h" |
#include "main/enums.h" |
#include "main/fbobject.h" |
#include "main/framebuffer.h" |
#include "main/renderbuffer.h" |
#include "drivers/common/meta.h" |
#include "radeon_common.h" |
#include "radeon_drm.h" |
#include "radeon_queryobj.h" |
/** |
* Enable verbose debug output for emit code. |
* 0 no output |
* 1 most output |
* 2 also print state alues |
*/ |
#define RADEON_CMDBUF 0 |
/* ============================================================= |
* Scissoring |
*/ |
/** |
* Update cliprects and scissors. |
*/ |
void radeonSetCliprects(radeonContextPtr radeon) |
{ |
__DRIdrawable *const drawable = radeon_get_drawable(radeon); |
__DRIdrawable *const readable = radeon_get_readable(radeon); |
if(drawable == NULL && readable == NULL) |
return; |
struct radeon_framebuffer *const draw_rfb = drawable->driverPrivate; |
struct radeon_framebuffer *const read_rfb = readable->driverPrivate; |
if ((draw_rfb->base.Width != drawable->w) || |
(draw_rfb->base.Height != drawable->h)) { |
_mesa_resize_framebuffer(&radeon->glCtx, &draw_rfb->base, |
drawable->w, drawable->h); |
} |
if (drawable != readable) { |
if ((read_rfb->base.Width != readable->w) || |
(read_rfb->base.Height != readable->h)) { |
_mesa_resize_framebuffer(&radeon->glCtx, &read_rfb->base, |
readable->w, readable->h); |
} |
} |
if (radeon->state.scissor.enabled) |
radeonUpdateScissor(&radeon->glCtx); |
} |
void radeonUpdateScissor( struct gl_context *ctx ) |
{ |
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
GLint x = ctx->Scissor.X, y = ctx->Scissor.Y; |
GLsizei w = ctx->Scissor.Width, h = ctx->Scissor.Height; |
int x1, y1, x2, y2; |
int min_x, min_y, max_x, max_y; |
if (!ctx->DrawBuffer) |
return; |
min_x = min_y = 0; |
max_x = ctx->DrawBuffer->Width - 1; |
max_y = ctx->DrawBuffer->Height - 1; |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
x1 = x; |
y1 = ctx->DrawBuffer->Height - (y + h); |
x2 = x + w - 1; |
y2 = y1 + h - 1; |
} else { |
x1 = x; |
y1 = y; |
x2 = x + w - 1; |
y2 = y + h - 1; |
} |
rmesa->state.scissor.rect.x1 = CLAMP(x1, min_x, max_x); |
rmesa->state.scissor.rect.y1 = CLAMP(y1, min_y, max_y); |
rmesa->state.scissor.rect.x2 = CLAMP(x2, min_x, max_x); |
rmesa->state.scissor.rect.y2 = CLAMP(y2, min_y, max_y); |
if (rmesa->vtbl.update_scissor) |
rmesa->vtbl.update_scissor(ctx); |
} |
/* ============================================================= |
* Scissoring |
*/ |
void radeonScissor(struct gl_context* ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
if (ctx->Scissor.Enabled) { |
/* We don't pipeline cliprect changes */ |
radeon_firevertices(radeon); |
radeonUpdateScissor(ctx); |
} |
} |
/* ================================================================ |
* SwapBuffers with client-side throttling |
*/ |
uint32_t radeonGetAge(radeonContextPtr radeon) |
{ |
drm_radeon_getparam_t gp; |
int ret; |
uint32_t age; |
gp.param = RADEON_PARAM_LAST_CLEAR; |
gp.value = (int *)&age; |
ret = drmCommandWriteRead(radeon->dri.fd, DRM_RADEON_GETPARAM, |
&gp, sizeof(gp)); |
if (ret) { |
fprintf(stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, |
ret); |
exit(1); |
} |
return age; |
} |
/** |
* Check if we're about to draw into the front color buffer. |
* If so, set the intel->front_buffer_dirty field to true. |
*/ |
void |
radeon_check_front_buffer_rendering(struct gl_context *ctx) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
const struct gl_framebuffer *fb = ctx->DrawBuffer; |
if (fb->Name == 0) { |
/* drawing to window system buffer */ |
if (fb->_NumColorDrawBuffers > 0) { |
if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { |
radeon->front_buffer_dirty = GL_TRUE; |
} |
} |
} |
} |
void radeon_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
struct radeon_renderbuffer *rrbDepth = NULL, *rrbStencil = NULL, |
*rrbColor = NULL; |
uint32_t offset = 0; |
if (!fb) { |
/* this can happen during the initial context initialization */ |
return; |
} |
/* radeons only handle 1 color draw so far */ |
if (fb->_NumColorDrawBuffers != 1) { |
radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE); |
return; |
} |
/* Do this here, note core Mesa, since this function is called from |
* many places within the driver. |
*/ |
if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { |
/* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ |
_mesa_update_framebuffer(ctx); |
/* this updates the DrawBuffer's Width/Height if it's a FBO */ |
_mesa_update_draw_buffer_bounds(ctx); |
} |
if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { |
/* this may occur when we're called by glBindFrameBuffer() during |
* the process of someone setting up renderbuffers, etc. |
*/ |
/*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/ |
return; |
} |
if (fb->Name) |
;/* do something depthy/stencily TODO */ |
/* none */ |
if (fb->Name == 0) { |
if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { |
rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); |
radeon->front_cliprects = GL_TRUE; |
} else { |
rrbColor = radeon_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); |
radeon->front_cliprects = GL_FALSE; |
} |
} else { |
/* user FBO in theory */ |
struct radeon_renderbuffer *rrb; |
rrb = radeon_renderbuffer(fb->_ColorDrawBuffers[0]); |
if (rrb) { |
offset = rrb->draw_offset; |
rrbColor = rrb; |
} |
} |
if (rrbColor == NULL) |
radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE); |
else |
radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE); |
if (fb->Attachment[BUFFER_DEPTH].Renderbuffer) { |
rrbDepth = radeon_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); |
if (rrbDepth && rrbDepth->bo) { |
radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_FALSE); |
} else { |
radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_TRUE); |
} |
} else { |
radeon->vtbl.fallback(ctx, RADEON_FALLBACK_DEPTH_BUFFER, GL_FALSE); |
rrbDepth = NULL; |
} |
if (fb->Attachment[BUFFER_STENCIL].Renderbuffer) { |
rrbStencil = radeon_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer); |
if (rrbStencil && rrbStencil->bo) { |
radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_FALSE); |
/* need to re-compute stencil hw state */ |
if (!rrbDepth) |
rrbDepth = rrbStencil; |
} else { |
radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_TRUE); |
} |
} else { |
radeon->vtbl.fallback(ctx, RADEON_FALLBACK_STENCIL_BUFFER, GL_FALSE); |
if (ctx->Driver.Enable != NULL) |
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); |
else |
ctx->NewState |= _NEW_STENCIL; |
} |
/* Update culling direction which changes depending on the |
* orientation of the buffer: |
*/ |
if (ctx->Driver.FrontFace) |
ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); |
else |
ctx->NewState |= _NEW_POLYGON; |
/* |
* Update depth test state |
*/ |
if (ctx->Driver.Enable) { |
ctx->Driver.Enable(ctx, GL_DEPTH_TEST, |
(ctx->Depth.Test && fb->Visual.depthBits > 0)); |
/* Need to update the derived ctx->Stencil._Enabled first */ |
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, |
(ctx->Stencil.Enabled && fb->Visual.stencilBits > 0)); |
} else { |
ctx->NewState |= (_NEW_DEPTH | _NEW_STENCIL); |
} |
_mesa_reference_renderbuffer(&radeon->state.depth.rb, &rrbDepth->base.Base); |
_mesa_reference_renderbuffer(&radeon->state.color.rb, &rrbColor->base.Base); |
radeon->state.color.draw_offset = offset; |
#if 0 |
/* update viewport since it depends on window size */ |
if (ctx->Driver.Viewport) { |
ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y, |
ctx->Viewport.Width, ctx->Viewport.Height); |
} else { |
} |
#endif |
ctx->NewState |= _NEW_VIEWPORT; |
/* Set state we know depends on drawable parameters: |
*/ |
radeonUpdateScissor(ctx); |
radeon->NewGLState |= _NEW_SCISSOR; |
if (ctx->Driver.DepthRange) |
ctx->Driver.DepthRange(ctx, |
ctx->Viewport.Near, |
ctx->Viewport.Far); |
/* Update culling direction which changes depending on the |
* orientation of the buffer: |
*/ |
if (ctx->Driver.FrontFace) |
ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); |
else |
ctx->NewState |= _NEW_POLYGON; |
} |
/** |
* Called via glDrawBuffer. |
*/ |
void radeonDrawBuffer( struct gl_context *ctx, GLenum mode ) |
{ |
if (RADEON_DEBUG & RADEON_DRI) |
fprintf(stderr, "%s %s\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr( mode )); |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
const GLboolean was_front_buffer_rendering = |
radeon->is_front_buffer_rendering; |
radeon->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) || |
(mode == GL_FRONT); |
/* If we weren't front-buffer rendering before but we are now, make sure |
* that the front-buffer has actually been allocated. |
*/ |
if (!was_front_buffer_rendering && radeon->is_front_buffer_rendering) { |
radeon_update_renderbuffers(radeon->dri.context, |
radeon->dri.context->driDrawablePriv, GL_FALSE); |
} |
} |
radeon_draw_buffer(ctx, ctx->DrawBuffer); |
} |
void radeonReadBuffer( struct gl_context *ctx, GLenum mode ) |
{ |
if (ctx->DrawBuffer && _mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
struct radeon_context *const rmesa = RADEON_CONTEXT(ctx); |
const GLboolean was_front_buffer_reading = rmesa->is_front_buffer_reading; |
rmesa->is_front_buffer_reading = (mode == GL_FRONT_LEFT) |
|| (mode == GL_FRONT); |
if (!was_front_buffer_reading && rmesa->is_front_buffer_reading) { |
radeon_update_renderbuffers(rmesa->dri.context, |
rmesa->dri.context->driReadablePriv, GL_FALSE); |
} |
} |
/* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ |
if (ctx->ReadBuffer == ctx->DrawBuffer) { |
/* This will update FBO completeness status. |
* A framebuffer will be incomplete if the GL_READ_BUFFER setting |
* refers to a missing renderbuffer. Calling glReadBuffer can set |
* that straight and can make the drawing buffer complete. |
*/ |
radeon_draw_buffer(ctx, ctx->DrawBuffer); |
} |
} |
void radeon_window_moved(radeonContextPtr radeon) |
{ |
/* Cliprects has to be updated before doing anything else */ |
radeonSetCliprects(radeon); |
} |
void radeon_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
__DRIcontext *driContext = radeon->dri.context; |
void (*old_viewport)(struct gl_context *ctx, GLint x, GLint y, |
GLsizei w, GLsizei h); |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer)) { |
if (radeon->is_front_buffer_rendering) { |
ctx->Driver.Flush(ctx); |
} |
radeon_update_renderbuffers(driContext, driContext->driDrawablePriv, GL_FALSE); |
if (driContext->driDrawablePriv != driContext->driReadablePriv) |
radeon_update_renderbuffers(driContext, driContext->driReadablePriv, GL_FALSE); |
} |
old_viewport = ctx->Driver.Viewport; |
ctx->Driver.Viewport = NULL; |
radeon_window_moved(radeon); |
radeon_draw_buffer(ctx, radeon->glCtx.DrawBuffer); |
ctx->Driver.Viewport = old_viewport; |
} |
static void radeon_print_state_atom(radeonContextPtr radeon, struct radeon_state_atom *state) |
{ |
int i, j, reg, count; |
int dwords; |
uint32_t packet0; |
if (!radeon_is_debug_enabled(RADEON_STATE, RADEON_VERBOSE) ) |
return; |
dwords = (*state->check) (&radeon->glCtx, state); |
fprintf(stderr, " emit %s %d/%d\n", state->name, dwords, state->cmd_size); |
if (state->cmd && radeon_is_debug_enabled(RADEON_STATE, RADEON_TRACE)) { |
if (dwords > state->cmd_size) |
dwords = state->cmd_size; |
for (i = 0; i < dwords;) { |
packet0 = state->cmd[i]; |
reg = (packet0 & 0x1FFF) << 2; |
count = ((packet0 & 0x3FFF0000) >> 16) + 1; |
fprintf(stderr, " %s[%d]: cmdpacket0 (first reg=0x%04x, count=%d)\n", |
state->name, i, reg, count); |
++i; |
for (j = 0; j < count && i < dwords; j++) { |
fprintf(stderr, " %s[%d]: 0x%04x = %08x\n", |
state->name, i, reg, state->cmd[i]); |
reg += 4; |
++i; |
} |
} |
} |
} |
/** |
* Count total size for next state emit. |
**/ |
GLuint radeonCountStateEmitSize(radeonContextPtr radeon) |
{ |
struct radeon_state_atom *atom; |
GLuint dwords = 0; |
/* check if we are going to emit full state */ |
if (radeon->cmdbuf.cs->cdw && !radeon->hw.all_dirty) { |
if (!radeon->hw.is_dirty) |
goto out; |
foreach(atom, &radeon->hw.atomlist) { |
if (atom->dirty) { |
const GLuint atom_size = atom->check(&radeon->glCtx, atom); |
dwords += atom_size; |
if (RADEON_CMDBUF && atom_size) { |
radeon_print_state_atom(radeon, atom); |
} |
} |
} |
} else { |
foreach(atom, &radeon->hw.atomlist) { |
const GLuint atom_size = atom->check(&radeon->glCtx, atom); |
dwords += atom_size; |
if (RADEON_CMDBUF && atom_size) { |
radeon_print_state_atom(radeon, atom); |
} |
} |
} |
out: |
radeon_print(RADEON_STATE, RADEON_NORMAL, "%s %u\n", __func__, dwords); |
return dwords; |
} |
static INLINE void radeon_emit_atom(radeonContextPtr radeon, struct radeon_state_atom *atom) |
{ |
BATCH_LOCALS(radeon); |
int dwords; |
dwords = (*atom->check) (&radeon->glCtx, atom); |
if (dwords) { |
radeon_print_state_atom(radeon, atom); |
if (atom->emit) { |
(*atom->emit)(&radeon->glCtx, atom); |
} else { |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_BATCH_TABLE(atom->cmd, dwords); |
END_BATCH(); |
} |
atom->dirty = GL_FALSE; |
} else { |
radeon_print(RADEON_STATE, RADEON_VERBOSE, " skip state %s\n", atom->name); |
} |
} |
static INLINE void radeonEmitAtoms(radeonContextPtr radeon, GLboolean emitAll) |
{ |
struct radeon_state_atom *atom; |
if (radeon->vtbl.pre_emit_atoms) |
radeon->vtbl.pre_emit_atoms(radeon); |
/* Emit actual atoms */ |
if (radeon->hw.all_dirty || emitAll) { |
foreach(atom, &radeon->hw.atomlist) |
radeon_emit_atom( radeon, atom ); |
} else { |
foreach(atom, &radeon->hw.atomlist) { |
if ( atom->dirty ) |
radeon_emit_atom( radeon, atom ); |
} |
} |
COMMIT_BATCH(); |
} |
static GLboolean radeon_revalidate_bos(struct gl_context *ctx) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
int ret; |
ret = radeon_cs_space_check(radeon->cmdbuf.cs); |
if (ret == RADEON_CS_SPACE_FLUSH) |
return GL_FALSE; |
return GL_TRUE; |
} |
void radeonEmitState(radeonContextPtr radeon) |
{ |
radeon_print(RADEON_STATE, RADEON_NORMAL, "%s\n", __FUNCTION__); |
if (radeon->vtbl.pre_emit_state) |
radeon->vtbl.pre_emit_state(radeon); |
/* this code used to return here but now it emits zbs */ |
if (radeon->cmdbuf.cs->cdw && !radeon->hw.is_dirty && !radeon->hw.all_dirty) |
return; |
if (!radeon->cmdbuf.cs->cdw) { |
if (RADEON_DEBUG & RADEON_STATE) |
fprintf(stderr, "Begin reemit state\n"); |
radeonEmitAtoms(radeon, GL_TRUE); |
} else { |
if (RADEON_DEBUG & RADEON_STATE) |
fprintf(stderr, "Begin dirty state\n"); |
radeonEmitAtoms(radeon, GL_FALSE); |
} |
radeon->hw.is_dirty = GL_FALSE; |
radeon->hw.all_dirty = GL_FALSE; |
} |
void radeonFlush(struct gl_context *ctx) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
if (RADEON_DEBUG & RADEON_IOCTL) |
fprintf(stderr, "%s %d\n", __FUNCTION__, radeon->cmdbuf.cs->cdw); |
/* okay if we have no cmds in the buffer && |
we have no DMA flush && |
we have no DMA buffer allocated. |
then no point flushing anything at all. |
*/ |
if (!radeon->dma.flush && !radeon->cmdbuf.cs->cdw && is_empty_list(&radeon->dma.reserved)) |
goto flush_front; |
if (radeon->dma.flush) |
radeon->dma.flush( ctx ); |
if (radeon->cmdbuf.cs->cdw) |
rcommonFlushCmdBuf(radeon, __FUNCTION__); |
flush_front: |
if (_mesa_is_winsys_fbo(ctx->DrawBuffer) && radeon->front_buffer_dirty) { |
__DRIscreen *const screen = radeon->radeonScreen->driScreen; |
if (screen->dri2.loader && (screen->dri2.loader->base.version >= 2) |
&& (screen->dri2.loader->flushFrontBuffer != NULL)) { |
__DRIdrawable * drawable = radeon_get_drawable(radeon); |
/* We set the dirty bit in radeon_prepare_render() if we're |
* front buffer rendering once we get there. |
*/ |
radeon->front_buffer_dirty = GL_FALSE; |
(*screen->dri2.loader->flushFrontBuffer)(drawable, drawable->loaderPrivate); |
} |
} |
} |
/* Make sure all commands have been sent to the hardware and have |
* completed processing. |
*/ |
void radeonFinish(struct gl_context * ctx) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
struct gl_framebuffer *fb = ctx->DrawBuffer; |
struct radeon_renderbuffer *rrb; |
int i; |
if (ctx->Driver.Flush) |
ctx->Driver.Flush(ctx); /* +r6/r7 */ |
for (i = 0; i < fb->_NumColorDrawBuffers; i++) { |
struct radeon_renderbuffer *rrb; |
rrb = radeon_renderbuffer(fb->_ColorDrawBuffers[i]); |
if (rrb && rrb->bo) |
radeon_bo_wait(rrb->bo); |
} |
rrb = radeon_get_depthbuffer(radeon); |
if (rrb && rrb->bo) |
radeon_bo_wait(rrb->bo); |
} |
/* cmdbuffer */ |
/** |
* Send the current command buffer via ioctl to the hardware. |
*/ |
int rcommonFlushCmdBufLocked(radeonContextPtr rmesa, const char *caller) |
{ |
int ret = 0; |
if (rmesa->cmdbuf.flushing) { |
fprintf(stderr, "Recursive call into r300FlushCmdBufLocked!\n"); |
exit(-1); |
} |
rmesa->cmdbuf.flushing = 1; |
if (RADEON_DEBUG & RADEON_IOCTL) { |
fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); |
} |
radeonEmitQueryEnd(&rmesa->glCtx); |
if (rmesa->cmdbuf.cs->cdw) { |
ret = radeon_cs_emit(rmesa->cmdbuf.cs); |
rmesa->hw.all_dirty = GL_TRUE; |
} |
radeon_cs_erase(rmesa->cmdbuf.cs); |
rmesa->cmdbuf.flushing = 0; |
if (radeon_revalidate_bos(&rmesa->glCtx) == GL_FALSE) { |
fprintf(stderr,"failed to revalidate buffers\n"); |
} |
return ret; |
} |
int rcommonFlushCmdBuf(radeonContextPtr rmesa, const char *caller) |
{ |
int ret; |
radeonReleaseDmaRegions(rmesa); |
ret = rcommonFlushCmdBufLocked(rmesa, caller); |
if (ret) { |
fprintf(stderr, "drmRadeonCmdBuffer: %d. Kernel failed to " |
"parse or rejected command stream. See dmesg " |
"for more info.\n", ret); |
exit(ret); |
} |
return ret; |
} |
/** |
* Make sure that enough space is available in the command buffer |
* by flushing if necessary. |
* |
* \param dwords The number of dwords we need to be free on the command buffer |
*/ |
GLboolean rcommonEnsureCmdBufSpace(radeonContextPtr rmesa, int dwords, const char *caller) |
{ |
if ((rmesa->cmdbuf.cs->cdw + dwords + 128) > rmesa->cmdbuf.size |
|| radeon_cs_need_flush(rmesa->cmdbuf.cs)) { |
/* If we try to flush empty buffer there is too big rendering operation. */ |
assert(rmesa->cmdbuf.cs->cdw); |
rcommonFlushCmdBuf(rmesa, caller); |
return GL_TRUE; |
} |
return GL_FALSE; |
} |
void rcommonInitCmdBuf(radeonContextPtr rmesa) |
{ |
GLuint size; |
struct drm_radeon_gem_info mminfo = { 0 }; |
/* Initialize command buffer */ |
size = 256 * driQueryOptioni(&rmesa->optionCache, |
"command_buffer_size"); |
if (size < 2 * rmesa->hw.max_state_size) { |
size = 2 * rmesa->hw.max_state_size + 65535; |
} |
if (size > 64 * 256) |
size = 64 * 256; |
radeon_print(RADEON_CS, RADEON_VERBOSE, |
"sizeof(drm_r300_cmd_header_t)=%zd\n", sizeof(drm_r300_cmd_header_t)); |
radeon_print(RADEON_CS, RADEON_VERBOSE, |
"sizeof(drm_radeon_cmd_buffer_t)=%zd\n", sizeof(drm_radeon_cmd_buffer_t)); |
radeon_print(RADEON_CS, RADEON_VERBOSE, |
"Allocating %d bytes command buffer (max state is %d bytes)\n", |
size * 4, rmesa->hw.max_state_size * 4); |
rmesa->cmdbuf.csm = |
radeon_cs_manager_gem_ctor(rmesa->radeonScreen->driScreen->fd); |
if (rmesa->cmdbuf.csm == NULL) { |
/* FIXME: fatal error */ |
return; |
} |
rmesa->cmdbuf.cs = radeon_cs_create(rmesa->cmdbuf.csm, size); |
assert(rmesa->cmdbuf.cs != NULL); |
rmesa->cmdbuf.size = size; |
radeon_cs_space_set_flush(rmesa->cmdbuf.cs, |
(void (*)(void *))rmesa->glCtx.Driver.Flush, &rmesa->glCtx); |
if (!drmCommandWriteRead(rmesa->dri.fd, DRM_RADEON_GEM_INFO, |
&mminfo, sizeof(mminfo))) { |
radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM, |
mminfo.vram_visible); |
radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT, |
mminfo.gart_size); |
} |
} |
/** |
* Destroy the command buffer |
*/ |
void rcommonDestroyCmdBuf(radeonContextPtr rmesa) |
{ |
radeon_cs_destroy(rmesa->cmdbuf.cs); |
radeon_cs_manager_gem_dtor(rmesa->cmdbuf.csm); |
} |
void rcommonBeginBatch(radeonContextPtr rmesa, int n, |
int dostate, |
const char *file, |
const char *function, |
int line) |
{ |
radeon_cs_begin(rmesa->cmdbuf.cs, n, file, function, line); |
radeon_print(RADEON_CS, RADEON_VERBOSE, "BEGIN_BATCH(%d) at %d, from %s:%i\n", |
n, rmesa->cmdbuf.cs->cdw, function, line); |
} |
void radeonUserClear(struct gl_context *ctx, GLuint mask) |
{ |
_mesa_meta_Clear(ctx, mask); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_common.h |
---|
0,0 → 1,88 |
#ifndef COMMON_MISC_H |
#define COMMON_MISC_H |
#include "radeon_common_context.h" |
#include "radeon_dma.h" |
#include "radeon_texture.h" |
void radeonUserClear(struct gl_context *ctx, GLuint mask); |
void radeonSetCliprects(radeonContextPtr radeon); |
void radeonUpdateScissor( struct gl_context *ctx ); |
void radeonScissor(struct gl_context* ctx, GLint x, GLint y, GLsizei w, GLsizei h); |
extern uint32_t radeonGetAge(radeonContextPtr radeon); |
void radeonFlush(struct gl_context *ctx); |
void radeonFinish(struct gl_context * ctx); |
void radeonEmitState(radeonContextPtr radeon); |
GLuint radeonCountStateEmitSize(radeonContextPtr radeon); |
void radeon_clear_tris(struct gl_context *ctx, GLbitfield mask); |
void radeon_window_moved(radeonContextPtr radeon); |
void radeon_draw_buffer(struct gl_context *ctx, struct gl_framebuffer *fb); |
void radeonDrawBuffer( struct gl_context *ctx, GLenum mode ); |
void radeonReadBuffer( struct gl_context *ctx, GLenum mode ); |
void radeon_viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height); |
void radeon_fbo_init(struct radeon_context *radeon); |
void |
radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb, |
struct radeon_bo *bo); |
struct radeon_renderbuffer * |
radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv); |
void |
radeonReadPixels(struct gl_context * ctx, |
GLint x, GLint y, GLsizei width, GLsizei height, |
GLenum format, GLenum type, |
const struct gl_pixelstore_attrib *pack, GLvoid * pixels); |
void radeon_check_front_buffer_rendering(struct gl_context *ctx); |
static inline struct radeon_renderbuffer *radeon_renderbuffer(struct gl_renderbuffer *rb) |
{ |
struct radeon_renderbuffer *rrb = (struct radeon_renderbuffer *)rb; |
radeon_print(RADEON_MEMORY, RADEON_TRACE, |
"%s(rb %p)\n", |
__func__, (void *) rb); |
if (rrb && rrb->base.Base.ClassID == RADEON_RB_CLASS) |
return rrb; |
else |
return NULL; |
} |
static inline struct radeon_renderbuffer *radeon_get_renderbuffer(struct gl_framebuffer *fb, int att_index) |
{ |
radeon_print(RADEON_MEMORY, RADEON_TRACE, |
"%s(fb %p, index %d)\n", |
__func__, (void *) fb, att_index); |
if (att_index >= 0) |
return radeon_renderbuffer(fb->Attachment[att_index].Renderbuffer); |
else |
return NULL; |
} |
static inline struct radeon_renderbuffer *radeon_get_depthbuffer(radeonContextPtr rmesa) |
{ |
struct radeon_renderbuffer *rrb; |
rrb = radeon_renderbuffer(rmesa->state.depth.rb); |
if (!rrb) |
return NULL; |
return rrb; |
} |
static inline struct radeon_renderbuffer *radeon_get_colorbuffer(radeonContextPtr rmesa) |
{ |
struct radeon_renderbuffer *rrb; |
rrb = radeon_renderbuffer(rmesa->state.color.rb); |
if (!rrb) |
return NULL; |
return rrb; |
} |
#include "radeon_cmdbuf.h" |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_common_context.c |
---|
0,0 → 1,628 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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, 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 COPYRIGHT OWNER(S) 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 "radeon_common.h" |
#include "xmlpool.h" /* for symbolic values of enum-type options */ |
#include "utils.h" |
#include "drivers/common/meta.h" |
#include "main/context.h" |
#include "main/framebuffer.h" |
#include "main/fbobject.h" |
#include "main/renderbuffer.h" |
#include "main/state.h" |
#include "main/simple_list.h" |
#include "swrast/swrast.h" |
#include "swrast_setup/swrast_setup.h" |
#include "tnl/tnl.h" |
#ifndef RADEON_DEBUG |
int RADEON_DEBUG = (0); |
#endif |
static const char* get_chip_family_name(int chip_family) |
{ |
switch(chip_family) { |
#if defined(RADEON_R100) |
case CHIP_FAMILY_R100: return "R100"; |
case CHIP_FAMILY_RV100: return "RV100"; |
case CHIP_FAMILY_RS100: return "RS100"; |
case CHIP_FAMILY_RV200: return "RV200"; |
case CHIP_FAMILY_RS200: return "RS200"; |
#elif defined(RADEON_R200) |
case CHIP_FAMILY_R200: return "R200"; |
case CHIP_FAMILY_RV250: return "RV250"; |
case CHIP_FAMILY_RS300: return "RS300"; |
case CHIP_FAMILY_RV280: return "RV280"; |
#endif |
default: return "unknown"; |
} |
} |
/* Return various strings for glGetString(). |
*/ |
static const GLubyte *radeonGetString(struct gl_context * ctx, GLenum name) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
static char buffer[128]; |
switch (name) { |
case GL_VENDOR: |
return (GLubyte *) "Tungsten Graphics, Inc."; |
case GL_RENDERER: |
{ |
unsigned offset; |
GLuint agp_mode = (radeon->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 : |
radeon->radeonScreen->AGPMode; |
char hardwarename[32]; |
sprintf(hardwarename, "%s (%s %04X)", |
#if defined(RADEON_R100) |
"R100", |
#elif defined(RADEON_R200) |
"R200", |
#endif |
get_chip_family_name(radeon->radeonScreen->chip_family), |
radeon->radeonScreen->device_id); |
offset = driGetRendererString(buffer, hardwarename, agp_mode); |
sprintf(&buffer[offset], " %sTCL", |
!(radeon->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE) |
? "" : "NO-"); |
strcat(buffer, " DRI2"); |
return (GLubyte *) buffer; |
} |
default: |
return NULL; |
} |
} |
/* Initialize the driver's misc functions. |
*/ |
static void radeonInitDriverFuncs(struct dd_function_table *functions) |
{ |
functions->GetString = radeonGetString; |
} |
/** |
* Create and initialize all common fields of the context, |
* including the Mesa context itself. |
*/ |
GLboolean radeonInitContext(radeonContextPtr radeon, |
struct dd_function_table* functions, |
const struct gl_config * glVisual, |
__DRIcontext * driContextPriv, |
void *sharedContextPrivate) |
{ |
__DRIscreen *sPriv = driContextPriv->driScreenPriv; |
radeonScreenPtr screen = (radeonScreenPtr) (sPriv->driverPrivate); |
struct gl_context* ctx; |
struct gl_context* shareCtx; |
int fthrottle_mode; |
/* Fill in additional standard functions. */ |
radeonInitDriverFuncs(functions); |
radeon->radeonScreen = screen; |
/* Allocate and initialize the Mesa context */ |
if (sharedContextPrivate) |
shareCtx = &((radeonContextPtr)sharedContextPrivate)->glCtx; |
else |
shareCtx = NULL; |
if (!_mesa_initialize_context(&radeon->glCtx, API_OPENGL_COMPAT, |
glVisual, shareCtx, |
functions)) |
return GL_FALSE; |
ctx = &radeon->glCtx; |
driContextPriv->driverPrivate = radeon; |
_mesa_meta_init(ctx); |
/* DRI fields */ |
radeon->dri.context = driContextPriv; |
radeon->dri.screen = sPriv; |
radeon->dri.fd = sPriv->fd; |
radeon->dri.drmMinor = sPriv->drm_version.minor; |
/* Setup IRQs */ |
fthrottle_mode = driQueryOptioni(&radeon->optionCache, "fthrottle_mode"); |
radeon->iw.irq_seq = -1; |
radeon->irqsEmitted = 0; |
radeon->do_irqs = (fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS && |
radeon->radeonScreen->irq); |
radeon->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS); |
if (!radeon->do_irqs) |
fprintf(stderr, |
"IRQ's not enabled, falling back to %s: %d %d\n", |
radeon->do_usleeps ? "usleeps" : "busy waits", |
fthrottle_mode, radeon->radeonScreen->irq); |
radeon->texture_depth = driQueryOptioni (&radeon->optionCache, |
"texture_depth"); |
if (radeon->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB) |
radeon->texture_depth = ( glVisual->rgbBits > 16 ) ? |
DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16; |
radeon->texture_row_align = 32; |
radeon->texture_rect_row_align = 64; |
radeon->texture_compressed_row_align = 32; |
radeon_init_dma(radeon); |
return GL_TRUE; |
} |
/** |
* Destroy the command buffer and state atoms. |
*/ |
static void radeon_destroy_atom_list(radeonContextPtr radeon) |
{ |
struct radeon_state_atom *atom; |
foreach(atom, &radeon->hw.atomlist) { |
free(atom->cmd); |
free(atom->lastcmd); |
} |
} |
/** |
* Cleanup common context fields. |
* Called by r200DestroyContext |
*/ |
void radeonDestroyContext(__DRIcontext *driContextPriv ) |
{ |
#ifdef RADEON_BO_TRACK |
FILE *track; |
#endif |
GET_CURRENT_CONTEXT(ctx); |
radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate; |
radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL; |
assert(radeon); |
_mesa_meta_free(&radeon->glCtx); |
if (radeon == current) { |
_mesa_make_current(NULL, NULL, NULL); |
} |
radeon_firevertices(radeon); |
if (!is_empty_list(&radeon->dma.reserved)) { |
rcommonFlushCmdBuf( radeon, __FUNCTION__ ); |
} |
radeonFreeDmaRegions(radeon); |
radeonReleaseArrays(&radeon->glCtx, ~0); |
if (radeon->vtbl.free_context) |
radeon->vtbl.free_context(&radeon->glCtx); |
_swsetup_DestroyContext( &radeon->glCtx ); |
_tnl_DestroyContext( &radeon->glCtx ); |
_vbo_DestroyContext( &radeon->glCtx ); |
_swrast_DestroyContext( &radeon->glCtx ); |
/* free atom list */ |
/* free the Mesa context data */ |
_mesa_free_context_data(&radeon->glCtx); |
/* free the option cache */ |
driDestroyOptionCache(&radeon->optionCache); |
rcommonDestroyCmdBuf(radeon); |
radeon_destroy_atom_list(radeon); |
#ifdef RADEON_BO_TRACK |
track = fopen("/tmp/tracklog", "w"); |
if (track) { |
radeon_tracker_print(&radeon->radeonScreen->bom->tracker, track); |
fclose(track); |
} |
#endif |
free(radeon); |
} |
/* Force the context `c' to be unbound from its buffer. |
*/ |
GLboolean radeonUnbindContext(__DRIcontext * driContextPriv) |
{ |
radeonContextPtr radeon = (radeonContextPtr) driContextPriv->driverPrivate; |
if (RADEON_DEBUG & RADEON_DRI) |
fprintf(stderr, "%s ctx %p\n", __FUNCTION__, |
&radeon->glCtx); |
/* Unset current context and dispath table */ |
_mesa_make_current(NULL, NULL, NULL); |
return GL_TRUE; |
} |
static unsigned |
radeon_bits_per_pixel(const struct radeon_renderbuffer *rb) |
{ |
return _mesa_get_format_bytes(rb->base.Base.Format) * 8; |
} |
/* |
* Check if drawable has been invalidated by dri2InvalidateDrawable(). |
* Update renderbuffers if so. This prevents a client from accessing |
* a backbuffer that has a swap pending but not yet completed. |
* |
* See intel_prepare_render for equivalent code in intel driver. |
* |
*/ |
void radeon_prepare_render(radeonContextPtr radeon) |
{ |
__DRIcontext *driContext = radeon->dri.context; |
__DRIdrawable *drawable; |
__DRIscreen *screen; |
screen = driContext->driScreenPriv; |
if (!screen->dri2.loader) |
return; |
drawable = driContext->driDrawablePriv; |
if (drawable->dri2.stamp != driContext->dri2.draw_stamp) { |
if (drawable->lastStamp != drawable->dri2.stamp) |
radeon_update_renderbuffers(driContext, drawable, GL_FALSE); |
/* Intel driver does the equivalent of this, no clue if it is needed:*/ |
radeon_draw_buffer(&radeon->glCtx, radeon->glCtx.DrawBuffer); |
driContext->dri2.draw_stamp = drawable->dri2.stamp; |
} |
drawable = driContext->driReadablePriv; |
if (drawable->dri2.stamp != driContext->dri2.read_stamp) { |
if (drawable->lastStamp != drawable->dri2.stamp) |
radeon_update_renderbuffers(driContext, drawable, GL_FALSE); |
driContext->dri2.read_stamp = drawable->dri2.stamp; |
} |
/* If we're currently rendering to the front buffer, the rendering |
* that will happen next will probably dirty the front buffer. So |
* mark it as dirty here. |
*/ |
if (radeon->is_front_buffer_rendering) |
radeon->front_buffer_dirty = GL_TRUE; |
} |
void |
radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, |
GLboolean front_only) |
{ |
unsigned int attachments[10]; |
__DRIbuffer *buffers = NULL; |
__DRIscreen *screen; |
struct radeon_renderbuffer *rb; |
int i, count; |
struct radeon_framebuffer *draw; |
radeonContextPtr radeon; |
char *regname; |
struct radeon_bo *depth_bo = NULL, *bo; |
if (RADEON_DEBUG & RADEON_DRI) |
fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable); |
draw = drawable->driverPrivate; |
screen = context->driScreenPriv; |
radeon = (radeonContextPtr) context->driverPrivate; |
/* Set this up front, so that in case our buffers get invalidated |
* while we're getting new buffers, we don't clobber the stamp and |
* thus ignore the invalidate. */ |
drawable->lastStamp = drawable->dri2.stamp; |
if (screen->dri2.loader |
&& (screen->dri2.loader->base.version > 2) |
&& (screen->dri2.loader->getBuffersWithFormat != NULL)) { |
struct radeon_renderbuffer *depth_rb; |
struct radeon_renderbuffer *stencil_rb; |
i = 0; |
if ((front_only || radeon->is_front_buffer_rendering || |
radeon->is_front_buffer_reading || |
!draw->color_rb[1]) |
&& draw->color_rb[0]) { |
attachments[i++] = __DRI_BUFFER_FRONT_LEFT; |
attachments[i++] = radeon_bits_per_pixel(draw->color_rb[0]); |
} |
if (!front_only) { |
if (draw->color_rb[1]) { |
attachments[i++] = __DRI_BUFFER_BACK_LEFT; |
attachments[i++] = radeon_bits_per_pixel(draw->color_rb[1]); |
} |
depth_rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH); |
stencil_rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL); |
if ((depth_rb != NULL) && (stencil_rb != NULL)) { |
attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; |
attachments[i++] = radeon_bits_per_pixel(depth_rb); |
} else if (depth_rb != NULL) { |
attachments[i++] = __DRI_BUFFER_DEPTH; |
attachments[i++] = radeon_bits_per_pixel(depth_rb); |
} else if (stencil_rb != NULL) { |
attachments[i++] = __DRI_BUFFER_STENCIL; |
attachments[i++] = radeon_bits_per_pixel(stencil_rb); |
} |
} |
buffers = (*screen->dri2.loader->getBuffersWithFormat)(drawable, |
&drawable->w, |
&drawable->h, |
attachments, i / 2, |
&count, |
drawable->loaderPrivate); |
} else if (screen->dri2.loader) { |
i = 0; |
if (draw->color_rb[0]) |
attachments[i++] = __DRI_BUFFER_FRONT_LEFT; |
if (!front_only) { |
if (draw->color_rb[1]) |
attachments[i++] = __DRI_BUFFER_BACK_LEFT; |
if (radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH)) |
attachments[i++] = __DRI_BUFFER_DEPTH; |
if (radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL)) |
attachments[i++] = __DRI_BUFFER_STENCIL; |
} |
buffers = (*screen->dri2.loader->getBuffers)(drawable, |
&drawable->w, |
&drawable->h, |
attachments, i, |
&count, |
drawable->loaderPrivate); |
} |
if (buffers == NULL) |
return; |
for (i = 0; i < count; i++) { |
switch (buffers[i].attachment) { |
case __DRI_BUFFER_FRONT_LEFT: |
rb = draw->color_rb[0]; |
regname = "dri2 front buffer"; |
break; |
case __DRI_BUFFER_FAKE_FRONT_LEFT: |
rb = draw->color_rb[0]; |
regname = "dri2 fake front buffer"; |
break; |
case __DRI_BUFFER_BACK_LEFT: |
rb = draw->color_rb[1]; |
regname = "dri2 back buffer"; |
break; |
case __DRI_BUFFER_DEPTH: |
rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH); |
regname = "dri2 depth buffer"; |
break; |
case __DRI_BUFFER_DEPTH_STENCIL: |
rb = radeon_get_renderbuffer(&draw->base, BUFFER_DEPTH); |
regname = "dri2 depth / stencil buffer"; |
break; |
case __DRI_BUFFER_STENCIL: |
rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL); |
regname = "dri2 stencil buffer"; |
break; |
case __DRI_BUFFER_ACCUM: |
default: |
fprintf(stderr, |
"unhandled buffer attach event, attacment type %d\n", |
buffers[i].attachment); |
return; |
} |
if (rb == NULL) |
continue; |
if (rb->bo) { |
uint32_t name = radeon_gem_name_bo(rb->bo); |
if (name == buffers[i].name) |
continue; |
} |
if (RADEON_DEBUG & RADEON_DRI) |
fprintf(stderr, |
"attaching buffer %s, %d, at %d, cpp %d, pitch %d\n", |
regname, buffers[i].name, buffers[i].attachment, |
buffers[i].cpp, buffers[i].pitch); |
rb->cpp = buffers[i].cpp; |
rb->pitch = buffers[i].pitch; |
rb->base.Base.Width = drawable->w; |
rb->base.Base.Height = drawable->h; |
rb->has_surface = 0; |
if (buffers[i].attachment == __DRI_BUFFER_STENCIL && depth_bo) { |
if (RADEON_DEBUG & RADEON_DRI) |
fprintf(stderr, "(reusing depth buffer as stencil)\n"); |
bo = depth_bo; |
radeon_bo_ref(bo); |
} else { |
uint32_t tiling_flags = 0, pitch = 0; |
int ret; |
bo = radeon_bo_open(radeon->radeonScreen->bom, |
buffers[i].name, |
0, |
0, |
RADEON_GEM_DOMAIN_VRAM, |
buffers[i].flags); |
if (bo == NULL) { |
fprintf(stderr, "failed to attach %s %d\n", |
regname, buffers[i].name); |
continue; |
} |
ret = radeon_bo_get_tiling(bo, &tiling_flags, &pitch); |
if (ret) { |
fprintf(stderr, |
"failed to get tiling for %s %d\n", |
regname, buffers[i].name); |
radeon_bo_unref(bo); |
bo = NULL; |
continue; |
} else { |
if (tiling_flags & RADEON_TILING_MACRO) |
bo->flags |= RADEON_BO_FLAGS_MACRO_TILE; |
if (tiling_flags & RADEON_TILING_MICRO) |
bo->flags |= RADEON_BO_FLAGS_MICRO_TILE; |
} |
} |
if (buffers[i].attachment == __DRI_BUFFER_DEPTH) { |
if (draw->base.Visual.depthBits == 16) |
rb->cpp = 2; |
depth_bo = bo; |
} |
radeon_renderbuffer_set_bo(rb, bo); |
radeon_bo_unref(bo); |
if (buffers[i].attachment == __DRI_BUFFER_DEPTH_STENCIL) { |
rb = radeon_get_renderbuffer(&draw->base, BUFFER_STENCIL); |
if (rb != NULL) { |
struct radeon_bo *stencil_bo = NULL; |
if (rb->bo) { |
uint32_t name = radeon_gem_name_bo(rb->bo); |
if (name == buffers[i].name) |
continue; |
} |
stencil_bo = bo; |
radeon_bo_ref(stencil_bo); |
radeon_renderbuffer_set_bo(rb, stencil_bo); |
radeon_bo_unref(stencil_bo); |
} |
} |
} |
driUpdateFramebufferSize(&radeon->glCtx, drawable); |
} |
/* Force the context `c' to be the current context and associate with it |
* buffer `b'. |
*/ |
GLboolean radeonMakeCurrent(__DRIcontext * driContextPriv, |
__DRIdrawable * driDrawPriv, |
__DRIdrawable * driReadPriv) |
{ |
radeonContextPtr radeon; |
GET_CURRENT_CONTEXT(curCtx); |
struct gl_framebuffer *drfb, *readfb; |
if (driContextPriv) |
radeon = (radeonContextPtr)driContextPriv->driverPrivate; |
else |
radeon = NULL; |
/* According to the glXMakeCurrent() man page: "Pending commands to |
* the previous context, if any, are flushed before it is released." |
* But only flush if we're actually changing contexts. |
*/ |
if ((radeonContextPtr)curCtx && (radeonContextPtr)curCtx != radeon) { |
_mesa_flush(curCtx); |
} |
if (!driContextPriv) { |
if (RADEON_DEBUG & RADEON_DRI) |
fprintf(stderr, "%s ctx is null\n", __FUNCTION__); |
_mesa_make_current(NULL, NULL, NULL); |
return GL_TRUE; |
} |
if(driDrawPriv == NULL && driReadPriv == NULL) { |
drfb = _mesa_create_framebuffer(&radeon->glCtx.Visual); |
readfb = drfb; |
} |
else { |
drfb = driDrawPriv->driverPrivate; |
readfb = driReadPriv->driverPrivate; |
} |
if(driDrawPriv) |
radeon_update_renderbuffers(driContextPriv, driDrawPriv, GL_FALSE); |
if (driDrawPriv != driReadPriv) |
radeon_update_renderbuffers(driContextPriv, driReadPriv, GL_FALSE); |
_mesa_reference_renderbuffer(&radeon->state.color.rb, |
&(radeon_get_renderbuffer(drfb, BUFFER_BACK_LEFT)->base.Base)); |
_mesa_reference_renderbuffer(&radeon->state.depth.rb, |
&(radeon_get_renderbuffer(drfb, BUFFER_DEPTH)->base.Base)); |
if (RADEON_DEBUG & RADEON_DRI) |
fprintf(stderr, "%s ctx %p dfb %p rfb %p\n", __FUNCTION__, &radeon->glCtx, drfb, readfb); |
if(driDrawPriv) |
driUpdateFramebufferSize(&radeon->glCtx, driDrawPriv); |
if (driReadPriv != driDrawPriv) |
driUpdateFramebufferSize(&radeon->glCtx, driReadPriv); |
_mesa_make_current(&radeon->glCtx, drfb, readfb); |
if (driDrawPriv == NULL && driReadPriv == NULL) |
_mesa_reference_framebuffer(&drfb, NULL); |
_mesa_update_state(&radeon->glCtx); |
if (radeon->glCtx.DrawBuffer == drfb) { |
if(driDrawPriv != NULL) { |
radeon_window_moved(radeon); |
} |
radeon_draw_buffer(&radeon->glCtx, drfb); |
} |
if (RADEON_DEBUG & RADEON_DRI) |
fprintf(stderr, "End %s\n", __FUNCTION__); |
return GL_TRUE; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_common_context.h |
---|
0,0 → 1,533 |
#ifndef COMMON_CONTEXT_H |
#define COMMON_CONTEXT_H |
#include "main/mm.h" |
#include "math/m_vector.h" |
#include "tnl/t_context.h" |
#include "main/colormac.h" |
#include "radeon_debug.h" |
#include "radeon_screen.h" |
#include "radeon_drm.h" |
#include "dri_util.h" |
#include "tnl/t_vertex.h" |
#include "swrast/s_context.h" |
struct radeon_context; |
#include "radeon_bo_gem.h" |
#include "radeon_cs_gem.h" |
/* This union is used to avoid warnings/miscompilation |
with float to uint32_t casts due to strict-aliasing */ |
typedef union { GLfloat f; uint32_t ui32; } float_ui32_type; |
struct radeon_context; |
typedef struct radeon_context radeonContextRec; |
typedef struct radeon_context *radeonContextPtr; |
#define TEX_0 0x1 |
#define TEX_1 0x2 |
#define TEX_2 0x4 |
#define TEX_3 0x8 |
#define TEX_4 0x10 |
#define TEX_5 0x20 |
/* Rasterizing fallbacks */ |
/* See correponding strings in r200_swtcl.c */ |
#define RADEON_FALLBACK_TEXTURE 0x0001 |
#define RADEON_FALLBACK_DRAW_BUFFER 0x0002 |
#define RADEON_FALLBACK_STENCIL 0x0004 |
#define RADEON_FALLBACK_RENDER_MODE 0x0008 |
#define RADEON_FALLBACK_BLEND_EQ 0x0010 |
#define RADEON_FALLBACK_BLEND_FUNC 0x0020 |
#define RADEON_FALLBACK_DISABLE 0x0040 |
#define RADEON_FALLBACK_BORDER_MODE 0x0080 |
#define RADEON_FALLBACK_DEPTH_BUFFER 0x0100 |
#define RADEON_FALLBACK_STENCIL_BUFFER 0x0200 |
#define R200_FALLBACK_TEXTURE 0x01 |
#define R200_FALLBACK_DRAW_BUFFER 0x02 |
#define R200_FALLBACK_STENCIL 0x04 |
#define R200_FALLBACK_RENDER_MODE 0x08 |
#define R200_FALLBACK_DISABLE 0x10 |
#define R200_FALLBACK_BORDER_MODE 0x20 |
#define RADEON_TCL_FALLBACK_RASTER 0x1 /* rasterization */ |
#define RADEON_TCL_FALLBACK_UNFILLED 0x2 /* unfilled tris */ |
#define RADEON_TCL_FALLBACK_LIGHT_TWOSIDE 0x4 /* twoside tris */ |
#define RADEON_TCL_FALLBACK_MATERIAL 0x8 /* material in vb */ |
#define RADEON_TCL_FALLBACK_TEXGEN_0 0x10 /* texgen, unit 0 */ |
#define RADEON_TCL_FALLBACK_TEXGEN_1 0x20 /* texgen, unit 1 */ |
#define RADEON_TCL_FALLBACK_TEXGEN_2 0x40 /* texgen, unit 2 */ |
#define RADEON_TCL_FALLBACK_TCL_DISABLE 0x80 /* user disable */ |
#define RADEON_TCL_FALLBACK_FOGCOORDSPEC 0x100 /* fogcoord, sep. spec light */ |
/* The blit width for texture uploads |
*/ |
#define BLIT_WIDTH_BYTES 1024 |
/* Use the templated vertex format: |
*/ |
#define COLOR_IS_RGBA |
#define TAG(x) radeon##x |
#include "tnl_dd/t_dd_vertex.h" |
#undef TAG |
#define RADEON_RB_CLASS 0xdeadbeef |
struct radeon_renderbuffer |
{ |
struct swrast_renderbuffer base; |
struct radeon_bo *bo; |
unsigned int cpp; |
/* unsigned int offset; */ |
unsigned int pitch; |
struct radeon_bo *map_bo; |
GLbitfield map_mode; |
int map_x, map_y, map_w, map_h; |
int map_pitch; |
void *map_buffer; |
uint32_t draw_offset; /* FBO */ |
/* boo Xorg 6.8.2 compat */ |
int has_surface; |
GLuint pf_pending; /**< sequence number of pending flip */ |
__DRIdrawable *dPriv; |
}; |
struct radeon_framebuffer |
{ |
struct gl_framebuffer base; |
struct radeon_renderbuffer *color_rb[2]; |
}; |
struct radeon_colorbuffer_state { |
int roundEnable; |
struct gl_renderbuffer *rb; |
uint32_t draw_offset; /* offset into color renderbuffer - FBOs */ |
}; |
struct radeon_depthbuffer_state { |
struct gl_renderbuffer *rb; |
}; |
struct radeon_scissor_state { |
drm_clip_rect_t rect; |
GLboolean enabled; |
}; |
struct radeon_state_atom { |
struct radeon_state_atom *next, *prev; |
const char *name; /* for debug */ |
int cmd_size; /* size in bytes */ |
GLuint idx; |
GLuint is_tcl; |
GLuint *cmd; /* one or more cmd's */ |
GLuint *lastcmd; /* one or more cmd's */ |
GLboolean dirty; /* dirty-mark in emit_state_list */ |
int (*check) (struct gl_context *, struct radeon_state_atom *atom); /* is this state active? */ |
void (*emit) (struct gl_context *, struct radeon_state_atom *atom); |
}; |
struct radeon_hw_state { |
/* Head of the linked list of state atoms. */ |
struct radeon_state_atom atomlist; |
int max_state_size; /* Number of bytes necessary for a full state emit. */ |
int max_post_flush_size; /* Number of bytes necessary for post flushing emits */ |
GLboolean is_dirty, all_dirty; |
}; |
/* Texture related */ |
typedef struct _radeon_texture_image radeon_texture_image; |
/** |
* This is a subclass of swrast_texture_image since we use swrast |
* for software fallback rendering. |
*/ |
struct _radeon_texture_image { |
struct swrast_texture_image base; |
/** |
* If mt != 0, the image is stored in hardware format in the |
* given mipmap tree. In this case, base.Data may point into the |
* mapping of the buffer object that contains the mipmap tree. |
* |
* If mt == 0, the image is stored in normal memory pointed to |
* by base.Data. |
*/ |
struct _radeon_mipmap_tree *mt; |
struct radeon_bo *bo; |
GLboolean used_as_render_target; |
}; |
static INLINE radeon_texture_image *get_radeon_texture_image(struct gl_texture_image *image) |
{ |
return (radeon_texture_image*)image; |
} |
typedef struct radeon_tex_obj radeonTexObj, *radeonTexObjPtr; |
#define RADEON_TXO_MICRO_TILE (1 << 3) |
/* Texture object in locally shared texture space. |
*/ |
struct radeon_tex_obj { |
struct gl_texture_object base; |
struct _radeon_mipmap_tree *mt; |
/** |
* This is true if we've verified that the mipmap tree above is complete |
* and so on. |
*/ |
GLboolean validated; |
/* Minimum LOD to be used during rendering */ |
unsigned minLod; |
/* Miximum LOD to be used during rendering */ |
unsigned maxLod; |
GLuint override_offset; |
GLboolean image_override; /* Image overridden by GLX_EXT_tfp */ |
GLuint tile_bits; /* hw texture tile bits used on this texture */ |
struct radeon_bo *bo; |
GLuint pp_txfilter; /* hardware register values */ |
GLuint pp_txformat; |
GLuint pp_txformat_x; |
GLuint pp_txsize; /* npot only */ |
GLuint pp_txpitch; /* npot only */ |
GLuint pp_border_color; |
GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */ |
GLboolean border_fallback; |
}; |
static INLINE radeonTexObj* radeon_tex_obj(struct gl_texture_object *texObj) |
{ |
return (radeonTexObj*)texObj; |
} |
/* occlusion query */ |
struct radeon_query_object { |
struct gl_query_object Base; |
struct radeon_bo *bo; |
int curr_offset; |
GLboolean emitted_begin; |
/* Double linked list of not flushed query objects */ |
struct radeon_query_object *prev, *next; |
}; |
/* Need refcounting on dma buffers: |
*/ |
struct radeon_dma_buffer { |
int refcount; /* the number of retained regions in buf */ |
drmBufPtr buf; |
}; |
struct radeon_aos { |
struct radeon_bo *bo; /** Buffer object where vertex data is stored */ |
int offset; /** Offset into buffer object, in bytes */ |
int components; /** Number of components per vertex */ |
int stride; /** Stride in dwords (may be 0 for repeating) */ |
int count; /** Number of vertices */ |
}; |
#define DMA_BO_FREE_TIME 100 |
struct radeon_dma_bo { |
struct radeon_dma_bo *next, *prev; |
struct radeon_bo *bo; |
int expire_counter; |
}; |
struct radeon_dma { |
/* Active dma region. Allocations for vertices and retained |
* regions come from here. Also used for emitting random vertices, |
* these may be flushed by calling flush_current(); |
*/ |
struct radeon_dma_bo free; |
struct radeon_dma_bo wait; |
struct radeon_dma_bo reserved; |
size_t current_used; /** Number of bytes allocated and forgotten about */ |
size_t current_vertexptr; /** End of active vertex region */ |
size_t minimum_size; |
/** |
* If current_vertexptr != current_used then flush must be non-zero. |
* flush must be called before non-active vertex allocations can be |
* performed. |
*/ |
void (*flush) (struct gl_context *); |
}; |
/* radeon_swtcl.c |
*/ |
struct radeon_swtcl_info { |
GLuint RenderIndex; |
GLuint vertex_size; |
GLubyte *verts; |
/* Fallback rasterization functions |
*/ |
GLuint hw_primitive; |
GLenum render_primitive; |
GLuint numverts; |
struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX]; |
GLuint vertex_attr_count; |
GLuint emit_prediction; |
struct radeon_bo *bo; |
}; |
#define RADEON_MAX_AOS_ARRAYS 16 |
struct radeon_tcl_info { |
struct radeon_aos aos[RADEON_MAX_AOS_ARRAYS]; |
GLuint aos_count; |
struct radeon_bo *elt_dma_bo; /** Buffer object that contains element indices */ |
int elt_dma_offset; /** Offset into this buffer object, in bytes */ |
}; |
struct radeon_ioctl { |
GLuint vertex_offset; |
GLuint vertex_max; |
struct radeon_bo *bo; |
GLuint vertex_size; |
}; |
#define RADEON_MAX_PRIMS 64 |
struct radeon_prim { |
GLuint start; |
GLuint end; |
GLuint prim; |
}; |
static INLINE GLuint radeonPackColor(GLuint cpp, |
GLubyte r, GLubyte g, |
GLubyte b, GLubyte a) |
{ |
switch (cpp) { |
case 2: |
return PACK_COLOR_565(r, g, b); |
case 4: |
return PACK_COLOR_8888(a, r, g, b); |
default: |
return 0; |
} |
} |
#define MAX_CMD_BUF_SZ (16*1024) |
#define MAX_DMA_BUF_SZ (64*1024) |
struct radeon_store { |
GLuint statenr; |
GLuint primnr; |
char cmd_buf[MAX_CMD_BUF_SZ]; |
int cmd_used; |
int elts_start; |
}; |
struct radeon_dri_mirror { |
__DRIcontext *context; /* DRI context */ |
__DRIscreen *screen; /* DRI screen */ |
drm_context_t hwContext; |
drm_hw_lock_t *hwLock; |
int hwLockCount; |
int fd; |
int drmMinor; |
}; |
typedef void (*radeon_tri_func) (radeonContextPtr, |
radeonVertex *, |
radeonVertex *, radeonVertex *); |
typedef void (*radeon_line_func) (radeonContextPtr, |
radeonVertex *, radeonVertex *); |
typedef void (*radeon_point_func) (radeonContextPtr, radeonVertex *); |
#define RADEON_MAX_BOS 32 |
struct radeon_state { |
struct radeon_colorbuffer_state color; |
struct radeon_depthbuffer_state depth; |
struct radeon_scissor_state scissor; |
}; |
/** |
* This structure holds the command buffer while it is being constructed. |
* |
* The first batch of commands in the buffer is always the state that needs |
* to be re-emitted when the context is lost. This batch can be skipped |
* otherwise. |
*/ |
struct radeon_cmdbuf { |
struct radeon_cs_manager *csm; |
struct radeon_cs *cs; |
int size; /** # of dwords total */ |
unsigned int flushing:1; /** whether we're currently in FlushCmdBufLocked */ |
}; |
struct radeon_context { |
struct gl_context glCtx; /**< base class, must be first */ |
radeonScreenPtr radeonScreen; /* Screen private DRI data */ |
/* Texture object bookkeeping |
*/ |
int texture_depth; |
float initialMaxAnisotropy; |
uint32_t texture_row_align; |
uint32_t texture_rect_row_align; |
uint32_t texture_compressed_row_align; |
struct radeon_dma dma; |
struct radeon_hw_state hw; |
/* Rasterization and vertex state: |
*/ |
GLuint TclFallback; |
GLuint Fallback; |
GLuint NewGLState; |
GLbitfield64 tnl_index_bitset; /* index of bits for last tnl_install_attrs */ |
/* Drawable information */ |
unsigned int lastStamp; |
drm_radeon_sarea_t *sarea; /* Private SAREA data */ |
/* Mirrors of some DRI state */ |
struct radeon_dri_mirror dri; |
/* Busy waiting */ |
GLuint do_usleeps; |
GLuint do_irqs; |
GLuint irqsEmitted; |
drm_radeon_irq_wait_t iw; |
/* Derived state - for r300 only */ |
struct radeon_state state; |
struct radeon_swtcl_info swtcl; |
struct radeon_tcl_info tcl; |
/* Configuration cache |
*/ |
driOptionCache optionCache; |
struct radeon_cmdbuf cmdbuf; |
struct radeon_debug debug; |
drm_clip_rect_t fboRect; |
GLboolean front_cliprects; |
/** |
* Set if rendering has occured to the drawable's front buffer. |
* |
* This is used in the DRI2 case to detect that glFlush should also copy |
* the contents of the fake front buffer to the real front buffer. |
*/ |
GLboolean front_buffer_dirty; |
/** |
* Track whether front-buffer rendering is currently enabled |
* |
* A separate flag is used to track this in order to support MRT more |
* easily. |
*/ |
GLboolean is_front_buffer_rendering; |
/** |
* Track whether front-buffer is the current read target. |
* |
* This is closely associated with is_front_buffer_rendering, but may |
* be set separately. The DRI2 fake front buffer must be referenced |
* either way. |
*/ |
GLboolean is_front_buffer_reading; |
struct { |
struct radeon_query_object *current; |
struct radeon_state_atom queryobj; |
} query; |
struct { |
void (*get_lock)(radeonContextPtr radeon); |
void (*update_viewport_offset)(struct gl_context *ctx); |
void (*emit_cs_header)(struct radeon_cs *cs, radeonContextPtr rmesa); |
void (*swtcl_flush)(struct gl_context *ctx, uint32_t offset); |
void (*pre_emit_atoms)(radeonContextPtr rmesa); |
void (*pre_emit_state)(radeonContextPtr rmesa); |
void (*fallback)(struct gl_context *ctx, GLuint bit, GLboolean mode); |
void (*free_context)(struct gl_context *ctx); |
void (*emit_query_finish)(radeonContextPtr radeon); |
void (*update_scissor)(struct gl_context *ctx); |
unsigned (*check_blit)(gl_format mesa_format, uint32_t dst_pitch); |
unsigned (*blit)(struct gl_context *ctx, |
struct radeon_bo *src_bo, |
intptr_t src_offset, |
gl_format src_mesaformat, |
unsigned src_pitch, |
unsigned src_width, |
unsigned src_height, |
unsigned src_x_offset, |
unsigned src_y_offset, |
struct radeon_bo *dst_bo, |
intptr_t dst_offset, |
gl_format dst_mesaformat, |
unsigned dst_pitch, |
unsigned dst_width, |
unsigned dst_height, |
unsigned dst_x_offset, |
unsigned dst_y_offset, |
unsigned reg_width, |
unsigned reg_height, |
unsigned flip_y); |
unsigned (*is_format_renderable)(gl_format mesa_format); |
} vtbl; |
}; |
static inline radeonContextPtr RADEON_CONTEXT(struct gl_context *ctx) |
{ |
return (radeonContextPtr) ctx; |
} |
static inline __DRIdrawable* radeon_get_drawable(radeonContextPtr radeon) |
{ |
return radeon->dri.context->driDrawablePriv; |
} |
static inline __DRIdrawable* radeon_get_readable(radeonContextPtr radeon) |
{ |
return radeon->dri.context->driReadablePriv; |
} |
GLboolean radeonInitContext(radeonContextPtr radeon, |
struct dd_function_table* functions, |
const struct gl_config * glVisual, |
__DRIcontext * driContextPriv, |
void *sharedContextPrivate); |
void radeonCleanupContext(radeonContextPtr radeon); |
GLboolean radeonUnbindContext(__DRIcontext * driContextPriv); |
void radeon_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable, |
GLboolean front_only); |
GLboolean radeonMakeCurrent(__DRIcontext * driContextPriv, |
__DRIdrawable * driDrawPriv, |
__DRIdrawable * driReadPriv); |
extern void radeonDestroyContext(__DRIcontext * driContextPriv); |
void radeon_prepare_render(radeonContextPtr radeon); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_context.c |
---|
0,0 → 1,411 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Kevin E. Martin <martin@valinux.com> |
* Gareth Hughes <gareth@valinux.com> |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#include <stdbool.h> |
#include "main/glheader.h" |
#include "main/api_arrayelt.h" |
#include "main/api_exec.h" |
#include "main/context.h" |
#include "main/simple_list.h" |
#include "main/imports.h" |
#include "main/extensions.h" |
#include "main/version.h" |
#include "main/vtxfmt.h" |
#include "swrast/swrast.h" |
#include "swrast_setup/swrast_setup.h" |
#include "vbo/vbo.h" |
#include "tnl/tnl.h" |
#include "tnl/t_pipeline.h" |
#include "drivers/common/driverfuncs.h" |
#include "radeon_common.h" |
#include "radeon_context.h" |
#include "radeon_ioctl.h" |
#include "radeon_state.h" |
#include "radeon_span.h" |
#include "radeon_tex.h" |
#include "radeon_swtcl.h" |
#include "radeon_tcl.h" |
#include "radeon_queryobj.h" |
#include "radeon_blit.h" |
#include "radeon_fog.h" |
#include "utils.h" |
#include "xmlpool.h" /* for symbolic values of enum-type options */ |
extern const struct tnl_pipeline_stage _radeon_render_stage; |
extern const struct tnl_pipeline_stage _radeon_tcl_stage; |
static const struct tnl_pipeline_stage *radeon_pipeline[] = { |
/* Try and go straight to t&l |
*/ |
&_radeon_tcl_stage, |
/* Catch any t&l fallbacks |
*/ |
&_tnl_vertex_transform_stage, |
&_tnl_normal_transform_stage, |
&_tnl_lighting_stage, |
&_tnl_fog_coordinate_stage, |
&_tnl_texgen_stage, |
&_tnl_texture_transform_stage, |
&_radeon_render_stage, |
&_tnl_render_stage, /* FALLBACK: */ |
NULL, |
}; |
static void r100_get_lock(radeonContextPtr radeon) |
{ |
r100ContextPtr rmesa = (r100ContextPtr)radeon; |
drm_radeon_sarea_t *sarea = radeon->sarea; |
RADEON_STATECHANGE(rmesa, ctx); |
if (rmesa->radeon.sarea->tiling_enabled) { |
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= |
RADEON_COLOR_TILE_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] &= |
~RADEON_COLOR_TILE_ENABLE; |
} |
if (sarea->ctx_owner != rmesa->radeon.dri.hwContext) { |
sarea->ctx_owner = rmesa->radeon.dri.hwContext; |
} |
} |
static void r100_vtbl_emit_cs_header(struct radeon_cs *cs, radeonContextPtr rmesa) |
{ |
} |
static void r100_vtbl_pre_emit_state(radeonContextPtr radeon) |
{ |
r100ContextPtr rmesa = (r100ContextPtr)radeon; |
/* r100 always needs to emit ZBS to avoid TCL lockups */ |
rmesa->hw.zbs.dirty = 1; |
radeon->hw.is_dirty = 1; |
} |
static void r100_vtbl_free_context(struct gl_context *ctx) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
_mesa_vector4f_free( &rmesa->tcl.ObjClean ); |
} |
static void r100_emit_query_finish(radeonContextPtr radeon) |
{ |
BATCH_LOCALS(radeon); |
struct radeon_query_object *query = radeon->query.current; |
BEGIN_BATCH_NO_AUTOSTATE(4); |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZPASS_ADDR, 0)); |
OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0); |
END_BATCH(); |
query->curr_offset += sizeof(uint32_t); |
assert(query->curr_offset < RADEON_QUERY_PAGE_SIZE); |
query->emitted_begin = GL_FALSE; |
} |
static void r100_init_vtbl(radeonContextPtr radeon) |
{ |
radeon->vtbl.get_lock = r100_get_lock; |
radeon->vtbl.update_viewport_offset = radeonUpdateViewportOffset; |
radeon->vtbl.emit_cs_header = r100_vtbl_emit_cs_header; |
radeon->vtbl.swtcl_flush = r100_swtcl_flush; |
radeon->vtbl.pre_emit_state = r100_vtbl_pre_emit_state; |
radeon->vtbl.fallback = radeonFallback; |
radeon->vtbl.free_context = r100_vtbl_free_context; |
radeon->vtbl.emit_query_finish = r100_emit_query_finish; |
radeon->vtbl.check_blit = r100_check_blit; |
radeon->vtbl.blit = r100_blit; |
radeon->vtbl.is_format_renderable = radeonIsFormatRenderable; |
} |
/* Create the device specific context. |
*/ |
GLboolean |
r100CreateContext( gl_api api, |
const struct gl_config *glVisual, |
__DRIcontext *driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
uint32_t flags, |
unsigned *error, |
void *sharedContextPrivate) |
{ |
__DRIscreen *sPriv = driContextPriv->driScreenPriv; |
radeonScreenPtr screen = (radeonScreenPtr)(sPriv->driverPrivate); |
struct dd_function_table functions; |
r100ContextPtr rmesa; |
struct gl_context *ctx; |
int i; |
int tcl_mode, fthrottle_mode; |
switch (api) { |
case API_OPENGL_COMPAT: |
if (major_version > 1 || minor_version > 3) { |
*error = __DRI_CTX_ERROR_BAD_VERSION; |
return GL_FALSE; |
} |
break; |
case API_OPENGLES: |
break; |
default: |
*error = __DRI_CTX_ERROR_BAD_API; |
return GL_FALSE; |
} |
/* Flag filtering is handled in dri2CreateContextAttribs. |
*/ |
(void) flags; |
assert(glVisual); |
assert(driContextPriv); |
assert(screen); |
/* Allocate the Radeon context */ |
rmesa = calloc(1, sizeof(*rmesa)); |
if ( !rmesa ) { |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
return GL_FALSE; |
} |
rmesa->radeon.radeonScreen = screen; |
r100_init_vtbl(&rmesa->radeon); |
/* init exp fog table data */ |
radeonInitStaticFogData(); |
/* Parse configuration files. |
* Do this here so that initialMaxAnisotropy is set before we create |
* the default textures. |
*/ |
driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache, |
screen->driScreen->myNum, "radeon"); |
rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache, |
"def_max_anisotropy"); |
if ( driQueryOptionb( &rmesa->radeon.optionCache, "hyperz" ) ) { |
if ( sPriv->drm_version.minor < 13 ) |
fprintf( stderr, "DRM version 1.%d too old to support HyperZ, " |
"disabling.\n", sPriv->drm_version.minor ); |
else |
rmesa->using_hyperz = GL_TRUE; |
} |
if ( sPriv->drm_version.minor >= 15 ) |
rmesa->texmicrotile = GL_TRUE; |
/* Init default driver functions then plug in our Radeon-specific functions |
* (the texture functions are especially important) |
*/ |
_mesa_init_driver_functions( &functions ); |
radeonInitTextureFuncs( &rmesa->radeon, &functions ); |
radeonInitQueryObjFunctions(&functions); |
if (!radeonInitContext(&rmesa->radeon, &functions, |
glVisual, driContextPriv, |
sharedContextPrivate)) { |
free(rmesa); |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
return GL_FALSE; |
} |
rmesa->radeon.swtcl.RenderIndex = ~0; |
rmesa->radeon.hw.all_dirty = GL_TRUE; |
ctx = &rmesa->radeon.glCtx; |
/* Initialize the software rasterizer and helper modules. |
*/ |
_swrast_CreateContext( ctx ); |
_vbo_CreateContext( ctx ); |
_tnl_CreateContext( ctx ); |
_swsetup_CreateContext( ctx ); |
_ae_create_context( ctx ); |
ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache, |
"texture_units"); |
ctx->Const.FragmentProgram.MaxTextureImageUnits = ctx->Const.MaxTextureUnits; |
ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits; |
ctx->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxTextureUnits; |
ctx->Const.StripTextureBorder = GL_TRUE; |
/* FIXME: When no memory manager is available we should set this |
* to some reasonable value based on texture memory pool size */ |
ctx->Const.MaxTextureLevels = 12; |
ctx->Const.Max3DTextureLevels = 9; |
ctx->Const.MaxCubeTextureLevels = 12; |
ctx->Const.MaxTextureRectSize = 2048; |
ctx->Const.MaxTextureMaxAnisotropy = 16.0; |
/* No wide points. |
*/ |
ctx->Const.MinPointSize = 1.0; |
ctx->Const.MinPointSizeAA = 1.0; |
ctx->Const.MaxPointSize = 1.0; |
ctx->Const.MaxPointSizeAA = 1.0; |
ctx->Const.MinLineWidth = 1.0; |
ctx->Const.MinLineWidthAA = 1.0; |
ctx->Const.MaxLineWidth = 10.0; |
ctx->Const.MaxLineWidthAA = 10.0; |
ctx->Const.LineWidthGranularity = 0.0625; |
/* Set maxlocksize (and hence vb size) small enough to avoid |
* fallbacks in radeon_tcl.c. ie. guarentee that all vertices can |
* fit in a single dma buffer for indexed rendering of quad strips, |
* etc. |
*/ |
ctx->Const.MaxArrayLockSize = |
MIN2( ctx->Const.MaxArrayLockSize, |
RADEON_BUFFER_SIZE / RADEON_MAX_TCL_VERTSIZE ); |
rmesa->boxes = 0; |
ctx->Const.MaxDrawBuffers = 1; |
ctx->Const.MaxColorAttachments = 1; |
ctx->Const.MaxRenderbufferSize = 2048; |
ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].PreferDP4 = true; |
/* Install the customized pipeline: |
*/ |
_tnl_destroy_pipeline( ctx ); |
_tnl_install_pipeline( ctx, radeon_pipeline ); |
/* Try and keep materials and vertices separate: |
*/ |
/* _tnl_isolate_materials( ctx, GL_TRUE ); */ |
/* Configure swrast and T&L to match hardware characteristics: |
*/ |
_swrast_allow_pixel_fog( ctx, GL_FALSE ); |
_swrast_allow_vertex_fog( ctx, GL_TRUE ); |
_tnl_allow_pixel_fog( ctx, GL_FALSE ); |
_tnl_allow_vertex_fog( ctx, GL_TRUE ); |
for ( i = 0 ; i < RADEON_MAX_TEXTURE_UNITS ; i++ ) { |
_math_matrix_ctr( &rmesa->TexGenMatrix[i] ); |
_math_matrix_ctr( &rmesa->tmpmat[i] ); |
_math_matrix_set_identity( &rmesa->TexGenMatrix[i] ); |
_math_matrix_set_identity( &rmesa->tmpmat[i] ); |
} |
ctx->Extensions.ARB_texture_border_clamp = true; |
ctx->Extensions.ARB_texture_env_combine = true; |
ctx->Extensions.ARB_texture_env_crossbar = true; |
ctx->Extensions.ARB_texture_env_dot3 = true; |
ctx->Extensions.EXT_packed_depth_stencil = true; |
ctx->Extensions.EXT_texture_env_dot3 = true; |
ctx->Extensions.EXT_texture_filter_anisotropic = true; |
ctx->Extensions.EXT_texture_mirror_clamp = true; |
ctx->Extensions.ATI_texture_env_combine3 = true; |
ctx->Extensions.ATI_texture_mirror_once = true; |
ctx->Extensions.MESA_ycbcr_texture = true; |
ctx->Extensions.OES_EGL_image = true; |
ctx->Extensions.ARB_texture_cube_map = true; |
if (rmesa->radeon.glCtx.Mesa_DXTn) { |
ctx->Extensions.EXT_texture_compression_s3tc = true; |
ctx->Extensions.ANGLE_texture_compression_dxt = true; |
} |
else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) { |
ctx->Extensions.EXT_texture_compression_s3tc = true; |
ctx->Extensions.ANGLE_texture_compression_dxt = true; |
} |
ctx->Extensions.NV_texture_rectangle = true; |
ctx->Extensions.ARB_occlusion_query = true; |
/* XXX these should really go right after _mesa_init_driver_functions() */ |
radeon_fbo_init(&rmesa->radeon); |
radeonInitSpanFuncs( ctx ); |
radeonInitIoctlFuncs( ctx ); |
radeonInitStateFuncs( ctx ); |
radeonInitState( rmesa ); |
radeonInitSwtcl( ctx ); |
_mesa_vector4f_alloc( &rmesa->tcl.ObjClean, 0, |
ctx->Const.MaxArrayLockSize, 32 ); |
fthrottle_mode = driQueryOptioni(&rmesa->radeon.optionCache, "fthrottle_mode"); |
rmesa->radeon.iw.irq_seq = -1; |
rmesa->radeon.irqsEmitted = 0; |
rmesa->radeon.do_irqs = (rmesa->radeon.radeonScreen->irq != 0 && |
fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS); |
rmesa->radeon.do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS); |
#if DO_DEBUG |
RADEON_DEBUG = driParseDebugString( getenv( "RADEON_DEBUG" ), |
debug_control ); |
#endif |
tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode"); |
if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) { |
fprintf(stderr, "disabling 3D acceleration\n"); |
FALLBACK(rmesa, RADEON_FALLBACK_DISABLE, 1); |
} else if (tcl_mode == DRI_CONF_TCL_SW || |
!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) { |
if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) { |
rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL; |
fprintf(stderr, "Disabling HW TCL support\n"); |
} |
TCL_FALLBACK(&rmesa->radeon.glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1); |
} |
if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) { |
/* _tnl_need_dlist_norm_lengths( ctx, GL_FALSE ); */ |
} |
_mesa_compute_version(ctx); |
/* Exec table initialization requires the version to be computed */ |
_mesa_initialize_dispatch_tables(ctx); |
_mesa_initialize_vbo_vtxfmt(ctx); |
*error = __DRI_CTX_ERROR_SUCCESS; |
return GL_TRUE; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_context.h |
---|
0,0 → 1,465 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Gareth Hughes <gareth@valinux.com> |
* Keith Whitwell <keith@tungstengraphics.com> |
* Kevin E. Martin <martin@valinux.com> |
* Nicolai Haehnle <prefect_@gmx.net> |
*/ |
#ifndef __RADEON_CONTEXT_H__ |
#define __RADEON_CONTEXT_H__ |
#include "tnl/t_vertex.h" |
#include "dri_util.h" |
#include "drm.h" |
#include "radeon_drm.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/colormac.h" |
#include "radeon_screen.h" |
#include "radeon_common.h" |
struct r100_context; |
typedef struct r100_context r100ContextRec; |
typedef struct r100_context *r100ContextPtr; |
#define R100_TEX_ALL 0x7 |
/* used for both tcl_vtx and vc_frmt tex bits (they are identical) */ |
#define RADEON_ST_BIT(unit) \ |
(unit == 0 ? RADEON_CP_VC_FRMT_ST0 : (RADEON_CP_VC_FRMT_ST1 >> 2) << (2 * unit)) |
#define RADEON_Q_BIT(unit) \ |
(unit == 0 ? RADEON_CP_VC_FRMT_Q0 : (RADEON_CP_VC_FRMT_Q1 >> 2) << (2 * unit)) |
struct radeon_texture_env_state { |
radeonTexObjPtr texobj; |
GLenum format; |
GLenum envMode; |
}; |
struct radeon_texture_state { |
struct radeon_texture_env_state unit[RADEON_MAX_TEXTURE_UNITS]; |
}; |
/* Trying to keep these relatively short as the variables are becoming |
* extravagently long. Drop the driver name prefix off the front of |
* everything - I think we know which driver we're in by now, and keep the |
* prefix to 3 letters unless absolutely impossible. |
*/ |
#define CTX_CMD_0 0 |
#define CTX_PP_MISC 1 |
#define CTX_PP_FOG_COLOR 2 |
#define CTX_RE_SOLID_COLOR 3 |
#define CTX_RB3D_BLENDCNTL 4 |
#define CTX_RB3D_DEPTHOFFSET 5 |
#define CTX_RB3D_DEPTHPITCH 6 |
#define CTX_RB3D_ZSTENCILCNTL 7 |
#define CTX_CMD_1 8 |
#define CTX_PP_CNTL 9 |
#define CTX_RB3D_CNTL 10 |
#define CTX_RB3D_COLOROFFSET 11 |
#define CTX_CMD_2 12 |
#define CTX_RB3D_COLORPITCH 13 |
#define CTX_STATE_SIZE 14 |
#define SET_CMD_0 0 |
#define SET_SE_CNTL 1 |
#define SET_SE_COORDFMT 2 |
#define SET_CMD_1 3 |
#define SET_SE_CNTL_STATUS 4 |
#define SET_STATE_SIZE 5 |
#define LIN_CMD_0 0 |
#define LIN_RE_LINE_PATTERN 1 |
#define LIN_RE_LINE_STATE 2 |
#define LIN_CMD_1 3 |
#define LIN_SE_LINE_WIDTH 4 |
#define LIN_STATE_SIZE 5 |
#define MSK_CMD_0 0 |
#define MSK_RB3D_STENCILREFMASK 1 |
#define MSK_RB3D_ROPCNTL 2 |
#define MSK_RB3D_PLANEMASK 3 |
#define MSK_STATE_SIZE 4 |
#define VPT_CMD_0 0 |
#define VPT_SE_VPORT_XSCALE 1 |
#define VPT_SE_VPORT_XOFFSET 2 |
#define VPT_SE_VPORT_YSCALE 3 |
#define VPT_SE_VPORT_YOFFSET 4 |
#define VPT_SE_VPORT_ZSCALE 5 |
#define VPT_SE_VPORT_ZOFFSET 6 |
#define VPT_STATE_SIZE 7 |
#define MSC_CMD_0 0 |
#define MSC_RE_MISC 1 |
#define MSC_STATE_SIZE 2 |
#define TEX_CMD_0 0 |
#define TEX_PP_TXFILTER 1 |
#define TEX_PP_TXFORMAT 2 |
#define TEX_PP_TXOFFSET 3 |
#define TEX_PP_TXCBLEND 4 |
#define TEX_PP_TXABLEND 5 |
#define TEX_PP_TFACTOR 6 |
#define TEX_CMD_1 7 |
#define TEX_PP_BORDER_COLOR 8 |
#define TEX_STATE_SIZE 9 |
#define TXR_CMD_0 0 /* rectangle textures */ |
#define TXR_PP_TEX_SIZE 1 /* 0x1d04, 0x1d0c for NPOT! */ |
#define TXR_PP_TEX_PITCH 2 /* 0x1d08, 0x1d10 for NPOT! */ |
#define TXR_STATE_SIZE 3 |
#define CUBE_CMD_0 0 |
#define CUBE_PP_CUBIC_FACES 1 |
#define CUBE_CMD_1 2 |
#define CUBE_PP_CUBIC_OFFSET_0 3 |
#define CUBE_PP_CUBIC_OFFSET_1 4 |
#define CUBE_PP_CUBIC_OFFSET_2 5 |
#define CUBE_PP_CUBIC_OFFSET_3 6 |
#define CUBE_PP_CUBIC_OFFSET_4 7 |
#define CUBE_STATE_SIZE 8 |
#define ZBS_CMD_0 0 |
#define ZBS_SE_ZBIAS_FACTOR 1 |
#define ZBS_SE_ZBIAS_CONSTANT 2 |
#define ZBS_STATE_SIZE 3 |
#define TCL_CMD_0 0 |
#define TCL_OUTPUT_VTXFMT 1 |
#define TCL_OUTPUT_VTXSEL 2 |
#define TCL_MATRIX_SELECT_0 3 |
#define TCL_MATRIX_SELECT_1 4 |
#define TCL_UCP_VERT_BLEND_CTL 5 |
#define TCL_TEXTURE_PROC_CTL 6 |
#define TCL_LIGHT_MODEL_CTL 7 |
#define TCL_PER_LIGHT_CTL_0 8 |
#define TCL_PER_LIGHT_CTL_1 9 |
#define TCL_PER_LIGHT_CTL_2 10 |
#define TCL_PER_LIGHT_CTL_3 11 |
#define TCL_STATE_SIZE 12 |
#define MTL_CMD_0 0 |
#define MTL_EMMISSIVE_RED 1 |
#define MTL_EMMISSIVE_GREEN 2 |
#define MTL_EMMISSIVE_BLUE 3 |
#define MTL_EMMISSIVE_ALPHA 4 |
#define MTL_AMBIENT_RED 5 |
#define MTL_AMBIENT_GREEN 6 |
#define MTL_AMBIENT_BLUE 7 |
#define MTL_AMBIENT_ALPHA 8 |
#define MTL_DIFFUSE_RED 9 |
#define MTL_DIFFUSE_GREEN 10 |
#define MTL_DIFFUSE_BLUE 11 |
#define MTL_DIFFUSE_ALPHA 12 |
#define MTL_SPECULAR_RED 13 |
#define MTL_SPECULAR_GREEN 14 |
#define MTL_SPECULAR_BLUE 15 |
#define MTL_SPECULAR_ALPHA 16 |
#define MTL_SHININESS 17 |
#define MTL_STATE_SIZE 18 |
#define VTX_CMD_0 0 |
#define VTX_SE_COORD_FMT 1 |
#define VTX_STATE_SIZE 2 |
#define MAT_CMD_0 0 |
#define MAT_ELT_0 1 |
#define MAT_STATE_SIZE 17 |
#define GRD_CMD_0 0 |
#define GRD_VERT_GUARD_CLIP_ADJ 1 |
#define GRD_VERT_GUARD_DISCARD_ADJ 2 |
#define GRD_HORZ_GUARD_CLIP_ADJ 3 |
#define GRD_HORZ_GUARD_DISCARD_ADJ 4 |
#define GRD_STATE_SIZE 5 |
/* position changes frequently when lighting in modelpos - separate |
* out to new state item? |
*/ |
#define LIT_CMD_0 0 |
#define LIT_AMBIENT_RED 1 |
#define LIT_AMBIENT_GREEN 2 |
#define LIT_AMBIENT_BLUE 3 |
#define LIT_AMBIENT_ALPHA 4 |
#define LIT_DIFFUSE_RED 5 |
#define LIT_DIFFUSE_GREEN 6 |
#define LIT_DIFFUSE_BLUE 7 |
#define LIT_DIFFUSE_ALPHA 8 |
#define LIT_SPECULAR_RED 9 |
#define LIT_SPECULAR_GREEN 10 |
#define LIT_SPECULAR_BLUE 11 |
#define LIT_SPECULAR_ALPHA 12 |
#define LIT_POSITION_X 13 |
#define LIT_POSITION_Y 14 |
#define LIT_POSITION_Z 15 |
#define LIT_POSITION_W 16 |
#define LIT_DIRECTION_X 17 |
#define LIT_DIRECTION_Y 18 |
#define LIT_DIRECTION_Z 19 |
#define LIT_DIRECTION_W 20 |
#define LIT_ATTEN_QUADRATIC 21 |
#define LIT_ATTEN_LINEAR 22 |
#define LIT_ATTEN_CONST 23 |
#define LIT_ATTEN_XXX 24 |
#define LIT_CMD_1 25 |
#define LIT_SPOT_DCD 26 |
#define LIT_SPOT_EXPONENT 27 |
#define LIT_SPOT_CUTOFF 28 |
#define LIT_SPECULAR_THRESH 29 |
#define LIT_RANGE_CUTOFF 30 /* ? */ |
#define LIT_ATTEN_CONST_INV 31 |
#define LIT_STATE_SIZE 32 |
/* Fog |
*/ |
#define FOG_CMD_0 0 |
#define FOG_R 1 |
#define FOG_C 2 |
#define FOG_D 3 |
#define FOG_PAD 4 |
#define FOG_STATE_SIZE 5 |
/* UCP |
*/ |
#define UCP_CMD_0 0 |
#define UCP_X 1 |
#define UCP_Y 2 |
#define UCP_Z 3 |
#define UCP_W 4 |
#define UCP_STATE_SIZE 5 |
/* GLT - Global ambient |
*/ |
#define GLT_CMD_0 0 |
#define GLT_RED 1 |
#define GLT_GREEN 2 |
#define GLT_BLUE 3 |
#define GLT_ALPHA 4 |
#define GLT_STATE_SIZE 5 |
/* EYE |
*/ |
#define EYE_CMD_0 0 |
#define EYE_X 1 |
#define EYE_Y 2 |
#define EYE_Z 3 |
#define EYE_RESCALE_FACTOR 4 |
#define EYE_STATE_SIZE 5 |
#define SHN_CMD_0 0 |
#define SHN_SHININESS 1 |
#define SHN_STATE_SIZE 2 |
#define R100_QUERYOBJ_CMD_0 0 |
#define R100_QUERYOBJ_DATA_0 1 |
#define R100_QUERYOBJ_CMDSIZE 2 |
#define STP_CMD_0 0 |
#define STP_DATA_0 1 |
#define STP_CMD_1 2 |
#define STP_STATE_SIZE 35 |
struct r100_hw_state { |
/* Hardware state, stored as cmdbuf commands: |
* -- Need to doublebuffer for |
* - eliding noop statechange loops? (except line stipple count) |
*/ |
struct radeon_state_atom ctx; |
struct radeon_state_atom set; |
struct radeon_state_atom lin; |
struct radeon_state_atom msk; |
struct radeon_state_atom vpt; |
struct radeon_state_atom tcl; |
struct radeon_state_atom msc; |
struct radeon_state_atom tex[3]; |
struct radeon_state_atom cube[3]; |
struct radeon_state_atom zbs; |
struct radeon_state_atom mtl; |
struct radeon_state_atom mat[6]; |
struct radeon_state_atom lit[8]; /* includes vec, scl commands */ |
struct radeon_state_atom ucp[6]; |
struct radeon_state_atom eye; /* eye pos */ |
struct radeon_state_atom grd; /* guard band clipping */ |
struct radeon_state_atom fog; |
struct radeon_state_atom glt; |
struct radeon_state_atom txr[3]; /* for NPOT */ |
struct radeon_state_atom stp; |
}; |
struct radeon_stipple_state { |
GLuint mask[32]; |
}; |
struct r100_state { |
struct radeon_stipple_state stipple; |
struct radeon_texture_state texture; |
}; |
#define RADEON_CMD_BUF_SZ (8*1024) |
#define R200_ELT_BUF_SZ (8*1024) |
/* radeon_tcl.c |
*/ |
struct r100_tcl_info { |
GLuint vertex_format; |
GLuint hw_primitive; |
/* Temporary for cases where incoming vertex data is incompatible |
* with maos code. |
*/ |
GLvector4f ObjClean; |
GLuint *Elts; |
int elt_cmd_offset; |
int elt_cmd_start; |
int elt_used; |
}; |
/* radeon_swtcl.c |
*/ |
struct r100_swtcl_info { |
GLuint vertex_format; |
GLubyte *verts; |
/* Fallback rasterization functions |
*/ |
radeon_point_func draw_point; |
radeon_line_func draw_line; |
radeon_tri_func draw_tri; |
/** |
* Offset of the 4UB color data within a hardware (swtcl) vertex. |
*/ |
GLuint coloroffset; |
/** |
* Offset of the 3UB specular color data within a hardware (swtcl) vertex. |
*/ |
GLuint specoffset; |
GLboolean needproj; |
}; |
/* A maximum total of 20 elements per vertex: 3 floats for position, 3 |
* floats for normal, 4 floats for color, 4 bytes for secondary color, |
* 3 floats for each texture unit (9 floats total). |
* |
* The position data is never actually stored here, so 3 elements could be |
* trimmed out of the buffer. This number is only valid for vtxfmt! |
*/ |
#define RADEON_MAX_VERTEX_SIZE 20 |
struct r100_context { |
struct radeon_context radeon; |
/* Driver and hardware state management |
*/ |
struct r100_hw_state hw; |
struct r100_state state; |
/* Vertex buffers |
*/ |
struct radeon_ioctl ioctl; |
struct radeon_store store; |
/* TCL stuff |
*/ |
GLmatrix TexGenMatrix[RADEON_MAX_TEXTURE_UNITS]; |
GLboolean recheck_texgen[RADEON_MAX_TEXTURE_UNITS]; |
GLboolean TexGenNeedNormals[RADEON_MAX_TEXTURE_UNITS]; |
GLuint TexGenEnabled; |
GLuint NeedTexMatrix; |
GLuint TexMatColSwap; |
GLmatrix tmpmat[RADEON_MAX_TEXTURE_UNITS]; |
GLuint last_ReallyEnabled; |
/* radeon_tcl.c |
*/ |
struct r100_tcl_info tcl; |
/* radeon_swtcl.c |
*/ |
struct r100_swtcl_info swtcl; |
GLboolean using_hyperz; |
GLboolean texmicrotile; |
/* Performance counters |
*/ |
GLuint boxes; /* Draw performance boxes */ |
GLuint hardwareWentIdle; |
GLuint c_clears; |
GLuint c_drawWaits; |
GLuint c_textureSwaps; |
GLuint c_textureBytes; |
GLuint c_vertexBuffers; |
}; |
static inline r100ContextPtr |
R100_CONTEXT(struct gl_context *ctx) |
{ |
return (r100ContextPtr) ctx; |
} |
#define RADEON_OLD_PACKETS 1 |
extern GLboolean r100CreateContext( gl_api api, |
const struct gl_config *glVisual, |
__DRIcontext *driContextPriv, |
unsigned major_version, |
unsigned minor_version, |
uint32_t flags, |
unsigned *error, |
void *sharedContextPrivate); |
#endif /* __RADEON_CONTEXT_H__ */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_debug.c |
---|
0,0 → 1,108 |
/* |
* Copyright © 2009 Pauli Nieminen |
* 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. |
*/ |
/* |
* Authors: |
* Pauli Nieminen <suokkos@gmail.com> |
*/ |
#include "utils.h" |
#include "radeon_debug.h" |
#include "radeon_common_context.h" |
#include <stdarg.h> |
#include <stdio.h> |
static const struct dri_debug_control debug_control[] = { |
{"fall", RADEON_FALLBACKS}, |
{"tex", RADEON_TEXTURE}, |
{"ioctl", RADEON_IOCTL}, |
{"verts", RADEON_VERTS}, |
{"render", RADEON_RENDER}, |
{"swrender", RADEON_SWRENDER}, |
{"state", RADEON_STATE}, |
{"shader", RADEON_SHADER}, |
{"vfmt", RADEON_VFMT}, |
{"vtxf", RADEON_VFMT}, |
{"dri", RADEON_DRI}, |
{"dma", RADEON_DMA}, |
{"sanity", RADEON_SANITY}, |
{"sync", RADEON_SYNC}, |
{"pixel", RADEON_PIXEL}, |
{"mem", RADEON_MEMORY}, |
{"cs", RADEON_CS}, |
{"allmsg", ~RADEON_SYNC}, /* avoid the term "sync" because the parser uses strstr */ |
{NULL, 0} |
}; |
radeon_debug_type_t radeon_enabled_debug_types; |
void radeon_init_debug(void) |
{ |
radeon_enabled_debug_types = driParseDebugString(getenv("RADEON_DEBUG"), debug_control); |
radeon_enabled_debug_types |= RADEON_GENERAL; |
} |
void _radeon_debug_add_indent(void) |
{ |
GET_CURRENT_CONTEXT(ctx); |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
const size_t length = sizeof(radeon->debug.indent) |
/ sizeof(radeon->debug.indent[0]); |
if (radeon->debug.indent_depth < length - 1) { |
radeon->debug.indent[radeon->debug.indent_depth] = '\t'; |
++radeon->debug.indent_depth; |
}; |
} |
void _radeon_debug_remove_indent(void) |
{ |
GET_CURRENT_CONTEXT(ctx); |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
if (radeon->debug.indent_depth > 0) { |
radeon->debug.indent[radeon->debug.indent_depth] = '\0'; |
--radeon->debug.indent_depth; |
} |
} |
void _radeon_print(const radeon_debug_type_t type, |
const radeon_debug_level_t level, |
const char* message, |
...) |
{ |
va_list values; |
GET_CURRENT_CONTEXT(ctx); |
if (ctx) { |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
// FIXME: Make this multi thread safe |
if (radeon->debug.indent_depth) |
fprintf(stderr, "%s", radeon->debug.indent); |
} |
va_start( values, message ); |
vfprintf(stderr, message, values); |
va_end( values ); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_debug.h |
---|
0,0 → 1,174 |
/* |
* Copyright © 2009 Pauli Nieminen |
* 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. |
*/ |
/* |
* Authors: |
* Pauli Nieminen <suokkos@gmail.com> |
*/ |
#ifndef RADEON_DEBUG_H_INCLUDED |
#define RADEON_DEBUG_H_INCLUDED |
#include <stdlib.h> |
typedef enum radeon_debug_levels { |
RADEON_CRITICAL = 0, /* Only errors */ |
RADEON_IMPORTANT = 1, /* Important warnings and messages */ |
RADEON_NORMAL = 2, /* Normal log messages usefull for debugging */ |
RADEON_VERBOSE = 3, /* Extra details to debugging */ |
RADEON_TRACE = 4 /* Log about everything that happens */ |
} radeon_debug_level_t; |
/** |
* Compile time option to change level of debugging compiled to dri driver. |
* Selecting critical level is not recommended because perfromance gains are |
* going to minimal but you will lose a lot of important warnings in case of |
* errors. |
*/ |
#ifndef RADEON_DEBUG_LEVEL |
# ifdef DEBUG |
# define RADEON_DEBUG_LEVEL RADEON_TRACE |
# else |
# define RADEON_DEBUG_LEVEL RADEON_VERBOSE |
# endif |
#endif |
typedef enum radeon_debug_types { |
RADEON_TEXTURE = 0x00001, |
RADEON_STATE = 0x00002, |
RADEON_IOCTL = 0x00004, |
RADEON_RENDER = 0x00008, |
RADEON_SWRENDER = 0x00010, |
RADEON_FALLBACKS = 0x00020, |
RADEON_VFMT = 0x00040, |
RADEON_SHADER = 0x00080, |
RADEON_CS = 0x00100, |
RADEON_DRI = 0x00200, |
RADEON_DMA = 0x00400, |
RADEON_SANITY = 0x00800, |
RADEON_SYNC = 0x01000, |
RADEON_PIXEL = 0x02000, |
RADEON_MEMORY = 0x04000, |
RADEON_VERTS = 0x08000, |
RADEON_GENERAL = 0x10000 /* Used for errors and warnings */ |
} radeon_debug_type_t; |
#define RADEON_MAX_INDENT 5 |
struct radeon_debug { |
size_t indent_depth; |
char indent[RADEON_MAX_INDENT]; |
}; |
extern radeon_debug_type_t radeon_enabled_debug_types; |
/** |
* Compabibility layer for old debug code |
**/ |
#define RADEON_DEBUG radeon_enabled_debug_types |
static inline int radeon_is_debug_enabled(const radeon_debug_type_t type, |
const radeon_debug_level_t level) |
{ |
return RADEON_DEBUG_LEVEL >= level |
&& (type & radeon_enabled_debug_types); |
} |
/* |
* define macro for gcc specific __attribute__ if using alternative compiler |
*/ |
#ifndef __GNUC__ |
#define __attribute__(x) /*empty*/ |
#endif |
extern void _radeon_print(const radeon_debug_type_t type, |
const radeon_debug_level_t level, |
const char* message, |
...) __attribute__((format(printf,3,4))); |
/** |
* Print out debug message if channel specified by type is enabled |
* and compile time debugging level is at least as high as level parameter |
*/ |
#define radeon_print(type, level, ...) do { \ |
const radeon_debug_level_t _debug_level = (level); \ |
const radeon_debug_type_t _debug_type = (type); \ |
/* Compile out if level of message is too high */ \ |
if (radeon_is_debug_enabled(type, level)) { \ |
_radeon_print(_debug_type, _debug_level, \ |
__VA_ARGS__); \ |
} \ |
} while(0) |
/** |
* printf style function for writing error messages. |
*/ |
#define radeon_error(...) do { \ |
radeon_print(RADEON_GENERAL, RADEON_CRITICAL, \ |
__VA_ARGS__); \ |
} while(0) |
/** |
* printf style function for writing warnings. |
*/ |
#define radeon_warning(...) do { \ |
radeon_print(RADEON_GENERAL, RADEON_IMPORTANT, \ |
__VA_ARGS__); \ |
} while(0) |
extern void radeon_init_debug(void); |
extern void _radeon_debug_add_indent(void); |
extern void _radeon_debug_remove_indent(void); |
static inline void radeon_debug_add_indent(void) |
{ |
if (RADEON_DEBUG_LEVEL >= RADEON_VERBOSE) { |
_radeon_debug_add_indent(); |
} |
} |
static inline void radeon_debug_remove_indent(void) |
{ |
if (RADEON_DEBUG_LEVEL >= RADEON_VERBOSE) { |
_radeon_debug_remove_indent(); |
} |
} |
/* From http://gcc. gnu.org/onlinedocs/gcc-3.2.3/gcc/Variadic-Macros.html . |
I suppose we could inline this and use macro to fetch out __LINE__ and stuff in case we run into trouble |
with other compilers ... GLUE! |
*/ |
#define WARN_ONCE(...) do { \ |
static int __warn_once=1; \ |
if(__warn_once){ \ |
radeon_warning("*********************************WARN_ONCE*********************************\n"); \ |
radeon_warning("File %s function %s line %d\n", \ |
__FILE__, __FUNCTION__, __LINE__); \ |
radeon_warning(__VA_ARGS__);\ |
radeon_warning("***************************************************************************\n"); \ |
__warn_once=0;\ |
} \ |
} while(0) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_dma.c |
---|
0,0 → 1,511 |
/************************************************************************** |
Copyright (C) 2004 Nicolai Haehnle. |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 |
on 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 |
ATI, VA LINUX SYSTEMS AND/OR THEIR 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 <errno.h> |
#include "radeon_common.h" |
#include "radeon_fog.h" |
#include "main/simple_list.h" |
#if defined(USE_X86_ASM) |
#define COPY_DWORDS( dst, src, nr ) \ |
do { \ |
int __tmp; \ |
__asm__ __volatile__( "rep ; movsl" \ |
: "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \ |
: "0" (nr), \ |
"D" ((long)dst), \ |
"S" ((long)src) ); \ |
} while (0) |
#else |
#define COPY_DWORDS( dst, src, nr ) \ |
do { \ |
int j; \ |
for ( j = 0 ; j < nr ; j++ ) \ |
dst[j] = ((int *)src)[j]; \ |
dst += nr; \ |
} while (0) |
#endif |
void radeonEmitVec4(uint32_t *out, const GLvoid * data, int stride, int count) |
{ |
int i; |
if (RADEON_DEBUG & RADEON_VERTS) |
fprintf(stderr, "%s count %d stride %d out %p data %p\n", |
__FUNCTION__, count, stride, (void *)out, (void *)data); |
if (stride == 4) |
COPY_DWORDS(out, data, count); |
else |
for (i = 0; i < count; i++) { |
out[0] = *(int *)data; |
out++; |
data += stride; |
} |
} |
void radeonEmitVec8(uint32_t *out, const GLvoid * data, int stride, int count) |
{ |
int i; |
if (RADEON_DEBUG & RADEON_VERTS) |
fprintf(stderr, "%s count %d stride %d out %p data %p\n", |
__FUNCTION__, count, stride, (void *)out, (void *)data); |
if (stride == 8) |
COPY_DWORDS(out, data, count * 2); |
else |
for (i = 0; i < count; i++) { |
out[0] = *(int *)data; |
out[1] = *(int *)(data + 4); |
out += 2; |
data += stride; |
} |
} |
void radeonEmitVec12(uint32_t *out, const GLvoid * data, int stride, int count) |
{ |
int i; |
if (RADEON_DEBUG & RADEON_VERTS) |
fprintf(stderr, "%s count %d stride %d out %p data %p\n", |
__FUNCTION__, count, stride, (void *)out, (void *)data); |
if (stride == 12) { |
COPY_DWORDS(out, data, count * 3); |
} |
else |
for (i = 0; i < count; i++) { |
out[0] = *(int *)data; |
out[1] = *(int *)(data + 4); |
out[2] = *(int *)(data + 8); |
out += 3; |
data += stride; |
} |
} |
void radeonEmitVec16(uint32_t *out, const GLvoid * data, int stride, int count) |
{ |
int i; |
if (RADEON_DEBUG & RADEON_VERTS) |
fprintf(stderr, "%s count %d stride %d out %p data %p\n", |
__FUNCTION__, count, stride, (void *)out, (void *)data); |
if (stride == 16) |
COPY_DWORDS(out, data, count * 4); |
else |
for (i = 0; i < count; i++) { |
out[0] = *(int *)data; |
out[1] = *(int *)(data + 4); |
out[2] = *(int *)(data + 8); |
out[3] = *(int *)(data + 12); |
out += 4; |
data += stride; |
} |
} |
void rcommon_emit_vector(struct gl_context * ctx, struct radeon_aos *aos, |
const GLvoid * data, int size, int stride, int count) |
{ |
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
uint32_t *out; |
if (stride == 0) { |
radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * 4, 32); |
count = 1; |
aos->stride = 0; |
} else { |
radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * count * 4, 32); |
aos->stride = size; |
} |
aos->components = size; |
aos->count = count; |
radeon_bo_map(aos->bo, 1); |
out = (uint32_t*)((char*)aos->bo->ptr + aos->offset); |
switch (size) { |
case 1: radeonEmitVec4(out, data, stride, count); break; |
case 2: radeonEmitVec8(out, data, stride, count); break; |
case 3: radeonEmitVec12(out, data, stride, count); break; |
case 4: radeonEmitVec16(out, data, stride, count); break; |
default: |
assert(0); |
break; |
} |
radeon_bo_unmap(aos->bo); |
} |
void rcommon_emit_vecfog(struct gl_context *ctx, struct radeon_aos *aos, |
GLvoid *data, int stride, int count) |
{ |
int i; |
float *out; |
int size = 1; |
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
if (RADEON_DEBUG & RADEON_VERTS) |
fprintf(stderr, "%s count %d stride %d\n", |
__FUNCTION__, count, stride); |
if (stride == 0) { |
radeonAllocDmaRegion( rmesa, &aos->bo, &aos->offset, size * 4, 32 ); |
count = 1; |
aos->stride = 0; |
} else { |
radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, size * count * 4, 32); |
aos->stride = size; |
} |
aos->components = size; |
aos->count = count; |
/* Emit the data */ |
radeon_bo_map(aos->bo, 1); |
out = (float*)((char*)aos->bo->ptr + aos->offset); |
for (i = 0; i < count; i++) { |
out[0] = radeonComputeFogBlendFactor( ctx, *(GLfloat *)data ); |
out++; |
data += stride; |
} |
radeon_bo_unmap(aos->bo); |
} |
void radeon_init_dma(radeonContextPtr rmesa) |
{ |
make_empty_list(&rmesa->dma.free); |
make_empty_list(&rmesa->dma.wait); |
make_empty_list(&rmesa->dma.reserved); |
rmesa->dma.minimum_size = MAX_DMA_BUF_SZ; |
} |
void radeonRefillCurrentDmaRegion(radeonContextPtr rmesa, int size) |
{ |
struct radeon_dma_bo *dma_bo = NULL; |
/* we set minimum sizes to at least requested size |
aligned to next 16 bytes. */ |
if (size > rmesa->dma.minimum_size) |
rmesa->dma.minimum_size = (size + 15) & (~15); |
radeon_print(RADEON_DMA, RADEON_NORMAL, "%s size %d minimum_size %Zi\n", |
__FUNCTION__, size, rmesa->dma.minimum_size); |
if (is_empty_list(&rmesa->dma.free) |
|| last_elem(&rmesa->dma.free)->bo->size < size) { |
dma_bo = CALLOC_STRUCT(radeon_dma_bo); |
assert(dma_bo); |
again_alloc: |
dma_bo->bo = radeon_bo_open(rmesa->radeonScreen->bom, |
0, rmesa->dma.minimum_size, 4, |
RADEON_GEM_DOMAIN_GTT, 0); |
if (!dma_bo->bo) { |
rcommonFlushCmdBuf(rmesa, __FUNCTION__); |
goto again_alloc; |
} |
insert_at_head(&rmesa->dma.reserved, dma_bo); |
} else { |
/* We push and pop buffers from end of list so we can keep |
counter on unused buffers for later freeing them from |
begin of list */ |
dma_bo = last_elem(&rmesa->dma.free); |
remove_from_list(dma_bo); |
insert_at_head(&rmesa->dma.reserved, dma_bo); |
} |
rmesa->dma.current_used = 0; |
rmesa->dma.current_vertexptr = 0; |
if (radeon_cs_space_check_with_bo(rmesa->cmdbuf.cs, |
first_elem(&rmesa->dma.reserved)->bo, |
RADEON_GEM_DOMAIN_GTT, 0)) |
fprintf(stderr,"failure to revalidate BOs - badness\n"); |
if (is_empty_list(&rmesa->dma.reserved)) { |
/* Cmd buff have been flushed in radeon_revalidate_bos */ |
goto again_alloc; |
} |
radeon_bo_map(first_elem(&rmesa->dma.reserved)->bo, 1); |
} |
/* Allocates a region from rmesa->dma.current. If there isn't enough |
* space in current, grab a new buffer (and discard what was left of current) |
*/ |
void radeonAllocDmaRegion(radeonContextPtr rmesa, |
struct radeon_bo **pbo, int *poffset, |
int bytes, int alignment) |
{ |
if (RADEON_DEBUG & RADEON_IOCTL) |
fprintf(stderr, "%s %d\n", __FUNCTION__, bytes); |
if (rmesa->dma.flush) |
rmesa->dma.flush(&rmesa->glCtx); |
assert(rmesa->dma.current_used == rmesa->dma.current_vertexptr); |
alignment--; |
rmesa->dma.current_used = (rmesa->dma.current_used + alignment) & ~alignment; |
if (is_empty_list(&rmesa->dma.reserved) |
|| rmesa->dma.current_used + bytes > first_elem(&rmesa->dma.reserved)->bo->size) |
radeonRefillCurrentDmaRegion(rmesa, bytes); |
*poffset = rmesa->dma.current_used; |
*pbo = first_elem(&rmesa->dma.reserved)->bo; |
radeon_bo_ref(*pbo); |
/* Always align to at least 16 bytes */ |
rmesa->dma.current_used = (rmesa->dma.current_used + bytes + 15) & ~15; |
rmesa->dma.current_vertexptr = rmesa->dma.current_used; |
assert(rmesa->dma.current_used <= first_elem(&rmesa->dma.reserved)->bo->size); |
} |
void radeonFreeDmaRegions(radeonContextPtr rmesa) |
{ |
struct radeon_dma_bo *dma_bo; |
struct radeon_dma_bo *temp; |
if (RADEON_DEBUG & RADEON_DMA) |
fprintf(stderr, "%s\n", __FUNCTION__); |
foreach_s(dma_bo, temp, &rmesa->dma.free) { |
remove_from_list(dma_bo); |
radeon_bo_unref(dma_bo->bo); |
free(dma_bo); |
} |
foreach_s(dma_bo, temp, &rmesa->dma.wait) { |
remove_from_list(dma_bo); |
radeon_bo_unref(dma_bo->bo); |
free(dma_bo); |
} |
foreach_s(dma_bo, temp, &rmesa->dma.reserved) { |
remove_from_list(dma_bo); |
radeon_bo_unref(dma_bo->bo); |
free(dma_bo); |
} |
} |
void radeonReturnDmaRegion(radeonContextPtr rmesa, int return_bytes) |
{ |
if (is_empty_list(&rmesa->dma.reserved)) |
return; |
if (RADEON_DEBUG & RADEON_IOCTL) |
fprintf(stderr, "%s %d\n", __FUNCTION__, return_bytes); |
rmesa->dma.current_used -= return_bytes; |
rmesa->dma.current_vertexptr = rmesa->dma.current_used; |
} |
static int radeon_bo_is_idle(struct radeon_bo* bo) |
{ |
uint32_t domain; |
int ret = radeon_bo_is_busy(bo, &domain); |
if (ret == -EINVAL) { |
WARN_ONCE("Your libdrm or kernel doesn't have support for busy query.\n" |
"This may cause small performance drop for you.\n"); |
} |
return ret != -EBUSY; |
} |
void radeonReleaseDmaRegions(radeonContextPtr rmesa) |
{ |
struct radeon_dma_bo *dma_bo; |
struct radeon_dma_bo *temp; |
const int expire_at = ++rmesa->dma.free.expire_counter + DMA_BO_FREE_TIME; |
const int time = rmesa->dma.free.expire_counter; |
if (RADEON_DEBUG & RADEON_DMA) { |
size_t free = 0, |
wait = 0, |
reserved = 0; |
foreach(dma_bo, &rmesa->dma.free) |
++free; |
foreach(dma_bo, &rmesa->dma.wait) |
++wait; |
foreach(dma_bo, &rmesa->dma.reserved) |
++reserved; |
fprintf(stderr, "%s: free %zu, wait %zu, reserved %zu, minimum_size: %zu\n", |
__FUNCTION__, free, wait, reserved, rmesa->dma.minimum_size); |
} |
/* move waiting bos to free list. |
wait list provides gpu time to handle data before reuse */ |
foreach_s(dma_bo, temp, &rmesa->dma.wait) { |
if (dma_bo->expire_counter == time) { |
WARN_ONCE("Leaking dma buffer object!\n"); |
radeon_bo_unref(dma_bo->bo); |
remove_from_list(dma_bo); |
free(dma_bo); |
continue; |
} |
/* free objects that are too small to be used because of large request */ |
if (dma_bo->bo->size < rmesa->dma.minimum_size) { |
radeon_bo_unref(dma_bo->bo); |
remove_from_list(dma_bo); |
free(dma_bo); |
continue; |
} |
if (!radeon_bo_is_idle(dma_bo->bo)) { |
break; |
} |
remove_from_list(dma_bo); |
dma_bo->expire_counter = expire_at; |
insert_at_tail(&rmesa->dma.free, dma_bo); |
} |
/* move reserved to wait list */ |
foreach_s(dma_bo, temp, &rmesa->dma.reserved) { |
radeon_bo_unmap(dma_bo->bo); |
/* free objects that are too small to be used because of large request */ |
if (dma_bo->bo->size < rmesa->dma.minimum_size) { |
radeon_bo_unref(dma_bo->bo); |
remove_from_list(dma_bo); |
free(dma_bo); |
continue; |
} |
remove_from_list(dma_bo); |
dma_bo->expire_counter = expire_at; |
insert_at_tail(&rmesa->dma.wait, dma_bo); |
} |
/* free bos that have been unused for some time */ |
foreach_s(dma_bo, temp, &rmesa->dma.free) { |
if (dma_bo->expire_counter != time) |
break; |
remove_from_list(dma_bo); |
radeon_bo_unref(dma_bo->bo); |
free(dma_bo); |
} |
} |
/* Flush vertices in the current dma region. |
*/ |
void rcommon_flush_last_swtcl_prim( struct gl_context *ctx ) |
{ |
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
struct radeon_dma *dma = &rmesa->dma; |
if (RADEON_DEBUG & RADEON_IOCTL) |
fprintf(stderr, "%s\n", __FUNCTION__); |
dma->flush = NULL; |
radeon_bo_unmap(rmesa->swtcl.bo); |
if (!is_empty_list(&dma->reserved)) { |
GLuint current_offset = dma->current_used; |
assert (dma->current_used + |
rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 == |
dma->current_vertexptr); |
if (dma->current_used != dma->current_vertexptr) { |
dma->current_used = dma->current_vertexptr; |
rmesa->vtbl.swtcl_flush(ctx, current_offset); |
} |
rmesa->swtcl.numverts = 0; |
} |
radeon_bo_unref(rmesa->swtcl.bo); |
rmesa->swtcl.bo = NULL; |
} |
/* Alloc space in the current dma region. |
*/ |
void * |
rcommonAllocDmaLowVerts( radeonContextPtr rmesa, int nverts, int vsize ) |
{ |
GLuint bytes = vsize * nverts; |
void *head; |
if (RADEON_DEBUG & RADEON_IOCTL) |
fprintf(stderr, "%s\n", __FUNCTION__); |
if(is_empty_list(&rmesa->dma.reserved) |
||rmesa->dma.current_vertexptr + bytes > first_elem(&rmesa->dma.reserved)->bo->size) { |
if (rmesa->dma.flush) { |
rmesa->dma.flush(&rmesa->glCtx); |
} |
radeonRefillCurrentDmaRegion(rmesa, bytes); |
return NULL; |
} |
if (!rmesa->dma.flush) { |
/* if cmdbuf flushed DMA restart */ |
rmesa->glCtx.Driver.NeedFlush |= FLUSH_STORED_VERTICES; |
rmesa->dma.flush = rcommon_flush_last_swtcl_prim; |
} |
ASSERT( vsize == rmesa->swtcl.vertex_size * 4 ); |
ASSERT( rmesa->dma.flush == rcommon_flush_last_swtcl_prim ); |
ASSERT( rmesa->dma.current_used + |
rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 == |
rmesa->dma.current_vertexptr ); |
if (!rmesa->swtcl.bo) { |
rmesa->swtcl.bo = first_elem(&rmesa->dma.reserved)->bo; |
radeon_bo_ref(rmesa->swtcl.bo); |
radeon_bo_map(rmesa->swtcl.bo, 1); |
} |
head = (rmesa->swtcl.bo->ptr + rmesa->dma.current_vertexptr); |
rmesa->dma.current_vertexptr += bytes; |
rmesa->swtcl.numverts += nverts; |
return head; |
} |
void radeonReleaseArrays( struct gl_context *ctx, GLuint newinputs ) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT( ctx ); |
int i; |
if (RADEON_DEBUG & RADEON_IOCTL) |
fprintf(stderr, "%s\n", __FUNCTION__); |
if (radeon->dma.flush) { |
radeon->dma.flush(&radeon->glCtx); |
} |
for (i = 0; i < radeon->tcl.aos_count; i++) { |
if (radeon->tcl.aos[i].bo) { |
radeon_bo_unref(radeon->tcl.aos[i].bo); |
radeon->tcl.aos[i].bo = NULL; |
} |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_dma.h |
---|
0,0 → 1,60 |
/************************************************************************** |
Copyright (C) 2004 Nicolai Haehnle. |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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 |
on 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 |
ATI, VA LINUX SYSTEMS AND/OR THEIR 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 RADEON_DMA_H |
#define RADEON_DMA_H |
void radeonEmitVec4(uint32_t *out, const GLvoid * data, int stride, int count); |
void radeonEmitVec8(uint32_t *out, const GLvoid * data, int stride, int count); |
void radeonEmitVec12(uint32_t *out, const GLvoid * data, int stride, int count); |
void radeonEmitVec16(uint32_t *out, const GLvoid * data, int stride, int count); |
void rcommon_emit_vector(struct gl_context * ctx, struct radeon_aos *aos, |
const GLvoid * data, int size, int stride, int count); |
void rcommon_emit_vecfog(struct gl_context *ctx, struct radeon_aos *aos, |
GLvoid *data, int stride, int count); |
void radeonReturnDmaRegion(radeonContextPtr rmesa, int return_bytes); |
void radeonRefillCurrentDmaRegion(radeonContextPtr rmesa, int size); |
void radeon_init_dma(radeonContextPtr rmesa); |
void radeonReturnDmaRegion(radeonContextPtr rmesa, int return_bytes); |
void radeonAllocDmaRegion(radeonContextPtr rmesa, |
struct radeon_bo **pbo, int *poffset, |
int bytes, int alignment); |
void radeonReleaseDmaRegions(radeonContextPtr rmesa); |
void rcommon_flush_last_swtcl_prim(struct gl_context *ctx); |
void *rcommonAllocDmaLowVerts(radeonContextPtr rmesa, int nverts, int vsize); |
void radeonFreeDmaRegions(radeonContextPtr rmesa); |
void radeonReleaseArrays( struct gl_context *ctx, GLuint newinputs ); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_fbo.c |
---|
0,0 → 1,892 |
/************************************************************************** |
* |
* Copyright 2008 Red Hat 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 "main/imports.h" |
#include "main/macros.h" |
#include "main/mtypes.h" |
#include "main/enums.h" |
#include "main/fbobject.h" |
#include "main/framebuffer.h" |
#include "main/renderbuffer.h" |
#include "main/context.h" |
#include "swrast/swrast.h" |
#include "drivers/common/meta.h" |
#include "radeon_common.h" |
#include "radeon_mipmap_tree.h" |
#define FILE_DEBUG_FLAG RADEON_TEXTURE |
#define DBG(...) do { \ |
if (RADEON_DEBUG & FILE_DEBUG_FLAG) \ |
printf(__VA_ARGS__); \ |
} while(0) |
static struct gl_framebuffer * |
radeon_new_framebuffer(struct gl_context *ctx, GLuint name) |
{ |
return _mesa_new_framebuffer(ctx, name); |
} |
static void |
radeon_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) |
{ |
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(rb %p, rrb %p) \n", |
__func__, rb, rrb); |
ASSERT(rrb); |
if (rrb && rrb->bo) { |
radeon_bo_unref(rrb->bo); |
} |
_mesa_delete_renderbuffer(ctx, rb); |
} |
#if defined(RADEON_R100) |
static GLuint get_depth_z32(const struct radeon_renderbuffer * rrb, |
GLint x, GLint y) |
{ |
GLuint ba, address = 0; |
ba = (y >> 4) * (rrb->pitch >> 6) + (x >> 4); |
address |= (x & 0x7) << 2; |
address |= (y & 0x3) << 5; |
address |= (((x & 0x10) >> 2) ^ (y & 0x4)) << 5; |
address |= (ba & 3) << 8; |
address |= (y & 0x8) << 7; |
address |= (((x & 0x8) << 1) ^ (y & 0x10)) << 7; |
address |= (ba & ~0x3) << 10; |
return address; |
} |
static GLuint get_depth_z16(const struct radeon_renderbuffer * rrb, |
GLint x, GLint y) |
{ |
GLuint ba, address = 0; /* a[0] = 0 */ |
ba = (y / 16) * (rrb->pitch >> 6) + (x / 32); |
address |= (x & 0x7) << 1; /* a[1..3] = x[0..2] */ |
address |= (y & 0x7) << 4; /* a[4..6] = y[0..2] */ |
address |= (x & 0x8) << 4; /* a[7] = x[3] */ |
address |= (ba & 0x3) << 8; /* a[8..9] = ba[0..1] */ |
address |= (y & 0x8) << 7; /* a[10] = y[3] */ |
address |= ((x & 0x10) ^ (y & 0x10)) << 7;/* a[11] = x[4] ^ y[4] */ |
address |= (ba & ~0x3) << 10; /* a[12..] = ba[2..] */ |
return address; |
} |
#endif |
#if defined(RADEON_R200) |
static GLuint get_depth_z32(const struct radeon_renderbuffer * rrb, |
GLint x, GLint y) |
{ |
GLuint offset; |
GLuint b; |
offset = 0; |
b = (((y & 0x7ff) >> 4) * (rrb->pitch >> 7) + (x >> 5)); |
offset += (b >> 1) << 12; |
offset += (((rrb->pitch >> 7) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11; |
offset += ((y >> 2) & 0x3) << 9; |
offset += ((x >> 2) & 0x1) << 8; |
offset += ((x >> 3) & 0x3) << 6; |
offset += ((y >> 1) & 0x1) << 5; |
offset += ((x >> 1) & 0x1) << 4; |
offset += (y & 0x1) << 3; |
offset += (x & 0x1) << 2; |
return offset; |
} |
static GLuint get_depth_z16(const struct radeon_renderbuffer *rrb, |
GLint x, GLint y) |
{ |
GLuint offset; |
GLuint b; |
offset = 0; |
b = (((y >> 4) * (rrb->pitch >> 7) + (x >> 6))); |
offset += (b >> 1) << 12; |
offset += (((rrb->pitch >> 7) & 0x1) ? (b & 0x1) : ((b & 0x1) ^ ((y >> 4) & 0x1))) << 11; |
offset += ((y >> 2) & 0x3) << 9; |
offset += ((x >> 3) & 0x1) << 8; |
offset += ((x >> 4) & 0x3) << 6; |
offset += ((x >> 2) & 0x1) << 5; |
offset += ((y >> 1) & 0x1) << 4; |
offset += ((x >> 1) & 0x1) << 3; |
offset += (y & 0x1) << 2; |
offset += (x & 0x1) << 1; |
return offset; |
} |
#endif |
static void |
radeon_map_renderbuffer_s8z24(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **out_map, |
GLint *out_stride) |
{ |
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); |
uint32_t *untiled_s8z24_map, *tiled_s8z24_map; |
int ret; |
int y_flip = (rb->Name == 0) ? -1 : 1; |
int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0; |
uint32_t pitch = w * rrb->cpp; |
rrb->map_pitch = pitch; |
rrb->map_buffer = malloc(w * h * 4); |
ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT)); |
assert(!ret); |
untiled_s8z24_map = rrb->map_buffer; |
tiled_s8z24_map = rrb->bo->ptr; |
for (uint32_t pix_y = 0; pix_y < h; ++ pix_y) { |
for (uint32_t pix_x = 0; pix_x < w; ++pix_x) { |
uint32_t flipped_y = y_flip * (int32_t)(y + pix_y) + y_bias; |
uint32_t src_offset = get_depth_z32(rrb, x + pix_x, flipped_y); |
uint32_t dst_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp; |
untiled_s8z24_map[dst_offset/4] = tiled_s8z24_map[src_offset/4]; |
} |
} |
radeon_bo_unmap(rrb->bo); |
*out_map = rrb->map_buffer; |
*out_stride = rrb->map_pitch; |
} |
static void |
radeon_map_renderbuffer_z16(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **out_map, |
GLint *out_stride) |
{ |
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); |
uint16_t *untiled_z16_map, *tiled_z16_map; |
int ret; |
int y_flip = (rb->Name == 0) ? -1 : 1; |
int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0; |
uint32_t pitch = w * rrb->cpp; |
rrb->map_pitch = pitch; |
rrb->map_buffer = malloc(w * h * 2); |
ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT)); |
assert(!ret); |
untiled_z16_map = rrb->map_buffer; |
tiled_z16_map = rrb->bo->ptr; |
for (uint32_t pix_y = 0; pix_y < h; ++ pix_y) { |
for (uint32_t pix_x = 0; pix_x < w; ++pix_x) { |
uint32_t flipped_y = y_flip * (int32_t)(y + pix_y) + y_bias; |
uint32_t src_offset = get_depth_z16(rrb, x + pix_x, flipped_y); |
uint32_t dst_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp; |
untiled_z16_map[dst_offset/2] = tiled_z16_map[src_offset/2]; |
} |
} |
radeon_bo_unmap(rrb->bo); |
*out_map = rrb->map_buffer; |
*out_stride = rrb->map_pitch; |
} |
static void |
radeon_map_renderbuffer(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **out_map, |
GLint *out_stride) |
{ |
struct radeon_context *const rmesa = RADEON_CONTEXT(ctx); |
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); |
GLubyte *map; |
GLboolean ok; |
int stride, flip_stride; |
int ret; |
int src_x, src_y; |
if (!rrb || !rrb->bo) { |
*out_map = NULL; |
*out_stride = 0; |
return; |
} |
rrb->map_mode = mode; |
rrb->map_x = x; |
rrb->map_y = y; |
rrb->map_w = w; |
rrb->map_h = h; |
rrb->map_pitch = rrb->pitch; |
ok = rmesa->vtbl.check_blit(rb->Format, rrb->pitch / rrb->cpp); |
if (ok) { |
if (rb->Name) { |
src_x = x; |
src_y = y; |
} else { |
src_x = x; |
src_y = rrb->base.Base.Height - y - h; |
} |
/* Make a temporary buffer and blit the current contents of the renderbuffer |
* out to it. This gives us linear access to the buffer, instead of having |
* to do detiling in software. |
*/ |
rrb->map_pitch = rrb->pitch; |
assert(!rrb->map_bo); |
rrb->map_bo = radeon_bo_open(rmesa->radeonScreen->bom, 0, |
rrb->map_pitch * h, 4, |
RADEON_GEM_DOMAIN_GTT, 0); |
ok = rmesa->vtbl.blit(ctx, rrb->bo, rrb->draw_offset, |
rb->Format, rrb->pitch / rrb->cpp, |
rb->Width, rb->Height, |
src_x, src_y, |
rrb->map_bo, 0, |
rb->Format, rrb->map_pitch / rrb->cpp, |
w, h, |
0, 0, |
w, h, |
GL_FALSE); |
assert(ok); |
ret = radeon_bo_map(rrb->map_bo, !!(mode & GL_MAP_WRITE_BIT)); |
assert(!ret); |
map = rrb->map_bo->ptr; |
if (rb->Name) { |
*out_map = map; |
*out_stride = rrb->map_pitch; |
} else { |
*out_map = map + (h - 1) * rrb->map_pitch; |
*out_stride = -rrb->map_pitch; |
} |
return; |
} |
/* sw fallback flush stuff */ |
if (radeon_bo_is_referenced_by_cs(rrb->bo, rmesa->cmdbuf.cs)) { |
radeon_firevertices(rmesa); |
} |
if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) { |
if (rb->Format == MESA_FORMAT_S8_Z24 || rb->Format == MESA_FORMAT_X8_Z24) { |
radeon_map_renderbuffer_s8z24(ctx, rb, x, y, w, h, |
mode, out_map, out_stride); |
return; |
} |
if (rb->Format == MESA_FORMAT_Z16) { |
radeon_map_renderbuffer_z16(ctx, rb, x, y, w, h, |
mode, out_map, out_stride); |
return; |
} |
} |
ret = radeon_bo_map(rrb->bo, !!(mode & GL_MAP_WRITE_BIT)); |
assert(!ret); |
map = rrb->bo->ptr; |
stride = rrb->map_pitch; |
if (rb->Name == 0) { |
y = rb->Height - 1 - y; |
flip_stride = -stride; |
} else { |
flip_stride = stride; |
map += rrb->draw_offset; |
} |
map += x * rrb->cpp; |
map += (int)y * stride; |
*out_map = map; |
*out_stride = flip_stride; |
} |
static void |
radeon_unmap_renderbuffer_s8z24(struct gl_context *ctx, |
struct gl_renderbuffer *rb) |
{ |
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); |
if (!rrb->map_buffer) |
return; |
if (rrb->map_mode & GL_MAP_WRITE_BIT) { |
uint32_t *untiled_s8z24_map = rrb->map_buffer; |
uint32_t *tiled_s8z24_map; |
int y_flip = (rb->Name == 0) ? -1 : 1; |
int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0; |
radeon_bo_map(rrb->bo, 1); |
tiled_s8z24_map = rrb->bo->ptr; |
for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) { |
for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) { |
uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias; |
uint32_t dst_offset = get_depth_z32(rrb, rrb->map_x + pix_x, flipped_y); |
uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp; |
tiled_s8z24_map[dst_offset/4] = untiled_s8z24_map[src_offset/4]; |
} |
} |
radeon_bo_unmap(rrb->bo); |
} |
free(rrb->map_buffer); |
rrb->map_buffer = NULL; |
} |
static void |
radeon_unmap_renderbuffer_z16(struct gl_context *ctx, |
struct gl_renderbuffer *rb) |
{ |
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); |
if (!rrb->map_buffer) |
return; |
if (rrb->map_mode & GL_MAP_WRITE_BIT) { |
uint16_t *untiled_z16_map = rrb->map_buffer; |
uint16_t *tiled_z16_map; |
int y_flip = (rb->Name == 0) ? -1 : 1; |
int y_bias = (rb->Name == 0) ? (rb->Height - 1) : 0; |
radeon_bo_map(rrb->bo, 1); |
tiled_z16_map = rrb->bo->ptr; |
for (uint32_t pix_y = 0; pix_y < rrb->map_h; pix_y++) { |
for (uint32_t pix_x = 0; pix_x < rrb->map_w; pix_x++) { |
uint32_t flipped_y = y_flip * (int32_t)(pix_y + rrb->map_y) + y_bias; |
uint32_t dst_offset = get_depth_z16(rrb, rrb->map_x + pix_x, flipped_y); |
uint32_t src_offset = pix_y * rrb->map_pitch + pix_x * rrb->cpp; |
tiled_z16_map[dst_offset/2] = untiled_z16_map[src_offset/2]; |
} |
} |
radeon_bo_unmap(rrb->bo); |
} |
free(rrb->map_buffer); |
rrb->map_buffer = NULL; |
} |
static void |
radeon_unmap_renderbuffer(struct gl_context *ctx, |
struct gl_renderbuffer *rb) |
{ |
struct radeon_context *const rmesa = RADEON_CONTEXT(ctx); |
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); |
GLboolean ok; |
if ((rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_DEPTH_ALWAYS_TILED) && !rrb->has_surface) { |
if (rb->Format == MESA_FORMAT_S8_Z24 || rb->Format == MESA_FORMAT_X8_Z24) { |
radeon_unmap_renderbuffer_s8z24(ctx, rb); |
return; |
} |
if (rb->Format == MESA_FORMAT_Z16) { |
radeon_unmap_renderbuffer_z16(ctx, rb); |
return; |
} |
} |
if (!rrb->map_bo) { |
if (rrb->bo) |
radeon_bo_unmap(rrb->bo); |
return; |
} |
radeon_bo_unmap(rrb->map_bo); |
if (rrb->map_mode & GL_MAP_WRITE_BIT) { |
ok = rmesa->vtbl.blit(ctx, rrb->map_bo, 0, |
rb->Format, rrb->map_pitch / rrb->cpp, |
rrb->map_w, rrb->map_h, |
0, 0, |
rrb->bo, rrb->draw_offset, |
rb->Format, rrb->pitch / rrb->cpp, |
rb->Width, rb->Height, |
rrb->map_x, rrb->map_y, |
rrb->map_w, rrb->map_h, |
GL_FALSE); |
assert(ok); |
} |
radeon_bo_unref(rrb->map_bo); |
rrb->map_bo = NULL; |
} |
/** |
* Called via glRenderbufferStorageEXT() to set the format and allocate |
* storage for a user-created renderbuffer. |
*/ |
static GLboolean |
radeon_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, |
GLuint width, GLuint height) |
{ |
struct radeon_context *radeon = RADEON_CONTEXT(ctx); |
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); |
uint32_t size, pitch; |
int cpp; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(%p, rb %p) \n", |
__func__, ctx, rb); |
ASSERT(rb->Name != 0); |
switch (internalFormat) { |
case GL_R3_G3_B2: |
case GL_RGB4: |
case GL_RGB5: |
rb->Format = _radeon_texformat_rgb565; |
cpp = 2; |
break; |
case GL_RGB: |
case GL_RGB8: |
case GL_RGB10: |
case GL_RGB12: |
case GL_RGB16: |
rb->Format = _radeon_texformat_argb8888; |
cpp = 4; |
break; |
case GL_RGBA: |
case GL_RGBA2: |
case GL_RGBA4: |
case GL_RGB5_A1: |
case GL_RGBA8: |
case GL_RGB10_A2: |
case GL_RGBA12: |
case GL_RGBA16: |
rb->Format = _radeon_texformat_argb8888; |
cpp = 4; |
break; |
case GL_STENCIL_INDEX: |
case GL_STENCIL_INDEX1_EXT: |
case GL_STENCIL_INDEX4_EXT: |
case GL_STENCIL_INDEX8_EXT: |
case GL_STENCIL_INDEX16_EXT: |
/* alloc a depth+stencil buffer */ |
rb->Format = MESA_FORMAT_S8_Z24; |
cpp = 4; |
break; |
case GL_DEPTH_COMPONENT16: |
rb->Format = MESA_FORMAT_Z16; |
cpp = 2; |
break; |
case GL_DEPTH_COMPONENT: |
case GL_DEPTH_COMPONENT24: |
case GL_DEPTH_COMPONENT32: |
rb->Format = MESA_FORMAT_X8_Z24; |
cpp = 4; |
break; |
case GL_DEPTH_STENCIL_EXT: |
case GL_DEPTH24_STENCIL8_EXT: |
rb->Format = MESA_FORMAT_S8_Z24; |
cpp = 4; |
break; |
default: |
_mesa_problem(ctx, |
"Unexpected format in radeon_alloc_renderbuffer_storage"); |
return GL_FALSE; |
} |
rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); |
if (ctx->Driver.Flush) |
ctx->Driver.Flush(ctx); /* +r6/r7 */ |
if (rrb->bo) |
radeon_bo_unref(rrb->bo); |
pitch = ((cpp * width + 63) & ~63) / cpp; |
if (RADEON_DEBUG & RADEON_MEMORY) |
fprintf(stderr,"Allocating %d x %d radeon RBO (pitch %d)\n", width, |
height, pitch); |
size = pitch * height * cpp; |
rrb->pitch = pitch * cpp; |
rrb->cpp = cpp; |
rrb->bo = radeon_bo_open(radeon->radeonScreen->bom, |
0, |
size, |
0, |
RADEON_GEM_DOMAIN_VRAM, |
0); |
rb->Width = width; |
rb->Height = height; |
return GL_TRUE; |
} |
static void |
radeon_image_target_renderbuffer_storage(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
void *image_handle) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
struct radeon_renderbuffer *rrb; |
__DRIscreen *screen; |
__DRIimage *image; |
screen = radeon->radeonScreen->driScreen; |
image = screen->dri2.image->lookupEGLImage(screen, image_handle, |
screen->loaderPrivate); |
if (image == NULL) |
return; |
rrb = radeon_renderbuffer(rb); |
if (ctx->Driver.Flush) |
ctx->Driver.Flush(ctx); /* +r6/r7 */ |
if (rrb->bo) |
radeon_bo_unref(rrb->bo); |
rrb->bo = image->bo; |
radeon_bo_ref(rrb->bo); |
fprintf(stderr, "image->bo: %p, name: %d, rbs: w %d -> p %d\n", image->bo, image->bo->handle, |
image->width, image->pitch); |
rrb->cpp = image->cpp; |
rrb->pitch = image->pitch * image->cpp; |
rb->Format = image->format; |
rb->InternalFormat = image->internal_format; |
rb->Width = image->width; |
rb->Height = image->height; |
rb->Format = image->format; |
rb->_BaseFormat = _mesa_base_fbo_format(&radeon->glCtx, |
image->internal_format); |
rb->NeedsFinishRenderTexture = GL_TRUE; |
} |
/** |
* Called for each hardware renderbuffer when a _window_ is resized. |
* Just update fields. |
* Not used for user-created renderbuffers! |
*/ |
static GLboolean |
radeon_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, GLuint width, GLuint height) |
{ |
ASSERT(rb->Name == 0); |
rb->Width = width; |
rb->Height = height; |
rb->InternalFormat = internalFormat; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(%p, rb %p) \n", |
__func__, ctx, rb); |
return GL_TRUE; |
} |
/** Dummy function for gl_renderbuffer::AllocStorage() */ |
static GLboolean |
radeon_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, GLuint width, GLuint height) |
{ |
_mesa_problem(ctx, "radeon_op_alloc_storage should never be called."); |
return GL_FALSE; |
} |
/** |
* Create a renderbuffer for a window's color, depth and/or stencil buffer. |
* Not used for user-created renderbuffers. |
*/ |
struct radeon_renderbuffer * |
radeon_create_renderbuffer(gl_format format, __DRIdrawable *driDrawPriv) |
{ |
struct radeon_renderbuffer *rrb; |
struct gl_renderbuffer *rb; |
rrb = CALLOC_STRUCT(radeon_renderbuffer); |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s( rrb %p ) \n", |
__func__, rrb); |
if (!rrb) |
return NULL; |
rb = &rrb->base.Base; |
_mesa_init_renderbuffer(rb, 0); |
rb->ClassID = RADEON_RB_CLASS; |
rb->Format = format; |
rb->_BaseFormat = _mesa_get_format_base_format(format); |
rb->InternalFormat = _mesa_get_format_base_format(format); |
rrb->dPriv = driDrawPriv; |
rb->Delete = radeon_delete_renderbuffer; |
rb->AllocStorage = radeon_alloc_window_storage; |
rrb->bo = NULL; |
return rrb; |
} |
static struct gl_renderbuffer * |
radeon_new_renderbuffer(struct gl_context * ctx, GLuint name) |
{ |
struct radeon_renderbuffer *rrb; |
struct gl_renderbuffer *rb; |
rrb = CALLOC_STRUCT(radeon_renderbuffer); |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(%p, rrb %p) \n", |
__func__, ctx, rrb); |
if (!rrb) |
return NULL; |
rb = &rrb->base.Base; |
_mesa_init_renderbuffer(rb, name); |
rb->ClassID = RADEON_RB_CLASS; |
rb->Delete = radeon_delete_renderbuffer; |
rb->AllocStorage = radeon_alloc_renderbuffer_storage; |
return rb; |
} |
static void |
radeon_bind_framebuffer(struct gl_context * ctx, GLenum target, |
struct gl_framebuffer *fb, struct gl_framebuffer *fbread) |
{ |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(%p, fb %p, target %s) \n", |
__func__, ctx, fb, |
_mesa_lookup_enum_by_nr(target)); |
if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { |
radeon_draw_buffer(ctx, fb); |
} |
else { |
/* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ |
} |
} |
static void |
radeon_framebuffer_renderbuffer(struct gl_context * ctx, |
struct gl_framebuffer *fb, |
GLenum attachment, struct gl_renderbuffer *rb) |
{ |
if (ctx->Driver.Flush) |
ctx->Driver.Flush(ctx); /* +r6/r7 */ |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(%p, fb %p, rb %p) \n", |
__func__, ctx, fb, rb); |
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); |
radeon_draw_buffer(ctx, fb); |
} |
static GLboolean |
radeon_update_wrapper(struct gl_context *ctx, struct radeon_renderbuffer *rrb, |
struct gl_texture_image *texImage) |
{ |
struct gl_renderbuffer *rb = &rrb->base.Base; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(%p, rrb %p, texImage %p, texFormat %s) \n", |
__func__, ctx, rrb, texImage, _mesa_get_format_name(texImage->TexFormat)); |
rrb->cpp = _mesa_get_format_bytes(texImage->TexFormat); |
rrb->pitch = texImage->Width * rrb->cpp; |
rb->Format = texImage->TexFormat; |
rb->InternalFormat = texImage->InternalFormat; |
rb->_BaseFormat = _mesa_base_fbo_format(ctx, rb->InternalFormat); |
rb->Width = texImage->Width; |
rb->Height = texImage->Height; |
rb->Delete = radeon_delete_renderbuffer; |
rb->AllocStorage = radeon_nop_alloc_storage; |
return GL_TRUE; |
} |
static void |
radeon_render_texture(struct gl_context * ctx, |
struct gl_framebuffer *fb, |
struct gl_renderbuffer_attachment *att) |
{ |
struct gl_renderbuffer *rb = att->Renderbuffer; |
struct gl_texture_image *newImage = rb->TexImage; |
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); |
radeon_texture_image *radeon_image; |
GLuint imageOffset; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(%p, fb %p, rrb %p, att %p)\n", |
__func__, ctx, fb, rrb, att); |
(void) fb; |
ASSERT(newImage); |
radeon_image = (radeon_texture_image *)newImage; |
if (!radeon_image->mt) { |
/* Fallback on drawing to a texture without a miptree. |
*/ |
_swrast_render_texture(ctx, fb, att); |
return; |
} |
if (!radeon_update_wrapper(ctx, rrb, newImage)) { |
_swrast_render_texture(ctx, fb, att); |
return; |
} |
DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n", |
_glthread_GetID(), |
att->Texture->Name, newImage->Width, newImage->Height, |
rb->RefCount); |
/* point the renderbufer's region to the texture image region */ |
if (rrb->bo != radeon_image->mt->bo) { |
if (rrb->bo) |
radeon_bo_unref(rrb->bo); |
rrb->bo = radeon_image->mt->bo; |
radeon_bo_ref(rrb->bo); |
} |
/* compute offset of the particular 2D image within the texture region */ |
imageOffset = radeon_miptree_image_offset(radeon_image->mt, |
att->CubeMapFace, |
att->TextureLevel); |
if (att->Texture->Target == GL_TEXTURE_3D) { |
imageOffset += radeon_image->mt->levels[att->TextureLevel].rowstride * |
radeon_image->mt->levels[att->TextureLevel].height * |
att->Zoffset; |
} |
/* store that offset in the region, along with the correct pitch for |
* the image we are rendering to */ |
rrb->draw_offset = imageOffset; |
rrb->pitch = radeon_image->mt->levels[att->TextureLevel].rowstride; |
radeon_image->used_as_render_target = GL_TRUE; |
/* update drawing region, etc */ |
radeon_draw_buffer(ctx, fb); |
} |
static void |
radeon_finish_render_texture(struct gl_context *ctx, struct gl_renderbuffer *rb) |
{ |
struct gl_texture_image *image = rb->TexImage; |
radeon_texture_image *radeon_image = (radeon_texture_image *)image; |
if (radeon_image) |
radeon_image->used_as_render_target = GL_FALSE; |
if (ctx->Driver.Flush) |
ctx->Driver.Flush(ctx); /* +r6/r7 */ |
} |
static void |
radeon_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
gl_format mesa_format; |
int i; |
for (i = -2; i < (GLint) ctx->Const.MaxColorAttachments; i++) { |
struct gl_renderbuffer_attachment *att; |
if (i == -2) { |
att = &fb->Attachment[BUFFER_DEPTH]; |
} else if (i == -1) { |
att = &fb->Attachment[BUFFER_STENCIL]; |
} else { |
att = &fb->Attachment[BUFFER_COLOR0 + i]; |
} |
if (att->Type == GL_TEXTURE) { |
mesa_format = att->Renderbuffer->TexImage->TexFormat; |
} else { |
/* All renderbuffer formats are renderable, but not sampable */ |
continue; |
} |
if (!radeon->vtbl.is_format_renderable(mesa_format)){ |
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s: HW doesn't support format %s as output format of attachment %d\n", |
__FUNCTION__, _mesa_get_format_name(mesa_format), i); |
return; |
} |
} |
} |
void radeon_fbo_init(struct radeon_context *radeon) |
{ |
radeon->glCtx.Driver.NewFramebuffer = radeon_new_framebuffer; |
radeon->glCtx.Driver.NewRenderbuffer = radeon_new_renderbuffer; |
radeon->glCtx.Driver.MapRenderbuffer = radeon_map_renderbuffer; |
radeon->glCtx.Driver.UnmapRenderbuffer = radeon_unmap_renderbuffer; |
radeon->glCtx.Driver.BindFramebuffer = radeon_bind_framebuffer; |
radeon->glCtx.Driver.FramebufferRenderbuffer = radeon_framebuffer_renderbuffer; |
radeon->glCtx.Driver.RenderTexture = radeon_render_texture; |
radeon->glCtx.Driver.FinishRenderTexture = radeon_finish_render_texture; |
radeon->glCtx.Driver.ValidateFramebuffer = radeon_validate_framebuffer; |
radeon->glCtx.Driver.BlitFramebuffer = _mesa_meta_BlitFramebuffer; |
radeon->glCtx.Driver.EGLImageTargetRenderbufferStorage = |
radeon_image_target_renderbuffer_storage; |
} |
void radeon_renderbuffer_set_bo(struct radeon_renderbuffer *rb, |
struct radeon_bo *bo) |
{ |
struct radeon_bo *old; |
old = rb->bo; |
rb->bo = bo; |
radeon_bo_ref(bo); |
if (old) |
radeon_bo_unref(old); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_fog.c |
---|
0,0 → 1,125 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
Tungsten Graphics Inc., Austin, 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, 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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/imports.h" |
#include "main/context.h" |
#include "main/mtypes.h" |
#include "main/enums.h" |
#include "main/macros.h" |
#include "radeon_fog.h" |
/**********************************************************************/ |
/* Fog blend factor computation for hw tcl */ |
/* same calculation used as in t_vb_fog.c */ |
/**********************************************************************/ |
#define FOG_EXP_TABLE_SIZE 256 |
#define FOG_MAX (10.0) |
#define EXP_FOG_MAX .0006595 |
#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE) |
static GLfloat exp_table[FOG_EXP_TABLE_SIZE]; |
#if 1 |
#define NEG_EXP( result, narg ) \ |
do { \ |
GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR)); \ |
GLint k = (GLint) f; \ |
if (k > FOG_EXP_TABLE_SIZE-2) \ |
result = (GLfloat) EXP_FOG_MAX; \ |
else \ |
result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]); \ |
} while (0) |
#else |
#define NEG_EXP( result, narg ) \ |
do { \ |
result = exp(-narg); \ |
} while (0) |
#endif |
/** |
* Initialize the exp_table[] lookup table for approximating exp(). |
*/ |
void |
radeonInitStaticFogData( void ) |
{ |
GLfloat f = 0.0F; |
GLint i = 0; |
for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) { |
exp_table[i] = (GLfloat) exp(-f); |
} |
} |
/** |
* Compute per-vertex fog blend factors from fog coordinates by |
* evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function. |
* Fog coordinates are distances from the eye (typically between the |
* near and far clip plane distances). |
* Note the fog (eye Z) coords may be negative so we use ABS(z) below. |
* Fog blend factors are in the range [0,1]. |
*/ |
float |
radeonComputeFogBlendFactor( struct gl_context *ctx, GLfloat fogcoord ) |
{ |
GLfloat end = ctx->Fog.End; |
GLfloat d, temp; |
const GLfloat z = FABSF(fogcoord); |
switch (ctx->Fog.Mode) { |
case GL_LINEAR: |
if (ctx->Fog.Start == ctx->Fog.End) |
d = 1.0F; |
else |
d = 1.0F / (ctx->Fog.End - ctx->Fog.Start); |
temp = (end - z) * d; |
return CLAMP(temp, 0.0F, 1.0F); |
break; |
case GL_EXP: |
d = ctx->Fog.Density; |
NEG_EXP( temp, d * z ); |
return temp; |
break; |
case GL_EXP2: |
d = ctx->Fog.Density*ctx->Fog.Density; |
NEG_EXP( temp, d * z * z ); |
return temp; |
break; |
default: |
_mesa_problem(ctx, "Bad fog mode in make_fog_coord"); |
return 0; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_fog.h |
---|
0,0 → 1,44 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
Tungsten Graphics Inc., Austin, 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, 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 COPYRIGHT OWNER(S) 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 RADEON_FOG_H |
#define RADEON_FOG_H |
void |
radeonInitStaticFogData( void ); |
float |
radeonComputeFogBlendFactor( struct gl_context *ctx, GLfloat fogcoord ); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_ioctl.c |
---|
0,0 → 1,418 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Kevin E. Martin <martin@valinux.com> |
* Gareth Hughes <gareth@valinux.com> |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#include <sched.h> |
#include <errno.h> |
#include "main/attrib.h" |
#include "main/bufferobj.h" |
#include "swrast/swrast.h" |
#include "main/glheader.h" |
#include "main/imports.h" |
#include "main/simple_list.h" |
#include "radeon_context.h" |
#include "radeon_common.h" |
#include "radeon_ioctl.h" |
#define RADEON_TIMEOUT 512 |
#define RADEON_IDLE_RETRY 16 |
/* ============================================================= |
* Kernel command buffer handling |
*/ |
/* The state atoms will be emitted in the order they appear in the atom list, |
* so this step is important. |
*/ |
void radeonSetUpAtomList( r100ContextPtr rmesa ) |
{ |
int i, mtu = rmesa->radeon.glCtx.Const.MaxTextureUnits; |
make_empty_list(&rmesa->radeon.hw.atomlist); |
rmesa->radeon.hw.atomlist.name = "atom-list"; |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.ctx); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.set); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.lin); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.msk); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.vpt); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.tcl); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.msc); |
for (i = 0; i < mtu; ++i) { |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.tex[i]); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.txr[i]); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.cube[i]); |
} |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.zbs); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.mtl); |
for (i = 0; i < 3 + mtu; ++i) |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.mat[i]); |
for (i = 0; i < 8; ++i) |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i]); |
for (i = 0; i < 6; ++i) |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i]); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.stp); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.eye); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.grd); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.fog); |
insert_at_tail(&rmesa->radeon.hw.atomlist, &rmesa->hw.glt); |
} |
static void radeonEmitScissor(r100ContextPtr rmesa) |
{ |
BATCH_LOCALS(&rmesa->radeon); |
if (rmesa->radeon.state.scissor.enabled) { |
BEGIN_BATCH(6); |
OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 0)); |
OUT_BATCH(rmesa->hw.ctx.cmd[CTX_PP_CNTL] | RADEON_SCISSOR_ENABLE); |
OUT_BATCH(CP_PACKET0(RADEON_RE_TOP_LEFT, 0)); |
OUT_BATCH((rmesa->radeon.state.scissor.rect.y1 << 16) | |
rmesa->radeon.state.scissor.rect.x1); |
OUT_BATCH(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0)); |
OUT_BATCH(((rmesa->radeon.state.scissor.rect.y2) << 16) | |
(rmesa->radeon.state.scissor.rect.x2)); |
END_BATCH(); |
} else { |
BEGIN_BATCH(2); |
OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 0)); |
OUT_BATCH(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ~RADEON_SCISSOR_ENABLE); |
END_BATCH(); |
} |
} |
/* Fire a section of the retained (indexed_verts) buffer as a regular |
* primtive. |
*/ |
extern void radeonEmitVbufPrim( r100ContextPtr rmesa, |
GLuint vertex_format, |
GLuint primitive, |
GLuint vertex_nr ) |
{ |
BATCH_LOCALS(&rmesa->radeon); |
assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND)); |
radeonEmitState(&rmesa->radeon); |
radeonEmitScissor(rmesa); |
#if RADEON_OLD_PACKETS |
BEGIN_BATCH(8); |
OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 3); |
OUT_BATCH(rmesa->ioctl.vertex_offset); |
OUT_BATCH(vertex_nr); |
OUT_BATCH(vertex_format); |
OUT_BATCH(primitive | RADEON_CP_VC_CNTL_PRIM_WALK_LIST | |
RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | |
RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | |
(vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT)); |
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs, |
rmesa->ioctl.bo, |
RADEON_GEM_DOMAIN_GTT, |
0, 0); |
END_BATCH(); |
#else |
BEGIN_BATCH(4); |
OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_DRAW_VBUF, 1); |
OUT_BATCH(vertex_format); |
OUT_BATCH(primitive | |
RADEON_CP_VC_CNTL_PRIM_WALK_LIST | |
RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | |
RADEON_CP_VC_CNTL_MAOS_ENABLE | |
RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | |
(vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT)); |
END_BATCH(); |
#endif |
} |
void radeonFlushElts( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
BATCH_LOCALS(&rmesa->radeon); |
int nr; |
uint32_t *cmd = (uint32_t *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_start); |
int dwords = (rmesa->radeon.cmdbuf.cs->section_ndw - rmesa->radeon.cmdbuf.cs->section_cdw); |
if (RADEON_DEBUG & RADEON_IOCTL) |
fprintf(stderr, "%s\n", __FUNCTION__); |
assert( rmesa->radeon.dma.flush == radeonFlushElts ); |
rmesa->radeon.dma.flush = NULL; |
nr = rmesa->tcl.elt_used; |
#if RADEON_OLD_PACKETS |
dwords -= 2; |
#endif |
#if RADEON_OLD_PACKETS |
cmd[1] |= (dwords + 3) << 16; |
cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT; |
#else |
cmd[1] |= (dwords + 2) << 16; |
cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT; |
#endif |
rmesa->radeon.cmdbuf.cs->cdw += dwords; |
rmesa->radeon.cmdbuf.cs->section_cdw += dwords; |
#if RADEON_OLD_PACKETS |
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs, |
rmesa->ioctl.bo, |
RADEON_GEM_DOMAIN_GTT, |
0, 0); |
#endif |
END_BATCH(); |
if (RADEON_DEBUG & RADEON_SYNC) { |
fprintf(stderr, "%s: Syncing\n", __FUNCTION__); |
radeonFinish( &rmesa->radeon.glCtx ); |
} |
} |
GLushort *radeonAllocEltsOpenEnded( r100ContextPtr rmesa, |
GLuint vertex_format, |
GLuint primitive, |
GLuint min_nr ) |
{ |
GLushort *retval; |
int align_min_nr; |
BATCH_LOCALS(&rmesa->radeon); |
if (RADEON_DEBUG & RADEON_IOCTL) |
fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive); |
assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND)); |
radeonEmitState(&rmesa->radeon); |
radeonEmitScissor(rmesa); |
rmesa->tcl.elt_cmd_start = rmesa->radeon.cmdbuf.cs->cdw; |
/* round up min_nr to align the state */ |
align_min_nr = (min_nr + 1) & ~1; |
#if RADEON_OLD_PACKETS |
BEGIN_BATCH_NO_AUTOSTATE(2+ELTS_BUFSZ(align_min_nr)/4); |
OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM, 0); |
OUT_BATCH(rmesa->ioctl.vertex_offset); |
OUT_BATCH(rmesa->ioctl.vertex_max); |
OUT_BATCH(vertex_format); |
OUT_BATCH(primitive | |
RADEON_CP_VC_CNTL_PRIM_WALK_IND | |
RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | |
RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE); |
#else |
BEGIN_BATCH_NO_AUTOSTATE(ELTS_BUFSZ(align_min_nr)/4); |
OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_DRAW_INDX, 0); |
OUT_BATCH(vertex_format); |
OUT_BATCH(primitive | |
RADEON_CP_VC_CNTL_PRIM_WALK_IND | |
RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | |
RADEON_CP_VC_CNTL_MAOS_ENABLE | |
RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE); |
#endif |
rmesa->tcl.elt_cmd_offset = rmesa->radeon.cmdbuf.cs->cdw; |
rmesa->tcl.elt_used = min_nr; |
retval = (GLushort *)(rmesa->radeon.cmdbuf.cs->packets + rmesa->tcl.elt_cmd_offset); |
if (RADEON_DEBUG & RADEON_RENDER) |
fprintf(stderr, "%s: header prim %x \n", |
__FUNCTION__, primitive); |
assert(!rmesa->radeon.dma.flush); |
rmesa->radeon.glCtx.Driver.NeedFlush |= FLUSH_STORED_VERTICES; |
rmesa->radeon.dma.flush = radeonFlushElts; |
return retval; |
} |
void radeonEmitVertexAOS( r100ContextPtr rmesa, |
GLuint vertex_size, |
struct radeon_bo *bo, |
GLuint offset ) |
{ |
#if RADEON_OLD_PACKETS |
rmesa->ioctl.vertex_offset = offset; |
rmesa->ioctl.bo = bo; |
#else |
BATCH_LOCALS(&rmesa->radeon); |
if (RADEON_DEBUG & (RADEON_PRIMS|DEBUG_IOCTL)) |
fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n", |
__FUNCTION__, vertex_size, offset); |
BEGIN_BATCH(7); |
OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, 2); |
OUT_BATCH(1); |
OUT_BATCH(vertex_size | (vertex_size << 8)); |
OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0); |
END_BATCH(); |
#endif |
} |
void radeonEmitAOS( r100ContextPtr rmesa, |
GLuint nr, |
GLuint offset ) |
{ |
#if RADEON_OLD_PACKETS |
assert( nr == 1 ); |
rmesa->ioctl.bo = rmesa->radeon.tcl.aos[0].bo; |
rmesa->ioctl.vertex_offset = |
(rmesa->radeon.tcl.aos[0].offset + offset * rmesa->radeon.tcl.aos[0].stride * 4); |
rmesa->ioctl.vertex_max = rmesa->radeon.tcl.aos[0].count; |
#else |
BATCH_LOCALS(&rmesa->radeon); |
uint32_t voffset; |
// int sz = AOS_BUFSZ(nr); |
int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2; |
int i; |
if (RADEON_DEBUG & RADEON_IOCTL) |
fprintf(stderr, "%s\n", __FUNCTION__); |
BEGIN_BATCH(sz+2+(nr * 2)); |
OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR, sz - 1); |
OUT_BATCH(nr); |
{ |
for (i = 0; i + 1 < nr; i += 2) { |
OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) | |
(rmesa->radeon.tcl.aos[i].stride << 8) | |
(rmesa->radeon.tcl.aos[i + 1].components << 16) | |
(rmesa->radeon.tcl.aos[i + 1].stride << 24)); |
voffset = rmesa->radeon.tcl.aos[i + 0].offset + |
offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride; |
OUT_BATCH(voffset); |
voffset = rmesa->radeon.tcl.aos[i + 1].offset + |
offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride; |
OUT_BATCH(voffset); |
} |
if (nr & 1) { |
OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) | |
(rmesa->radeon.tcl.aos[nr - 1].stride << 8)); |
voffset = rmesa->radeon.tcl.aos[nr - 1].offset + |
offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride; |
OUT_BATCH(voffset); |
} |
for (i = 0; i + 1 < nr; i += 2) { |
voffset = rmesa->radeon.tcl.aos[i + 0].offset + |
offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride; |
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs, |
rmesa->radeon.tcl.aos[i+0].bo, |
RADEON_GEM_DOMAIN_GTT, |
0, 0); |
voffset = rmesa->radeon.tcl.aos[i + 1].offset + |
offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride; |
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs, |
rmesa->radeon.tcl.aos[i+1].bo, |
RADEON_GEM_DOMAIN_GTT, |
0, 0); |
} |
if (nr & 1) { |
voffset = rmesa->radeon.tcl.aos[nr - 1].offset + |
offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride; |
radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs, |
rmesa->radeon.tcl.aos[nr-1].bo, |
RADEON_GEM_DOMAIN_GTT, |
0, 0); |
} |
} |
END_BATCH(); |
#endif |
} |
/* ================================================================ |
* Buffer clear |
*/ |
#define RADEON_MAX_CLEARS 256 |
static void radeonClear( struct gl_context *ctx, GLbitfield mask ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint hwmask, swmask; |
GLuint hwbits = BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT | |
BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL | |
BUFFER_BIT_COLOR0; |
if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_FRONT_RIGHT)) { |
rmesa->radeon.front_buffer_dirty = GL_TRUE; |
} |
if ( RADEON_DEBUG & RADEON_IOCTL ) { |
fprintf( stderr, "radeonClear\n"); |
} |
radeon_firevertices(&rmesa->radeon); |
hwmask = mask & hwbits; |
swmask = mask & ~hwbits; |
if ( swmask ) { |
if (RADEON_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, swmask); |
_swrast_Clear( ctx, swmask ); |
} |
if ( !hwmask ) |
return; |
radeonUserClear(ctx, hwmask); |
} |
void radeonInitIoctlFuncs( struct gl_context *ctx ) |
{ |
ctx->Driver.Clear = radeonClear; |
ctx->Driver.Finish = radeonFinish; |
ctx->Driver.Flush = radeonFlush; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_ioctl.h |
---|
0,0 → 1,171 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Kevin E. Martin <martin@valinux.com> |
* Gareth Hughes <gareth@valinux.com> |
*/ |
#ifndef __RADEON_IOCTL_H__ |
#define __RADEON_IOCTL_H__ |
#include "main/simple_list.h" |
#include "radeon_bo_gem.h" |
#include "radeon_cs_gem.h" |
extern void radeonEmitVertexAOS( r100ContextPtr rmesa, |
GLuint vertex_size, |
struct radeon_bo *bo, |
GLuint offset ); |
extern void radeonEmitVbufPrim( r100ContextPtr rmesa, |
GLuint vertex_format, |
GLuint primitive, |
GLuint vertex_nr ); |
extern void radeonFlushElts( struct gl_context *ctx ); |
extern GLushort *radeonAllocEltsOpenEnded( r100ContextPtr rmesa, |
GLuint vertex_format, |
GLuint primitive, |
GLuint min_nr ); |
extern void radeonEmitAOS( r100ContextPtr rmesa, |
GLuint n, |
GLuint offset ); |
extern void radeonEmitBlit( r100ContextPtr rmesa, |
GLuint color_fmt, |
GLuint src_pitch, |
GLuint src_offset, |
GLuint dst_pitch, |
GLuint dst_offset, |
GLint srcx, GLint srcy, |
GLint dstx, GLint dsty, |
GLuint w, GLuint h ); |
extern void radeonEmitWait( r100ContextPtr rmesa, GLuint flags ); |
extern void radeonFlushCmdBuf( r100ContextPtr rmesa, const char * ); |
extern void radeonFlush( struct gl_context *ctx ); |
extern void radeonFinish( struct gl_context *ctx ); |
extern void radeonInitIoctlFuncs( struct gl_context *ctx ); |
extern void radeonGetAllParams( r100ContextPtr rmesa ); |
extern void radeonSetUpAtomList( r100ContextPtr rmesa ); |
/* ================================================================ |
* Helper macros: |
*/ |
/* Close off the last primitive, if it exists. |
*/ |
#define RADEON_NEWPRIM( rmesa ) \ |
do { \ |
if ( rmesa->radeon.dma.flush ) \ |
rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); \ |
} while (0) |
/* Can accomodate several state changes and primitive changes without |
* actually firing the buffer. |
*/ |
#define RADEON_STATECHANGE( rmesa, ATOM ) \ |
do { \ |
RADEON_NEWPRIM( rmesa ); \ |
rmesa->hw.ATOM.dirty = GL_TRUE; \ |
rmesa->radeon.hw.is_dirty = GL_TRUE; \ |
} while (0) |
#define RADEON_DB_STATE( ATOM ) \ |
memcpy( rmesa->hw.ATOM.lastcmd, rmesa->hw.ATOM.cmd, \ |
rmesa->hw.ATOM.cmd_size * 4) |
static INLINE int RADEON_DB_STATECHANGE(r100ContextPtr rmesa, |
struct radeon_state_atom *atom ) |
{ |
if (memcmp(atom->cmd, atom->lastcmd, atom->cmd_size*4)) { |
GLuint *tmp; |
RADEON_NEWPRIM( rmesa ); |
atom->dirty = GL_TRUE; |
rmesa->radeon.hw.is_dirty = GL_TRUE; |
tmp = atom->cmd; |
atom->cmd = atom->lastcmd; |
atom->lastcmd = tmp; |
return 1; |
} |
else |
return 0; |
} |
/* Command lengths. Note that any time you ensure ELTS_BUFSZ or VBUF_BUFSZ |
* are available, you will also be adding an rmesa->state.max_state_size because |
* r200EmitState is called from within r200EmitVbufPrim and r200FlushElts. |
*/ |
#if RADEON_OLD_PACKETS |
#define AOS_BUFSZ(nr) ((3 + ((nr / 2) * 3) + ((nr & 1) * 2))+nr*2) |
#define VERT_AOS_BUFSZ (0) |
#define ELTS_BUFSZ(nr) (24 + nr * 2) |
#define VBUF_BUFSZ (8) |
#else |
#define AOS_BUFSZ(nr) ((3 + ((nr / 2) * 3) + ((nr & 1) * 2) + nr*2)) |
#define VERT_AOS_BUFSZ (5) |
#define ELTS_BUFSZ(nr) (16 + nr * 2) |
#define VBUF_BUFSZ (4) |
#endif |
#define SCISSOR_BUFSZ (8) |
#define INDEX_BUFSZ (7) |
static inline uint32_t cmdpacket3(int cmd_type) |
{ |
drm_radeon_cmd_header_t cmd; |
cmd.i = 0; |
cmd.header.cmd_type = cmd_type; |
return (uint32_t)cmd.i; |
} |
#define OUT_BATCH_PACKET3(packet, num_extra) do { \ |
OUT_BATCH(CP_PACKET2); \ |
OUT_BATCH(CP_PACKET3((packet), (num_extra))); \ |
} while(0) |
#define OUT_BATCH_PACKET3_CLIP(packet, num_extra) do { \ |
OUT_BATCH(CP_PACKET2); \ |
OUT_BATCH(CP_PACKET3((packet), (num_extra))); \ |
} while(0) |
#endif /* __RADEON_IOCTL_H__ */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_maos.c |
---|
0,0 → 1,12 |
/* If using new packets, can choose either verts or arrays. |
* Otherwise, must use verts. |
*/ |
#include "radeon_context.h" |
#define RADEON_MAOS_VERTS 0 |
#if (RADEON_MAOS_VERTS) || (RADEON_OLD_PACKETS) |
#include "radeon_maos_verts.c" |
#else |
#include "radeon_maos_arrays.c" |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_maos.h |
---|
0,0 → 1,42 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
Tungsten Grahpics Inc., Austin, 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, 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 COPYRIGHT OWNER(S) 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 __RADEON_MAOS_H__ |
#define __RADEON_MAOS_H__ |
#include "radeon_context.h" |
extern void radeonEmitArrays( struct gl_context *ctx, GLuint inputs ); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c |
---|
0,0 → 1,289 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
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, 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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/imports.h" |
#include "main/mtypes.h" |
#include "main/macros.h" |
#include "swrast_setup/swrast_setup.h" |
#include "math/m_translate.h" |
#include "tnl/tnl.h" |
#include "radeon_context.h" |
#include "radeon_ioctl.h" |
#include "radeon_state.h" |
#include "radeon_swtcl.h" |
#include "radeon_maos.h" |
#include "radeon_tcl.h" |
static void emit_s0_vec(uint32_t *out, GLvoid *data, int stride, int count) |
{ |
int i; |
if (RADEON_DEBUG & RADEON_VERTS) |
fprintf(stderr, "%s count %d stride %d\n", |
__FUNCTION__, count, stride); |
for (i = 0; i < count; i++) { |
out[0] = *(int *)data; |
out[1] = 0; |
out += 2; |
data += stride; |
} |
} |
static void emit_stq_vec(uint32_t *out, GLvoid *data, int stride, int count) |
{ |
int i; |
if (RADEON_DEBUG & RADEON_VERTS) |
fprintf(stderr, "%s count %d stride %d\n", |
__FUNCTION__, count, stride); |
for (i = 0; i < count; i++) { |
out[0] = *(int *)data; |
out[1] = *(int *)(data+4); |
out[2] = *(int *)(data+12); |
out += 3; |
data += stride; |
} |
} |
static void emit_tex_vector(struct gl_context *ctx, struct radeon_aos *aos, |
GLvoid *data, int size, int stride, int count) |
{ |
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
int emitsize; |
uint32_t *out; |
if (RADEON_DEBUG & RADEON_VERTS) |
fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size); |
switch (size) { |
case 4: emitsize = 3; break; |
case 3: emitsize = 3; break; |
default: emitsize = 2; break; |
} |
if (stride == 0) { |
radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, emitsize * 4, 32); |
count = 1; |
aos->stride = 0; |
} |
else { |
radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, emitsize * count * 4, 32); |
aos->stride = emitsize; |
} |
aos->components = emitsize; |
aos->count = count; |
/* Emit the data |
*/ |
radeon_bo_map(aos->bo, 1); |
out = (uint32_t*)((char*)aos->bo->ptr + aos->offset); |
switch (size) { |
case 1: |
emit_s0_vec( out, data, stride, count ); |
break; |
case 2: |
radeonEmitVec8( out, data, stride, count ); |
break; |
case 3: |
radeonEmitVec12( out, data, stride, count ); |
break; |
case 4: |
emit_stq_vec( out, data, stride, count ); |
break; |
default: |
assert(0); |
exit(1); |
break; |
} |
radeon_bo_unmap(aos->bo); |
} |
/* Emit any changed arrays to new GART memory, re-emit a packet to |
* update the arrays. |
*/ |
void radeonEmitArrays( struct gl_context *ctx, GLuint inputs ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT( ctx ); |
struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb; |
GLuint nr = 0; |
GLuint vfmt = 0; |
GLuint count = VB->Count; |
GLuint vtx, unit; |
#if 0 |
if (RADEON_DEBUG & RADEON_VERTS) |
_tnl_print_vert_flags( __FUNCTION__, inputs ); |
#endif |
if (1) { |
if (!rmesa->tcl.obj.buf) |
rcommon_emit_vector( ctx, |
&(rmesa->tcl.aos[nr]), |
(char *)VB->AttribPtr[_TNL_ATTRIB_POS]->data, |
VB->AttribPtr[_TNL_ATTRIB_POS]->size, |
VB->AttribPtr[_TNL_ATTRIB_POS]->stride, |
count); |
switch( VB->AttribPtr[_TNL_ATTRIB_POS]->size ) { |
case 4: vfmt |= RADEON_CP_VC_FRMT_W0; |
case 3: vfmt |= RADEON_CP_VC_FRMT_Z; |
case 2: vfmt |= RADEON_CP_VC_FRMT_XY; |
default: |
break; |
} |
nr++; |
} |
if (inputs & VERT_BIT_NORMAL) { |
if (!rmesa->tcl.norm.buf) |
rcommon_emit_vector( ctx, |
&(rmesa->tcl.aos[nr]), |
(char *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data, |
3, |
VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride, |
count); |
vfmt |= RADEON_CP_VC_FRMT_N0; |
nr++; |
} |
if (inputs & VERT_BIT_COLOR0) { |
int emitsize; |
if (VB->AttribPtr[_TNL_ATTRIB_COLOR0]->size == 4 && |
(VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride != 0 || |
VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data[0][3] != 1.0)) { |
vfmt |= RADEON_CP_VC_FRMT_FPCOLOR | RADEON_CP_VC_FRMT_FPALPHA; |
emitsize = 4; |
} |
else { |
vfmt |= RADEON_CP_VC_FRMT_FPCOLOR; |
emitsize = 3; |
} |
if (!rmesa->tcl.rgba.buf) |
rcommon_emit_vector( ctx, |
&(rmesa->tcl.aos[nr]), |
(char *)VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data, |
emitsize, |
VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride, |
count); |
nr++; |
} |
if (inputs & VERT_BIT_COLOR1) { |
if (!rmesa->tcl.spec.buf) { |
rcommon_emit_vector( ctx, |
&(rmesa->tcl.aos[nr]), |
(char *)VB->AttribPtr[_TNL_ATTRIB_COLOR1]->data, |
3, |
VB->AttribPtr[_TNL_ATTRIB_COLOR1]->stride, |
count); |
} |
vfmt |= RADEON_CP_VC_FRMT_FPSPEC; |
nr++; |
} |
/* FIXME: not sure if this is correct. May need to stitch this together with |
secondary color. It seems odd that for primary color color and alpha values |
are emitted together but for secondary color not. */ |
if (inputs & VERT_BIT_FOG) { |
if (!rmesa->tcl.fog.buf) |
rcommon_emit_vecfog( ctx, |
&(rmesa->tcl.aos[nr]), |
(char *)VB->AttribPtr[_TNL_ATTRIB_FOG]->data, |
VB->AttribPtr[_TNL_ATTRIB_FOG]->stride, |
count); |
vfmt |= RADEON_CP_VC_FRMT_FPFOG; |
nr++; |
} |
vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] & |
~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1|RADEON_TCL_VTX_Q2)); |
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { |
if (inputs & VERT_BIT_TEX(unit)) { |
if (!rmesa->tcl.tex[unit].buf) |
emit_tex_vector( ctx, |
&(rmesa->tcl.aos[nr]), |
(char *)VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->data, |
VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size, |
VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->stride, |
count ); |
nr++; |
vfmt |= RADEON_ST_BIT(unit); |
/* assume we need the 3rd coord if texgen is active for r/q OR at least |
3 coords are submitted. This may not be 100% correct */ |
if (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) { |
vtx |= RADEON_Q_BIT(unit); |
vfmt |= RADEON_Q_BIT(unit); |
} |
if ( (ctx->Texture.Unit[unit].TexGenEnabled & (R_BIT | Q_BIT)) ) |
vtx |= RADEON_Q_BIT(unit); |
else if ((VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) && |
((ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_CUBE_BIT)) == 0)) { |
GLuint swaptexmatcol = (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size - 3); |
if (((rmesa->NeedTexMatrix >> unit) & 1) && |
(swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1))) |
radeonUploadTexMatrix( rmesa, unit, swaptexmatcol ) ; |
} |
} |
} |
if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) { |
RADEON_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx; |
} |
rmesa->tcl.nr_aos_components = nr; |
rmesa->tcl.vertex_format = vfmt; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h |
---|
0,0 → 1,300 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2002 Brian Paul 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, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
* OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#ifndef LOCALVARS |
#define LOCALVARS |
#endif |
#undef TCL_DEBUG |
#ifndef TCL_DEBUG |
#define TCL_DEBUG 0 |
#endif |
static void TAG(emit)( struct gl_context *ctx, |
GLuint start, GLuint end, |
void *dest ) |
{ |
LOCALVARS |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
GLuint (*tc0)[4], (*tc1)[4], (*tc2)[4]; |
GLfloat (*col)[4], (*spec)[4]; |
GLfloat (*fog)[4]; |
GLuint (*norm)[4]; |
GLuint tc0_stride, tc1_stride, col_stride, spec_stride, fog_stride; |
GLuint tc2_stride, norm_stride; |
GLuint fill_tex = 0; |
GLuint rqcoordsnoswap = 0; |
GLuint (*coord)[4]; |
GLuint coord_stride; /* object coordinates */ |
int i; |
union emit_union *v = (union emit_union *)dest; |
radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, "%s\n", __FUNCTION__); |
coord = (GLuint (*)[4])VB->AttribPtr[_TNL_ATTRIB_POS]->data; |
coord_stride = VB->AttribPtr[_TNL_ATTRIB_POS]->stride; |
if (DO_TEX2) { |
if (VB->AttribPtr[_TNL_ATTRIB_TEX2]) { |
const GLuint t2 = GET_TEXSOURCE(2); |
tc2 = (GLuint (*)[4])VB->AttribPtr[_TNL_ATTRIB_TEX0 + t2]->data; |
tc2_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t2]->stride; |
if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t2]->size < 3) { |
fill_tex |= (1<<2); |
} |
else if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t2]->size < 4) { |
rqcoordsnoswap |= (1<<2); |
} |
} else { |
tc2 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX2]; |
tc2_stride = 0; |
} |
} |
if (DO_TEX1) { |
if (VB->AttribPtr[_TNL_ATTRIB_TEX1]) { |
const GLuint t1 = GET_TEXSOURCE(1); |
tc1 = (GLuint (*)[4])VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->data; |
tc1_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->stride; |
if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->size < 3) { |
fill_tex |= (1<<1); |
} |
else if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t1]->size < 4) { |
rqcoordsnoswap |= (1<<1); |
} |
} else { |
tc1 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX1]; |
tc1_stride = 0; |
} |
} |
if (DO_TEX0) { |
if (VB->AttribPtr[_TNL_ATTRIB_TEX0]) { |
const GLuint t0 = GET_TEXSOURCE(0); |
tc0_stride = VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->stride; |
tc0 = (GLuint (*)[4])VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->data; |
if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->size < 3) { |
fill_tex |= (1<<0); |
} |
else if (DO_PTEX && VB->AttribPtr[_TNL_ATTRIB_TEX0 + t0]->size < 4) { |
rqcoordsnoswap |= (1<<0); |
} |
} else { |
tc0 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX0]; |
tc0_stride = 0; |
} |
} |
if (DO_NORM) { |
if (VB->AttribPtr[_TNL_ATTRIB_NORMAL]) { |
norm_stride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride; |
norm = (GLuint (*)[4])VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data; |
} else { |
norm_stride = 0; |
norm = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_NORMAL]; |
} |
} |
if (DO_RGBA) { |
if (VB->AttribPtr[_TNL_ATTRIB_COLOR0]) { |
col = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data; |
col_stride = VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride; |
} else { |
col = (GLfloat (*)[4])ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; |
col_stride = 0; |
} |
} |
if (DO_SPEC_OR_FOG) { |
if (VB->AttribPtr[_TNL_ATTRIB_COLOR1]) { |
spec = VB->AttribPtr[_TNL_ATTRIB_COLOR1]->data; |
spec_stride = VB->AttribPtr[_TNL_ATTRIB_COLOR1]->stride; |
} else { |
spec = (GLfloat (*)[4])ctx->Current.Attrib[VERT_ATTRIB_COLOR1]; |
spec_stride = 0; |
} |
} |
if (DO_SPEC_OR_FOG) { |
if (VB->AttribPtr[_TNL_ATTRIB_FOG]) { |
fog = VB->AttribPtr[_TNL_ATTRIB_FOG]->data; |
fog_stride = VB->AttribPtr[_TNL_ATTRIB_FOG]->stride; |
} else { |
fog = (GLfloat (*)[4])ctx->Current.Attrib[VERT_ATTRIB_FOG]; |
fog_stride = 0; |
} |
} |
if (start) { |
coord = (GLuint (*)[4])((GLubyte *)coord + start * coord_stride); |
if (DO_TEX0) |
tc0 = (GLuint (*)[4])((GLubyte *)tc0 + start * tc0_stride); |
if (DO_TEX1) |
tc1 = (GLuint (*)[4])((GLubyte *)tc1 + start * tc1_stride); |
if (DO_TEX2) |
tc2 = (GLuint (*)[4])((GLubyte *)tc2 + start * tc2_stride); |
if (DO_NORM) |
norm = (GLuint (*)[4])((GLubyte *)norm + start * norm_stride); |
if (DO_RGBA) |
STRIDE_4F(col, start * col_stride); |
if (DO_SPEC) |
STRIDE_4F(spec, start * spec_stride); |
if (DO_FOG) |
STRIDE_4F(fog, start * fog_stride); |
} |
{ |
for (i=start; i < end; i++) { |
v[0].ui = coord[0][0]; |
v[1].ui = coord[0][1]; |
v[2].ui = coord[0][2]; |
if (DO_W) { |
v[3].ui = coord[0][3]; |
v += 4; |
} |
else |
v += 3; |
coord = (GLuint (*)[4])((GLubyte *)coord + coord_stride); |
if (DO_NORM) { |
v[0].ui = norm[0][0]; |
v[1].ui = norm[0][1]; |
v[2].ui = norm[0][2]; |
v += 3; |
norm = (GLuint (*)[4])((GLubyte *)norm + norm_stride); |
} |
if (DO_RGBA) { |
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.red, col[0][0]); |
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.green, col[0][1]); |
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.blue, col[0][2]); |
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.alpha, col[0][3]); |
STRIDE_4F(col, col_stride); |
v++; |
} |
if (DO_SPEC_OR_FOG) { |
if (DO_SPEC) { |
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.red, spec[0][0]); |
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.green, spec[0][1]); |
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.blue, spec[0][2]); |
STRIDE_4F(spec, spec_stride); |
} |
if (DO_FOG) { |
UNCLAMPED_FLOAT_TO_UBYTE(v[0].rgba.alpha, radeonComputeFogBlendFactor(ctx, fog[0][0])); |
STRIDE_4F(fog, fog_stride); |
} |
if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui); |
v++; |
} |
if (DO_TEX0) { |
v[0].ui = tc0[0][0]; |
v[1].ui = tc0[0][1]; |
if (TCL_DEBUG) fprintf(stderr, "t0: %.2f %.2f ", v[0].f, v[1].f); |
if (DO_PTEX) { |
if (fill_tex & (1<<0)) |
v[2].f = 1.0; |
else if (rqcoordsnoswap & (1<<0)) |
v[2].ui = tc0[0][2]; |
else |
v[2].ui = tc0[0][3]; |
if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f); |
v += 3; |
} |
else |
v += 2; |
tc0 = (GLuint (*)[4])((GLubyte *)tc0 + tc0_stride); |
} |
if (DO_TEX1) { |
v[0].ui = tc1[0][0]; |
v[1].ui = tc1[0][1]; |
if (TCL_DEBUG) fprintf(stderr, "t1: %.2f %.2f ", v[0].f, v[1].f); |
if (DO_PTEX) { |
if (fill_tex & (1<<1)) |
v[2].f = 1.0; |
else if (rqcoordsnoswap & (1<<1)) |
v[2].ui = tc1[0][2]; |
else |
v[2].ui = tc1[0][3]; |
if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f); |
v += 3; |
} |
else |
v += 2; |
tc1 = (GLuint (*)[4])((GLubyte *)tc1 + tc1_stride); |
} |
if (DO_TEX2) { |
v[0].ui = tc2[0][0]; |
v[1].ui = tc2[0][1]; |
if (TCL_DEBUG) fprintf(stderr, "t2: %.2f %.2f ", v[0].f, v[1].f); |
if (DO_PTEX) { |
if (fill_tex & (1<<2)) |
v[2].f = 1.0; |
else if (rqcoordsnoswap & (1<<2)) |
v[2].ui = tc2[0][2]; |
else |
v[2].ui = tc2[0][3]; |
if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f); |
v += 3; |
} |
else |
v += 2; |
tc2 = (GLuint (*)[4])((GLubyte *)tc2 + tc2_stride); |
} |
if (TCL_DEBUG) fprintf(stderr, "\n"); |
} |
} |
} |
static void TAG(init)( void ) |
{ |
int sz = 3; |
if (DO_W) sz++; |
if (DO_NORM) sz += 3; |
if (DO_RGBA) sz++; |
if (DO_SPEC_OR_FOG) sz++; |
if (DO_TEX0) sz += 2; |
if (DO_TEX0 && DO_PTEX) sz++; |
if (DO_TEX1) sz += 2; |
if (DO_TEX1 && DO_PTEX) sz++; |
if (DO_TEX2) sz += 2; |
if (DO_TEX2 && DO_PTEX) sz++; |
setup_tab[IDX].emit = TAG(emit); |
setup_tab[IDX].vertex_format = IND; |
setup_tab[IDX].vertex_size = sz; |
} |
#undef IND |
#undef TAG |
#undef IDX |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_maos_verts.c |
---|
0,0 → 1,433 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
Tungsten Graphics Inc., Austin, 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, 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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/imports.h" |
#include "main/mtypes.h" |
#include "main/state.h" |
#include "vbo/vbo.h" |
#include "math/m_translate.h" |
#include "tnl/tnl.h" |
#include "tnl/t_pipeline.h" |
#include "radeon_context.h" |
#include "radeon_state.h" |
#include "radeon_ioctl.h" |
#include "radeon_tex.h" |
#include "radeon_tcl.h" |
#include "radeon_swtcl.h" |
#include "radeon_maos.h" |
#include "radeon_fog.h" |
#define RADEON_TCL_MAX_SETUP 19 |
union emit_union { float f; GLuint ui; radeon_color_t rgba; }; |
static struct { |
void (*emit)( struct gl_context *, GLuint, GLuint, void * ); |
GLuint vertex_size; |
GLuint vertex_format; |
} setup_tab[RADEON_TCL_MAX_SETUP]; |
#define DO_W (IND & RADEON_CP_VC_FRMT_W0) |
#define DO_RGBA (IND & RADEON_CP_VC_FRMT_PKCOLOR) |
#define DO_SPEC_OR_FOG (IND & RADEON_CP_VC_FRMT_PKSPEC) |
#define DO_SPEC ((IND & RADEON_CP_VC_FRMT_PKSPEC) && \ |
_mesa_need_secondary_color(ctx)) |
#define DO_FOG ((IND & RADEON_CP_VC_FRMT_PKSPEC) && ctx->Fog.Enabled && \ |
(ctx->Fog.FogCoordinateSource == GL_FOG_COORD)) |
#define DO_TEX0 (IND & RADEON_CP_VC_FRMT_ST0) |
#define DO_TEX1 (IND & RADEON_CP_VC_FRMT_ST1) |
#define DO_TEX2 (IND & RADEON_CP_VC_FRMT_ST2) |
#define DO_PTEX (IND & RADEON_CP_VC_FRMT_Q0) |
#define DO_NORM (IND & RADEON_CP_VC_FRMT_N0) |
#define DO_TEX3 0 |
#define GET_TEXSOURCE(n) n |
/*********************************************************************** |
* Generate vertex emit functions * |
***********************************************************************/ |
/* Defined in order of increasing vertex size: |
*/ |
#define IDX 0 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR) |
#define TAG(x) x##_rgba |
#include "radeon_maos_vbtmp.h" |
#define IDX 1 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_N0) |
#define TAG(x) x##_n |
#include "radeon_maos_vbtmp.h" |
#define IDX 2 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_ST0) |
#define TAG(x) x##_rgba_st |
#include "radeon_maos_vbtmp.h" |
#define IDX 3 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_N0) |
#define TAG(x) x##_rgba_n |
#include "radeon_maos_vbtmp.h" |
#define IDX 4 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_N0) |
#define TAG(x) x##_st_n |
#include "radeon_maos_vbtmp.h" |
#define IDX 5 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_ST1) |
#define TAG(x) x##_rgba_st_st |
#include "radeon_maos_vbtmp.h" |
#define IDX 6 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_N0) |
#define TAG(x) x##_rgba_st_n |
#include "radeon_maos_vbtmp.h" |
#define IDX 7 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_PKSPEC| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_ST1) |
#define TAG(x) x##_rgba_spec_st_st |
#include "radeon_maos_vbtmp.h" |
#define IDX 8 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_ST1| \ |
RADEON_CP_VC_FRMT_N0) |
#define TAG(x) x##_st_st_n |
#include "radeon_maos_vbtmp.h" |
#define IDX 9 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_PKSPEC| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_ST1| \ |
RADEON_CP_VC_FRMT_N0) |
#define TAG(x) x##_rgba_spec_st_st_n |
#include "radeon_maos_vbtmp.h" |
#define IDX 10 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_Q0) |
#define TAG(x) x##_rgba_stq |
#include "radeon_maos_vbtmp.h" |
#define IDX 11 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_ST1| \ |
RADEON_CP_VC_FRMT_Q1| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_Q0) |
#define TAG(x) x##_rgba_stq_stq |
#include "radeon_maos_vbtmp.h" |
#define IDX 12 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_W0| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_PKSPEC| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_Q0| \ |
RADEON_CP_VC_FRMT_ST1| \ |
RADEON_CP_VC_FRMT_Q1| \ |
RADEON_CP_VC_FRMT_N0) |
#define TAG(x) x##_w_rgba_spec_stq_stq_n |
#include "radeon_maos_vbtmp.h" |
#define IDX 13 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_ST1| \ |
RADEON_CP_VC_FRMT_ST2) |
#define TAG(x) x##_rgba_st_st_st |
#include "radeon_maos_vbtmp.h" |
#define IDX 14 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_PKSPEC| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_ST1| \ |
RADEON_CP_VC_FRMT_ST2) |
#define TAG(x) x##_rgba_spec_st_st_st |
#include "radeon_maos_vbtmp.h" |
#define IDX 15 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_ST1| \ |
RADEON_CP_VC_FRMT_ST2| \ |
RADEON_CP_VC_FRMT_N0) |
#define TAG(x) x##_st_st_st_n |
#include "radeon_maos_vbtmp.h" |
#define IDX 16 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_PKSPEC| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_ST1| \ |
RADEON_CP_VC_FRMT_ST2| \ |
RADEON_CP_VC_FRMT_N0) |
#define TAG(x) x##_rgba_spec_st_st_st_n |
#include "radeon_maos_vbtmp.h" |
#define IDX 17 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_Q0| \ |
RADEON_CP_VC_FRMT_ST1| \ |
RADEON_CP_VC_FRMT_Q1| \ |
RADEON_CP_VC_FRMT_ST2| \ |
RADEON_CP_VC_FRMT_Q2) |
#define TAG(x) x##_rgba_stq_stq_stq |
#include "radeon_maos_vbtmp.h" |
#define IDX 18 |
#define IND (RADEON_CP_VC_FRMT_XY| \ |
RADEON_CP_VC_FRMT_Z| \ |
RADEON_CP_VC_FRMT_W0| \ |
RADEON_CP_VC_FRMT_PKCOLOR| \ |
RADEON_CP_VC_FRMT_PKSPEC| \ |
RADEON_CP_VC_FRMT_ST0| \ |
RADEON_CP_VC_FRMT_Q0| \ |
RADEON_CP_VC_FRMT_ST1| \ |
RADEON_CP_VC_FRMT_Q1| \ |
RADEON_CP_VC_FRMT_ST2| \ |
RADEON_CP_VC_FRMT_Q2| \ |
RADEON_CP_VC_FRMT_N0) |
#define TAG(x) x##_w_rgba_spec_stq_stq_stq_n |
#include "radeon_maos_vbtmp.h" |
/*********************************************************************** |
* Initialization |
***********************************************************************/ |
static void init_tcl_verts( void ) |
{ |
init_rgba(); |
init_n(); |
init_rgba_n(); |
init_rgba_st(); |
init_st_n(); |
init_rgba_st_st(); |
init_rgba_st_n(); |
init_rgba_spec_st_st(); |
init_st_st_n(); |
init_rgba_spec_st_st_n(); |
init_rgba_stq(); |
init_rgba_stq_stq(); |
init_w_rgba_spec_stq_stq_n(); |
init_rgba_st_st_st(); |
init_rgba_spec_st_st_st(); |
init_st_st_st_n(); |
init_rgba_spec_st_st_st_n(); |
init_rgba_stq_stq_stq(); |
init_w_rgba_spec_stq_stq_stq_n(); |
} |
void radeonEmitArrays( struct gl_context *ctx, GLuint inputs ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
GLuint req = 0; |
GLuint unit; |
GLuint vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] & |
~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1|RADEON_TCL_VTX_Q2)); |
int i; |
static int firsttime = 1; |
if (firsttime) { |
init_tcl_verts(); |
firsttime = 0; |
} |
if (1) { |
req |= RADEON_CP_VC_FRMT_Z; |
if (VB->AttribPtr[_TNL_ATTRIB_POS]->size == 4) { |
req |= RADEON_CP_VC_FRMT_W0; |
} |
} |
if (inputs & VERT_BIT_NORMAL) { |
req |= RADEON_CP_VC_FRMT_N0; |
} |
if (inputs & VERT_BIT_COLOR0) { |
req |= RADEON_CP_VC_FRMT_PKCOLOR; |
} |
if (inputs & (VERT_BIT_COLOR1|VERT_BIT_FOG)) { |
req |= RADEON_CP_VC_FRMT_PKSPEC; |
} |
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { |
if (inputs & VERT_BIT_TEX(unit)) { |
req |= RADEON_ST_BIT(unit); |
/* assume we need the 3rd coord if texgen is active for r/q OR at least |
3 coords are submitted. This may not be 100% correct */ |
if (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) { |
req |= RADEON_Q_BIT(unit); |
vtx |= RADEON_Q_BIT(unit); |
} |
if ( (ctx->Texture.Unit[unit].TexGenEnabled & (R_BIT | Q_BIT)) ) |
vtx |= RADEON_Q_BIT(unit); |
else if ((VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) && |
((ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_CUBE_BIT)) == 0)) { |
GLuint swaptexmatcol = (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size - 3); |
if (((rmesa->NeedTexMatrix >> unit) & 1) && |
(swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1))) |
radeonUploadTexMatrix( rmesa, unit, swaptexmatcol ) ; |
} |
} |
} |
if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) { |
RADEON_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx; |
} |
for (i = 0 ; i < RADEON_TCL_MAX_SETUP ; i++) |
if ((setup_tab[i].vertex_format & req) == req) |
break; |
if (rmesa->tcl.vertex_format == setup_tab[i].vertex_format && |
rmesa->radeon.tcl.aos[0].bo) |
return; |
if (rmesa->radeon.tcl.aos[0].bo) |
radeonReleaseArrays( ctx, ~0 ); |
radeonAllocDmaRegion( &rmesa->radeon, |
&rmesa->radeon.tcl.aos[0].bo, |
&rmesa->radeon.tcl.aos[0].offset, |
VB->Count * setup_tab[i].vertex_size * 4, |
4); |
/* The vertex code expects Obj to be clean to element 3. To fix |
* this, add more vertex code (for obj-2, obj-3) or preferably move |
* to maos. |
*/ |
if (VB->AttribPtr[_TNL_ATTRIB_POS]->size < 3 || |
(VB->AttribPtr[_TNL_ATTRIB_POS]->size == 3 && |
(setup_tab[i].vertex_format & RADEON_CP_VC_FRMT_W0))) { |
_math_trans_4f( rmesa->tcl.ObjClean.data, |
VB->AttribPtr[_TNL_ATTRIB_POS]->data, |
VB->AttribPtr[_TNL_ATTRIB_POS]->stride, |
GL_FLOAT, |
VB->AttribPtr[_TNL_ATTRIB_POS]->size, |
0, |
VB->Count ); |
switch (VB->AttribPtr[_TNL_ATTRIB_POS]->size) { |
case 1: |
_mesa_vector4f_clean_elem(&rmesa->tcl.ObjClean, VB->Count, 1); |
case 2: |
_mesa_vector4f_clean_elem(&rmesa->tcl.ObjClean, VB->Count, 2); |
case 3: |
if (setup_tab[i].vertex_format & RADEON_CP_VC_FRMT_W0) { |
_mesa_vector4f_clean_elem(&rmesa->tcl.ObjClean, VB->Count, 3); |
} |
case 4: |
default: |
break; |
} |
VB->AttribPtr[_TNL_ATTRIB_POS] = &rmesa->tcl.ObjClean; |
} |
radeon_bo_map(rmesa->radeon.tcl.aos[0].bo, 1); |
setup_tab[i].emit( ctx, 0, VB->Count, |
rmesa->radeon.tcl.aos[0].bo->ptr + rmesa->radeon.tcl.aos[0].offset); |
radeon_bo_unmap(rmesa->radeon.tcl.aos[0].bo); |
// rmesa->radeon.tcl.aos[0].size = setup_tab[i].vertex_size; |
rmesa->radeon.tcl.aos[0].stride = setup_tab[i].vertex_size; |
rmesa->tcl.vertex_format = setup_tab[i].vertex_format; |
rmesa->radeon.tcl.aos_count = 1; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.c |
---|
0,0 → 1,580 |
/* |
* Copyright (C) 2009 Maciej Cencora. |
* Copyright (C) 2008 Nicolai Haehnle. |
* |
* 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, 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 COPYRIGHT OWNER(S) 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 "radeon_mipmap_tree.h" |
#include <errno.h> |
#include <unistd.h> |
#include "main/simple_list.h" |
#include "main/teximage.h" |
#include "main/texobj.h" |
#include "main/enums.h" |
#include "radeon_texture.h" |
#include "radeon_tile.h" |
static unsigned get_aligned_compressed_row_stride( |
gl_format format, |
unsigned width, |
unsigned minStride) |
{ |
const unsigned blockBytes = _mesa_get_format_bytes(format); |
unsigned blockWidth, blockHeight; |
unsigned stride; |
_mesa_get_format_block_size(format, &blockWidth, &blockHeight); |
/* Count number of blocks required to store the given width. |
* And then multiple it with bytes required to store a block. |
*/ |
stride = (width + blockWidth - 1) / blockWidth * blockBytes; |
/* Round the given minimum stride to the next full blocksize. |
* (minStride + blockBytes - 1) / blockBytes * blockBytes |
*/ |
if ( stride < minStride ) |
stride = (minStride + blockBytes - 1) / blockBytes * blockBytes; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s width %u, minStride %u, block(bytes %u, width %u):" |
"stride %u\n", |
__func__, width, minStride, |
blockBytes, blockWidth, |
stride); |
return stride; |
} |
unsigned get_texture_image_size( |
gl_format format, |
unsigned rowStride, |
unsigned height, |
unsigned depth, |
unsigned tiling) |
{ |
if (_mesa_is_format_compressed(format)) { |
unsigned blockWidth, blockHeight; |
_mesa_get_format_block_size(format, &blockWidth, &blockHeight); |
return rowStride * ((height + blockHeight - 1) / blockHeight) * depth; |
} else if (tiling) { |
/* Need to align height to tile height */ |
unsigned tileWidth, tileHeight; |
get_tile_size(format, &tileWidth, &tileHeight); |
tileHeight--; |
height = (height + tileHeight) & ~tileHeight; |
} |
return rowStride * height * depth; |
} |
unsigned get_texture_image_row_stride(radeonContextPtr rmesa, gl_format format, unsigned width, unsigned tiling, GLuint target) |
{ |
if (_mesa_is_format_compressed(format)) { |
return get_aligned_compressed_row_stride(format, width, rmesa->texture_compressed_row_align); |
} else { |
unsigned row_align; |
if (!_mesa_is_pow_two(width) || target == GL_TEXTURE_RECTANGLE) { |
row_align = rmesa->texture_rect_row_align - 1; |
} else if (tiling) { |
unsigned tileWidth, tileHeight; |
get_tile_size(format, &tileWidth, &tileHeight); |
row_align = tileWidth * _mesa_get_format_bytes(format) - 1; |
} else { |
row_align = rmesa->texture_row_align - 1; |
} |
return (_mesa_format_row_stride(format, width) + row_align) & ~row_align; |
} |
} |
/** |
* Compute sizes and fill in offset and blit information for the given |
* image (determined by \p face and \p level). |
* |
* \param curOffset points to the offset at which the image is to be stored |
* and is updated by this function according to the size of the image. |
*/ |
static void compute_tex_image_offset(radeonContextPtr rmesa, radeon_mipmap_tree *mt, |
GLuint face, GLuint level, GLuint* curOffset) |
{ |
radeon_mipmap_level *lvl = &mt->levels[level]; |
GLuint height; |
height = _mesa_next_pow_two_32(lvl->height); |
lvl->rowstride = get_texture_image_row_stride(rmesa, mt->mesaFormat, lvl->width, mt->tilebits, mt->target); |
lvl->size = get_texture_image_size(mt->mesaFormat, lvl->rowstride, height, lvl->depth, mt->tilebits); |
assert(lvl->size > 0); |
lvl->faces[face].offset = *curOffset; |
*curOffset += lvl->size; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(%p) level %d, face %d: rs:%d %dx%d at %d\n", |
__func__, rmesa, |
level, face, |
lvl->rowstride, lvl->width, height, lvl->faces[face].offset); |
} |
static void calculate_miptree_layout(radeonContextPtr rmesa, radeon_mipmap_tree *mt) |
{ |
GLuint curOffset, i, face, level; |
assert(mt->numLevels <= rmesa->glCtx.Const.MaxTextureLevels); |
curOffset = 0; |
for(face = 0; face < mt->faces; face++) { |
for(i = 0, level = mt->baseLevel; i < mt->numLevels; i++, level++) { |
mt->levels[level].valid = 1; |
mt->levels[level].width = minify(mt->width0, i); |
mt->levels[level].height = minify(mt->height0, i); |
mt->levels[level].depth = minify(mt->depth0, i); |
compute_tex_image_offset(rmesa, mt, face, level, &curOffset); |
} |
} |
/* Note the required size in memory */ |
mt->totalsize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(%p, %p) total size %d\n", |
__func__, rmesa, mt, mt->totalsize); |
} |
/** |
* Create a new mipmap tree, calculate its layout and allocate memory. |
*/ |
radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, |
GLenum target, gl_format mesaFormat, GLuint baseLevel, GLuint numLevels, |
GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits) |
{ |
radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree); |
radeon_print(RADEON_TEXTURE, RADEON_NORMAL, |
"%s(%p) new tree is %p.\n", |
__func__, rmesa, mt); |
mt->mesaFormat = mesaFormat; |
mt->refcount = 1; |
mt->target = target; |
mt->faces = _mesa_num_tex_faces(target); |
mt->baseLevel = baseLevel; |
mt->numLevels = numLevels; |
mt->width0 = width0; |
mt->height0 = height0; |
mt->depth0 = depth0; |
mt->tilebits = tilebits; |
calculate_miptree_layout(rmesa, mt); |
mt->bo = radeon_bo_open(rmesa->radeonScreen->bom, |
0, mt->totalsize, 1024, |
RADEON_GEM_DOMAIN_VRAM, |
0); |
return mt; |
} |
void radeon_miptree_reference(radeon_mipmap_tree *mt, radeon_mipmap_tree **ptr) |
{ |
assert(!*ptr); |
mt->refcount++; |
assert(mt->refcount > 0); |
*ptr = mt; |
} |
void radeon_miptree_unreference(radeon_mipmap_tree **ptr) |
{ |
radeon_mipmap_tree *mt = *ptr; |
if (!mt) |
return; |
assert(mt->refcount > 0); |
mt->refcount--; |
if (!mt->refcount) { |
radeon_bo_unref(mt->bo); |
free(mt); |
} |
*ptr = 0; |
} |
/** |
* Calculate min and max LOD for the given texture object. |
* @param[in] tObj texture object whose LOD values to calculate |
* @param[out] pminLod minimal LOD |
* @param[out] pmaxLod maximal LOD |
*/ |
static void calculate_min_max_lod(struct gl_sampler_object *samp, struct gl_texture_object *tObj, |
unsigned *pminLod, unsigned *pmaxLod) |
{ |
int minLod, maxLod; |
/* Yes, this looks overly complicated, but it's all needed. |
*/ |
switch (tObj->Target) { |
case GL_TEXTURE_1D: |
case GL_TEXTURE_2D: |
case GL_TEXTURE_3D: |
case GL_TEXTURE_CUBE_MAP: |
if (samp->MinFilter == GL_NEAREST || samp->MinFilter == GL_LINEAR) { |
/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. |
*/ |
minLod = maxLod = tObj->BaseLevel; |
} else { |
minLod = tObj->BaseLevel + (GLint)(samp->MinLod); |
minLod = MAX2(minLod, tObj->BaseLevel); |
minLod = MIN2(minLod, tObj->MaxLevel); |
maxLod = tObj->BaseLevel + (GLint)(samp->MaxLod + 0.5); |
maxLod = MIN2(maxLod, tObj->MaxLevel); |
maxLod = MIN2(maxLod, tObj->Image[0][minLod]->MaxNumLevels - 1 + minLod); |
maxLod = MAX2(maxLod, minLod); /* need at least one level */ |
} |
break; |
case GL_TEXTURE_RECTANGLE_NV: |
case GL_TEXTURE_4D_SGIS: |
minLod = maxLod = 0; |
break; |
default: |
return; |
} |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s(%p) target %s, min %d, max %d.\n", |
__func__, tObj, |
_mesa_lookup_enum_by_nr(tObj->Target), |
minLod, maxLod); |
/* save these values */ |
*pminLod = minLod; |
*pmaxLod = maxLod; |
} |
/** |
* Checks whether the given miptree can hold the given texture image at the |
* given face and level. |
*/ |
GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt, |
struct gl_texture_image *texImage) |
{ |
radeon_mipmap_level *lvl; |
GLuint level = texImage->Level; |
if (texImage->TexFormat != mt->mesaFormat) |
return GL_FALSE; |
lvl = &mt->levels[level]; |
if (!lvl->valid || |
lvl->width != texImage->Width || |
lvl->height != texImage->Height || |
lvl->depth != texImage->Depth) |
return GL_FALSE; |
return GL_TRUE; |
} |
/** |
* Checks whether the given miptree has the right format to store the given texture object. |
*/ |
static GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj) |
{ |
struct gl_texture_image *firstImage; |
unsigned numLevels; |
radeon_mipmap_level *mtBaseLevel; |
if (texObj->BaseLevel < mt->baseLevel) |
return GL_FALSE; |
mtBaseLevel = &mt->levels[texObj->BaseLevel - mt->baseLevel]; |
firstImage = texObj->Image[0][texObj->BaseLevel]; |
numLevels = MIN2(texObj->_MaxLevel - texObj->BaseLevel + 1, firstImage->MaxNumLevels); |
if (radeon_is_debug_enabled(RADEON_TEXTURE,RADEON_TRACE)) { |
fprintf(stderr, "Checking if miptree %p matches texObj %p\n", mt, texObj); |
fprintf(stderr, "target %d vs %d\n", mt->target, texObj->Target); |
fprintf(stderr, "format %d vs %d\n", mt->mesaFormat, firstImage->TexFormat); |
fprintf(stderr, "numLevels %d vs %d\n", mt->numLevels, numLevels); |
fprintf(stderr, "width0 %d vs %d\n", mtBaseLevel->width, firstImage->Width); |
fprintf(stderr, "height0 %d vs %d\n", mtBaseLevel->height, firstImage->Height); |
fprintf(stderr, "depth0 %d vs %d\n", mtBaseLevel->depth, firstImage->Depth); |
if (mt->target == texObj->Target && |
mt->mesaFormat == firstImage->TexFormat && |
mt->numLevels >= numLevels && |
mtBaseLevel->width == firstImage->Width && |
mtBaseLevel->height == firstImage->Height && |
mtBaseLevel->depth == firstImage->Depth) { |
fprintf(stderr, "MATCHED\n"); |
} else { |
fprintf(stderr, "NOT MATCHED\n"); |
} |
} |
return (mt->target == texObj->Target && |
mt->mesaFormat == firstImage->TexFormat && |
mt->numLevels >= numLevels && |
mtBaseLevel->width == firstImage->Width && |
mtBaseLevel->height == firstImage->Height && |
mtBaseLevel->depth == firstImage->Depth); |
} |
/** |
* Try to allocate a mipmap tree for the given texture object. |
* @param[in] rmesa radeon context |
* @param[in] t radeon texture object |
*/ |
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t) |
{ |
struct gl_texture_object *texObj = &t->base; |
struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel]; |
GLuint numLevels; |
assert(!t->mt); |
if (!texImg) { |
radeon_warning("%s(%p) No image in given texture object(%p).\n", |
__func__, rmesa, t); |
return; |
} |
numLevels = MIN2(texObj->MaxLevel - texObj->BaseLevel + 1, texImg->MaxNumLevels); |
t->mt = radeon_miptree_create(rmesa, t->base.Target, |
texImg->TexFormat, texObj->BaseLevel, |
numLevels, texImg->Width, texImg->Height, |
texImg->Depth, t->tile_bits); |
} |
GLuint |
radeon_miptree_image_offset(radeon_mipmap_tree *mt, |
GLuint face, GLuint level) |
{ |
if (mt->target == GL_TEXTURE_CUBE_MAP_ARB) |
return (mt->levels[level].faces[face].offset); |
else |
return mt->levels[level].faces[0].offset; |
} |
/** |
* Ensure that the given image is stored in the given miptree from now on. |
*/ |
static void migrate_image_to_miptree(radeon_mipmap_tree *mt, |
radeon_texture_image *image, |
int face, int level) |
{ |
radeon_mipmap_level *dstlvl = &mt->levels[level]; |
unsigned char *dest; |
assert(image->mt != mt); |
assert(dstlvl->valid); |
assert(dstlvl->width == image->base.Base.Width); |
assert(dstlvl->height == image->base.Base.Height); |
assert(dstlvl->depth == image->base.Base.Depth); |
radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, |
"%s miptree %p, image %p, face %d, level %d.\n", |
__func__, mt, image, face, level); |
radeon_bo_map(mt->bo, GL_TRUE); |
dest = mt->bo->ptr + dstlvl->faces[face].offset; |
if (image->mt) { |
/* Format etc. should match, so we really just need a memcpy(). |
* In fact, that memcpy() could be done by the hardware in many |
* cases, provided that we have a proper memory manager. |
*/ |
assert(mt->mesaFormat == image->base.Base.TexFormat); |
radeon_mipmap_level *srclvl = &image->mt->levels[image->base.Base.Level]; |
assert(image->base.Base.Level == level); |
assert(srclvl->size == dstlvl->size); |
assert(srclvl->rowstride == dstlvl->rowstride); |
radeon_bo_map(image->mt->bo, GL_FALSE); |
memcpy(dest, |
image->mt->bo->ptr + srclvl->faces[face].offset, |
dstlvl->size); |
radeon_bo_unmap(image->mt->bo); |
radeon_miptree_unreference(&image->mt); |
} |
radeon_bo_unmap(mt->bo); |
radeon_miptree_reference(mt, &image->mt); |
} |
/** |
* Filter matching miptrees, and select one with the most of data. |
* @param[in] texObj radeon texture object |
* @param[in] firstLevel first texture level to check |
* @param[in] lastLevel last texture level to check |
*/ |
static radeon_mipmap_tree * get_biggest_matching_miptree(radeonTexObj *texObj, |
unsigned firstLevel, |
unsigned lastLevel) |
{ |
const unsigned numLevels = lastLevel - firstLevel + 1; |
unsigned *mtSizes = calloc(numLevels, sizeof(unsigned)); |
radeon_mipmap_tree **mts = calloc(numLevels, sizeof(radeon_mipmap_tree *)); |
unsigned mtCount = 0; |
unsigned maxMtIndex = 0; |
radeon_mipmap_tree *tmp; |
unsigned int level; |
int i; |
for (level = firstLevel; level <= lastLevel; ++level) { |
radeon_texture_image *img = get_radeon_texture_image(texObj->base.Image[0][level]); |
unsigned found = 0; |
// TODO: why this hack?? |
if (!img) |
break; |
if (!img->mt) |
continue; |
for (i = 0; i < mtCount; ++i) { |
if (mts[i] == img->mt) { |
found = 1; |
mtSizes[i] += img->mt->levels[img->base.Base.Level].size; |
break; |
} |
} |
if (!found && radeon_miptree_matches_texture(img->mt, &texObj->base)) { |
mtSizes[mtCount] = img->mt->levels[img->base.Base.Level].size; |
mts[mtCount] = img->mt; |
mtCount++; |
} |
} |
if (mtCount == 0) { |
free(mtSizes); |
free(mts); |
return NULL; |
} |
for (i = 1; i < mtCount; ++i) { |
if (mtSizes[i] > mtSizes[maxMtIndex]) { |
maxMtIndex = i; |
} |
} |
tmp = mts[maxMtIndex]; |
free(mtSizes); |
free(mts); |
return tmp; |
} |
/** |
* Validate texture mipmap tree. |
* If individual images are stored in different mipmap trees |
* use the mipmap tree that has the most of the correct data. |
*/ |
int radeon_validate_texture_miptree(struct gl_context * ctx, |
struct gl_sampler_object *samp, |
struct gl_texture_object *texObj) |
{ |
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
radeonTexObj *t = radeon_tex_obj(texObj); |
radeon_mipmap_tree *dst_miptree; |
if (samp == &texObj->Sampler && (t->validated || t->image_override)) { |
return GL_TRUE; |
} |
calculate_min_max_lod(samp, &t->base, &t->minLod, &t->maxLod); |
radeon_print(RADEON_TEXTURE, RADEON_NORMAL, |
"%s: Validating texture %p now, minLod = %d, maxLod = %d\n", |
__FUNCTION__, texObj ,t->minLod, t->maxLod); |
dst_miptree = get_biggest_matching_miptree(t, t->base.BaseLevel, t->base._MaxLevel); |
radeon_miptree_unreference(&t->mt); |
if (!dst_miptree) { |
radeon_try_alloc_miptree(rmesa, t); |
radeon_print(RADEON_TEXTURE, RADEON_NORMAL, |
"%s: No matching miptree found, allocated new one %p\n", |
__FUNCTION__, t->mt); |
} else { |
radeon_miptree_reference(dst_miptree, &t->mt); |
radeon_print(RADEON_TEXTURE, RADEON_NORMAL, |
"%s: Using miptree %p\n", __FUNCTION__, t->mt); |
} |
const unsigned faces = _mesa_num_tex_faces(texObj->Target); |
unsigned face, level; |
radeon_texture_image *img; |
/* Validate only the levels that will actually be used during rendering */ |
for (face = 0; face < faces; ++face) { |
for (level = t->minLod; level <= t->maxLod; ++level) { |
img = get_radeon_texture_image(texObj->Image[face][level]); |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"Checking image level %d, face %d, mt %p ... ", |
level, face, img->mt); |
if (img->mt != t->mt && !img->used_as_render_target) { |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"MIGRATING\n"); |
struct radeon_bo *src_bo = (img->mt) ? img->mt->bo : img->bo; |
if (src_bo && radeon_bo_is_referenced_by_cs(src_bo, rmesa->cmdbuf.cs)) { |
radeon_firevertices(rmesa); |
} |
migrate_image_to_miptree(t->mt, img, face, level); |
} else |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, "OK\n"); |
} |
} |
t->validated = GL_TRUE; |
return GL_TRUE; |
} |
uint32_t get_base_teximage_offset(radeonTexObj *texObj) |
{ |
if (!texObj->mt) { |
return 0; |
} else { |
return radeon_miptree_image_offset(texObj->mt, 0, texObj->minLod); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_mipmap_tree.h |
---|
0,0 → 1,106 |
/* |
* Copyright (C) 2008 Nicolai Haehnle. |
* |
* 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, 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 COPYRIGHT OWNER(S) 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 __RADEON_MIPMAP_TREE_H_ |
#define __RADEON_MIPMAP_TREE_H_ |
#include "radeon_common.h" |
typedef struct _radeon_mipmap_tree radeon_mipmap_tree; |
typedef struct _radeon_mipmap_level radeon_mipmap_level; |
typedef struct _radeon_mipmap_image radeon_mipmap_image; |
struct _radeon_mipmap_image { |
GLuint offset; /** Offset of this image from the start of mipmap tree buffer, in bytes */ |
}; |
struct _radeon_mipmap_level { |
GLuint width; |
GLuint height; |
GLuint depth; |
GLuint size; /** Size of each image, in bytes */ |
GLuint rowstride; /** in bytes */ |
GLuint valid; |
radeon_mipmap_image faces[6]; |
}; |
/* store the max possible in the miptree */ |
#define RADEON_MIPTREE_MAX_TEXTURE_LEVELS 15 |
/** |
* A mipmap tree contains texture images in the layout that the hardware |
* expects. |
* |
* The meta-data of mipmap trees is immutable, i.e. you cannot change the |
* layout on-the-fly; however, the texture contents (i.e. texels) can be |
* changed. |
*/ |
struct _radeon_mipmap_tree { |
struct radeon_bo *bo; |
GLuint refcount; |
GLuint totalsize; /** total size of the miptree, in bytes */ |
GLenum target; /** GL_TEXTURE_xxx */ |
GLenum mesaFormat; /** MESA_FORMAT_xxx */ |
GLuint faces; /** # of faces: 6 for cubemaps, 1 otherwise */ |
GLuint baseLevel; /** gl_texture_object->baseLevel it was created for */ |
GLuint numLevels; /** Number of mip levels stored in this mipmap tree */ |
GLuint width0; /** Width of baseLevel image */ |
GLuint height0; /** Height of baseLevel image */ |
GLuint depth0; /** Depth of baseLevel image */ |
GLuint tilebits; /** RADEON_TXO_xxx_TILE */ |
radeon_mipmap_level levels[RADEON_MIPTREE_MAX_TEXTURE_LEVELS]; |
}; |
void radeon_miptree_reference(radeon_mipmap_tree *mt, radeon_mipmap_tree **ptr); |
void radeon_miptree_unreference(radeon_mipmap_tree **ptr); |
GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt, |
struct gl_texture_image *texImage); |
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t); |
GLuint radeon_miptree_image_offset(radeon_mipmap_tree *mt, |
GLuint face, GLuint level); |
uint32_t get_base_teximage_offset(radeonTexObj *texObj); |
unsigned get_texture_image_row_stride(radeonContextPtr rmesa, gl_format format, unsigned width, unsigned tiling, unsigned target); |
unsigned get_texture_image_size( |
gl_format format, |
unsigned rowStride, |
unsigned height, |
unsigned depth, |
unsigned tiling); |
radeon_mipmap_tree *radeon_miptree_create(radeonContextPtr rmesa, |
GLenum target, gl_format mesaFormat, GLuint baseLevel, GLuint numLevels, |
GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits); |
#endif /* __RADEON_MIPMAP_TREE_H_ */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_pixel_read.c |
---|
0,0 → 1,221 |
/* |
* Copyright (C) 2010 Maciej Cencora <m.cencora@gmail.com> |
* |
* 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, 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 COPYRIGHT OWNER(S) 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 "stdint.h" |
#include "main/bufferobj.h" |
#include "main/enums.h" |
#include "main/fbobject.h" |
#include "main/image.h" |
#include "main/readpix.h" |
#include "main/state.h" |
#include "radeon_buffer_objects.h" |
#include "radeon_common_context.h" |
#include "radeon_debug.h" |
#include "radeon_mipmap_tree.h" |
static gl_format gl_format_and_type_to_mesa_format(GLenum format, GLenum type) |
{ |
switch (format) |
{ |
case GL_RGB: |
switch (type) { |
case GL_UNSIGNED_SHORT_5_6_5: |
return MESA_FORMAT_RGB565; |
case GL_UNSIGNED_SHORT_5_6_5_REV: |
return MESA_FORMAT_RGB565_REV; |
} |
break; |
case GL_RGBA: |
switch (type) { |
case GL_FLOAT: |
return MESA_FORMAT_RGBA_FLOAT32; |
case GL_UNSIGNED_SHORT_5_5_5_1: |
return MESA_FORMAT_RGBA5551; |
case GL_UNSIGNED_INT_8_8_8_8: |
return MESA_FORMAT_RGBA8888; |
case GL_UNSIGNED_BYTE: |
case GL_UNSIGNED_INT_8_8_8_8_REV: |
return MESA_FORMAT_RGBA8888_REV; |
} |
break; |
case GL_BGRA: |
switch (type) { |
case GL_UNSIGNED_SHORT_4_4_4_4: |
return MESA_FORMAT_ARGB4444_REV; |
case GL_UNSIGNED_SHORT_4_4_4_4_REV: |
return MESA_FORMAT_ARGB4444; |
case GL_UNSIGNED_SHORT_5_5_5_1: |
return MESA_FORMAT_ARGB1555_REV; |
case GL_UNSIGNED_SHORT_1_5_5_5_REV: |
return MESA_FORMAT_ARGB1555; |
case GL_UNSIGNED_INT_8_8_8_8: |
return MESA_FORMAT_ARGB8888_REV; |
case GL_UNSIGNED_BYTE: |
case GL_UNSIGNED_INT_8_8_8_8_REV: |
return MESA_FORMAT_ARGB8888; |
} |
break; |
} |
return MESA_FORMAT_NONE; |
} |
static GLboolean |
do_blit_readpixels(struct gl_context * ctx, |
GLint x, GLint y, GLsizei width, GLsizei height, |
GLenum format, GLenum type, |
const struct gl_pixelstore_attrib *pack, GLvoid * pixels) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
const struct radeon_renderbuffer *rrb = radeon_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer); |
const gl_format dst_format = gl_format_and_type_to_mesa_format(format, type); |
unsigned dst_rowstride, dst_imagesize, aligned_rowstride, flip_y; |
struct radeon_bo *dst_buffer; |
GLint dst_x = 0, dst_y = 0; |
intptr_t dst_offset; |
/* It's not worth if number of pixels to copy is really small */ |
if (width * height < 100) { |
return GL_FALSE; |
} |
if (dst_format == MESA_FORMAT_NONE || |
!radeon->vtbl.check_blit(dst_format, rrb->pitch / rrb->cpp) || !radeon->vtbl.blit) { |
return GL_FALSE; |
} |
if (ctx->_ImageTransferState || ctx->Color.ColorLogicOpEnabled) { |
return GL_FALSE; |
} |
if (pack->SwapBytes || pack->LsbFirst) { |
return GL_FALSE; |
} |
if (pack->RowLength > 0) { |
dst_rowstride = pack->RowLength; |
} else { |
dst_rowstride = width; |
} |
if (!_mesa_clip_copytexsubimage(ctx, &dst_x, &dst_y, &x, &y, &width, &height)) { |
return GL_TRUE; |
} |
assert(x >= 0 && y >= 0); |
aligned_rowstride = get_texture_image_row_stride(radeon, dst_format, dst_rowstride, 0, GL_TEXTURE_2D); |
dst_rowstride *= _mesa_get_format_bytes(dst_format); |
if (_mesa_is_bufferobj(pack->BufferObj) && aligned_rowstride != dst_rowstride) |
return GL_FALSE; |
dst_imagesize = get_texture_image_size(dst_format, |
aligned_rowstride, |
height, 1, 0); |
if (!_mesa_is_bufferobj(pack->BufferObj)) |
{ |
dst_buffer = radeon_bo_open(radeon->radeonScreen->bom, 0, dst_imagesize, 1024, RADEON_GEM_DOMAIN_GTT, 0); |
dst_offset = 0; |
} |
else |
{ |
dst_buffer = get_radeon_buffer_object(pack->BufferObj)->bo; |
dst_offset = (intptr_t)pixels; |
} |
/* Disable source Y flipping for FBOs */ |
flip_y = _mesa_is_winsys_fbo(ctx->ReadBuffer); |
if (pack->Invert) { |
y = rrb->base.Base.Height - height - y; |
flip_y = !flip_y; |
} |
if (radeon->vtbl.blit(ctx, |
rrb->bo, |
rrb->draw_offset, |
rrb->base.Base.Format, |
rrb->pitch / rrb->cpp, |
rrb->base.Base.Width, |
rrb->base.Base.Height, |
x, |
y, |
dst_buffer, |
dst_offset, |
dst_format, |
aligned_rowstride / _mesa_get_format_bytes(dst_format), |
width, |
height, |
0, /* dst_x */ |
0, /* dst_y */ |
width, |
height, |
flip_y)) |
{ |
if (!_mesa_is_bufferobj(pack->BufferObj)) |
{ |
radeon_bo_map(dst_buffer, 0); |
copy_rows(pixels, dst_rowstride, dst_buffer->ptr, |
aligned_rowstride, height, dst_rowstride); |
radeon_bo_unmap(dst_buffer); |
radeon_bo_unref(dst_buffer); |
} |
return GL_TRUE; |
} |
if (!_mesa_is_bufferobj(pack->BufferObj)) |
radeon_bo_unref(dst_buffer); |
return GL_FALSE; |
} |
void |
radeonReadPixels(struct gl_context * ctx, |
GLint x, GLint y, GLsizei width, GLsizei height, |
GLenum format, GLenum type, |
const struct gl_pixelstore_attrib *pack, GLvoid * pixels) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
radeon_prepare_render(radeon); |
if (do_blit_readpixels(ctx, x, y, width, height, format, type, pack, pixels)) |
return; |
/* Update Mesa state before calling _mesa_readpixels(). |
* XXX this may not be needed since ReadPixels no longer uses the |
* span code. |
*/ |
radeon_print(RADEON_FALLBACKS, RADEON_NORMAL, |
"Falling back to sw for ReadPixels (format %s, type %s)\n", |
_mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); |
if (ctx->NewState) |
_mesa_update_state(ctx); |
_mesa_readpixels(ctx, x, y, width, height, format, type, pack, pixels); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_queryobj.c |
---|
0,0 → 1,217 |
/* |
* Copyright © 2008-2009 Maciej Cencora <m.cencora@gmail.com> |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, 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. |
* |
* Authors: |
* Maciej Cencora <m.cencora@gmail.com> |
* |
*/ |
#include "radeon_common.h" |
#include "radeon_queryobj.h" |
#include "radeon_debug.h" |
#include "main/imports.h" |
#include "main/simple_list.h" |
#include <inttypes.h> |
static void radeonQueryGetResult(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct radeon_query_object *query = (struct radeon_query_object *)q; |
uint32_t *result; |
int i; |
radeon_print(RADEON_STATE, RADEON_VERBOSE, |
"%s: query id %d, result %d\n", |
__FUNCTION__, query->Base.Id, (int) query->Base.Result); |
radeon_bo_map(query->bo, GL_FALSE); |
result = query->bo->ptr; |
query->Base.Result = 0; |
for (i = 0; i < query->curr_offset/sizeof(uint32_t); ++i) { |
query->Base.Result += LE32_TO_CPU(result[i]); |
radeon_print(RADEON_STATE, RADEON_TRACE, "result[%d] = %d\n", i, LE32_TO_CPU(result[i])); |
} |
radeon_bo_unmap(query->bo); |
} |
static struct gl_query_object * radeonNewQueryObject(struct gl_context *ctx, GLuint id) |
{ |
struct radeon_query_object *query; |
query = calloc(1, sizeof(struct radeon_query_object)); |
query->Base.Id = id; |
query->Base.Result = 0; |
query->Base.Active = GL_FALSE; |
query->Base.Ready = GL_TRUE; |
radeon_print(RADEON_STATE, RADEON_VERBOSE,"%s: query id %d\n", __FUNCTION__, query->Base.Id); |
return &query->Base; |
} |
static void radeonDeleteQuery(struct gl_context *ctx, struct gl_query_object *q) |
{ |
struct radeon_query_object *query = (struct radeon_query_object *)q; |
radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d\n", __FUNCTION__, q->Id); |
if (query->bo) { |
radeon_bo_unref(query->bo); |
} |
free(query); |
} |
static void radeonWaitQuery(struct gl_context *ctx, struct gl_query_object *q) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
struct radeon_query_object *query = (struct radeon_query_object *)q; |
/* If the cmdbuf with packets for this query hasn't been flushed yet, do it now */ |
if (radeon_bo_is_referenced_by_cs(query->bo, radeon->cmdbuf.cs)) |
ctx->Driver.Flush(ctx); |
radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, q->Id, query->bo, query->curr_offset); |
radeonQueryGetResult(ctx, q); |
query->Base.Ready = GL_TRUE; |
} |
static void radeonBeginQuery(struct gl_context *ctx, struct gl_query_object *q) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
struct radeon_query_object *query = (struct radeon_query_object *)q; |
radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d\n", __FUNCTION__, q->Id); |
assert(radeon->query.current == NULL); |
if (radeon->dma.flush) |
radeon->dma.flush(&radeon->glCtx); |
if (!query->bo) { |
query->bo = radeon_bo_open(radeon->radeonScreen->bom, 0, RADEON_QUERY_PAGE_SIZE, RADEON_QUERY_PAGE_SIZE, RADEON_GEM_DOMAIN_GTT, 0); |
} |
query->curr_offset = 0; |
radeon->query.current = query; |
radeon->query.queryobj.dirty = GL_TRUE; |
radeon->hw.is_dirty = GL_TRUE; |
} |
void radeonEmitQueryEnd(struct gl_context *ctx) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
struct radeon_query_object *query = radeon->query.current; |
if (!query) |
return; |
if (query->emitted_begin == GL_FALSE) |
return; |
radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, query->Base.Id, query->bo, query->curr_offset); |
radeon_cs_space_check_with_bo(radeon->cmdbuf.cs, |
query->bo, |
0, RADEON_GEM_DOMAIN_GTT); |
radeon->vtbl.emit_query_finish(radeon); |
} |
static void radeonEndQuery(struct gl_context *ctx, struct gl_query_object *q) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
radeon_print(RADEON_STATE, RADEON_NORMAL, "%s: query id %d\n", __FUNCTION__, q->Id); |
if (radeon->dma.flush) |
radeon->dma.flush(&radeon->glCtx); |
radeonEmitQueryEnd(ctx); |
radeon->query.current = NULL; |
} |
static void radeonCheckQuery(struct gl_context *ctx, struct gl_query_object *q) |
{ |
radeon_print(RADEON_STATE, RADEON_TRACE, "%s: query id %d\n", __FUNCTION__, q->Id); |
\ |
#ifdef DRM_RADEON_GEM_BUSY |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
struct radeon_query_object *query = (struct radeon_query_object *)q; |
uint32_t domain; |
/* Need to perform a flush, as per ARB_occlusion_query spec */ |
if (radeon_bo_is_referenced_by_cs(query->bo, radeon->cmdbuf.cs)) { |
ctx->Driver.Flush(ctx); |
} |
if (radeon_bo_is_busy(query->bo, &domain) == 0) { |
radeonQueryGetResult(ctx, q); |
query->Base.Ready = GL_TRUE; |
} |
#else |
radeonWaitQuery(ctx, q); |
#endif |
} |
void radeonInitQueryObjFunctions(struct dd_function_table *functions) |
{ |
functions->NewQueryObject = radeonNewQueryObject; |
functions->DeleteQuery = radeonDeleteQuery; |
functions->BeginQuery = radeonBeginQuery; |
functions->EndQuery = radeonEndQuery; |
functions->CheckQuery = radeonCheckQuery; |
functions->WaitQuery = radeonWaitQuery; |
} |
int radeon_check_query_active(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
struct radeon_query_object *query = radeon->query.current; |
if (!query || query->emitted_begin) |
return 0; |
return atom->cmd_size; |
} |
void radeon_emit_queryobj(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
BATCH_LOCALS(radeon); |
int dwords; |
dwords = (*atom->check) (ctx, atom); |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_BATCH_TABLE(atom->cmd, dwords); |
END_BATCH(); |
radeon->query.current->emitted_begin = GL_TRUE; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_queryobj.h |
---|
0,0 → 1,55 |
/* |
* Copyright © 2008 Maciej Cencora <m.cencora@gmail.com> |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, 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. |
* |
* Authors: |
* Maciej Cencora <m.cencora@gmail.com> |
* |
*/ |
#include "main/imports.h" |
#include "main/simple_list.h" |
#include "radeon_common_context.h" |
extern void radeonEmitQueryBegin(struct gl_context *ctx); |
extern void radeonEmitQueryEnd(struct gl_context *ctx); |
extern void radeonInitQueryObjFunctions(struct dd_function_table *functions); |
#define RADEON_QUERY_PAGE_SIZE 4096 |
int radeon_check_query_active(struct gl_context *ctx, struct radeon_state_atom *atom); |
void radeon_emit_queryobj(struct gl_context *ctx, struct radeon_state_atom *atom); |
static inline void radeon_init_query_stateobj(radeonContextPtr radeon, int SZ) |
{ |
radeon->query.queryobj.cmd_size = (SZ); |
radeon->query.queryobj.cmd = calloc(SZ, sizeof(uint32_t)); |
radeon->query.queryobj.name = "queryobj"; |
radeon->query.queryobj.idx = 0; |
radeon->query.queryobj.check = radeon_check_query_active; |
radeon->query.queryobj.dirty = GL_FALSE; |
radeon->query.queryobj.emit = radeon_emit_queryobj; |
radeon->hw.max_state_size += (SZ); |
insert_at_tail(&radeon->hw.atomlist, &radeon->query.queryobj); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_sanity.c |
---|
0,0 → 1,1079 |
/************************************************************************** |
Copyright 2002 ATI Technologies Inc., Ontario, Canada, and |
Tungsten Graphics Inc, Cedar Park, TX. |
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 |
on 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 |
ATI, TUNGSTEN GRAPHICS AND/OR THEIR 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 <errno.h> |
#include "main/glheader.h" |
#include "radeon_context.h" |
#include "radeon_sanity.h" |
/* Set this '1' to get more verbiage. |
*/ |
#define MORE_VERBOSE 1 |
#if MORE_VERBOSE |
#define VERBOSE (RADEON_DEBUG & RADEON_VERBOSE) |
#define NORMAL (1) |
#else |
#define VERBOSE 0 |
#define NORMAL (RADEON_DEBUG & RADEON_VERBOSE) |
#endif |
/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in |
* 1.3 cmdbuffers allow all previous state to be updated as well as |
* the tcl scalar and vector areas. |
*/ |
static struct { |
int start; |
int len; |
const char *name; |
} packet[RADEON_MAX_STATE_PACKETS] = { |
{ RADEON_PP_MISC,7,"RADEON_PP_MISC" }, |
{ RADEON_PP_CNTL,3,"RADEON_PP_CNTL" }, |
{ RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" }, |
{ RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" }, |
{ RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" }, |
{ RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" }, |
{ RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" }, |
{ RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" }, |
{ RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" }, |
{ RADEON_SE_CNTL,2,"RADEON_SE_CNTL" }, |
{ RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" }, |
{ RADEON_RE_MISC,1,"RADEON_RE_MISC" }, |
{ RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" }, |
{ RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" }, |
{ RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" }, |
{ RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" }, |
{ RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" }, |
{ RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" }, |
{ RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" }, |
{ RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" }, |
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" }, |
{ 0, 4, "R200_PP_TXCBLEND_0" }, |
{ 0, 4, "R200_PP_TXCBLEND_1" }, |
{ 0, 4, "R200_PP_TXCBLEND_2" }, |
{ 0, 4, "R200_PP_TXCBLEND_3" }, |
{ 0, 4, "R200_PP_TXCBLEND_4" }, |
{ 0, 4, "R200_PP_TXCBLEND_5" }, |
{ 0, 4, "R200_PP_TXCBLEND_6" }, |
{ 0, 4, "R200_PP_TXCBLEND_7" }, |
{ 0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" }, |
{ 0, 6, "R200_PP_TFACTOR_0" }, |
{ 0, 4, "R200_SE_VTX_FMT_0" }, |
{ 0, 1, "R200_SE_VAP_CNTL" }, |
{ 0, 5, "R200_SE_TCL_MATRIX_SEL_0" }, |
{ 0, 5, "R200_SE_TCL_TEX_PROC_CTL_2" }, |
{ 0, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" }, |
{ 0, 6, "R200_PP_TXFILTER_0" }, |
{ 0, 6, "R200_PP_TXFILTER_1" }, |
{ 0, 6, "R200_PP_TXFILTER_2" }, |
{ 0, 6, "R200_PP_TXFILTER_3" }, |
{ 0, 6, "R200_PP_TXFILTER_4" }, |
{ 0, 6, "R200_PP_TXFILTER_5" }, |
{ 0, 1, "R200_PP_TXOFFSET_0" }, |
{ 0, 1, "R200_PP_TXOFFSET_1" }, |
{ 0, 1, "R200_PP_TXOFFSET_2" }, |
{ 0, 1, "R200_PP_TXOFFSET_3" }, |
{ 0, 1, "R200_PP_TXOFFSET_4" }, |
{ 0, 1, "R200_PP_TXOFFSET_5" }, |
{ 0, 1, "R200_SE_VTE_CNTL" }, |
{ 0, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" }, |
{ 0, 1, "R200_PP_TAM_DEBUG3" }, |
{ 0, 1, "R200_PP_CNTL_X" }, |
{ 0, 1, "R200_RB3D_DEPTHXY_OFFSET" }, |
{ 0, 1, "R200_RE_AUX_SCISSOR_CNTL" }, |
{ 0, 2, "R200_RE_SCISSOR_TL_0" }, |
{ 0, 2, "R200_RE_SCISSOR_TL_1" }, |
{ 0, 2, "R200_RE_SCISSOR_TL_2" }, |
{ 0, 1, "R200_SE_VAP_CNTL_STATUS" }, |
{ 0, 1, "R200_SE_VTX_STATE_CNTL" }, |
{ 0, 1, "R200_RE_POINTSIZE" }, |
{ 0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" }, |
{ 0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */ |
{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */ |
{ 0, 1, "R200_PP_CUBIC_FACES_1" }, |
{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_1" }, |
{ 0, 1, "R200_PP_CUBIC_FACES_2" }, |
{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_2" }, |
{ 0, 1, "R200_PP_CUBIC_FACES_3" }, |
{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_3" }, |
{ 0, 1, "R200_PP_CUBIC_FACES_4" }, |
{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_4" }, |
{ 0, 1, "R200_PP_CUBIC_FACES_5" }, |
{ 0, 5, "R200_PP_CUBIC_OFFSET_F1_5" }, |
{ RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" }, |
{ RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" }, |
{ RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2" }, |
{ 0, 3, "R200_RB3D_BLENDCOLOR" }, |
{ 0, 1, "R200_SE_TCL_POINT_SPRITE_CNTL" }, |
{ RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0" }, |
{ RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0" }, |
{ RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1" }, |
{ RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0" }, |
{ RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2" }, |
{ RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0" }, |
{ 0, 2, "R200_PP_TRI_PERF" }, |
{ 0, 32, "R200_PP_AFS_0"}, /* 85 */ |
{ 0, 32, "R200_PP_AFS_1"}, |
{ 0, 8, "R200_ATF_TFACTOR"}, |
{ 0, 8, "R200_PP_TXCTLALL_0"}, |
{ 0, 8, "R200_PP_TXCTLALL_1"}, |
{ 0, 8, "R200_PP_TXCTLALL_2"}, |
{ 0, 8, "R200_PP_TXCTLALL_3"}, |
{ 0, 8, "R200_PP_TXCTLALL_4"}, |
{ 0, 8, "R200_PP_TXCTLALL_5"}, |
{ 0, 2, "R200_VAP_PVS_CNTL"}, |
}; |
struct reg_names { |
int idx; |
const char *name; |
}; |
static struct reg_names reg_names[] = { |
{ RADEON_PP_MISC, "RADEON_PP_MISC" }, |
{ RADEON_PP_FOG_COLOR, "RADEON_PP_FOG_COLOR" }, |
{ RADEON_RE_SOLID_COLOR, "RADEON_RE_SOLID_COLOR" }, |
{ RADEON_RB3D_BLENDCNTL, "RADEON_RB3D_BLENDCNTL" }, |
{ RADEON_RB3D_DEPTHOFFSET, "RADEON_RB3D_DEPTHOFFSET" }, |
{ RADEON_RB3D_DEPTHPITCH, "RADEON_RB3D_DEPTHPITCH" }, |
{ RADEON_RB3D_ZSTENCILCNTL, "RADEON_RB3D_ZSTENCILCNTL" }, |
{ RADEON_PP_CNTL, "RADEON_PP_CNTL" }, |
{ RADEON_RB3D_CNTL, "RADEON_RB3D_CNTL" }, |
{ RADEON_RB3D_COLOROFFSET, "RADEON_RB3D_COLOROFFSET" }, |
{ RADEON_RB3D_COLORPITCH, "RADEON_RB3D_COLORPITCH" }, |
{ RADEON_SE_CNTL, "RADEON_SE_CNTL" }, |
{ RADEON_SE_COORD_FMT, "RADEON_SE_COORDFMT" }, |
{ RADEON_SE_CNTL_STATUS, "RADEON_SE_CNTL_STATUS" }, |
{ RADEON_RE_LINE_PATTERN, "RADEON_RE_LINE_PATTERN" }, |
{ RADEON_RE_LINE_STATE, "RADEON_RE_LINE_STATE" }, |
{ RADEON_SE_LINE_WIDTH, "RADEON_SE_LINE_WIDTH" }, |
{ RADEON_RB3D_STENCILREFMASK, "RADEON_RB3D_STENCILREFMASK" }, |
{ RADEON_RB3D_ROPCNTL, "RADEON_RB3D_ROPCNTL" }, |
{ RADEON_RB3D_PLANEMASK, "RADEON_RB3D_PLANEMASK" }, |
{ RADEON_SE_VPORT_XSCALE, "RADEON_SE_VPORT_XSCALE" }, |
{ RADEON_SE_VPORT_XOFFSET, "RADEON_SE_VPORT_XOFFSET" }, |
{ RADEON_SE_VPORT_YSCALE, "RADEON_SE_VPORT_YSCALE" }, |
{ RADEON_SE_VPORT_YOFFSET, "RADEON_SE_VPORT_YOFFSET" }, |
{ RADEON_SE_VPORT_ZSCALE, "RADEON_SE_VPORT_ZSCALE" }, |
{ RADEON_SE_VPORT_ZOFFSET, "RADEON_SE_VPORT_ZOFFSET" }, |
{ RADEON_RE_MISC, "RADEON_RE_MISC" }, |
{ RADEON_PP_TXFILTER_0, "RADEON_PP_TXFILTER_0" }, |
{ RADEON_PP_TXFILTER_1, "RADEON_PP_TXFILTER_1" }, |
{ RADEON_PP_TXFILTER_2, "RADEON_PP_TXFILTER_2" }, |
{ RADEON_PP_TXFORMAT_0, "RADEON_PP_TXFORMAT_0" }, |
{ RADEON_PP_TXFORMAT_1, "RADEON_PP_TXFORMAT_1" }, |
{ RADEON_PP_TXFORMAT_2, "RADEON_PP_TXFORMAT_2" }, |
{ RADEON_PP_TXOFFSET_0, "RADEON_PP_TXOFFSET_0" }, |
{ RADEON_PP_TXOFFSET_1, "RADEON_PP_TXOFFSET_1" }, |
{ RADEON_PP_TXOFFSET_2, "RADEON_PP_TXOFFSET_2" }, |
{ RADEON_PP_TXCBLEND_0, "RADEON_PP_TXCBLEND_0" }, |
{ RADEON_PP_TXCBLEND_1, "RADEON_PP_TXCBLEND_1" }, |
{ RADEON_PP_TXCBLEND_2, "RADEON_PP_TXCBLEND_2" }, |
{ RADEON_PP_TXABLEND_0, "RADEON_PP_TXABLEND_0" }, |
{ RADEON_PP_TXABLEND_1, "RADEON_PP_TXABLEND_1" }, |
{ RADEON_PP_TXABLEND_2, "RADEON_PP_TXABLEND_2" }, |
{ RADEON_PP_TFACTOR_0, "RADEON_PP_TFACTOR_0" }, |
{ RADEON_PP_TFACTOR_1, "RADEON_PP_TFACTOR_1" }, |
{ RADEON_PP_TFACTOR_2, "RADEON_PP_TFACTOR_2" }, |
{ RADEON_PP_BORDER_COLOR_0, "RADEON_PP_BORDER_COLOR_0" }, |
{ RADEON_PP_BORDER_COLOR_1, "RADEON_PP_BORDER_COLOR_1" }, |
{ RADEON_PP_BORDER_COLOR_2, "RADEON_PP_BORDER_COLOR_2" }, |
{ RADEON_SE_ZBIAS_FACTOR, "RADEON_SE_ZBIAS_FACTOR" }, |
{ RADEON_SE_ZBIAS_CONSTANT, "RADEON_SE_ZBIAS_CONSTANT" }, |
{ RADEON_SE_TCL_OUTPUT_VTX_FMT, "RADEON_SE_TCL_OUTPUT_VTXFMT" }, |
{ RADEON_SE_TCL_OUTPUT_VTX_SEL, "RADEON_SE_TCL_OUTPUT_VTXSEL" }, |
{ RADEON_SE_TCL_MATRIX_SELECT_0, "RADEON_SE_TCL_MATRIX_SELECT_0" }, |
{ RADEON_SE_TCL_MATRIX_SELECT_1, "RADEON_SE_TCL_MATRIX_SELECT_1" }, |
{ RADEON_SE_TCL_UCP_VERT_BLEND_CTL, "RADEON_SE_TCL_UCP_VERT_BLEND_CTL" }, |
{ RADEON_SE_TCL_TEXTURE_PROC_CTL, "RADEON_SE_TCL_TEXTURE_PROC_CTL" }, |
{ RADEON_SE_TCL_LIGHT_MODEL_CTL, "RADEON_SE_TCL_LIGHT_MODEL_CTL" }, |
{ RADEON_SE_TCL_PER_LIGHT_CTL_0, "RADEON_SE_TCL_PER_LIGHT_CTL_0" }, |
{ RADEON_SE_TCL_PER_LIGHT_CTL_1, "RADEON_SE_TCL_PER_LIGHT_CTL_1" }, |
{ RADEON_SE_TCL_PER_LIGHT_CTL_2, "RADEON_SE_TCL_PER_LIGHT_CTL_2" }, |
{ RADEON_SE_TCL_PER_LIGHT_CTL_3, "RADEON_SE_TCL_PER_LIGHT_CTL_3" }, |
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, "RADEON_SE_TCL_EMMISSIVE_RED" }, |
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN, "RADEON_SE_TCL_EMMISSIVE_GREEN" }, |
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE, "RADEON_SE_TCL_EMMISSIVE_BLUE" }, |
{ RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA, "RADEON_SE_TCL_EMMISSIVE_ALPHA" }, |
{ RADEON_SE_TCL_MATERIAL_AMBIENT_RED, "RADEON_SE_TCL_AMBIENT_RED" }, |
{ RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN, "RADEON_SE_TCL_AMBIENT_GREEN" }, |
{ RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE, "RADEON_SE_TCL_AMBIENT_BLUE" }, |
{ RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA, "RADEON_SE_TCL_AMBIENT_ALPHA" }, |
{ RADEON_SE_TCL_MATERIAL_DIFFUSE_RED, "RADEON_SE_TCL_DIFFUSE_RED" }, |
{ RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN, "RADEON_SE_TCL_DIFFUSE_GREEN" }, |
{ RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE, "RADEON_SE_TCL_DIFFUSE_BLUE" }, |
{ RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA, "RADEON_SE_TCL_DIFFUSE_ALPHA" }, |
{ RADEON_SE_TCL_MATERIAL_SPECULAR_RED, "RADEON_SE_TCL_SPECULAR_RED" }, |
{ RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN, "RADEON_SE_TCL_SPECULAR_GREEN" }, |
{ RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE, "RADEON_SE_TCL_SPECULAR_BLUE" }, |
{ RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA, "RADEON_SE_TCL_SPECULAR_ALPHA" }, |
{ RADEON_SE_TCL_SHININESS, "RADEON_SE_TCL_SHININESS" }, |
{ RADEON_SE_COORD_FMT, "RADEON_SE_COORD_FMT" }, |
{ RADEON_PP_TEX_SIZE_0, "RADEON_PP_TEX_SIZE_0" }, |
{ RADEON_PP_TEX_SIZE_1, "RADEON_PP_TEX_SIZE_1" }, |
{ RADEON_PP_TEX_SIZE_2, "RADEON_PP_TEX_SIZE_2" }, |
{ RADEON_PP_TEX_SIZE_0+4, "RADEON_PP_TEX_PITCH_0" }, |
{ RADEON_PP_TEX_SIZE_1+4, "RADEON_PP_TEX_PITCH_1" }, |
{ RADEON_PP_TEX_SIZE_2+4, "RADEON_PP_TEX_PITCH_2" }, |
{ RADEON_PP_CUBIC_FACES_0, "RADEON_PP_CUBIC_FACES_0" }, |
{ RADEON_PP_CUBIC_FACES_1, "RADEON_PP_CUBIC_FACES_1" }, |
{ RADEON_PP_CUBIC_FACES_2, "RADEON_PP_CUBIC_FACES_2" }, |
{ RADEON_PP_CUBIC_OFFSET_T0_0, "RADEON_PP_CUBIC_OFFSET_T0_0" }, |
{ RADEON_PP_CUBIC_OFFSET_T0_1, "RADEON_PP_CUBIC_OFFSET_T0_1" }, |
{ RADEON_PP_CUBIC_OFFSET_T0_2, "RADEON_PP_CUBIC_OFFSET_T0_2" }, |
{ RADEON_PP_CUBIC_OFFSET_T0_3, "RADEON_PP_CUBIC_OFFSET_T0_3" }, |
{ RADEON_PP_CUBIC_OFFSET_T0_4, "RADEON_PP_CUBIC_OFFSET_T0_4" }, |
{ RADEON_PP_CUBIC_OFFSET_T1_0, "RADEON_PP_CUBIC_OFFSET_T1_0" }, |
{ RADEON_PP_CUBIC_OFFSET_T1_1, "RADEON_PP_CUBIC_OFFSET_T1_1" }, |
{ RADEON_PP_CUBIC_OFFSET_T1_2, "RADEON_PP_CUBIC_OFFSET_T1_2" }, |
{ RADEON_PP_CUBIC_OFFSET_T1_3, "RADEON_PP_CUBIC_OFFSET_T1_3" }, |
{ RADEON_PP_CUBIC_OFFSET_T1_4, "RADEON_PP_CUBIC_OFFSET_T1_4" }, |
{ RADEON_PP_CUBIC_OFFSET_T2_0, "RADEON_PP_CUBIC_OFFSET_T2_0" }, |
{ RADEON_PP_CUBIC_OFFSET_T2_1, "RADEON_PP_CUBIC_OFFSET_T2_1" }, |
{ RADEON_PP_CUBIC_OFFSET_T2_2, "RADEON_PP_CUBIC_OFFSET_T2_2" }, |
{ RADEON_PP_CUBIC_OFFSET_T2_3, "RADEON_PP_CUBIC_OFFSET_T2_3" }, |
{ RADEON_PP_CUBIC_OFFSET_T2_4, "RADEON_PP_CUBIC_OFFSET_T2_4" }, |
}; |
static struct reg_names scalar_names[] = { |
{ RADEON_SS_LIGHT_DCD_ADDR, "LIGHT_DCD" }, |
{ RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR, "LIGHT_SPOT_EXPONENT" }, |
{ RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR, "LIGHT_SPOT_CUTOFF" }, |
{ RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR, "LIGHT_SPECULAR_THRESH" }, |
{ RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR, "LIGHT_RANGE_CUTOFF" }, |
{ RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, "VERT_GUARD_CLIP" }, |
{ RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR, "VERT_GUARD_DISCARD" }, |
{ RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR, "HORZ_GUARD_CLIP" }, |
{ RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR, "HORZ_GUARD_DISCARD" }, |
{ RADEON_SS_SHININESS, "SHININESS" }, |
{ 1000, "" }, |
}; |
/* Puff these out to make them look like normal (dword) registers. |
*/ |
static struct reg_names vector_names[] = { |
{ RADEON_VS_MATRIX_0_ADDR * 4, "MATRIX_0" }, |
{ RADEON_VS_MATRIX_1_ADDR * 4, "MATRIX_1" }, |
{ RADEON_VS_MATRIX_2_ADDR * 4, "MATRIX_2" }, |
{ RADEON_VS_MATRIX_3_ADDR * 4, "MATRIX_3" }, |
{ RADEON_VS_MATRIX_4_ADDR * 4, "MATRIX_4" }, |
{ RADEON_VS_MATRIX_5_ADDR * 4, "MATRIX_5" }, |
{ RADEON_VS_MATRIX_6_ADDR * 4, "MATRIX_6" }, |
{ RADEON_VS_MATRIX_7_ADDR * 4, "MATRIX_7" }, |
{ RADEON_VS_MATRIX_8_ADDR * 4, "MATRIX_8" }, |
{ RADEON_VS_MATRIX_9_ADDR * 4, "MATRIX_9" }, |
{ RADEON_VS_MATRIX_10_ADDR * 4, "MATRIX_10" }, |
{ RADEON_VS_MATRIX_11_ADDR * 4, "MATRIX_11" }, |
{ RADEON_VS_MATRIX_12_ADDR * 4, "MATRIX_12" }, |
{ RADEON_VS_MATRIX_13_ADDR * 4, "MATRIX_13" }, |
{ RADEON_VS_MATRIX_14_ADDR * 4, "MATRIX_14" }, |
{ RADEON_VS_MATRIX_15_ADDR * 4, "MATRIX_15" }, |
{ RADEON_VS_LIGHT_AMBIENT_ADDR * 4, "LIGHT_AMBIENT" }, |
{ RADEON_VS_LIGHT_DIFFUSE_ADDR * 4, "LIGHT_DIFFUSE" }, |
{ RADEON_VS_LIGHT_SPECULAR_ADDR * 4, "LIGHT_SPECULAR" }, |
{ RADEON_VS_LIGHT_DIRPOS_ADDR * 4, "LIGHT_DIRPOS" }, |
{ RADEON_VS_LIGHT_HWVSPOT_ADDR * 4, "LIGHT_HWVSPOT" }, |
{ RADEON_VS_LIGHT_ATTENUATION_ADDR * 4, "LIGHT_ATTENUATION" }, |
{ RADEON_VS_MATRIX_EYE2CLIP_ADDR * 4, "MATRIX_EYE2CLIP" }, |
{ RADEON_VS_UCP_ADDR * 4, "UCP" }, |
{ RADEON_VS_GLOBAL_AMBIENT_ADDR * 4, "GLOBAL_AMBIENT" }, |
{ RADEON_VS_FOG_PARAM_ADDR * 4, "FOG_PARAM" }, |
{ RADEON_VS_EYE_VECTOR_ADDR * 4, "EYE_VECTOR" }, |
{ 1000, "" }, |
}; |
union fi { float f; int i; }; |
#define ISVEC 1 |
#define ISFLOAT 2 |
#define TOUCHED 4 |
struct reg { |
int idx; |
struct reg_names *closest; |
int flags; |
union fi current; |
union fi *values; |
int nvalues; |
int nalloc; |
float vmin, vmax; |
}; |
static struct reg regs[Elements(reg_names)+1]; |
static struct reg scalars[512+1]; |
static struct reg vectors[512*4+1]; |
static int total, total_changed, bufs; |
static void init_regs( void ) |
{ |
struct reg_names *tmp; |
int i; |
for (i = 0 ; i < Elements(regs)-1 ; i++) { |
regs[i].idx = reg_names[i].idx; |
regs[i].closest = ®_names[i]; |
regs[i].flags = 0; |
} |
for (i = 0, tmp = scalar_names ; i < Elements(scalars) ; i++) { |
if (tmp[1].idx == i) tmp++; |
scalars[i].idx = i; |
scalars[i].closest = tmp; |
scalars[i].flags = ISFLOAT; |
} |
for (i = 0, tmp = vector_names ; i < Elements(vectors) ; i++) { |
if (tmp[1].idx*4 == i) tmp++; |
vectors[i].idx = i; |
vectors[i].closest = tmp; |
vectors[i].flags = ISFLOAT|ISVEC; |
} |
regs[Elements(regs)-1].idx = -1; |
scalars[Elements(scalars)-1].idx = -1; |
vectors[Elements(vectors)-1].idx = -1; |
} |
static int find_or_add_value( struct reg *reg, int val ) |
{ |
int j; |
for ( j = 0 ; j < reg->nvalues ; j++) |
if ( val == reg->values[j].i ) |
return 1; |
if (j == reg->nalloc) { |
reg->nalloc += 5; |
reg->nalloc *= 2; |
reg->values = realloc( reg->values, reg->nalloc * sizeof(union fi) ); |
} |
reg->values[reg->nvalues++].i = val; |
return 0; |
} |
static struct reg *lookup_reg( struct reg *tab, int reg ) |
{ |
int i; |
for (i = 0 ; tab[i].idx != -1 ; i++) { |
if (tab[i].idx == reg) |
return &tab[i]; |
} |
fprintf(stderr, "*** unknown reg 0x%x\n", reg); |
return NULL; |
} |
static const char *get_reg_name( struct reg *reg ) |
{ |
static char tmp[80]; |
if (reg->idx == reg->closest->idx) |
return reg->closest->name; |
if (reg->flags & ISVEC) { |
if (reg->idx/4 != reg->closest->idx) |
sprintf(tmp, "%s+%d[%d]", |
reg->closest->name, |
(reg->idx/4) - reg->closest->idx, |
reg->idx%4); |
else |
sprintf(tmp, "%s[%d]", reg->closest->name, reg->idx%4); |
} |
else { |
if (reg->idx != reg->closest->idx) |
sprintf(tmp, "%s+%d", reg->closest->name, reg->idx - reg->closest->idx); |
else |
sprintf(tmp, "%s", reg->closest->name); |
} |
return tmp; |
} |
static int print_int_reg_assignment( struct reg *reg, int data ) |
{ |
int changed = (reg->current.i != data); |
int ever_seen = find_or_add_value( reg, data ); |
if (VERBOSE || (NORMAL && (changed || !ever_seen))) |
fprintf(stderr, " %s <-- 0x%x", get_reg_name(reg), data); |
if (NORMAL) { |
if (!ever_seen) |
fprintf(stderr, " *** BRAND NEW VALUE"); |
else if (changed) |
fprintf(stderr, " *** CHANGED"); |
} |
reg->current.i = data; |
if (VERBOSE || (NORMAL && (changed || !ever_seen))) |
fprintf(stderr, "\n"); |
return changed; |
} |
static int print_float_reg_assignment( struct reg *reg, float data ) |
{ |
int changed = (reg->current.f != data); |
int newmin = (data < reg->vmin); |
int newmax = (data > reg->vmax); |
if (VERBOSE || (NORMAL && (newmin || newmax || changed))) |
fprintf(stderr, " %s <-- %.3f", get_reg_name(reg), data); |
if (NORMAL) { |
if (newmin) { |
fprintf(stderr, " *** NEW MIN (prev %.3f)", reg->vmin); |
reg->vmin = data; |
} |
else if (newmax) { |
fprintf(stderr, " *** NEW MAX (prev %.3f)", reg->vmax); |
reg->vmax = data; |
} |
else if (changed) { |
fprintf(stderr, " *** CHANGED"); |
} |
} |
reg->current.f = data; |
if (VERBOSE || (NORMAL && (newmin || newmax || changed))) |
fprintf(stderr, "\n"); |
return changed; |
} |
static int print_reg_assignment( struct reg *reg, int data ) |
{ |
float_ui32_type datau; |
datau.ui32 = data; |
reg->flags |= TOUCHED; |
if (reg->flags & ISFLOAT) |
return print_float_reg_assignment( reg, datau.f ); |
else |
return print_int_reg_assignment( reg, data ); |
} |
static void print_reg( struct reg *reg ) |
{ |
if (reg->flags & TOUCHED) { |
if (reg->flags & ISFLOAT) { |
fprintf(stderr, " %s == %f\n", get_reg_name(reg), reg->current.f); |
} else { |
fprintf(stderr, " %s == 0x%x\n", get_reg_name(reg), reg->current.i); |
} |
} |
} |
static void dump_state( void ) |
{ |
int i; |
for (i = 0 ; i < Elements(regs) ; i++) |
print_reg( ®s[i] ); |
for (i = 0 ; i < Elements(scalars) ; i++) |
print_reg( &scalars[i] ); |
for (i = 0 ; i < Elements(vectors) ; i++) |
print_reg( &vectors[i] ); |
} |
static int radeon_emit_packets( |
drm_radeon_cmd_header_t header, |
drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
int id = (int)header.packet.packet_id; |
int sz = packet[id].len; |
int *data = (int *)cmdbuf->buf; |
int i; |
if (sz * sizeof(int) > cmdbuf->bufsz) { |
fprintf(stderr, "Packet overflows cmdbuf\n"); |
return -EINVAL; |
} |
if (!packet[id].name) { |
fprintf(stderr, "*** Unknown packet 0 nr %d\n", id ); |
return -EINVAL; |
} |
if (VERBOSE) |
fprintf(stderr, "Packet 0 reg %s nr %d\n", packet[id].name, sz ); |
for ( i = 0 ; i < sz ; i++) { |
struct reg *reg = lookup_reg( regs, packet[id].start + i*4 ); |
if (print_reg_assignment( reg, data[i] )) |
total_changed++; |
total++; |
} |
cmdbuf->buf += sz * sizeof(int); |
cmdbuf->bufsz -= sz * sizeof(int); |
return 0; |
} |
static int radeon_emit_scalars( |
drm_radeon_cmd_header_t header, |
drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
int sz = header.scalars.count; |
int *data = (int *)cmdbuf->buf; |
int start = header.scalars.offset; |
int stride = header.scalars.stride; |
int i; |
if (VERBOSE) |
fprintf(stderr, "emit scalars, start %d stride %d nr %d (end %d)\n", |
start, stride, sz, start + stride * sz); |
for (i = 0 ; i < sz ; i++, start += stride) { |
struct reg *reg = lookup_reg( scalars, start ); |
if (print_reg_assignment( reg, data[i] )) |
total_changed++; |
total++; |
} |
cmdbuf->buf += sz * sizeof(int); |
cmdbuf->bufsz -= sz * sizeof(int); |
return 0; |
} |
static int radeon_emit_scalars2( |
drm_radeon_cmd_header_t header, |
drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
int sz = header.scalars.count; |
int *data = (int *)cmdbuf->buf; |
int start = header.scalars.offset + 0x100; |
int stride = header.scalars.stride; |
int i; |
if (VERBOSE) |
fprintf(stderr, "emit scalars2, start %d stride %d nr %d (end %d)\n", |
start, stride, sz, start + stride * sz); |
if (start + stride * sz > 257) { |
fprintf(stderr, "emit scalars OVERFLOW %d/%d/%d\n", start, stride, sz); |
return -1; |
} |
for (i = 0 ; i < sz ; i++, start += stride) { |
struct reg *reg = lookup_reg( scalars, start ); |
if (print_reg_assignment( reg, data[i] )) |
total_changed++; |
total++; |
} |
cmdbuf->buf += sz * sizeof(int); |
cmdbuf->bufsz -= sz * sizeof(int); |
return 0; |
} |
/* Check: inf/nan/extreme-size? |
* Check: table start, end, nr, etc. |
*/ |
static int radeon_emit_vectors( |
drm_radeon_cmd_header_t header, |
drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
int sz = header.vectors.count; |
int *data = (int *)cmdbuf->buf; |
int start = header.vectors.offset; |
int stride = header.vectors.stride; |
int i,j; |
if (VERBOSE) |
fprintf(stderr, "emit vectors, start %d stride %d nr %d (end %d) (0x%x)\n", |
start, stride, sz, start + stride * sz, header.i); |
/* if (start + stride * (sz/4) > 128) { */ |
/* fprintf(stderr, "emit vectors OVERFLOW %d/%d/%d\n", start, stride, sz); */ |
/* return -1; */ |
/* } */ |
for (i = 0 ; i < sz ; start += stride) { |
int changed = 0; |
for (j = 0 ; j < 4 ; i++,j++) { |
struct reg *reg = lookup_reg( vectors, start*4+j ); |
if (print_reg_assignment( reg, data[i] )) |
changed = 1; |
} |
if (changed) |
total_changed += 4; |
total += 4; |
} |
cmdbuf->buf += sz * sizeof(int); |
cmdbuf->bufsz -= sz * sizeof(int); |
return 0; |
} |
static int print_vertex_format( int vfmt ) |
{ |
if (NORMAL) { |
fprintf(stderr, " %s(%x): %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", |
"vertex format", |
vfmt, |
"xy,", |
(vfmt & RADEON_CP_VC_FRMT_Z) ? "z," : "", |
(vfmt & RADEON_CP_VC_FRMT_W0) ? "w0," : "", |
(vfmt & RADEON_CP_VC_FRMT_FPCOLOR) ? "fpcolor," : "", |
(vfmt & RADEON_CP_VC_FRMT_FPALPHA) ? "fpalpha," : "", |
(vfmt & RADEON_CP_VC_FRMT_PKCOLOR) ? "pkcolor," : "", |
(vfmt & RADEON_CP_VC_FRMT_FPSPEC) ? "fpspec," : "", |
(vfmt & RADEON_CP_VC_FRMT_FPFOG) ? "fpfog," : "", |
(vfmt & RADEON_CP_VC_FRMT_PKSPEC) ? "pkspec," : "", |
(vfmt & RADEON_CP_VC_FRMT_ST0) ? "st0," : "", |
(vfmt & RADEON_CP_VC_FRMT_ST1) ? "st1," : "", |
(vfmt & RADEON_CP_VC_FRMT_Q1) ? "q1," : "", |
(vfmt & RADEON_CP_VC_FRMT_ST2) ? "st2," : "", |
(vfmt & RADEON_CP_VC_FRMT_Q2) ? "q2," : "", |
(vfmt & RADEON_CP_VC_FRMT_ST3) ? "st3," : "", |
(vfmt & RADEON_CP_VC_FRMT_Q3) ? "q3," : "", |
(vfmt & RADEON_CP_VC_FRMT_Q0) ? "q0," : "", |
(vfmt & RADEON_CP_VC_FRMT_N0) ? "n0," : "", |
(vfmt & RADEON_CP_VC_FRMT_XY1) ? "xy1," : "", |
(vfmt & RADEON_CP_VC_FRMT_Z1) ? "z1," : "", |
(vfmt & RADEON_CP_VC_FRMT_W1) ? "w1," : "", |
(vfmt & RADEON_CP_VC_FRMT_N1) ? "n1," : ""); |
/* if (!find_or_add_value( &others[V_VTXFMT], vfmt )) */ |
/* fprintf(stderr, " *** NEW VALUE"); */ |
fprintf(stderr, "\n"); |
} |
return 0; |
} |
static char *primname[0xf] = { |
"NONE", |
"POINTS", |
"LINES", |
"LINE_STRIP", |
"TRIANGLES", |
"TRIANGLE_FAN", |
"TRIANGLE_STRIP", |
"TRI_TYPE_2", |
"RECT_LIST", |
"3VRT_POINTS", |
"3VRT_LINES", |
}; |
static int print_prim_and_flags( int prim ) |
{ |
int numverts; |
if (NORMAL) |
fprintf(stderr, " %s(%x): %s%s%s%s%s%s%s\n", |
"prim flags", |
prim, |
((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_IND) ? "IND," : "", |
((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_LIST) ? "LIST," : "", |
((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_RING) ? "RING," : "", |
(prim & RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA) ? "RGBA," : "BGRA, ", |
(prim & RADEON_CP_VC_CNTL_MAOS_ENABLE) ? "MAOS," : "", |
(prim & RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE) ? "RADEON," : "", |
(prim & RADEON_CP_VC_CNTL_TCL_ENABLE) ? "TCL," : ""); |
if ((prim & 0xf) > RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST) { |
fprintf(stderr, " *** Bad primitive: %x\n", prim & 0xf); |
return -1; |
} |
numverts = prim>>16; |
if (NORMAL) |
fprintf(stderr, " prim: %s numverts %d\n", primname[prim&0xf], numverts); |
switch (prim & 0xf) { |
case RADEON_CP_VC_CNTL_PRIM_TYPE_NONE: |
case RADEON_CP_VC_CNTL_PRIM_TYPE_POINT: |
if (numverts < 1) { |
fprintf(stderr, "Bad nr verts for line %d\n", numverts); |
return -1; |
} |
break; |
case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE: |
if ((numverts & 1) || numverts == 0) { |
fprintf(stderr, "Bad nr verts for line %d\n", numverts); |
return -1; |
} |
break; |
case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP: |
if (numverts < 2) { |
fprintf(stderr, "Bad nr verts for line_strip %d\n", numverts); |
return -1; |
} |
break; |
case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST: |
case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST: |
case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST: |
case RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST: |
if (numverts % 3 || numverts == 0) { |
fprintf(stderr, "Bad nr verts for tri %d\n", numverts); |
return -1; |
} |
break; |
case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN: |
case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP: |
if (numverts < 3) { |
fprintf(stderr, "Bad nr verts for strip/fan %d\n", numverts); |
return -1; |
} |
break; |
default: |
fprintf(stderr, "Bad primitive\n"); |
return -1; |
} |
return 0; |
} |
/* build in knowledge about each packet type |
*/ |
static int radeon_emit_packet3( drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
int cmdsz; |
int *cmd = (int *)cmdbuf->buf; |
int *tmp; |
int i, stride, size, start; |
cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); |
if ((cmd[0] & RADEON_CP_PACKET_MASK) != RADEON_CP_PACKET3 || |
cmdsz * 4 > cmdbuf->bufsz || |
cmdsz > RADEON_CP_PACKET_MAX_DWORDS) { |
fprintf(stderr, "Bad packet\n"); |
return -EINVAL; |
} |
switch( cmd[0] & ~RADEON_CP_PACKET_COUNT_MASK ) { |
case RADEON_CP_PACKET3_NOP: |
if (NORMAL) |
fprintf(stderr, "PACKET3_NOP, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_NEXT_CHAR: |
if (NORMAL) |
fprintf(stderr, "PACKET3_NEXT_CHAR, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_PLY_NEXTSCAN: |
if (NORMAL) |
fprintf(stderr, "PACKET3_PLY_NEXTSCAN, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_SET_SCISSORS: |
if (NORMAL) |
fprintf(stderr, "PACKET3_SET_SCISSORS, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM: |
if (NORMAL) |
fprintf(stderr, "PACKET3_3D_RNDR_GEN_INDX_PRIM, %d dwords\n", |
cmdsz); |
break; |
case RADEON_CP_PACKET3_LOAD_MICROCODE: |
if (NORMAL) |
fprintf(stderr, "PACKET3_LOAD_MICROCODE, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_WAIT_FOR_IDLE: |
if (NORMAL) |
fprintf(stderr, "PACKET3_WAIT_FOR_IDLE, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_3D_DRAW_VBUF: |
if (NORMAL) |
fprintf(stderr, "PACKET3_3D_DRAW_VBUF, %d dwords\n", cmdsz); |
print_vertex_format(cmd[1]); |
print_prim_and_flags(cmd[2]); |
break; |
case RADEON_CP_PACKET3_3D_DRAW_IMMD: |
if (NORMAL) |
fprintf(stderr, "PACKET3_3D_DRAW_IMMD, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_3D_DRAW_INDX: { |
int neltdwords; |
if (NORMAL) |
fprintf(stderr, "PACKET3_3D_DRAW_INDX, %d dwords\n", cmdsz); |
print_vertex_format(cmd[1]); |
print_prim_and_flags(cmd[2]); |
neltdwords = cmd[2]>>16; |
neltdwords += neltdwords & 1; |
neltdwords /= 2; |
if (neltdwords + 3 != cmdsz) |
fprintf(stderr, "Mismatch in DRAW_INDX, %d vs cmdsz %d\n", |
neltdwords, cmdsz); |
break; |
} |
case RADEON_CP_PACKET3_LOAD_PALETTE: |
if (NORMAL) |
fprintf(stderr, "PACKET3_LOAD_PALETTE, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_3D_LOAD_VBPNTR: |
if (NORMAL) { |
fprintf(stderr, "PACKET3_3D_LOAD_VBPNTR, %d dwords\n", cmdsz); |
fprintf(stderr, " nr arrays: %d\n", cmd[1]); |
} |
if (cmd[1]/2 + cmd[1]%2 != cmdsz - 3) { |
fprintf(stderr, " ****** MISMATCH %d/%d *******\n", |
cmd[1]/2 + cmd[1]%2 + 3, cmdsz); |
return -EINVAL; |
} |
if (NORMAL) { |
tmp = cmd+2; |
for (i = 0 ; i < cmd[1] ; i++) { |
if (i & 1) { |
stride = (tmp[0]>>24) & 0xff; |
size = (tmp[0]>>16) & 0xff; |
start = tmp[2]; |
tmp += 3; |
} |
else { |
stride = (tmp[0]>>8) & 0xff; |
size = (tmp[0]) & 0xff; |
start = tmp[1]; |
} |
fprintf(stderr, " array %d: start 0x%x vsize %d vstride %d\n", |
i, start, size, stride ); |
} |
} |
break; |
case RADEON_CP_PACKET3_CNTL_PAINT: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_PAINT, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_CNTL_BITBLT: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_BITBLT, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_CNTL_SMALLTEXT: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_SMALLTEXT, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_HOSTDATA_BLT, %d dwords\n", |
cmdsz); |
break; |
case RADEON_CP_PACKET3_CNTL_POLYLINE: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_POLYLINE, %d dwords\n", cmdsz); |
break; |
case RADEON_CP_PACKET3_CNTL_POLYSCANLINES: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_POLYSCANLINES, %d dwords\n", |
cmdsz); |
break; |
case RADEON_CP_PACKET3_CNTL_PAINT_MULTI: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_PAINT_MULTI, %d dwords\n", |
cmdsz); |
break; |
case RADEON_CP_PACKET3_CNTL_BITBLT_MULTI: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_BITBLT_MULTI, %d dwords\n", |
cmdsz); |
break; |
case RADEON_CP_PACKET3_CNTL_TRANS_BITBLT: |
if (NORMAL) |
fprintf(stderr, "PACKET3_CNTL_TRANS_BITBLT, %d dwords\n", |
cmdsz); |
break; |
default: |
fprintf(stderr, "UNKNOWN PACKET, %d dwords\n", cmdsz); |
break; |
} |
cmdbuf->buf += cmdsz * 4; |
cmdbuf->bufsz -= cmdsz * 4; |
return 0; |
} |
/* Check cliprects for bounds, then pass on to above: |
*/ |
static int radeon_emit_packet3_cliprect( drm_radeon_cmd_buffer_t *cmdbuf ) |
{ |
drm_clip_rect_t *boxes = cmdbuf->boxes; |
int i = 0; |
if (VERBOSE && total_changed) { |
dump_state(); |
total_changed = 0; |
} |
else fprintf(stderr, "total_changed zero\n"); |
if (NORMAL) { |
do { |
if ( i < cmdbuf->nbox ) { |
fprintf(stderr, "Emit box %d/%d %d,%d %d,%d\n", |
i, cmdbuf->nbox, |
boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2); |
} |
} while ( ++i < cmdbuf->nbox ); |
} |
if (cmdbuf->nbox == 1) |
cmdbuf->nbox = 0; |
return radeon_emit_packet3( cmdbuf ); |
} |
int radeonSanityCmdBuffer( r100ContextPtr rmesa, |
int nbox, |
drm_clip_rect_t *boxes ) |
{ |
int idx; |
drm_radeon_cmd_buffer_t cmdbuf; |
drm_radeon_cmd_header_t header; |
static int inited = 0; |
if (!inited) { |
init_regs(); |
inited = 1; |
} |
cmdbuf.buf = rmesa->store.cmd_buf; |
cmdbuf.bufsz = rmesa->store.cmd_used; |
cmdbuf.boxes = boxes; |
cmdbuf.nbox = nbox; |
while ( cmdbuf.bufsz >= sizeof(header) ) { |
header.i = *(int *)cmdbuf.buf; |
cmdbuf.buf += sizeof(header); |
cmdbuf.bufsz -= sizeof(header); |
switch (header.header.cmd_type) { |
case RADEON_CMD_PACKET: |
if (radeon_emit_packets( header, &cmdbuf )) { |
fprintf(stderr,"radeon_emit_packets failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_SCALARS: |
if (radeon_emit_scalars( header, &cmdbuf )) { |
fprintf(stderr,"radeon_emit_scalars failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_SCALARS2: |
if (radeon_emit_scalars2( header, &cmdbuf )) { |
fprintf(stderr,"radeon_emit_scalars failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_VECTORS: |
if (radeon_emit_vectors( header, &cmdbuf )) { |
fprintf(stderr,"radeon_emit_vectors failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_DMA_DISCARD: |
idx = header.dma.buf_idx; |
if (NORMAL) |
fprintf(stderr, "RADEON_CMD_DMA_DISCARD buf %d\n", idx); |
bufs++; |
break; |
case RADEON_CMD_PACKET3: |
if (radeon_emit_packet3( &cmdbuf )) { |
fprintf(stderr,"radeon_emit_packet3 failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_PACKET3_CLIP: |
if (radeon_emit_packet3_cliprect( &cmdbuf )) { |
fprintf(stderr,"radeon_emit_packet3_clip failed\n"); |
return -EINVAL; |
} |
break; |
case RADEON_CMD_WAIT: |
break; |
default: |
fprintf(stderr,"bad cmd_type %d at %p\n", |
header.header.cmd_type, |
cmdbuf.buf - sizeof(header)); |
return -EINVAL; |
} |
} |
if (0) |
{ |
static int n = 0; |
n++; |
if (n == 10) { |
fprintf(stderr, "Bufs %d Total emitted %d real changes %d (%.2f%%)\n", |
bufs, |
total, total_changed, |
((float)total_changed/(float)total*100.0)); |
fprintf(stderr, "Total emitted per buf: %.2f\n", |
(float)total/(float)bufs); |
fprintf(stderr, "Real changes per buf: %.2f\n", |
(float)total_changed/(float)bufs); |
bufs = n = total = total_changed = 0; |
} |
} |
return 0; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_sanity.h |
---|
0,0 → 1,8 |
#ifndef RADEON_SANITY_H |
#define RADEON_SANITY_H |
extern int radeonSanityCmdBuffer( r100ContextPtr rmesa, |
int nbox, |
drm_clip_rect_t *boxes ); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_screen.c |
---|
0,0 → 1,784 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
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, 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 COPYRIGHT OWNER(S) 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. |
**************************************************************************/ |
/** |
* \file radeon_screen.c |
* Screen initialization functions for the Radeon driver. |
* |
* \author Kevin E. Martin <martin@valinux.com> |
* \author Gareth Hughes <gareth@valinux.com> |
*/ |
#include <errno.h> |
#include "main/glheader.h" |
#include "main/imports.h" |
#include "main/mtypes.h" |
#include "main/framebuffer.h" |
#include "main/renderbuffer.h" |
#include "main/fbobject.h" |
#include "swrast/s_renderbuffer.h" |
#include "radeon_chipset.h" |
#include "radeon_macros.h" |
#include "radeon_screen.h" |
#include "radeon_common.h" |
#include "radeon_common_context.h" |
#if defined(RADEON_R100) |
#include "radeon_context.h" |
#include "radeon_tex.h" |
#elif defined(RADEON_R200) |
#include "r200_context.h" |
#include "r200_tex.h" |
#endif |
#include "utils.h" |
#include "GL/internal/dri_interface.h" |
/* Radeon configuration |
*/ |
#include "xmlpool.h" |
#define DRI_CONF_COMMAND_BUFFER_SIZE(def,min,max) \ |
DRI_CONF_OPT_BEGIN_V(command_buffer_size,int,def, # min ":" # max ) \ |
DRI_CONF_DESC(en,"Size of command buffer (in KB)") \ |
DRI_CONF_DESC(de,"Grösse des Befehlspuffers (in KB)") \ |
DRI_CONF_OPT_END |
#if defined(RADEON_R100) /* R100 */ |
PUBLIC const char __driConfigOptions[] = |
DRI_CONF_BEGIN |
DRI_CONF_SECTION_PERFORMANCE |
DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN) |
DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) |
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) |
DRI_CONF_MAX_TEXTURE_UNITS(3,2,3) |
DRI_CONF_HYPERZ("false") |
DRI_CONF_COMMAND_BUFFER_SIZE(8, 8, 32) |
DRI_CONF_SECTION_END |
DRI_CONF_SECTION_QUALITY |
DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB) |
DRI_CONF_DEF_MAX_ANISOTROPY(1.0,"1.0,2.0,4.0,8.0,16.0") |
DRI_CONF_NO_NEG_LOD_BIAS("false") |
DRI_CONF_FORCE_S3TC_ENABLE("false") |
DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER) |
DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC) |
DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF) |
DRI_CONF_SECTION_END |
DRI_CONF_SECTION_DEBUG |
DRI_CONF_NO_RAST("false") |
DRI_CONF_SECTION_END |
DRI_CONF_END; |
static const GLuint __driNConfigOptions = 14; |
#elif defined(RADEON_R200) |
PUBLIC const char __driConfigOptions[] = |
DRI_CONF_BEGIN |
DRI_CONF_SECTION_PERFORMANCE |
DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN) |
DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) |
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) |
DRI_CONF_MAX_TEXTURE_UNITS(6,2,6) |
DRI_CONF_HYPERZ("false") |
DRI_CONF_COMMAND_BUFFER_SIZE(8, 8, 32) |
DRI_CONF_SECTION_END |
DRI_CONF_SECTION_QUALITY |
DRI_CONF_TEXTURE_DEPTH(DRI_CONF_TEXTURE_DEPTH_FB) |
DRI_CONF_DEF_MAX_ANISOTROPY(1.0,"1.0,2.0,4.0,8.0,16.0") |
DRI_CONF_NO_NEG_LOD_BIAS("false") |
DRI_CONF_FORCE_S3TC_ENABLE("false") |
DRI_CONF_COLOR_REDUCTION(DRI_CONF_COLOR_REDUCTION_DITHER) |
DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC) |
DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF) |
DRI_CONF_TEXTURE_BLEND_QUALITY(1.0,"0.0:1.0") |
DRI_CONF_SECTION_END |
DRI_CONF_SECTION_DEBUG |
DRI_CONF_NO_RAST("false") |
DRI_CONF_SECTION_END |
DRI_CONF_END; |
static const GLuint __driNConfigOptions = 15; |
#endif |
#ifndef RADEON_INFO_TILE_CONFIG |
#define RADEON_INFO_TILE_CONFIG 0x6 |
#endif |
static int |
radeonGetParam(__DRIscreen *sPriv, int param, void *value) |
{ |
int ret; |
drm_radeon_getparam_t gp = { 0 }; |
struct drm_radeon_info info = { 0 }; |
if (sPriv->drm_version.major >= 2) { |
info.value = (uint64_t)(uintptr_t)value; |
switch (param) { |
case RADEON_PARAM_DEVICE_ID: |
info.request = RADEON_INFO_DEVICE_ID; |
break; |
case RADEON_PARAM_NUM_GB_PIPES: |
info.request = RADEON_INFO_NUM_GB_PIPES; |
break; |
case RADEON_PARAM_NUM_Z_PIPES: |
info.request = RADEON_INFO_NUM_Z_PIPES; |
break; |
case RADEON_INFO_TILE_CONFIG: |
info.request = RADEON_INFO_TILE_CONFIG; |
break; |
default: |
return -EINVAL; |
} |
ret = drmCommandWriteRead(sPriv->fd, DRM_RADEON_INFO, &info, sizeof(info)); |
} else { |
gp.param = param; |
gp.value = value; |
ret = drmCommandWriteRead(sPriv->fd, DRM_RADEON_GETPARAM, &gp, sizeof(gp)); |
} |
return ret; |
} |
#if defined(RADEON_R100) |
static const __DRItexBufferExtension radeonTexBufferExtension = { |
{ __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, |
radeonSetTexBuffer, |
radeonSetTexBuffer2, |
}; |
#elif defined(RADEON_R200) |
static const __DRItexBufferExtension r200TexBufferExtension = { |
{ __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, |
r200SetTexBuffer, |
r200SetTexBuffer2, |
}; |
#endif |
static void |
radeonDRI2Flush(__DRIdrawable *drawable) |
{ |
radeonContextPtr rmesa; |
rmesa = (radeonContextPtr) drawable->driContextPriv->driverPrivate; |
radeonFlush(&rmesa->glCtx); |
} |
static const struct __DRI2flushExtensionRec radeonFlushExtension = { |
{ __DRI2_FLUSH, 3 }, |
radeonDRI2Flush, |
dri2InvalidateDrawable, |
}; |
static __DRIimage * |
radeon_create_image_from_name(__DRIscreen *screen, |
int width, int height, int format, |
int name, int pitch, void *loaderPrivate) |
{ |
__DRIimage *image; |
radeonScreenPtr radeonScreen = screen->driverPrivate; |
if (name == 0) |
return NULL; |
image = calloc(1, sizeof *image); |
if (image == NULL) |
return NULL; |
switch (format) { |
case __DRI_IMAGE_FORMAT_RGB565: |
image->format = MESA_FORMAT_RGB565; |
image->internal_format = GL_RGB; |
image->data_type = GL_UNSIGNED_BYTE; |
break; |
case __DRI_IMAGE_FORMAT_XRGB8888: |
image->format = MESA_FORMAT_XRGB8888; |
image->internal_format = GL_RGB; |
image->data_type = GL_UNSIGNED_BYTE; |
break; |
case __DRI_IMAGE_FORMAT_ARGB8888: |
image->format = MESA_FORMAT_ARGB8888; |
image->internal_format = GL_RGBA; |
image->data_type = GL_UNSIGNED_BYTE; |
break; |
default: |
free(image); |
return NULL; |
} |
image->data = loaderPrivate; |
image->cpp = _mesa_get_format_bytes(image->format); |
image->width = width; |
image->pitch = pitch; |
image->height = height; |
image->bo = radeon_bo_open(radeonScreen->bom, |
(uint32_t)name, |
image->pitch * image->height * image->cpp, |
0, |
RADEON_GEM_DOMAIN_VRAM, |
0); |
if (image->bo == NULL) { |
free(image); |
return NULL; |
} |
return image; |
} |
static __DRIimage * |
radeon_create_image_from_renderbuffer(__DRIcontext *context, |
int renderbuffer, void *loaderPrivate) |
{ |
__DRIimage *image; |
radeonContextPtr radeon = context->driverPrivate; |
struct gl_renderbuffer *rb; |
struct radeon_renderbuffer *rrb; |
rb = _mesa_lookup_renderbuffer(&radeon->glCtx, renderbuffer); |
if (!rb) { |
_mesa_error(&radeon->glCtx, |
GL_INVALID_OPERATION, "glRenderbufferExternalMESA"); |
return NULL; |
} |
rrb = radeon_renderbuffer(rb); |
image = calloc(1, sizeof *image); |
if (image == NULL) |
return NULL; |
image->internal_format = rb->InternalFormat; |
image->format = rb->Format; |
image->cpp = rrb->cpp; |
image->data_type = GL_UNSIGNED_BYTE; |
image->data = loaderPrivate; |
radeon_bo_ref(rrb->bo); |
image->bo = rrb->bo; |
image->width = rb->Width; |
image->height = rb->Height; |
image->pitch = rrb->pitch / image->cpp; |
return image; |
} |
static void |
radeon_destroy_image(__DRIimage *image) |
{ |
radeon_bo_unref(image->bo); |
free(image); |
} |
static __DRIimage * |
radeon_create_image(__DRIscreen *screen, |
int width, int height, int format, |
unsigned int use, |
void *loaderPrivate) |
{ |
__DRIimage *image; |
radeonScreenPtr radeonScreen = screen->driverPrivate; |
image = calloc(1, sizeof *image); |
if (image == NULL) |
return NULL; |
image->dri_format = format; |
switch (format) { |
case __DRI_IMAGE_FORMAT_RGB565: |
image->format = MESA_FORMAT_RGB565; |
image->internal_format = GL_RGB; |
image->data_type = GL_UNSIGNED_BYTE; |
break; |
case __DRI_IMAGE_FORMAT_XRGB8888: |
image->format = MESA_FORMAT_XRGB8888; |
image->internal_format = GL_RGB; |
image->data_type = GL_UNSIGNED_BYTE; |
break; |
case __DRI_IMAGE_FORMAT_ARGB8888: |
image->format = MESA_FORMAT_ARGB8888; |
image->internal_format = GL_RGBA; |
image->data_type = GL_UNSIGNED_BYTE; |
break; |
default: |
free(image); |
return NULL; |
} |
image->data = loaderPrivate; |
image->cpp = _mesa_get_format_bytes(image->format); |
image->width = width; |
image->height = height; |
image->pitch = ((image->cpp * image->width + 255) & ~255) / image->cpp; |
image->bo = radeon_bo_open(radeonScreen->bom, |
0, |
image->pitch * image->height * image->cpp, |
0, |
RADEON_GEM_DOMAIN_VRAM, |
0); |
if (image->bo == NULL) { |
free(image); |
return NULL; |
} |
return image; |
} |
static GLboolean |
radeon_query_image(__DRIimage *image, int attrib, int *value) |
{ |
switch (attrib) { |
case __DRI_IMAGE_ATTRIB_STRIDE: |
*value = image->pitch * image->cpp; |
return GL_TRUE; |
case __DRI_IMAGE_ATTRIB_HANDLE: |
*value = image->bo->handle; |
return GL_TRUE; |
case __DRI_IMAGE_ATTRIB_NAME: |
radeon_gem_get_kernel_name(image->bo, (uint32_t *) value); |
return GL_TRUE; |
default: |
return GL_FALSE; |
} |
} |
static struct __DRIimageExtensionRec radeonImageExtension = { |
{ __DRI_IMAGE, 1 }, |
radeon_create_image_from_name, |
radeon_create_image_from_renderbuffer, |
radeon_destroy_image, |
radeon_create_image, |
radeon_query_image |
}; |
static int radeon_set_screen_flags(radeonScreenPtr screen, int device_id) |
{ |
screen->device_id = device_id; |
screen->chip_flags = 0; |
switch ( device_id ) { |
#if defined(RADEON_R100) |
case PCI_CHIP_RN50_515E: |
case PCI_CHIP_RN50_5969: |
return -1; |
case PCI_CHIP_RADEON_LY: |
case PCI_CHIP_RADEON_LZ: |
case PCI_CHIP_RADEON_QY: |
case PCI_CHIP_RADEON_QZ: |
screen->chip_family = CHIP_FAMILY_RV100; |
break; |
case PCI_CHIP_RS100_4136: |
case PCI_CHIP_RS100_4336: |
screen->chip_family = CHIP_FAMILY_RS100; |
break; |
case PCI_CHIP_RS200_4137: |
case PCI_CHIP_RS200_4337: |
case PCI_CHIP_RS250_4237: |
case PCI_CHIP_RS250_4437: |
screen->chip_family = CHIP_FAMILY_RS200; |
break; |
case PCI_CHIP_RADEON_QD: |
case PCI_CHIP_RADEON_QE: |
case PCI_CHIP_RADEON_QF: |
case PCI_CHIP_RADEON_QG: |
/* all original radeons (7200) presumably have a stencil op bug */ |
screen->chip_family = CHIP_FAMILY_R100; |
screen->chip_flags = RADEON_CHIPSET_TCL | RADEON_CHIPSET_BROKEN_STENCIL | RADEON_CHIPSET_DEPTH_ALWAYS_TILED; |
break; |
case PCI_CHIP_RV200_QW: |
case PCI_CHIP_RV200_QX: |
case PCI_CHIP_RADEON_LW: |
case PCI_CHIP_RADEON_LX: |
screen->chip_family = CHIP_FAMILY_RV200; |
screen->chip_flags = RADEON_CHIPSET_TCL | RADEON_CHIPSET_DEPTH_ALWAYS_TILED; |
break; |
#elif defined(RADEON_R200) |
case PCI_CHIP_R200_BB: |
case PCI_CHIP_R200_QH: |
case PCI_CHIP_R200_QL: |
case PCI_CHIP_R200_QM: |
screen->chip_family = CHIP_FAMILY_R200; |
screen->chip_flags = RADEON_CHIPSET_TCL | RADEON_CHIPSET_DEPTH_ALWAYS_TILED; |
break; |
case PCI_CHIP_RV250_If: |
case PCI_CHIP_RV250_Ig: |
case PCI_CHIP_RV250_Ld: |
case PCI_CHIP_RV250_Lf: |
case PCI_CHIP_RV250_Lg: |
screen->chip_family = CHIP_FAMILY_RV250; |
screen->chip_flags = R200_CHIPSET_YCBCR_BROKEN | RADEON_CHIPSET_TCL | RADEON_CHIPSET_DEPTH_ALWAYS_TILED; |
break; |
case PCI_CHIP_RV280_4C6E: |
case PCI_CHIP_RV280_5960: |
case PCI_CHIP_RV280_5961: |
case PCI_CHIP_RV280_5962: |
case PCI_CHIP_RV280_5964: |
case PCI_CHIP_RV280_5965: |
case PCI_CHIP_RV280_5C61: |
case PCI_CHIP_RV280_5C63: |
screen->chip_family = CHIP_FAMILY_RV280; |
screen->chip_flags = RADEON_CHIPSET_TCL | RADEON_CHIPSET_DEPTH_ALWAYS_TILED; |
break; |
case PCI_CHIP_RS300_5834: |
case PCI_CHIP_RS300_5835: |
case PCI_CHIP_RS350_7834: |
case PCI_CHIP_RS350_7835: |
screen->chip_family = CHIP_FAMILY_RS300; |
screen->chip_flags = RADEON_CHIPSET_DEPTH_ALWAYS_TILED; |
break; |
#endif |
default: |
fprintf(stderr, "unknown chip id 0x%x, can't guess.\n", |
device_id); |
return -1; |
} |
return 0; |
} |
static radeonScreenPtr |
radeonCreateScreen2(__DRIscreen *sPriv) |
{ |
radeonScreenPtr screen; |
int i; |
int ret; |
uint32_t device_id = 0; |
/* Allocate the private area */ |
screen = calloc(1, sizeof(*screen)); |
if ( !screen ) { |
fprintf(stderr, "%s: Could not allocate memory for screen structure", __FUNCTION__); |
fprintf(stderr, "leaving here\n"); |
return NULL; |
} |
radeon_init_debug(); |
/* parse information in __driConfigOptions */ |
driParseOptionInfo (&screen->optionCache, |
__driConfigOptions, __driNConfigOptions); |
screen->chip_flags = 0; |
screen->irq = 1; |
ret = radeonGetParam(sPriv, RADEON_PARAM_DEVICE_ID, &device_id); |
if (ret) { |
free( screen ); |
fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_DEVICE_ID): %d\n", ret); |
return NULL; |
} |
ret = radeon_set_screen_flags(screen, device_id); |
if (ret == -1) { |
free(screen); |
return NULL; |
} |
if (getenv("RADEON_NO_TCL")) |
screen->chip_flags &= ~RADEON_CHIPSET_TCL; |
i = 0; |
screen->extensions[i++] = &dri2ConfigQueryExtension.base; |
#if defined(RADEON_R100) |
screen->extensions[i++] = &radeonTexBufferExtension.base; |
#elif defined(RADEON_R200) |
screen->extensions[i++] = &r200TexBufferExtension.base; |
#endif |
screen->extensions[i++] = &radeonFlushExtension.base; |
screen->extensions[i++] = &radeonImageExtension.base; |
screen->extensions[i++] = NULL; |
sPriv->extensions = screen->extensions; |
screen->driScreen = sPriv; |
screen->bom = radeon_bo_manager_gem_ctor(sPriv->fd); |
if (screen->bom == NULL) { |
free(screen); |
return NULL; |
} |
return screen; |
} |
/* Destroy the device specific screen private data struct. |
*/ |
static void |
radeonDestroyScreen( __DRIscreen *sPriv ) |
{ |
radeonScreenPtr screen = (radeonScreenPtr)sPriv->driverPrivate; |
if (!screen) |
return; |
#ifdef RADEON_BO_TRACK |
radeon_tracker_print(&screen->bom->tracker, stderr); |
#endif |
radeon_bo_manager_gem_dtor(screen->bom); |
/* free all option information */ |
driDestroyOptionInfo (&screen->optionCache); |
free( screen ); |
sPriv->driverPrivate = NULL; |
} |
/* Initialize the driver specific screen private data. |
*/ |
static GLboolean |
radeonInitDriver( __DRIscreen *sPriv ) |
{ |
sPriv->driverPrivate = (void *) radeonCreateScreen2( sPriv ); |
if ( !sPriv->driverPrivate ) { |
radeonDestroyScreen( sPriv ); |
return GL_FALSE; |
} |
return GL_TRUE; |
} |
/** |
* Create the Mesa framebuffer and renderbuffers for a given window/drawable. |
* |
* \todo This function (and its interface) will need to be updated to support |
* pbuffers. |
*/ |
static GLboolean |
radeonCreateBuffer( __DRIscreen *driScrnPriv, |
__DRIdrawable *driDrawPriv, |
const struct gl_config *mesaVis, |
GLboolean isPixmap ) |
{ |
radeonScreenPtr screen = (radeonScreenPtr) driScrnPriv->driverPrivate; |
const GLboolean swDepth = GL_FALSE; |
const GLboolean swAlpha = GL_FALSE; |
const GLboolean swAccum = mesaVis->accumRedBits > 0; |
const GLboolean swStencil = mesaVis->stencilBits > 0 && |
mesaVis->depthBits != 24; |
gl_format rgbFormat; |
struct radeon_framebuffer *rfb; |
if (isPixmap) |
return GL_FALSE; /* not implemented */ |
rfb = CALLOC_STRUCT(radeon_framebuffer); |
if (!rfb) |
return GL_FALSE; |
_mesa_initialize_window_framebuffer(&rfb->base, mesaVis); |
if (mesaVis->redBits == 5) |
rgbFormat = _mesa_little_endian() ? MESA_FORMAT_RGB565 : MESA_FORMAT_RGB565_REV; |
else if (mesaVis->alphaBits == 0) |
rgbFormat = _mesa_little_endian() ? MESA_FORMAT_XRGB8888 : MESA_FORMAT_XRGB8888_REV; |
else |
rgbFormat = _mesa_little_endian() ? MESA_FORMAT_ARGB8888 : MESA_FORMAT_ARGB8888_REV; |
/* front color renderbuffer */ |
rfb->color_rb[0] = radeon_create_renderbuffer(rgbFormat, driDrawPriv); |
_mesa_add_renderbuffer(&rfb->base, BUFFER_FRONT_LEFT, &rfb->color_rb[0]->base.Base); |
rfb->color_rb[0]->has_surface = 1; |
/* back color renderbuffer */ |
if (mesaVis->doubleBufferMode) { |
rfb->color_rb[1] = radeon_create_renderbuffer(rgbFormat, driDrawPriv); |
_mesa_add_renderbuffer(&rfb->base, BUFFER_BACK_LEFT, &rfb->color_rb[1]->base.Base); |
rfb->color_rb[1]->has_surface = 1; |
} |
if (mesaVis->depthBits == 24) { |
if (mesaVis->stencilBits == 8) { |
struct radeon_renderbuffer *depthStencilRb = |
radeon_create_renderbuffer(MESA_FORMAT_S8_Z24, driDrawPriv); |
_mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depthStencilRb->base.Base); |
_mesa_add_renderbuffer(&rfb->base, BUFFER_STENCIL, &depthStencilRb->base.Base); |
depthStencilRb->has_surface = screen->depthHasSurface; |
} else { |
/* depth renderbuffer */ |
struct radeon_renderbuffer *depth = |
radeon_create_renderbuffer(MESA_FORMAT_X8_Z24, driDrawPriv); |
_mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depth->base.Base); |
depth->has_surface = screen->depthHasSurface; |
} |
} else if (mesaVis->depthBits == 16) { |
/* just 16-bit depth buffer, no hw stencil */ |
struct radeon_renderbuffer *depth = |
radeon_create_renderbuffer(MESA_FORMAT_Z16, driDrawPriv); |
_mesa_add_renderbuffer(&rfb->base, BUFFER_DEPTH, &depth->base.Base); |
depth->has_surface = screen->depthHasSurface; |
} |
_swrast_add_soft_renderbuffers(&rfb->base, |
GL_FALSE, /* color */ |
swDepth, |
swStencil, |
swAccum, |
swAlpha, |
GL_FALSE /* aux */); |
driDrawPriv->driverPrivate = (void *) rfb; |
return (driDrawPriv->driverPrivate != NULL); |
} |
static void radeon_cleanup_renderbuffers(struct radeon_framebuffer *rfb) |
{ |
struct radeon_renderbuffer *rb; |
rb = rfb->color_rb[0]; |
if (rb && rb->bo) { |
radeon_bo_unref(rb->bo); |
rb->bo = NULL; |
} |
rb = rfb->color_rb[1]; |
if (rb && rb->bo) { |
radeon_bo_unref(rb->bo); |
rb->bo = NULL; |
} |
rb = radeon_get_renderbuffer(&rfb->base, BUFFER_DEPTH); |
if (rb && rb->bo) { |
radeon_bo_unref(rb->bo); |
rb->bo = NULL; |
} |
} |
void |
radeonDestroyBuffer(__DRIdrawable *driDrawPriv) |
{ |
struct radeon_framebuffer *rfb; |
if (!driDrawPriv) |
return; |
rfb = (void*)driDrawPriv->driverPrivate; |
if (!rfb) |
return; |
radeon_cleanup_renderbuffers(rfb); |
_mesa_reference_framebuffer((struct gl_framebuffer **)(&(driDrawPriv->driverPrivate)), NULL); |
} |
/** |
* This is the driver specific part of the createNewScreen entry point. |
* Called when using DRI2. |
* |
* \return the struct gl_config supported by this driver |
*/ |
static const |
__DRIconfig **radeonInitScreen2(__DRIscreen *psp) |
{ |
static const gl_format formats[3] = { |
MESA_FORMAT_RGB565, |
MESA_FORMAT_XRGB8888, |
MESA_FORMAT_ARGB8888 |
}; |
/* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't |
* support pageflipping at all. |
*/ |
static const GLenum back_buffer_modes[] = { |
GLX_NONE, GLX_SWAP_UNDEFINED_OML, /*, GLX_SWAP_COPY_OML*/ |
}; |
uint8_t depth_bits[4], stencil_bits[4], msaa_samples_array[1]; |
int color; |
__DRIconfig **configs = NULL; |
if (!radeonInitDriver(psp)) { |
return NULL; |
} |
depth_bits[0] = 0; |
stencil_bits[0] = 0; |
depth_bits[1] = 16; |
stencil_bits[1] = 0; |
depth_bits[2] = 24; |
stencil_bits[2] = 0; |
depth_bits[3] = 24; |
stencil_bits[3] = 8; |
msaa_samples_array[0] = 0; |
for (color = 0; color < ARRAY_SIZE(formats); color++) { |
__DRIconfig **new_configs; |
new_configs = driCreateConfigs(formats[color], |
depth_bits, |
stencil_bits, |
ARRAY_SIZE(depth_bits), |
back_buffer_modes, |
ARRAY_SIZE(back_buffer_modes), |
msaa_samples_array, |
ARRAY_SIZE(msaa_samples_array), |
GL_TRUE); |
configs = driConcatConfigs(configs, new_configs); |
} |
if (configs == NULL) { |
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, |
__LINE__); |
return NULL; |
} |
return (const __DRIconfig **)configs; |
} |
const struct __DriverAPIRec driDriverAPI = { |
.InitScreen = radeonInitScreen2, |
.DestroyScreen = radeonDestroyScreen, |
#if defined(RADEON_R200) |
.CreateContext = r200CreateContext, |
.DestroyContext = r200DestroyContext, |
#else |
.CreateContext = r100CreateContext, |
.DestroyContext = radeonDestroyContext, |
#endif |
.CreateBuffer = radeonCreateBuffer, |
.DestroyBuffer = radeonDestroyBuffer, |
.MakeCurrent = radeonMakeCurrent, |
.UnbindContext = radeonUnbindContext, |
}; |
/* This is the table of extensions that the loader will dlsym() for. */ |
PUBLIC const __DRIextension *__driDriverExtensions[] = { |
&driCoreExtension.base, |
&driDRI2Extension.base, |
NULL |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_screen.h |
---|
0,0 → 1,122 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Kevin E. Martin <martin@valinux.com> |
* Gareth Hughes <gareth@valinux.com> |
*/ |
#ifndef __RADEON_SCREEN_H__ |
#define __RADEON_SCREEN_H__ |
/* |
* IMPORTS: these headers contain all the DRI, X and kernel-related |
* definitions that we need. |
*/ |
#include "dri_util.h" |
#include "radeon_dri.h" |
#include "radeon_chipset.h" |
#include "radeon_reg.h" |
#include "drm_sarea.h" |
#include "xmlconfig.h" |
typedef struct { |
drm_handle_t handle; /* Handle to the DRM region */ |
drmSize size; /* Size of the DRM region */ |
drmAddress map; /* Mapping of the DRM region */ |
} radeonRegionRec, *radeonRegionPtr; |
typedef struct radeon_screen { |
int chip_family; |
int chip_flags; |
int cpp; |
int card_type; |
int device_id; /* PCI ID */ |
int AGPMode; |
unsigned int irq; /* IRQ number (0 means none) */ |
unsigned int fbLocation; |
unsigned int frontOffset; |
unsigned int frontPitch; |
unsigned int backOffset; |
unsigned int backPitch; |
unsigned int depthOffset; |
unsigned int depthPitch; |
/* Shared texture data */ |
int numTexHeaps; |
int texOffset[RADEON_NR_TEX_HEAPS]; |
int texSize[RADEON_NR_TEX_HEAPS]; |
int logTexGranularity[RADEON_NR_TEX_HEAPS]; |
radeonRegionRec mmio; |
radeonRegionRec status; |
radeonRegionRec gartTextures; |
drmBufMapPtr buffers; |
__volatile__ uint32_t *scratch; |
__DRIscreen *driScreen; |
unsigned int sarea_priv_offset; |
unsigned int gart_buffer_offset; /* offset in card memory space */ |
unsigned int gart_texture_offset; /* offset in card memory space */ |
unsigned int gart_base; |
GLboolean depthHasSurface; |
/* Configuration cache with default values for all contexts */ |
driOptionCache optionCache; |
const __DRIextension *extensions[17]; |
int num_gb_pipes; |
int num_z_pipes; |
drm_radeon_sarea_t *sarea; /* Private SAREA data */ |
struct radeon_bo_manager *bom; |
} radeonScreenRec, *radeonScreenPtr; |
struct __DRIimageRec { |
struct radeon_bo *bo; |
GLenum internal_format; |
uint32_t dri_format; |
GLuint format; |
GLenum data_type; |
int width, height; /* in pixels */ |
int pitch; /* in pixels */ |
int cpp; |
void *data; |
}; |
extern void radeonDestroyBuffer(__DRIdrawable *driDrawPriv); |
#endif /* __RADEON_SCREEN_H__ */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_span.c |
---|
0,0 → 1,149 |
/************************************************************************** |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Kevin E. Martin <martin@valinux.com> |
* Gareth Hughes <gareth@valinux.com> |
* Keith Whitwell <keith@tungstengraphics.com> |
* |
*/ |
#include "main/glheader.h" |
#include "main/texformat.h" |
#include "main/renderbuffer.h" |
#include "main/samplerobj.h" |
#include "swrast/swrast.h" |
#include "swrast/s_renderbuffer.h" |
#include "radeon_common.h" |
#include "radeon_span.h" |
static void |
radeon_renderbuffer_map(struct gl_context *ctx, struct gl_renderbuffer *rb) |
{ |
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); |
GLubyte *map; |
int stride; |
if (!rb || !rrb) |
return; |
ctx->Driver.MapRenderbuffer(ctx, rb, 0, 0, rb->Width, rb->Height, |
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, |
&map, &stride); |
rrb->base.Map = map; |
rrb->base.RowStride = stride; |
/* No floating point color buffers, use GLubytes */ |
rrb->base.ColorType = GL_UNSIGNED_BYTE; |
} |
static void |
radeon_renderbuffer_unmap(struct gl_context *ctx, struct gl_renderbuffer *rb) |
{ |
struct radeon_renderbuffer *rrb = radeon_renderbuffer(rb); |
if (!rb || !rrb) |
return; |
ctx->Driver.UnmapRenderbuffer(ctx, rb); |
rrb->base.Map = NULL; |
rrb->base.RowStride = 0; |
} |
static void |
radeon_map_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) |
{ |
GLuint i; |
radeon_print(RADEON_MEMORY, RADEON_TRACE, |
"%s( %p , fb %p )\n", |
__func__, ctx, fb); |
/* check for render to textures */ |
for (i = 0; i < BUFFER_COUNT; i++) |
radeon_renderbuffer_map(ctx, fb->Attachment[i].Renderbuffer); |
radeon_check_front_buffer_rendering(ctx); |
} |
static void |
radeon_unmap_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) |
{ |
GLuint i; |
radeon_print(RADEON_MEMORY, RADEON_TRACE, |
"%s( %p , fb %p)\n", |
__func__, ctx, fb); |
/* check for render to textures */ |
for (i = 0; i < BUFFER_COUNT; i++) |
radeon_renderbuffer_unmap(ctx, fb->Attachment[i].Renderbuffer); |
radeon_check_front_buffer_rendering(ctx); |
} |
static void radeonSpanRenderStart(struct gl_context * ctx) |
{ |
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
radeon_firevertices(rmesa); |
_swrast_map_textures(ctx); |
radeon_map_framebuffer(ctx, ctx->DrawBuffer); |
if (ctx->ReadBuffer != ctx->DrawBuffer) |
radeon_map_framebuffer(ctx, ctx->ReadBuffer); |
} |
static void radeonSpanRenderFinish(struct gl_context * ctx) |
{ |
_swrast_flush(ctx); |
_swrast_unmap_textures(ctx); |
radeon_unmap_framebuffer(ctx, ctx->DrawBuffer); |
if (ctx->ReadBuffer != ctx->DrawBuffer) |
radeon_unmap_framebuffer(ctx, ctx->ReadBuffer); |
} |
void radeonInitSpanFuncs(struct gl_context * ctx) |
{ |
struct swrast_device_driver *swdd = |
_swrast_GetDeviceDriverReference(ctx); |
swdd->SpanRenderStart = radeonSpanRenderStart; |
swdd->SpanRenderFinish = radeonSpanRenderFinish; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_span.h |
---|
0,0 → 1,47 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
The Weather Channel (TM) funded Tungsten Graphics to develop the |
initial release of the Radeon 8500 driver under the XFree86 license. |
This notice must be preserved. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Gareth Hughes <gareth@valinux.com> |
* Keith Whitwell <keith@tungstengraphics.com> |
* Kevin E. Martin <martin@valinux.com> |
*/ |
#ifndef __RADEON_SPAN_H__ |
#define __RADEON_SPAN_H__ |
extern void radeonInitSpanFuncs(struct gl_context * ctx); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_state.c |
---|
0,0 → 1,2221 |
/************************************************************************** |
Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Gareth Hughes <gareth@valinux.com> |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#include "main/glheader.h" |
#include "main/imports.h" |
#include "main/api_arrayelt.h" |
#include "main/enums.h" |
#include "main/light.h" |
#include "main/context.h" |
#include "main/framebuffer.h" |
#include "main/fbobject.h" |
#include "main/simple_list.h" |
#include "main/state.h" |
#include "main/core.h" |
#include "main/stencil.h" |
#include "vbo/vbo.h" |
#include "tnl/tnl.h" |
#include "tnl/t_pipeline.h" |
#include "swrast_setup/swrast_setup.h" |
#include "drivers/common/meta.h" |
#include "radeon_context.h" |
#include "radeon_mipmap_tree.h" |
#include "radeon_ioctl.h" |
#include "radeon_state.h" |
#include "radeon_tcl.h" |
#include "radeon_tex.h" |
#include "radeon_swtcl.h" |
static void radeonUpdateSpecular( struct gl_context *ctx ); |
/* ============================================================= |
* Alpha blending |
*/ |
static void radeonAlphaFunc( struct gl_context *ctx, GLenum func, GLfloat ref ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC]; |
GLubyte refByte; |
CLAMPED_FLOAT_TO_UBYTE(refByte, ref); |
RADEON_STATECHANGE( rmesa, ctx ); |
pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | RADEON_REF_ALPHA_MASK); |
pp_misc |= (refByte & RADEON_REF_ALPHA_MASK); |
switch ( func ) { |
case GL_NEVER: |
pp_misc |= RADEON_ALPHA_TEST_FAIL; |
break; |
case GL_LESS: |
pp_misc |= RADEON_ALPHA_TEST_LESS; |
break; |
case GL_EQUAL: |
pp_misc |= RADEON_ALPHA_TEST_EQUAL; |
break; |
case GL_LEQUAL: |
pp_misc |= RADEON_ALPHA_TEST_LEQUAL; |
break; |
case GL_GREATER: |
pp_misc |= RADEON_ALPHA_TEST_GREATER; |
break; |
case GL_NOTEQUAL: |
pp_misc |= RADEON_ALPHA_TEST_NEQUAL; |
break; |
case GL_GEQUAL: |
pp_misc |= RADEON_ALPHA_TEST_GEQUAL; |
break; |
case GL_ALWAYS: |
pp_misc |= RADEON_ALPHA_TEST_PASS; |
break; |
} |
rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc; |
} |
static void radeonBlendEquationSeparate( struct gl_context *ctx, |
GLenum modeRGB, GLenum modeA ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK; |
GLboolean fallback = GL_FALSE; |
assert( modeRGB == modeA ); |
switch ( modeRGB ) { |
case GL_FUNC_ADD: |
case GL_LOGIC_OP: |
b |= RADEON_COMB_FCN_ADD_CLAMP; |
break; |
case GL_FUNC_SUBTRACT: |
b |= RADEON_COMB_FCN_SUB_CLAMP; |
break; |
default: |
if (ctx->Color.BlendEnabled) |
fallback = GL_TRUE; |
else |
b |= RADEON_COMB_FCN_ADD_CLAMP; |
break; |
} |
FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, fallback ); |
if ( !fallback ) { |
RADEON_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b; |
if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled |
&& ctx->Color.Blend[0].EquationRGB == GL_LOGIC_OP)) ) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; |
} |
} |
} |
static void radeonBlendFuncSeparate( struct gl_context *ctx, |
GLenum sfactorRGB, GLenum dfactorRGB, |
GLenum sfactorA, GLenum dfactorA ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & |
~(RADEON_SRC_BLEND_MASK | RADEON_DST_BLEND_MASK); |
GLboolean fallback = GL_FALSE; |
switch ( ctx->Color.Blend[0].SrcRGB ) { |
case GL_ZERO: |
b |= RADEON_SRC_BLEND_GL_ZERO; |
break; |
case GL_ONE: |
b |= RADEON_SRC_BLEND_GL_ONE; |
break; |
case GL_DST_COLOR: |
b |= RADEON_SRC_BLEND_GL_DST_COLOR; |
break; |
case GL_ONE_MINUS_DST_COLOR: |
b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR; |
break; |
case GL_SRC_COLOR: |
b |= RADEON_SRC_BLEND_GL_SRC_COLOR; |
break; |
case GL_ONE_MINUS_SRC_COLOR: |
b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR; |
break; |
case GL_SRC_ALPHA: |
b |= RADEON_SRC_BLEND_GL_SRC_ALPHA; |
break; |
case GL_ONE_MINUS_SRC_ALPHA: |
b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA; |
break; |
case GL_DST_ALPHA: |
b |= RADEON_SRC_BLEND_GL_DST_ALPHA; |
break; |
case GL_ONE_MINUS_DST_ALPHA: |
b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA; |
break; |
case GL_SRC_ALPHA_SATURATE: |
b |= RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE; |
break; |
case GL_CONSTANT_COLOR: |
case GL_ONE_MINUS_CONSTANT_COLOR: |
case GL_CONSTANT_ALPHA: |
case GL_ONE_MINUS_CONSTANT_ALPHA: |
if (ctx->Color.BlendEnabled) |
fallback = GL_TRUE; |
else |
b |= RADEON_SRC_BLEND_GL_ONE; |
break; |
default: |
break; |
} |
switch ( ctx->Color.Blend[0].DstRGB ) { |
case GL_ZERO: |
b |= RADEON_DST_BLEND_GL_ZERO; |
break; |
case GL_ONE: |
b |= RADEON_DST_BLEND_GL_ONE; |
break; |
case GL_SRC_COLOR: |
b |= RADEON_DST_BLEND_GL_SRC_COLOR; |
break; |
case GL_ONE_MINUS_SRC_COLOR: |
b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR; |
break; |
case GL_SRC_ALPHA: |
b |= RADEON_DST_BLEND_GL_SRC_ALPHA; |
break; |
case GL_ONE_MINUS_SRC_ALPHA: |
b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA; |
break; |
case GL_DST_COLOR: |
b |= RADEON_DST_BLEND_GL_DST_COLOR; |
break; |
case GL_ONE_MINUS_DST_COLOR: |
b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR; |
break; |
case GL_DST_ALPHA: |
b |= RADEON_DST_BLEND_GL_DST_ALPHA; |
break; |
case GL_ONE_MINUS_DST_ALPHA: |
b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA; |
break; |
case GL_CONSTANT_COLOR: |
case GL_ONE_MINUS_CONSTANT_COLOR: |
case GL_CONSTANT_ALPHA: |
case GL_ONE_MINUS_CONSTANT_ALPHA: |
if (ctx->Color.BlendEnabled) |
fallback = GL_TRUE; |
else |
b |= RADEON_DST_BLEND_GL_ZERO; |
break; |
default: |
break; |
} |
FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, fallback ); |
if ( !fallback ) { |
RADEON_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b; |
} |
} |
/* ============================================================= |
* Depth testing |
*/ |
static void radeonDepthFunc( struct gl_context *ctx, GLenum func ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
RADEON_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK; |
switch ( ctx->Depth.Func ) { |
case GL_NEVER: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEVER; |
break; |
case GL_LESS: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LESS; |
break; |
case GL_EQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_EQUAL; |
break; |
case GL_LEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LEQUAL; |
break; |
case GL_GREATER: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GREATER; |
break; |
case GL_NOTEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEQUAL; |
break; |
case GL_GEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GEQUAL; |
break; |
case GL_ALWAYS: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_ALWAYS; |
break; |
} |
} |
static void radeonDepthMask( struct gl_context *ctx, GLboolean flag ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
RADEON_STATECHANGE( rmesa, ctx ); |
if ( ctx->Depth.Mask ) { |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_WRITE_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_WRITE_ENABLE; |
} |
} |
/* ============================================================= |
* Fog |
*/ |
static void radeonFogfv( struct gl_context *ctx, GLenum pname, const GLfloat *param ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
union { int i; float f; } c, d; |
GLubyte col[4]; |
switch (pname) { |
case GL_FOG_MODE: |
if (!ctx->Fog.Enabled) |
return; |
RADEON_STATECHANGE(rmesa, tcl); |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK; |
switch (ctx->Fog.Mode) { |
case GL_LINEAR: |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR; |
break; |
case GL_EXP: |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP; |
break; |
case GL_EXP2: |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2; |
break; |
default: |
return; |
} |
/* fallthrough */ |
case GL_FOG_DENSITY: |
case GL_FOG_START: |
case GL_FOG_END: |
if (!ctx->Fog.Enabled) |
return; |
c.i = rmesa->hw.fog.cmd[FOG_C]; |
d.i = rmesa->hw.fog.cmd[FOG_D]; |
switch (ctx->Fog.Mode) { |
case GL_EXP: |
c.f = 0.0; |
/* While this is the opposite sign from the DDK, it makes the fog test |
* pass, and matches r200. |
*/ |
d.f = -ctx->Fog.Density; |
break; |
case GL_EXP2: |
c.f = 0.0; |
d.f = -(ctx->Fog.Density * ctx->Fog.Density); |
break; |
case GL_LINEAR: |
if (ctx->Fog.Start == ctx->Fog.End) { |
c.f = 1.0F; |
d.f = 1.0F; |
} else { |
c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); |
/* While this is the opposite sign from the DDK, it makes the fog |
* test pass, and matches r200. |
*/ |
d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start); |
} |
break; |
default: |
break; |
} |
if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) { |
RADEON_STATECHANGE( rmesa, fog ); |
rmesa->hw.fog.cmd[FOG_C] = c.i; |
rmesa->hw.fog.cmd[FOG_D] = d.i; |
} |
break; |
case GL_FOG_COLOR: |
RADEON_STATECHANGE( rmesa, ctx ); |
_mesa_unclamped_float_rgba_to_ubyte(col, ctx->Fog.Color ); |
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~RADEON_FOG_COLOR_MASK; |
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= |
radeonPackColor( 4, col[0], col[1], col[2], 0 ); |
break; |
case GL_FOG_COORD_SRC: |
radeonUpdateSpecular( ctx ); |
break; |
default: |
return; |
} |
} |
/* ============================================================= |
* Culling |
*/ |
static void radeonCullFace( struct gl_context *ctx, GLenum unused ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; |
GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL]; |
s |= RADEON_FFACE_SOLID | RADEON_BFACE_SOLID; |
t &= ~(RADEON_CULL_FRONT | RADEON_CULL_BACK); |
if ( ctx->Polygon.CullFlag ) { |
switch ( ctx->Polygon.CullFaceMode ) { |
case GL_FRONT: |
s &= ~RADEON_FFACE_SOLID; |
t |= RADEON_CULL_FRONT; |
break; |
case GL_BACK: |
s &= ~RADEON_BFACE_SOLID; |
t |= RADEON_CULL_BACK; |
break; |
case GL_FRONT_AND_BACK: |
s &= ~(RADEON_FFACE_SOLID | RADEON_BFACE_SOLID); |
t |= (RADEON_CULL_FRONT | RADEON_CULL_BACK); |
break; |
} |
} |
if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { |
RADEON_STATECHANGE(rmesa, set ); |
rmesa->hw.set.cmd[SET_SE_CNTL] = s; |
} |
if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) { |
RADEON_STATECHANGE(rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t; |
} |
} |
static void radeonFrontFace( struct gl_context *ctx, GLenum mode ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
int cull_face = (mode == GL_CW) ? RADEON_FFACE_CULL_CW : RADEON_FFACE_CULL_CCW; |
RADEON_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_FFACE_CULL_DIR_MASK; |
RADEON_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_CULL_FRONT_IS_CCW; |
/* Winding is inverted when rendering to FBO */ |
if (ctx->DrawBuffer && _mesa_is_user_fbo(ctx->DrawBuffer)) |
cull_face = (mode == GL_CCW) ? RADEON_FFACE_CULL_CW : RADEON_FFACE_CULL_CCW; |
rmesa->hw.set.cmd[SET_SE_CNTL] |= cull_face; |
if ( mode == GL_CCW ) |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_CULL_FRONT_IS_CCW; |
} |
/* ============================================================= |
* Line state |
*/ |
static void radeonLineWidth( struct gl_context *ctx, GLfloat widthf ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
RADEON_STATECHANGE( rmesa, lin ); |
RADEON_STATECHANGE( rmesa, set ); |
/* Line width is stored in U6.4 format. |
*/ |
rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (GLuint)(widthf * 16.0); |
if ( widthf > 1.0 ) { |
rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_WIDELINE_ENABLE; |
} else { |
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_WIDELINE_ENABLE; |
} |
} |
static void radeonLineStipple( struct gl_context *ctx, GLint factor, GLushort pattern ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
RADEON_STATECHANGE( rmesa, lin ); |
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = |
((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern)); |
} |
/* ============================================================= |
* Masks |
*/ |
static void radeonColorMask( struct gl_context *ctx, |
GLboolean r, GLboolean g, |
GLboolean b, GLboolean a ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
struct radeon_renderbuffer *rrb; |
GLuint mask; |
rrb = radeon_get_colorbuffer(&rmesa->radeon); |
if (!rrb) |
return; |
mask = radeonPackColor( rrb->cpp, |
ctx->Color.ColorMask[0][RCOMP], |
ctx->Color.ColorMask[0][GCOMP], |
ctx->Color.ColorMask[0][BCOMP], |
ctx->Color.ColorMask[0][ACOMP] ); |
if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) { |
RADEON_STATECHANGE( rmesa, msk ); |
rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask; |
} |
} |
/* ============================================================= |
* Polygon state |
*/ |
static void radeonPolygonOffset( struct gl_context *ctx, |
GLfloat factor, GLfloat units ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF; |
float_ui32_type constant = { units * depthScale }; |
float_ui32_type factoru = { factor }; |
RADEON_STATECHANGE( rmesa, zbs ); |
rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32; |
rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32; |
} |
static void radeonPolygonMode( struct gl_context *ctx, GLenum face, GLenum mode ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL); |
/* Can't generally do unfilled via tcl, but some good special |
* cases work. |
*/ |
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, unfilled); |
if (rmesa->radeon.TclFallback) { |
radeonChooseRenderState( ctx ); |
radeonChooseVertexState( ctx ); |
} |
} |
/* ============================================================= |
* Rendering attributes |
* |
* We really don't want to recalculate all this every time we bind a |
* texture. These things shouldn't change all that often, so it makes |
* sense to break them out of the core texture state update routines. |
*/ |
/* Examine lighting and texture state to determine if separate specular |
* should be enabled. |
*/ |
static void radeonUpdateSpecular( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL]; |
GLuint flag = 0; |
RADEON_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR; |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE; |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC; |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_DIFFUSE; |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE; |
p &= ~RADEON_SPECULAR_ENABLE; |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_DIFFUSE_SPECULAR_COMBINE; |
if (ctx->Light.Enabled && |
ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) { |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR; |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; |
p |= RADEON_SPECULAR_ENABLE; |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= |
~RADEON_DIFFUSE_SPECULAR_COMBINE; |
} |
else if (ctx->Light.Enabled) { |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; |
} else if (ctx->Fog.ColorSumEnabled ) { |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; |
p |= RADEON_SPECULAR_ENABLE; |
} else { |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; |
} |
if (ctx->Fog.Enabled) { |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; |
if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH) { |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR; |
/* Bizzare: have to leave lighting enabled to get fog. */ |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; |
} |
else { |
/* cannot do tcl fog factor calculation with fog coord source |
* (send precomputed factors). Cannot use precomputed fog |
* factors together with tcl spec light (need tcl fallback) */ |
flag = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] & |
RADEON_TCL_COMPUTE_SPECULAR) != 0; |
} |
} |
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_FOGCOORDSPEC, flag); |
if (_mesa_need_secondary_color(ctx)) { |
assert( (p & RADEON_SPECULAR_ENABLE) != 0 ); |
} else { |
assert( (p & RADEON_SPECULAR_ENABLE) == 0 ); |
} |
if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) { |
RADEON_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p; |
} |
/* Update vertex/render formats |
*/ |
if (rmesa->radeon.TclFallback) { |
radeonChooseRenderState( ctx ); |
radeonChooseVertexState( ctx ); |
} |
} |
/* ============================================================= |
* Materials |
*/ |
/* Update on colormaterial, material emmissive/ambient, |
* lightmodel.globalambient |
*/ |
static void update_global_ambient( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
float *fcmd = (float *)RADEON_DB_STATE( glt ); |
/* Need to do more if both emmissive & ambient are PREMULT: |
* Hope this is not needed for MULT |
*/ |
if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] & |
((3 << RADEON_EMISSIVE_SOURCE_SHIFT) | |
(3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0) |
{ |
COPY_3V( &fcmd[GLT_RED], |
ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]); |
ACC_SCALE_3V( &fcmd[GLT_RED], |
ctx->Light.Model.Ambient, |
ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]); |
} |
else |
{ |
COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient ); |
} |
RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt); |
} |
/* Update on change to |
* - light[p].colors |
* - light[p].enabled |
*/ |
static void update_light_colors( struct gl_context *ctx, GLuint p ) |
{ |
struct gl_light *l = &ctx->Light.Light[p]; |
/* fprintf(stderr, "%s\n", __FUNCTION__); */ |
if (l->Enabled) { |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
float *fcmd = (float *)RADEON_DB_STATE( lit[p] ); |
COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient ); |
COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse ); |
COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular ); |
RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); |
} |
} |
/* Also fallback for asym colormaterial mode in twoside lighting... |
*/ |
static void check_twoside_fallback( struct gl_context *ctx ) |
{ |
GLboolean fallback = GL_FALSE; |
GLint i; |
if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) { |
if (ctx->Light.ColorMaterialEnabled && |
(ctx->Light._ColorMaterialBitmask & BACK_MATERIAL_BITS) != |
((ctx->Light._ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1)) |
fallback = GL_TRUE; |
else { |
for (i = MAT_ATTRIB_FRONT_AMBIENT; i < MAT_ATTRIB_FRONT_INDEXES; i+=2) |
if (memcmp( ctx->Light.Material.Attrib[i], |
ctx->Light.Material.Attrib[i+1], |
sizeof(GLfloat)*4) != 0) { |
fallback = GL_TRUE; |
break; |
} |
} |
} |
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback ); |
} |
static void radeonColorMaterial( struct gl_context *ctx, GLenum face, GLenum mode ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]; |
light_model_ctl1 &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) | |
(3 << RADEON_AMBIENT_SOURCE_SHIFT) | |
(3 << RADEON_DIFFUSE_SOURCE_SHIFT) | |
(3 << RADEON_SPECULAR_SOURCE_SHIFT)); |
if (ctx->Light.ColorMaterialEnabled) { |
GLuint mask = ctx->Light._ColorMaterialBitmask; |
if (mask & MAT_BIT_FRONT_EMISSION) { |
light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << |
RADEON_EMISSIVE_SOURCE_SHIFT); |
} |
else { |
light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << |
RADEON_EMISSIVE_SOURCE_SHIFT); |
} |
if (mask & MAT_BIT_FRONT_AMBIENT) { |
light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << |
RADEON_AMBIENT_SOURCE_SHIFT); |
} |
else { |
light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << |
RADEON_AMBIENT_SOURCE_SHIFT); |
} |
if (mask & MAT_BIT_FRONT_DIFFUSE) { |
light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << |
RADEON_DIFFUSE_SOURCE_SHIFT); |
} |
else { |
light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << |
RADEON_DIFFUSE_SOURCE_SHIFT); |
} |
if (mask & MAT_BIT_FRONT_SPECULAR) { |
light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << |
RADEON_SPECULAR_SOURCE_SHIFT); |
} |
else { |
light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << |
RADEON_SPECULAR_SOURCE_SHIFT); |
} |
} |
else { |
/* Default to MULT: |
*/ |
light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << RADEON_EMISSIVE_SOURCE_SHIFT) | |
(RADEON_LM_SOURCE_STATE_MULT << RADEON_AMBIENT_SOURCE_SHIFT) | |
(RADEON_LM_SOURCE_STATE_MULT << RADEON_DIFFUSE_SOURCE_SHIFT) | |
(RADEON_LM_SOURCE_STATE_MULT << RADEON_SPECULAR_SOURCE_SHIFT); |
} |
if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) { |
RADEON_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl1; |
} |
} |
void radeonUpdateMaterial( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLfloat (*mat)[4] = ctx->Light.Material.Attrib; |
GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl ); |
GLuint mask = ~0; |
if (ctx->Light.ColorMaterialEnabled) |
mask &= ~ctx->Light._ColorMaterialBitmask; |
if (RADEON_DEBUG & RADEON_STATE) |
fprintf(stderr, "%s\n", __FUNCTION__); |
if (mask & MAT_BIT_FRONT_EMISSION) { |
fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0]; |
fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1]; |
fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2]; |
fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3]; |
} |
if (mask & MAT_BIT_FRONT_AMBIENT) { |
fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0]; |
fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1]; |
fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2]; |
fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3]; |
} |
if (mask & MAT_BIT_FRONT_DIFFUSE) { |
fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0]; |
fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1]; |
fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2]; |
fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3]; |
} |
if (mask & MAT_BIT_FRONT_SPECULAR) { |
fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0]; |
fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1]; |
fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2]; |
fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3]; |
} |
if (mask & MAT_BIT_FRONT_SHININESS) { |
fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0]; |
} |
RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl ); |
check_twoside_fallback( ctx ); |
/* update_global_ambient( ctx );*/ |
} |
/* _NEW_LIGHT |
* _NEW_MODELVIEW |
* _MESA_NEW_NEED_EYE_COORDS |
* |
* Uses derived state from mesa: |
* _VP_inf_norm |
* _h_inf_norm |
* _Position |
* _NormSpotDirection |
* _ModelViewInvScale |
* _NeedEyeCoords |
* _EyeZDir |
* |
* which are calculated in light.c and are correct for the current |
* lighting space (model or eye), hence dependencies on _NEW_MODELVIEW |
* and _MESA_NEW_NEED_EYE_COORDS. |
*/ |
static void update_light( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
/* Have to check these, or have an automatic shortcircuit mechanism |
* to remove noop statechanges. (Or just do a better job on the |
* front end). |
*/ |
{ |
GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]; |
if (ctx->_NeedEyeCoords) |
tmp &= ~RADEON_LIGHT_IN_MODELSPACE; |
else |
tmp |= RADEON_LIGHT_IN_MODELSPACE; |
/* Leave this test disabled: (unexplained q3 lockup) (even with |
new packets) |
*/ |
if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) |
{ |
RADEON_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp; |
} |
} |
{ |
GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye ); |
fcmd[EYE_X] = ctx->_EyeZDir[0]; |
fcmd[EYE_Y] = ctx->_EyeZDir[1]; |
fcmd[EYE_Z] = - ctx->_EyeZDir[2]; |
fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale; |
RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye ); |
} |
if (ctx->Light.Enabled) { |
GLint p; |
for (p = 0 ; p < MAX_LIGHTS; p++) { |
if (ctx->Light.Light[p].Enabled) { |
struct gl_light *l = &ctx->Light.Light[p]; |
GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] ); |
if (l->EyePosition[3] == 0.0) { |
COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm ); |
COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm ); |
fcmd[LIT_POSITION_W] = 0; |
fcmd[LIT_DIRECTION_W] = 0; |
} else { |
COPY_4V( &fcmd[LIT_POSITION_X], l->_Position ); |
fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0]; |
fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1]; |
fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2]; |
fcmd[LIT_DIRECTION_W] = 0; |
} |
RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); |
} |
} |
} |
} |
static void radeonLightfv( struct gl_context *ctx, GLenum light, |
GLenum pname, const GLfloat *params ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLint p = light - GL_LIGHT0; |
struct gl_light *l = &ctx->Light.Light[p]; |
GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd; |
switch (pname) { |
case GL_AMBIENT: |
case GL_DIFFUSE: |
case GL_SPECULAR: |
update_light_colors( ctx, p ); |
break; |
case GL_SPOT_DIRECTION: |
/* picked up in update_light */ |
break; |
case GL_POSITION: { |
/* positions picked up in update_light, but can do flag here */ |
GLuint flag; |
GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; |
/* FIXME: Set RANGE_ATTEN only when needed */ |
if (p&1) |
flag = RADEON_LIGHT_1_IS_LOCAL; |
else |
flag = RADEON_LIGHT_0_IS_LOCAL; |
RADEON_STATECHANGE(rmesa, tcl); |
if (l->EyePosition[3] != 0.0F) |
rmesa->hw.tcl.cmd[idx] |= flag; |
else |
rmesa->hw.tcl.cmd[idx] &= ~flag; |
break; |
} |
case GL_SPOT_EXPONENT: |
RADEON_STATECHANGE(rmesa, lit[p]); |
fcmd[LIT_SPOT_EXPONENT] = params[0]; |
break; |
case GL_SPOT_CUTOFF: { |
GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT; |
GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; |
RADEON_STATECHANGE(rmesa, lit[p]); |
fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff; |
RADEON_STATECHANGE(rmesa, tcl); |
if (l->SpotCutoff != 180.0F) |
rmesa->hw.tcl.cmd[idx] |= flag; |
else |
rmesa->hw.tcl.cmd[idx] &= ~flag; |
break; |
} |
case GL_CONSTANT_ATTENUATION: |
RADEON_STATECHANGE(rmesa, lit[p]); |
fcmd[LIT_ATTEN_CONST] = params[0]; |
if ( params[0] == 0.0 ) |
fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX; |
else |
fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0]; |
break; |
case GL_LINEAR_ATTENUATION: |
RADEON_STATECHANGE(rmesa, lit[p]); |
fcmd[LIT_ATTEN_LINEAR] = params[0]; |
break; |
case GL_QUADRATIC_ATTENUATION: |
RADEON_STATECHANGE(rmesa, lit[p]); |
fcmd[LIT_ATTEN_QUADRATIC] = params[0]; |
break; |
default: |
return; |
} |
/* Set RANGE_ATTEN only when needed */ |
switch (pname) { |
case GL_POSITION: |
case GL_CONSTANT_ATTENUATION: |
case GL_LINEAR_ATTENUATION: |
case GL_QUADRATIC_ATTENUATION: |
{ |
GLuint *icmd = (GLuint *)RADEON_DB_STATE( tcl ); |
GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; |
GLuint atten_flag = ( p&1 ) ? RADEON_LIGHT_1_ENABLE_RANGE_ATTEN |
: RADEON_LIGHT_0_ENABLE_RANGE_ATTEN; |
GLuint atten_const_flag = ( p&1 ) ? RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN |
: RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN; |
if ( l->EyePosition[3] == 0.0F || |
( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) && |
fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) { |
/* Disable attenuation */ |
icmd[idx] &= ~atten_flag; |
} else { |
if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) { |
/* Enable only constant portion of attenuation calculation */ |
icmd[idx] |= ( atten_flag | atten_const_flag ); |
} else { |
/* Enable full attenuation calculation */ |
icmd[idx] &= ~atten_const_flag; |
icmd[idx] |= atten_flag; |
} |
} |
RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tcl ); |
break; |
} |
default: |
break; |
} |
} |
static void radeonLightModelfv( struct gl_context *ctx, GLenum pname, |
const GLfloat *param ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
switch (pname) { |
case GL_LIGHT_MODEL_AMBIENT: |
update_global_ambient( ctx ); |
break; |
case GL_LIGHT_MODEL_LOCAL_VIEWER: |
RADEON_STATECHANGE( rmesa, tcl ); |
if (ctx->Light.Model.LocalViewer) |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER; |
else |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER; |
break; |
case GL_LIGHT_MODEL_TWO_SIDE: |
RADEON_STATECHANGE( rmesa, tcl ); |
if (ctx->Light.Model.TwoSide) |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE; |
else |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE; |
check_twoside_fallback( ctx ); |
if (rmesa->radeon.TclFallback) { |
radeonChooseRenderState( ctx ); |
radeonChooseVertexState( ctx ); |
} |
break; |
case GL_LIGHT_MODEL_COLOR_CONTROL: |
radeonUpdateSpecular(ctx); |
break; |
default: |
break; |
} |
} |
static void radeonShadeModel( struct gl_context *ctx, GLenum mode ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; |
s &= ~(RADEON_DIFFUSE_SHADE_MASK | |
RADEON_ALPHA_SHADE_MASK | |
RADEON_SPECULAR_SHADE_MASK | |
RADEON_FOG_SHADE_MASK); |
switch ( mode ) { |
case GL_FLAT: |
s |= (RADEON_DIFFUSE_SHADE_FLAT | |
RADEON_ALPHA_SHADE_FLAT | |
RADEON_SPECULAR_SHADE_FLAT | |
RADEON_FOG_SHADE_FLAT); |
break; |
case GL_SMOOTH: |
s |= (RADEON_DIFFUSE_SHADE_GOURAUD | |
RADEON_ALPHA_SHADE_GOURAUD | |
RADEON_SPECULAR_SHADE_GOURAUD | |
RADEON_FOG_SHADE_GOURAUD); |
break; |
default: |
return; |
} |
if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { |
RADEON_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_SE_CNTL] = s; |
} |
} |
/* ============================================================= |
* User clip planes |
*/ |
static void radeonClipPlane( struct gl_context *ctx, GLenum plane, const GLfloat *eq ) |
{ |
GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0; |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; |
RADEON_STATECHANGE( rmesa, ucp[p] ); |
rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; |
rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; |
rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; |
rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; |
} |
static void radeonUpdateClipPlanes( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint p; |
for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { |
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { |
GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; |
RADEON_STATECHANGE( rmesa, ucp[p] ); |
rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; |
rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; |
rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; |
rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; |
} |
} |
} |
/* ============================================================= |
* Stencil |
*/ |
static void |
radeonStencilFuncSeparate( struct gl_context *ctx, GLenum face, GLenum func, |
GLint ref, GLuint mask ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint refmask = ((_mesa_get_stencil_ref(ctx, 0) << RADEON_STENCIL_REF_SHIFT) | |
((ctx->Stencil.ValueMask[0] & 0xff) << RADEON_STENCIL_MASK_SHIFT)); |
RADEON_STATECHANGE( rmesa, ctx ); |
RADEON_STATECHANGE( rmesa, msk ); |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_STENCIL_TEST_MASK; |
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(RADEON_STENCIL_REF_MASK| |
RADEON_STENCIL_VALUE_MASK); |
switch ( ctx->Stencil.Function[0] ) { |
case GL_NEVER: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEVER; |
break; |
case GL_LESS: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LESS; |
break; |
case GL_EQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_EQUAL; |
break; |
case GL_LEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LEQUAL; |
break; |
case GL_GREATER: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GREATER; |
break; |
case GL_NOTEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEQUAL; |
break; |
case GL_GEQUAL: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GEQUAL; |
break; |
case GL_ALWAYS: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_ALWAYS; |
break; |
} |
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask; |
} |
static void |
radeonStencilMaskSeparate( struct gl_context *ctx, GLenum face, GLuint mask ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
RADEON_STATECHANGE( rmesa, msk ); |
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK; |
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= |
((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT); |
} |
static void radeonStencilOpSeparate( struct gl_context *ctx, GLenum face, GLenum fail, |
GLenum zfail, GLenum zpass ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
/* radeon 7200 have stencil bug, DEC and INC_WRAP will actually both do DEC_WRAP, |
and DEC_WRAP (and INVERT) will do INVERT. No way to get correct INC_WRAP and DEC, |
but DEC_WRAP can be fixed by using DEC and INC_WRAP at least use INC. */ |
GLuint tempRADEON_STENCIL_FAIL_DEC_WRAP; |
GLuint tempRADEON_STENCIL_FAIL_INC_WRAP; |
GLuint tempRADEON_STENCIL_ZFAIL_DEC_WRAP; |
GLuint tempRADEON_STENCIL_ZFAIL_INC_WRAP; |
GLuint tempRADEON_STENCIL_ZPASS_DEC_WRAP; |
GLuint tempRADEON_STENCIL_ZPASS_INC_WRAP; |
if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_BROKEN_STENCIL) { |
tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC; |
tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC; |
tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC; |
tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC; |
tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC; |
tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC; |
} |
else { |
tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC_WRAP; |
tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC_WRAP; |
tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC_WRAP; |
tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC_WRAP; |
tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC_WRAP; |
tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC_WRAP; |
} |
RADEON_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK | |
RADEON_STENCIL_ZFAIL_MASK | |
RADEON_STENCIL_ZPASS_MASK); |
switch ( ctx->Stencil.FailFunc[0] ) { |
case GL_KEEP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_KEEP; |
break; |
case GL_ZERO: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_ZERO; |
break; |
case GL_REPLACE: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_REPLACE; |
break; |
case GL_INCR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INC; |
break; |
case GL_DECR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC; |
break; |
case GL_INCR_WRAP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_INC_WRAP; |
break; |
case GL_DECR_WRAP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_DEC_WRAP; |
break; |
case GL_INVERT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT; |
break; |
} |
switch ( ctx->Stencil.ZFailFunc[0] ) { |
case GL_KEEP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_KEEP; |
break; |
case GL_ZERO: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_ZERO; |
break; |
case GL_REPLACE: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_REPLACE; |
break; |
case GL_INCR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INC; |
break; |
case GL_DECR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC; |
break; |
case GL_INCR_WRAP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_INC_WRAP; |
break; |
case GL_DECR_WRAP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_DEC_WRAP; |
break; |
case GL_INVERT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT; |
break; |
} |
switch ( ctx->Stencil.ZPassFunc[0] ) { |
case GL_KEEP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_KEEP; |
break; |
case GL_ZERO: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_ZERO; |
break; |
case GL_REPLACE: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_REPLACE; |
break; |
case GL_INCR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INC; |
break; |
case GL_DECR: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC; |
break; |
case GL_INCR_WRAP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_INC_WRAP; |
break; |
case GL_DECR_WRAP: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_DEC_WRAP; |
break; |
case GL_INVERT: |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT; |
break; |
} |
} |
/* ============================================================= |
* Window position and viewport transformation |
*/ |
/* |
* To correctly position primitives: |
*/ |
#define SUBPIXEL_X 0.125 |
#define SUBPIXEL_Y 0.125 |
/** |
* Called when window size or position changes or viewport or depth range |
* state is changed. We update the hardware viewport state here. |
*/ |
void radeonUpdateWindow( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
__DRIdrawable *dPriv = radeon_get_drawable(&rmesa->radeon); |
GLfloat xoffset = 0.0; |
GLfloat yoffset = dPriv ? (GLfloat) dPriv->h : 0; |
const GLfloat *v = ctx->Viewport._WindowMap.m; |
const GLboolean render_to_fbo = (ctx->DrawBuffer ? _mesa_is_user_fbo(ctx->DrawBuffer) : 0); |
const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF; |
GLfloat y_scale, y_bias; |
if (render_to_fbo) { |
y_scale = 1.0; |
y_bias = 0; |
} else { |
y_scale = -1.0; |
y_bias = yoffset; |
} |
float_ui32_type sx = { v[MAT_SX] }; |
float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X }; |
float_ui32_type sy = { v[MAT_SY] * y_scale }; |
float_ui32_type ty = { (v[MAT_TY] * y_scale) + y_bias + SUBPIXEL_Y }; |
float_ui32_type sz = { v[MAT_SZ] * depthScale }; |
float_ui32_type tz = { v[MAT_TZ] * depthScale }; |
RADEON_STATECHANGE( rmesa, vpt ); |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32; |
} |
static void radeonViewport( struct gl_context *ctx, GLint x, GLint y, |
GLsizei width, GLsizei height ) |
{ |
/* Don't pipeline viewport changes, conflict with window offset |
* setting below. Could apply deltas to rescue pipelined viewport |
* values, or keep the originals hanging around. |
*/ |
radeonUpdateWindow( ctx ); |
radeon_viewport(ctx, x, y, width, height); |
} |
static void radeonDepthRange( struct gl_context *ctx, GLclampd nearval, |
GLclampd farval ) |
{ |
radeonUpdateWindow( ctx ); |
} |
void radeonUpdateViewportOffset( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
__DRIdrawable *dPriv = radeon_get_drawable(&rmesa->radeon); |
GLfloat xoffset = 0.0; |
GLfloat yoffset = (GLfloat)dPriv->h; |
const GLfloat *v = ctx->Viewport._WindowMap.m; |
float_ui32_type tx; |
float_ui32_type ty; |
tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X; |
ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y; |
if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 || |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 ) |
{ |
/* Note: this should also modify whatever data the context reset |
* code uses... |
*/ |
RADEON_STATECHANGE( rmesa, vpt ); |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; |
/* update polygon stipple x/y screen offset */ |
{ |
GLuint stx, sty; |
GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC]; |
m &= ~(RADEON_STIPPLE_X_OFFSET_MASK | |
RADEON_STIPPLE_Y_OFFSET_MASK); |
/* add magic offsets, then invert */ |
stx = 31 - ((-1) & RADEON_STIPPLE_COORD_MASK); |
sty = 31 - ((dPriv->h - 1) |
& RADEON_STIPPLE_COORD_MASK); |
m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) | |
(sty << RADEON_STIPPLE_Y_OFFSET_SHIFT)); |
if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) { |
RADEON_STATECHANGE( rmesa, msc ); |
rmesa->hw.msc.cmd[MSC_RE_MISC] = m; |
} |
} |
} |
radeonUpdateScissor( ctx ); |
} |
/* ============================================================= |
* Miscellaneous |
*/ |
static void radeonRenderMode( struct gl_context *ctx, GLenum mode ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
FALLBACK( rmesa, RADEON_FALLBACK_RENDER_MODE, (mode != GL_RENDER) ); |
} |
static GLuint radeon_rop_tab[] = { |
RADEON_ROP_CLEAR, |
RADEON_ROP_AND, |
RADEON_ROP_AND_REVERSE, |
RADEON_ROP_COPY, |
RADEON_ROP_AND_INVERTED, |
RADEON_ROP_NOOP, |
RADEON_ROP_XOR, |
RADEON_ROP_OR, |
RADEON_ROP_NOR, |
RADEON_ROP_EQUIV, |
RADEON_ROP_INVERT, |
RADEON_ROP_OR_REVERSE, |
RADEON_ROP_COPY_INVERTED, |
RADEON_ROP_OR_INVERTED, |
RADEON_ROP_NAND, |
RADEON_ROP_SET, |
}; |
static void radeonLogicOpCode( struct gl_context *ctx, GLenum opcode ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint rop = (GLuint)opcode - GL_CLEAR; |
ASSERT( rop < 16 ); |
RADEON_STATECHANGE( rmesa, msk ); |
rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop]; |
} |
/* ============================================================= |
* State enable/disable |
*/ |
static void radeonEnable( struct gl_context *ctx, GLenum cap, GLboolean state ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint p, flag; |
if ( RADEON_DEBUG & RADEON_STATE ) |
fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr( cap ), |
state ? "GL_TRUE" : "GL_FALSE" ); |
switch ( cap ) { |
/* Fast track this one... |
*/ |
case GL_TEXTURE_1D: |
case GL_TEXTURE_2D: |
case GL_TEXTURE_3D: |
break; |
case GL_ALPHA_TEST: |
RADEON_STATECHANGE( rmesa, ctx ); |
if (state) { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE; |
} |
break; |
case GL_BLEND: |
RADEON_STATECHANGE( rmesa, ctx ); |
if (state) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ALPHA_BLEND_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE; |
} |
if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled |
&& ctx->Color.Blend[0].EquationRGB == GL_LOGIC_OP)) ) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; |
} |
/* Catch a possible fallback: |
*/ |
if (state) { |
ctx->Driver.BlendEquationSeparate( ctx, |
ctx->Color.Blend[0].EquationRGB, |
ctx->Color.Blend[0].EquationA ); |
ctx->Driver.BlendFuncSeparate( ctx, ctx->Color.Blend[0].SrcRGB, |
ctx->Color.Blend[0].DstRGB, |
ctx->Color.Blend[0].SrcA, |
ctx->Color.Blend[0].DstA ); |
} |
else { |
FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, GL_FALSE ); |
FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, GL_FALSE ); |
} |
break; |
case GL_CLIP_PLANE0: |
case GL_CLIP_PLANE1: |
case GL_CLIP_PLANE2: |
case GL_CLIP_PLANE3: |
case GL_CLIP_PLANE4: |
case GL_CLIP_PLANE5: |
p = cap-GL_CLIP_PLANE0; |
RADEON_STATECHANGE( rmesa, tcl ); |
if (state) { |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (RADEON_UCP_ENABLE_0<<p); |
radeonClipPlane( ctx, cap, NULL ); |
} |
else { |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(RADEON_UCP_ENABLE_0<<p); |
} |
break; |
case GL_COLOR_MATERIAL: |
radeonColorMaterial( ctx, 0, 0 ); |
radeonUpdateMaterial( ctx ); |
break; |
case GL_CULL_FACE: |
radeonCullFace( ctx, 0 ); |
break; |
case GL_DEPTH_TEST: |
RADEON_STATECHANGE(rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_Z_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE; |
} |
break; |
case GL_DITHER: |
RADEON_STATECHANGE(rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE; |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE; |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable; |
} |
break; |
case GL_FOG: |
RADEON_STATECHANGE(rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE; |
radeonFogfv( ctx, GL_FOG_MODE, NULL ); |
} else { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE; |
RADEON_STATECHANGE(rmesa, tcl); |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK; |
} |
radeonUpdateSpecular( ctx ); /* for PK_SPEC */ |
_mesa_allow_light_in_model( ctx, !state ); |
break; |
case GL_LIGHT0: |
case GL_LIGHT1: |
case GL_LIGHT2: |
case GL_LIGHT3: |
case GL_LIGHT4: |
case GL_LIGHT5: |
case GL_LIGHT6: |
case GL_LIGHT7: |
RADEON_STATECHANGE(rmesa, tcl); |
p = cap - GL_LIGHT0; |
if (p&1) |
flag = (RADEON_LIGHT_1_ENABLE | |
RADEON_LIGHT_1_ENABLE_AMBIENT | |
RADEON_LIGHT_1_ENABLE_SPECULAR); |
else |
flag = (RADEON_LIGHT_0_ENABLE | |
RADEON_LIGHT_0_ENABLE_AMBIENT | |
RADEON_LIGHT_0_ENABLE_SPECULAR); |
if (state) |
rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag; |
else |
rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag; |
/* |
*/ |
update_light_colors( ctx, p ); |
break; |
case GL_LIGHTING: |
RADEON_STATECHANGE(rmesa, tcl); |
radeonUpdateSpecular(ctx); |
check_twoside_fallback( ctx ); |
break; |
case GL_LINE_SMOOTH: |
RADEON_STATECHANGE( rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_LINE; |
} else { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE; |
} |
break; |
case GL_LINE_STIPPLE: |
RADEON_STATECHANGE( rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_PATTERN_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE; |
} |
break; |
case GL_COLOR_LOGIC_OP: |
RADEON_STATECHANGE( rmesa, ctx ); |
if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled |
&& ctx->Color.Blend[0].EquationRGB == GL_LOGIC_OP)) ) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; |
} |
break; |
case GL_NORMALIZE: |
RADEON_STATECHANGE( rmesa, tcl ); |
if ( state ) { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_NORMALIZE_NORMALS; |
} else { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS; |
} |
break; |
case GL_POLYGON_OFFSET_POINT: |
RADEON_STATECHANGE( rmesa, set ); |
if ( state ) { |
rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_POINT; |
} else { |
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT; |
} |
break; |
case GL_POLYGON_OFFSET_LINE: |
RADEON_STATECHANGE( rmesa, set ); |
if ( state ) { |
rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_LINE; |
} else { |
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE; |
} |
break; |
case GL_POLYGON_OFFSET_FILL: |
RADEON_STATECHANGE( rmesa, set ); |
if ( state ) { |
rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_TRI; |
} else { |
rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI; |
} |
break; |
case GL_POLYGON_SMOOTH: |
RADEON_STATECHANGE( rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_POLY; |
} else { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY; |
} |
break; |
case GL_POLYGON_STIPPLE: |
RADEON_STATECHANGE(rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_STIPPLE_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_STIPPLE_ENABLE; |
} |
break; |
case GL_RESCALE_NORMAL_EXT: { |
GLboolean tmp = ctx->_NeedEyeCoords ? state : !state; |
RADEON_STATECHANGE( rmesa, tcl ); |
if ( tmp ) { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS; |
} else { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS; |
} |
break; |
} |
case GL_SCISSOR_TEST: |
radeon_firevertices(&rmesa->radeon); |
rmesa->radeon.state.scissor.enabled = state; |
radeonUpdateScissor( ctx ); |
break; |
case GL_STENCIL_TEST: |
{ |
GLboolean hw_stencil = GL_FALSE; |
if (ctx->DrawBuffer) { |
struct radeon_renderbuffer *rrbStencil |
= radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); |
hw_stencil = (rrbStencil && rrbStencil->bo); |
} |
if (hw_stencil) { |
RADEON_STATECHANGE( rmesa, ctx ); |
if ( state ) { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE; |
} else { |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE; |
} |
} else { |
FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state ); |
} |
} |
break; |
case GL_TEXTURE_GEN_Q: |
case GL_TEXTURE_GEN_R: |
case GL_TEXTURE_GEN_S: |
case GL_TEXTURE_GEN_T: |
/* Picked up in radeonUpdateTextureState. |
*/ |
rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE; |
break; |
case GL_COLOR_SUM_EXT: |
radeonUpdateSpecular ( ctx ); |
break; |
default: |
return; |
} |
} |
static void radeonLightingSpaceChange( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLboolean tmp; |
RADEON_STATECHANGE( rmesa, tcl ); |
if (RADEON_DEBUG & RADEON_STATE) |
fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords, |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]); |
if (ctx->_NeedEyeCoords) |
tmp = ctx->Transform.RescaleNormals; |
else |
tmp = !ctx->Transform.RescaleNormals; |
if ( tmp ) { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS; |
} else { |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS; |
} |
if (RADEON_DEBUG & RADEON_STATE) |
fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords, |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]); |
} |
/* ============================================================= |
* Deferred state management - matrices, textures, other? |
*/ |
void radeonUploadTexMatrix( r100ContextPtr rmesa, |
int unit, GLboolean swapcols ) |
{ |
/* Here's how this works: on r100, only 3 tex coords can be submitted, so the |
vector looks like this probably: (s t r|q 0) (not sure if the last coord |
is hardwired to 0, could be 1 too). Interestingly, it actually looks like |
texgen generates all 4 coords, at least tests with projtex indicated that. |
So: if we need the q coord in the end (solely determined by the texture |
target, i.e. 2d / 1d / texrect targets) we swap the third and 4th row. |
Additionally, if we don't have texgen but 4 tex coords submitted, we swap |
column 3 and 4 (for the 2d / 1d / texrect targets) since the q coord |
will get submitted in the "wrong", i.e. 3rd, slot. |
If an app submits 3 coords for 2d targets, we assume it is saving on vertex |
size and using the texture matrix to swap the r and q coords around (ut2k3 |
does exactly that), so we don't need the 3rd / 4th column swap - still need |
the 3rd / 4th row swap of course. This will potentially break for apps which |
use TexCoord3x just for fun. Additionally, it will never work if an app uses |
an "advanced" texture matrix and relies on all 4 texcoord inputs to generate |
the maximum needed 3. This seems impossible to do with hw tcl on r100, and |
incredibly hard to detect so we can't just fallback in such a case. Assume |
it never happens... - rs |
*/ |
int idx = TEXMAT_0 + unit; |
float *dest = ((float *)RADEON_DB_STATE( mat[idx] )) + MAT_ELT_0; |
int i; |
struct gl_texture_unit tUnit = rmesa->radeon.glCtx.Texture.Unit[unit]; |
GLfloat *src = rmesa->tmpmat[unit].m; |
rmesa->TexMatColSwap &= ~(1 << unit); |
if ((tUnit._ReallyEnabled & (TEXTURE_3D_BIT | TEXTURE_CUBE_BIT)) == 0) { |
if (swapcols) { |
rmesa->TexMatColSwap |= 1 << unit; |
/* attention some elems are swapped 2 times! */ |
*dest++ = src[0]; |
*dest++ = src[4]; |
*dest++ = src[12]; |
*dest++ = src[8]; |
*dest++ = src[1]; |
*dest++ = src[5]; |
*dest++ = src[13]; |
*dest++ = src[9]; |
*dest++ = src[2]; |
*dest++ = src[6]; |
*dest++ = src[15]; |
*dest++ = src[11]; |
/* those last 4 are probably never used */ |
*dest++ = src[3]; |
*dest++ = src[7]; |
*dest++ = src[14]; |
*dest++ = src[10]; |
} |
else { |
for (i = 0; i < 2; i++) { |
*dest++ = src[i]; |
*dest++ = src[i+4]; |
*dest++ = src[i+8]; |
*dest++ = src[i+12]; |
} |
for (i = 3; i >= 2; i--) { |
*dest++ = src[i]; |
*dest++ = src[i+4]; |
*dest++ = src[i+8]; |
*dest++ = src[i+12]; |
} |
} |
} |
else { |
for (i = 0 ; i < 4 ; i++) { |
*dest++ = src[i]; |
*dest++ = src[i+4]; |
*dest++ = src[i+8]; |
*dest++ = src[i+12]; |
} |
} |
RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); |
} |
static void upload_matrix( r100ContextPtr rmesa, GLfloat *src, int idx ) |
{ |
float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0; |
int i; |
for (i = 0 ; i < 4 ; i++) { |
*dest++ = src[i]; |
*dest++ = src[i+4]; |
*dest++ = src[i+8]; |
*dest++ = src[i+12]; |
} |
RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); |
} |
static void upload_matrix_t( r100ContextPtr rmesa, GLfloat *src, int idx ) |
{ |
float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0; |
memcpy(dest, src, 16*sizeof(float)); |
RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); |
} |
static void update_texturematrix( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT( ctx ); |
GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL]; |
GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]; |
int unit; |
GLuint texMatEnabled = 0; |
rmesa->NeedTexMatrix = 0; |
rmesa->TexMatColSwap = 0; |
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) { |
if (ctx->Texture.Unit[unit]._ReallyEnabled) { |
GLboolean needMatrix = GL_FALSE; |
if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) { |
needMatrix = GL_TRUE; |
texMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE | |
RADEON_TEXMAT_0_ENABLE) << unit; |
if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) { |
/* Need to preconcatenate any active texgen |
* obj/eyeplane matrices: |
*/ |
_math_matrix_mul_matrix( &rmesa->tmpmat[unit], |
ctx->TextureMatrixStack[unit].Top, |
&rmesa->TexGenMatrix[unit] ); |
} |
else { |
_math_matrix_copy( &rmesa->tmpmat[unit], |
ctx->TextureMatrixStack[unit].Top ); |
} |
} |
else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) { |
_math_matrix_copy( &rmesa->tmpmat[unit], &rmesa->TexGenMatrix[unit] ); |
needMatrix = GL_TRUE; |
} |
if (needMatrix) { |
rmesa->NeedTexMatrix |= 1 << unit; |
radeonUploadTexMatrix( rmesa, unit, |
!ctx->Texture.Unit[unit].TexGenEnabled ); |
} |
} |
} |
tpc = (texMatEnabled | rmesa->TexGenEnabled); |
/* TCL_TEX_COMPUTED_x is TCL_TEX_INPUT_x | 0x8 */ |
vs &= ~((RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) | |
(RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) | |
(RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_2_OUTPUT_SHIFT)); |
vs |= (((tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE) << |
(RADEON_TCL_TEX_0_OUTPUT_SHIFT + 3)) | |
((tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE) << |
(RADEON_TCL_TEX_1_OUTPUT_SHIFT + 2)) | |
((tpc & RADEON_TEXGEN_TEXMAT_2_ENABLE) << |
(RADEON_TCL_TEX_2_OUTPUT_SHIFT + 1))); |
if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] || |
vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) { |
RADEON_STATECHANGE(rmesa, tcl); |
rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc; |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs; |
} |
} |
static GLboolean r100ValidateBuffers(struct gl_context *ctx) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
struct radeon_renderbuffer *rrb; |
int i, ret; |
radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs); |
rrb = radeon_get_colorbuffer(&rmesa->radeon); |
/* color buffer */ |
if (rrb && rrb->bo) { |
radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo, |
0, RADEON_GEM_DOMAIN_VRAM); |
} |
/* depth buffer */ |
rrb = radeon_get_depthbuffer(&rmesa->radeon); |
/* color buffer */ |
if (rrb && rrb->bo) { |
radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo, |
0, RADEON_GEM_DOMAIN_VRAM); |
} |
for (i = 0; i < ctx->Const.FragmentProgram.MaxTextureImageUnits; ++i) { |
radeonTexObj *t; |
if (!ctx->Texture.Unit[i]._ReallyEnabled) |
continue; |
t = rmesa->state.texture.unit[i].texobj; |
if (!t) |
continue; |
if (t->image_override && t->bo) |
radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo, |
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); |
else if (t->mt->bo) |
radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo, |
RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); |
} |
ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, first_elem(&rmesa->radeon.dma.reserved)->bo, RADEON_GEM_DOMAIN_GTT, 0); |
if (ret) |
return GL_FALSE; |
return GL_TRUE; |
} |
GLboolean radeonValidateState( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint new_state = rmesa->radeon.NewGLState; |
if (new_state & _NEW_BUFFERS) { |
_mesa_update_framebuffer(ctx); |
/* this updates the DrawBuffer's Width/Height if it's a FBO */ |
_mesa_update_draw_buffer_bounds(ctx); |
RADEON_STATECHANGE(rmesa, ctx); |
} |
if (new_state & _NEW_TEXTURE) { |
radeonUpdateTextureState( ctx ); |
new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */ |
} |
/* we need to do a space check here */ |
if (!r100ValidateBuffers(ctx)) |
return GL_FALSE; |
/* Need an event driven matrix update? |
*/ |
if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) |
upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ ); |
/* Need these for lighting (shouldn't upload otherwise) |
*/ |
if (new_state & (_NEW_MODELVIEW)) { |
upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, MODEL ); |
upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, MODEL_IT ); |
} |
/* Does this need to be triggered on eg. modelview for |
* texgen-derived objplane/eyeplane matrices? |
*/ |
if (new_state & _NEW_TEXTURE_MATRIX) { |
update_texturematrix( ctx ); |
} |
if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) { |
update_light( ctx ); |
} |
/* emit all active clip planes if projection matrix changes. |
*/ |
if (new_state & (_NEW_PROJECTION)) { |
if (ctx->Transform.ClipPlanesEnabled) |
radeonUpdateClipPlanes( ctx ); |
} |
rmesa->radeon.NewGLState = 0; |
return GL_TRUE; |
} |
static void radeonInvalidateState( struct gl_context *ctx, GLuint new_state ) |
{ |
_swrast_InvalidateState( ctx, new_state ); |
_swsetup_InvalidateState( ctx, new_state ); |
_vbo_InvalidateState( ctx, new_state ); |
_tnl_InvalidateState( ctx, new_state ); |
_ae_invalidate_state( ctx, new_state ); |
R100_CONTEXT(ctx)->radeon.NewGLState |= new_state; |
} |
/* A hack. Need a faster way to find this out. |
*/ |
static GLboolean check_material( struct gl_context *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLint i; |
for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; |
i < _TNL_ATTRIB_MAT_BACK_INDEXES; |
i++) |
if (tnl->vb.AttribPtr[i] && |
tnl->vb.AttribPtr[i]->stride) |
return GL_TRUE; |
return GL_FALSE; |
} |
static void radeonWrapRunPipeline( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLboolean has_material; |
if (0) |
fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->radeon.NewGLState); |
/* Validate state: |
*/ |
if (rmesa->radeon.NewGLState) |
if (!radeonValidateState( ctx )) |
FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE); |
has_material = (ctx->Light.Enabled && check_material( ctx )); |
if (has_material) { |
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE ); |
} |
/* Run the pipeline. |
*/ |
_tnl_run_pipeline( ctx ); |
if (has_material) { |
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE ); |
} |
} |
static void radeonPolygonStipple( struct gl_context *ctx, const GLubyte *mask ) |
{ |
r100ContextPtr r100 = R100_CONTEXT(ctx); |
GLint i; |
radeon_firevertices(&r100->radeon); |
RADEON_STATECHANGE(r100, stp); |
/* Must flip pattern upside down. |
*/ |
for ( i = 31 ; i >= 0; i--) { |
r100->hw.stp.cmd[3 + i] = ((GLuint *) mask)[i]; |
} |
} |
/* Initialize the driver's state functions. |
* Many of the ctx->Driver functions might have been initialized to |
* software defaults in the earlier _mesa_init_driver_functions() call. |
*/ |
void radeonInitStateFuncs( struct gl_context *ctx ) |
{ |
ctx->Driver.UpdateState = radeonInvalidateState; |
ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange; |
ctx->Driver.DrawBuffer = radeonDrawBuffer; |
ctx->Driver.ReadBuffer = radeonReadBuffer; |
ctx->Driver.CopyPixels = _mesa_meta_CopyPixels; |
ctx->Driver.DrawPixels = _mesa_meta_DrawPixels; |
ctx->Driver.ReadPixels = radeonReadPixels; |
ctx->Driver.AlphaFunc = radeonAlphaFunc; |
ctx->Driver.BlendEquationSeparate = radeonBlendEquationSeparate; |
ctx->Driver.BlendFuncSeparate = radeonBlendFuncSeparate; |
ctx->Driver.ClipPlane = radeonClipPlane; |
ctx->Driver.ColorMask = radeonColorMask; |
ctx->Driver.CullFace = radeonCullFace; |
ctx->Driver.DepthFunc = radeonDepthFunc; |
ctx->Driver.DepthMask = radeonDepthMask; |
ctx->Driver.DepthRange = radeonDepthRange; |
ctx->Driver.Enable = radeonEnable; |
ctx->Driver.Fogfv = radeonFogfv; |
ctx->Driver.FrontFace = radeonFrontFace; |
ctx->Driver.Hint = NULL; |
ctx->Driver.LightModelfv = radeonLightModelfv; |
ctx->Driver.Lightfv = radeonLightfv; |
ctx->Driver.LineStipple = radeonLineStipple; |
ctx->Driver.LineWidth = radeonLineWidth; |
ctx->Driver.LogicOpcode = radeonLogicOpCode; |
ctx->Driver.PolygonMode = radeonPolygonMode; |
ctx->Driver.PolygonOffset = radeonPolygonOffset; |
ctx->Driver.PolygonStipple = radeonPolygonStipple; |
ctx->Driver.RenderMode = radeonRenderMode; |
ctx->Driver.Scissor = radeonScissor; |
ctx->Driver.ShadeModel = radeonShadeModel; |
ctx->Driver.StencilFuncSeparate = radeonStencilFuncSeparate; |
ctx->Driver.StencilMaskSeparate = radeonStencilMaskSeparate; |
ctx->Driver.StencilOpSeparate = radeonStencilOpSeparate; |
ctx->Driver.Viewport = radeonViewport; |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial; |
TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_state.h |
---|
0,0 → 1,71 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Kevin E. Martin <martin@valinux.com> |
* Gareth Hughes <gareth@valinux.com> |
* |
*/ |
#ifndef __RADEON_STATE_H__ |
#define __RADEON_STATE_H__ |
#include "radeon_context.h" |
extern void radeonInitState( r100ContextPtr rmesa ); |
extern void radeonInitStateFuncs( struct gl_context *ctx ); |
extern void radeonUpdateMaterial( struct gl_context *ctx ); |
extern void radeonUpdateViewportOffset( struct gl_context *ctx ); |
extern void radeonUpdateWindow( struct gl_context *ctx ); |
extern void radeonUpdateDrawBuffer( struct gl_context *ctx ); |
extern void radeonUploadTexMatrix( r100ContextPtr rmesa, |
int unit, GLboolean swapcols ); |
extern GLboolean radeonValidateState( struct gl_context *ctx ); |
extern void radeonFallback( struct gl_context *ctx, GLuint bit, GLboolean mode ); |
#define FALLBACK( rmesa, bit, mode ) do { \ |
if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n", \ |
__FUNCTION__, bit, mode ); \ |
radeonFallback( &rmesa->radeon.glCtx, bit, mode ); \ |
} while (0) |
#define MODEL_PROJ 0 |
#define MODEL 1 |
#define MODEL_IT 2 |
#define TEXMAT_0 3 |
#define TEXMAT_1 4 |
#define TEXMAT_2 5 |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_state_init.c |
---|
0,0 → 1,924 |
/* |
* Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California. |
* |
* 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 |
* on 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 |
* VA LINUX SYSTEMS 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: |
* Gareth Hughes <gareth@valinux.com> |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#include "main/glheader.h" |
#include "main/imports.h" |
#include "main/api_arrayelt.h" |
#include "swrast/swrast.h" |
#include "vbo/vbo.h" |
#include "tnl/t_pipeline.h" |
#include "swrast_setup/swrast_setup.h" |
#include "radeon_context.h" |
#include "radeon_mipmap_tree.h" |
#include "radeon_ioctl.h" |
#include "radeon_state.h" |
#include "radeon_queryobj.h" |
#include "../r200/r200_reg.h" |
#include "xmlpool.h" |
/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in |
* 1.3 cmdbuffers allow all previous state to be updated as well as |
* the tcl scalar and vector areas. |
*/ |
static struct { |
int start; |
int len; |
const char *name; |
} packet[RADEON_MAX_STATE_PACKETS] = { |
{RADEON_PP_MISC, 7, "RADEON_PP_MISC"}, |
{RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"}, |
{RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"}, |
{RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"}, |
{RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"}, |
{RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"}, |
{RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"}, |
{RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"}, |
{RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"}, |
{RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"}, |
{RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"}, |
{RADEON_RE_MISC, 1, "RADEON_RE_MISC"}, |
{RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"}, |
{RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"}, |
{RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"}, |
{RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"}, |
{RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"}, |
{RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"}, |
{RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"}, |
{RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"}, |
{RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17, |
"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"}, |
{R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"}, |
{R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"}, |
{R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"}, |
{R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"}, |
{R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"}, |
{R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"}, |
{R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"}, |
{R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"}, |
{R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"}, |
{R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"}, |
{R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"}, |
{R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"}, |
{R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"}, |
{R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"}, |
{R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"}, |
{R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"}, |
{R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"}, |
{R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"}, |
{R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"}, |
{R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"}, |
{R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"}, |
{R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"}, |
{R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"}, |
{R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"}, |
{R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"}, |
{R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"}, |
{R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"}, |
{R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"}, |
{R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, |
"R200_SE_TCL_OUTPUT_VTX_COMP_SEL"}, |
{R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"}, |
{R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"}, |
{R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"}, |
{R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"}, |
{R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"}, |
{R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"}, |
{R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"}, |
{R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"}, |
{R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"}, |
{R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"}, |
{R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, |
"R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"}, |
{R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */ |
{R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */ |
{R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"}, |
{R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"}, |
{R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"}, |
{R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"}, |
{R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"}, |
{R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"}, |
{R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"}, |
{R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"}, |
{R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"}, |
{R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"}, |
{RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"}, |
{RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"}, |
{RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"}, |
{R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"}, |
{R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"}, |
{RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"}, |
{RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"}, |
{RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"}, |
{RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"}, |
{RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"}, |
{RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"}, |
{R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"}, |
{R200_PP_TXCBLEND_8, 32, "R200_PP_AFS_0"}, /* 85 */ |
{R200_PP_TXCBLEND_0, 32, "R200_PP_AFS_1"}, |
{R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"}, |
{R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"}, |
{R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"}, |
{R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"}, |
{R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"}, |
{R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"}, |
{R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"}, |
{R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"}, |
}; |
/* ============================================================= |
* State initialization |
*/ |
static int cmdpkt( r100ContextPtr rmesa, int id ) |
{ |
return CP_PACKET0(packet[id].start, packet[id].len - 1); |
} |
static int cmdvec( int offset, int stride, int count ) |
{ |
drm_radeon_cmd_header_t h; |
h.i = 0; |
h.vectors.cmd_type = RADEON_CMD_VECTORS; |
h.vectors.offset = offset; |
h.vectors.stride = stride; |
h.vectors.count = count; |
return h.i; |
} |
static int cmdscl( int offset, int stride, int count ) |
{ |
drm_radeon_cmd_header_t h; |
h.i = 0; |
h.scalars.cmd_type = RADEON_CMD_SCALARS; |
h.scalars.offset = offset; |
h.scalars.stride = stride; |
h.scalars.count = count; |
return h.i; |
} |
#define CHECK( NM, FLAG, ADD ) \ |
static int check_##NM( struct gl_context *ctx, struct radeon_state_atom *atom ) \ |
{ \ |
return FLAG ? atom->cmd_size + (ADD) : 0; \ |
} |
#define TCL_CHECK( NM, FLAG, ADD ) \ |
static int check_##NM( struct gl_context *ctx, struct radeon_state_atom *atom ) \ |
{ \ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); \ |
return (!rmesa->radeon.TclFallback && (FLAG)) ? atom->cmd_size + (ADD) : 0; \ |
} |
CHECK( always, GL_TRUE, 0 ) |
CHECK( always_add2, GL_TRUE, 2 ) |
CHECK( always_add4, GL_TRUE, 4 ) |
CHECK( tex0_mm, GL_TRUE, 3 ) |
CHECK( tex1_mm, GL_TRUE, 3 ) |
/* need this for the cubic_map on disabled unit 2 bug, maybe r100 only? */ |
CHECK( tex2_mm, GL_TRUE, 3 ) |
CHECK( cube0_mm, (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_CUBE_BIT), 2 + 4*5 - CUBE_STATE_SIZE ) |
CHECK( cube1_mm, (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_CUBE_BIT), 2 + 4*5 - CUBE_STATE_SIZE ) |
CHECK( cube2_mm, (ctx->Texture.Unit[2]._ReallyEnabled & TEXTURE_CUBE_BIT), 2 + 4*5 - CUBE_STATE_SIZE ) |
CHECK( fog_add4, ctx->Fog.Enabled, 4 ) |
TCL_CHECK( tcl_add4, GL_TRUE, 4 ) |
TCL_CHECK( tcl_tex0_add4, ctx->Texture.Unit[0]._ReallyEnabled, 4 ) |
TCL_CHECK( tcl_tex1_add4, ctx->Texture.Unit[1]._ReallyEnabled, 4 ) |
TCL_CHECK( tcl_tex2_add4, ctx->Texture.Unit[2]._ReallyEnabled, 4 ) |
TCL_CHECK( tcl_lighting, ctx->Light.Enabled, 0 ) |
TCL_CHECK( tcl_lighting_add4, ctx->Light.Enabled, 4 ) |
TCL_CHECK( tcl_eyespace_or_lighting_add4, ctx->_NeedEyeCoords || ctx->Light.Enabled, 4 ) |
TCL_CHECK( tcl_lit0_add6, ctx->Light.Enabled && ctx->Light.Light[0].Enabled, 6 ) |
TCL_CHECK( tcl_lit1_add6, ctx->Light.Enabled && ctx->Light.Light[1].Enabled, 6 ) |
TCL_CHECK( tcl_lit2_add6, ctx->Light.Enabled && ctx->Light.Light[2].Enabled, 6 ) |
TCL_CHECK( tcl_lit3_add6, ctx->Light.Enabled && ctx->Light.Light[3].Enabled, 6 ) |
TCL_CHECK( tcl_lit4_add6, ctx->Light.Enabled && ctx->Light.Light[4].Enabled, 6 ) |
TCL_CHECK( tcl_lit5_add6, ctx->Light.Enabled && ctx->Light.Light[5].Enabled, 6 ) |
TCL_CHECK( tcl_lit6_add6, ctx->Light.Enabled && ctx->Light.Light[6].Enabled, 6 ) |
TCL_CHECK( tcl_lit7_add6, ctx->Light.Enabled && ctx->Light.Light[7].Enabled, 6 ) |
TCL_CHECK( tcl_ucp0_add4, (ctx->Transform.ClipPlanesEnabled & 0x1), 4 ) |
TCL_CHECK( tcl_ucp1_add4, (ctx->Transform.ClipPlanesEnabled & 0x2), 4 ) |
TCL_CHECK( tcl_ucp2_add4, (ctx->Transform.ClipPlanesEnabled & 0x4), 4 ) |
TCL_CHECK( tcl_ucp3_add4, (ctx->Transform.ClipPlanesEnabled & 0x8), 4 ) |
TCL_CHECK( tcl_ucp4_add4, (ctx->Transform.ClipPlanesEnabled & 0x10), 4 ) |
TCL_CHECK( tcl_ucp5_add4, (ctx->Transform.ClipPlanesEnabled & 0x20), 4 ) |
TCL_CHECK( tcl_eyespace_or_fog_add4, ctx->_NeedEyeCoords || ctx->Fog.Enabled, 4 ) |
CHECK( txr0, (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_RECT_BIT), 0 ) |
CHECK( txr1, (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_RECT_BIT), 0 ) |
CHECK( txr2, (ctx->Texture.Unit[2]._ReallyEnabled & TEXTURE_RECT_BIT), 0 ) |
#define OUT_VEC(hdr, data) do { \ |
drm_radeon_cmd_header_t h; \ |
h.i = hdr; \ |
OUT_BATCH(CP_PACKET0(RADEON_SE_TCL_STATE_FLUSH, 0)); \ |
OUT_BATCH(0); \ |
OUT_BATCH(CP_PACKET0(R200_SE_TCL_VECTOR_INDX_REG, 0)); \ |
OUT_BATCH(h.vectors.offset | (h.vectors.stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); \ |
OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_VECTOR_DATA_REG, h.vectors.count - 1)); \ |
OUT_BATCH_TABLE((data), h.vectors.count); \ |
} while(0) |
#define OUT_SCL(hdr, data) do { \ |
drm_radeon_cmd_header_t h; \ |
h.i = hdr; \ |
OUT_BATCH(CP_PACKET0(R200_SE_TCL_SCALAR_INDX_REG, 0)); \ |
OUT_BATCH((h.scalars.offset) | (h.scalars.stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); \ |
OUT_BATCH(CP_PACKET0_ONE(R200_SE_TCL_SCALAR_DATA_REG, h.scalars.count - 1)); \ |
OUT_BATCH_TABLE((data), h.scalars.count); \ |
} while(0) |
static void scl_emit(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r100ContextPtr r100 = R100_CONTEXT(ctx); |
BATCH_LOCALS(&r100->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_SCL(atom->cmd[0], atom->cmd+1); |
END_BATCH(); |
} |
static void vec_emit(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r100ContextPtr r100 = R100_CONTEXT(ctx); |
BATCH_LOCALS(&r100->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_VEC(atom->cmd[0], atom->cmd+1); |
END_BATCH(); |
} |
static void lit_emit(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r100ContextPtr r100 = R100_CONTEXT(ctx); |
BATCH_LOCALS(&r100->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_VEC(atom->cmd[LIT_CMD_0], atom->cmd+1); |
OUT_SCL(atom->cmd[LIT_CMD_1], atom->cmd+LIT_CMD_1+1); |
END_BATCH(); |
} |
static int check_always_ctx( struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r100ContextPtr r100 = R100_CONTEXT(ctx); |
struct radeon_renderbuffer *rrb, *drb; |
uint32_t dwords; |
rrb = radeon_get_colorbuffer(&r100->radeon); |
if (!rrb || !rrb->bo) { |
return 0; |
} |
drb = radeon_get_depthbuffer(&r100->radeon); |
dwords = 10; |
if (drb) |
dwords += 6; |
if (rrb) |
dwords += 8; |
return dwords; |
} |
static void ctx_emit_cs(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r100ContextPtr r100 = R100_CONTEXT(ctx); |
BATCH_LOCALS(&r100->radeon); |
struct radeon_renderbuffer *rrb, *drb; |
uint32_t cbpitch = 0; |
uint32_t zbpitch = 0; |
uint32_t dwords = atom->check(ctx, atom); |
uint32_t depth_fmt; |
rrb = radeon_get_colorbuffer(&r100->radeon); |
if (!rrb || !rrb->bo) { |
fprintf(stderr, "no rrb\n"); |
return; |
} |
atom->cmd[CTX_RB3D_CNTL] &= ~(0xf << 10); |
if (rrb->cpp == 4) |
atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB8888; |
else switch (rrb->base.Base.Format) { |
case MESA_FORMAT_RGB565: |
atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_RGB565; |
break; |
case MESA_FORMAT_ARGB4444: |
atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB4444; |
break; |
case MESA_FORMAT_ARGB1555: |
atom->cmd[CTX_RB3D_CNTL] |= RADEON_COLOR_FORMAT_ARGB1555; |
break; |
default: |
_mesa_problem(ctx, "unexpected format in ctx_emit_cs()"); |
} |
cbpitch = (rrb->pitch / rrb->cpp); |
if (rrb->bo->flags & RADEON_BO_FLAGS_MACRO_TILE) |
cbpitch |= R200_COLOR_TILE_ENABLE; |
if (rrb->bo->flags & RADEON_BO_FLAGS_MICRO_TILE) |
cbpitch |= RADEON_COLOR_MICROTILE_ENABLE; |
drb = radeon_get_depthbuffer(&r100->radeon); |
if (drb) { |
zbpitch = (drb->pitch / drb->cpp); |
if (drb->cpp == 4) |
depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z; |
else |
depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z; |
atom->cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_DEPTH_FORMAT_MASK; |
atom->cmd[CTX_RB3D_ZSTENCILCNTL] |= depth_fmt; |
} |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
/* In the CS case we need to split this up */ |
OUT_BATCH(CP_PACKET0(packet[0].start, 3)); |
OUT_BATCH_TABLE((atom->cmd + 1), 4); |
if (drb) { |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_DEPTHOFFSET, 0)); |
OUT_BATCH_RELOC(0, drb->bo, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_DEPTHPITCH, 0)); |
OUT_BATCH(zbpitch); |
} |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_ZSTENCILCNTL, 0)); |
OUT_BATCH(atom->cmd[CTX_RB3D_ZSTENCILCNTL]); |
OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL, 1)); |
OUT_BATCH(atom->cmd[CTX_PP_CNTL]); |
OUT_BATCH(atom->cmd[CTX_RB3D_CNTL]); |
if (rrb) { |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_COLOROFFSET, 0)); |
OUT_BATCH_RELOC(rrb->draw_offset, rrb->bo, rrb->draw_offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); |
OUT_BATCH(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0)); |
OUT_BATCH_RELOC(cbpitch, rrb->bo, cbpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0); |
} |
// if (atom->cmd_size == CTX_STATE_SIZE_NEWDRM) { |
// OUT_BATCH_TABLE((atom->cmd + 14), 4); |
// } |
END_BATCH(); |
BEGIN_BATCH_NO_AUTOSTATE(4); |
OUT_BATCH(CP_PACKET0(RADEON_RE_TOP_LEFT, 0)); |
OUT_BATCH(0); |
OUT_BATCH(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0)); |
if (rrb) { |
OUT_BATCH(((rrb->base.Base.Width - 1) << RADEON_RE_WIDTH_SHIFT) | |
((rrb->base.Base.Height - 1) << RADEON_RE_HEIGHT_SHIFT)); |
} else { |
OUT_BATCH(0); |
} |
END_BATCH(); |
} |
static void cube_emit_cs(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r100ContextPtr r100 = R100_CONTEXT(ctx); |
BATCH_LOCALS(&r100->radeon); |
uint32_t dwords = atom->check(ctx, atom); |
int i = atom->idx, j; |
radeonTexObj *t = r100->state.texture.unit[i].texobj; |
radeon_mipmap_level *lvl; |
uint32_t base_reg; |
if (!(ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_CUBE_BIT)) |
return; |
if (!t) |
return; |
if (!t->mt) |
return; |
switch(i) { |
case 1: base_reg = RADEON_PP_CUBIC_OFFSET_T1_0; break; |
case 2: base_reg = RADEON_PP_CUBIC_OFFSET_T2_0; break; |
default: |
case 0: base_reg = RADEON_PP_CUBIC_OFFSET_T0_0; break; |
}; |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_BATCH_TABLE(atom->cmd, 2); |
lvl = &t->mt->levels[0]; |
for (j = 0; j < 5; j++) { |
OUT_BATCH(CP_PACKET0(base_reg + (4 * j), 0)); |
OUT_BATCH_RELOC(lvl->faces[j].offset, t->mt->bo, lvl->faces[j].offset, |
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); |
} |
END_BATCH(); |
} |
static void tex_emit_cs(struct gl_context *ctx, struct radeon_state_atom *atom) |
{ |
r100ContextPtr r100 = R100_CONTEXT(ctx); |
BATCH_LOCALS(&r100->radeon); |
uint32_t dwords = atom->cmd_size; |
int i = atom->idx; |
radeonTexObj *t = r100->state.texture.unit[i].texobj; |
radeon_mipmap_level *lvl; |
int hastexture = 1; |
if (!t) |
hastexture = 0; |
else { |
if (!t->mt && !t->bo) |
hastexture = 0; |
} |
dwords += 1; |
if (hastexture) |
dwords += 2; |
else |
dwords -= 2; |
BEGIN_BATCH_NO_AUTOSTATE(dwords); |
OUT_BATCH(CP_PACKET0(RADEON_PP_TXFILTER_0 + (24 * i), 1)); |
OUT_BATCH_TABLE((atom->cmd + 1), 2); |
if (hastexture) { |
OUT_BATCH(CP_PACKET0(RADEON_PP_TXOFFSET_0 + (24 * i), 0)); |
if (t->mt && !t->image_override) { |
if ((ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_CUBE_BIT)) { |
lvl = &t->mt->levels[t->minLod]; |
OUT_BATCH_RELOC(lvl->faces[5].offset, t->mt->bo, lvl->faces[5].offset, |
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); |
} else { |
OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, get_base_teximage_offset(t), |
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); |
} |
} else { |
if (t->bo) |
OUT_BATCH_RELOC(t->tile_bits, t->bo, 0, |
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0); |
} |
} |
OUT_BATCH(CP_PACKET0(RADEON_PP_TXCBLEND_0 + (i * 24), 1)); |
OUT_BATCH_TABLE((atom->cmd+4), 2); |
OUT_BATCH(CP_PACKET0(RADEON_PP_BORDER_COLOR_0 + (i * 4), 0)); |
OUT_BATCH((atom->cmd[TEX_PP_BORDER_COLOR])); |
END_BATCH(); |
} |
/* Initialize the context's hardware state. |
*/ |
void radeonInitState( r100ContextPtr rmesa ) |
{ |
struct gl_context *ctx = &rmesa->radeon.glCtx; |
GLuint i; |
rmesa->radeon.Fallback = 0; |
rmesa->radeon.hw.max_state_size = 0; |
#define ALLOC_STATE_IDX( ATOM, CHK, SZ, NM, FLAG, IDX ) \ |
do { \ |
rmesa->hw.ATOM.cmd_size = SZ; \ |
rmesa->hw.ATOM.cmd = (GLuint *) calloc(SZ, sizeof(int)); \ |
rmesa->hw.ATOM.lastcmd = (GLuint *) calloc(SZ, sizeof(int)); \ |
rmesa->hw.ATOM.name = NM; \ |
rmesa->hw.ATOM.is_tcl = FLAG; \ |
rmesa->hw.ATOM.check = check_##CHK; \ |
rmesa->hw.ATOM.dirty = GL_TRUE; \ |
rmesa->hw.ATOM.idx = IDX; \ |
rmesa->radeon.hw.max_state_size += SZ * sizeof(int); \ |
} while (0) |
#define ALLOC_STATE( ATOM, CHK, SZ, NM, FLAG ) \ |
ALLOC_STATE_IDX(ATOM, CHK, SZ, NM, FLAG, 0) |
/* Allocate state buffers: |
*/ |
ALLOC_STATE( ctx, always_add4, CTX_STATE_SIZE, "CTX/context", 0 ); |
rmesa->hw.ctx.emit = ctx_emit_cs; |
rmesa->hw.ctx.check = check_always_ctx; |
ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 ); |
ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 ); |
ALLOC_STATE( vpt, always, VPT_STATE_SIZE, "VPT/viewport", 0 ); |
ALLOC_STATE( set, always, SET_STATE_SIZE, "SET/setup", 0 ); |
ALLOC_STATE( msc, always, MSC_STATE_SIZE, "MSC/misc", 0 ); |
ALLOC_STATE( zbs, always, ZBS_STATE_SIZE, "ZBS/zbias", 0 ); |
ALLOC_STATE( tcl, always, TCL_STATE_SIZE, "TCL/tcl", 1 ); |
ALLOC_STATE( mtl, tcl_lighting, MTL_STATE_SIZE, "MTL/material", 1 ); |
ALLOC_STATE( grd, always_add2, GRD_STATE_SIZE, "GRD/guard-band", 1 ); |
ALLOC_STATE( fog, fog_add4, FOG_STATE_SIZE, "FOG/fog", 1 ); |
ALLOC_STATE( glt, tcl_lighting_add4, GLT_STATE_SIZE, "GLT/light-global", 1 ); |
ALLOC_STATE( eye, tcl_lighting_add4, EYE_STATE_SIZE, "EYE/eye-vector", 1 ); |
ALLOC_STATE_IDX( tex[0], tex0_mm, TEX_STATE_SIZE, "TEX/tex-0", 0, 0); |
ALLOC_STATE_IDX( tex[1], tex1_mm, TEX_STATE_SIZE, "TEX/tex-1", 0, 1); |
ALLOC_STATE_IDX( tex[2], tex2_mm, TEX_STATE_SIZE, "TEX/tex-2", 0, 2); |
ALLOC_STATE( mat[0], tcl_add4, MAT_STATE_SIZE, "MAT/modelproject", 1 ); |
ALLOC_STATE( mat[1], tcl_eyespace_or_fog_add4, MAT_STATE_SIZE, "MAT/modelview", 1 ); |
ALLOC_STATE( mat[2], tcl_eyespace_or_lighting_add4, MAT_STATE_SIZE, "MAT/it-modelview", 1 ); |
ALLOC_STATE( mat[3], tcl_tex0_add4, MAT_STATE_SIZE, "MAT/texmat0", 1 ); |
ALLOC_STATE( mat[4], tcl_tex1_add4, MAT_STATE_SIZE, "MAT/texmat1", 1 ); |
ALLOC_STATE( mat[5], tcl_tex2_add4, MAT_STATE_SIZE, "MAT/texmat2", 1 ); |
ALLOC_STATE( lit[0], tcl_lit0_add6, LIT_STATE_SIZE, "LIT/light-0", 1 ); |
ALLOC_STATE( lit[1], tcl_lit1_add6, LIT_STATE_SIZE, "LIT/light-1", 1 ); |
ALLOC_STATE( lit[2], tcl_lit2_add6, LIT_STATE_SIZE, "LIT/light-2", 1 ); |
ALLOC_STATE( lit[3], tcl_lit3_add6, LIT_STATE_SIZE, "LIT/light-3", 1 ); |
ALLOC_STATE( lit[4], tcl_lit4_add6, LIT_STATE_SIZE, "LIT/light-4", 1 ); |
ALLOC_STATE( lit[5], tcl_lit5_add6, LIT_STATE_SIZE, "LIT/light-5", 1 ); |
ALLOC_STATE( lit[6], tcl_lit6_add6, LIT_STATE_SIZE, "LIT/light-6", 1 ); |
ALLOC_STATE( lit[7], tcl_lit7_add6, LIT_STATE_SIZE, "LIT/light-7", 1 ); |
ALLOC_STATE( ucp[0], tcl_ucp0_add4, UCP_STATE_SIZE, "UCP/userclip-0", 1 ); |
ALLOC_STATE( ucp[1], tcl_ucp1_add4, UCP_STATE_SIZE, "UCP/userclip-1", 1 ); |
ALLOC_STATE( ucp[2], tcl_ucp2_add4, UCP_STATE_SIZE, "UCP/userclip-2", 1 ); |
ALLOC_STATE( ucp[3], tcl_ucp3_add4, UCP_STATE_SIZE, "UCP/userclip-3", 1 ); |
ALLOC_STATE( ucp[4], tcl_ucp4_add4, UCP_STATE_SIZE, "UCP/userclip-4", 1 ); |
ALLOC_STATE( ucp[5], tcl_ucp5_add4, UCP_STATE_SIZE, "UCP/userclip-5", 1 ); |
ALLOC_STATE( stp, always, STP_STATE_SIZE, "STP/stp", 0 ); |
for (i = 0; i < 3; i++) { |
rmesa->hw.tex[i].emit = tex_emit_cs; |
} |
ALLOC_STATE_IDX( cube[0], cube0_mm, CUBE_STATE_SIZE, "CUBE/cube-0", 0, 0 ); |
ALLOC_STATE_IDX( cube[1], cube1_mm, CUBE_STATE_SIZE, "CUBE/cube-1", 0, 1 ); |
ALLOC_STATE_IDX( cube[2], cube2_mm, CUBE_STATE_SIZE, "CUBE/cube-2", 0, 2 ); |
for (i = 0; i < 3; i++) |
rmesa->hw.cube[i].emit = cube_emit_cs; |
ALLOC_STATE_IDX( txr[0], txr0, TXR_STATE_SIZE, "TXR/txr-0", 0, 0 ); |
ALLOC_STATE_IDX( txr[1], txr1, TXR_STATE_SIZE, "TXR/txr-1", 0, 1 ); |
ALLOC_STATE_IDX( txr[2], txr2, TXR_STATE_SIZE, "TXR/txr-2", 0, 2 ); |
radeonSetUpAtomList( rmesa ); |
/* Fill in the packet headers: |
*/ |
rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_MISC); |
rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CNTL); |
rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(rmesa, RADEON_EMIT_RB3D_COLORPITCH); |
rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RE_LINE_PATTERN); |
rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_SE_LINE_WIDTH); |
rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RB3D_STENCILREFMASK); |
rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_VPORT_XSCALE); |
rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_CNTL); |
rmesa->hw.set.cmd[SET_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_SE_CNTL_STATUS); |
rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_RE_MISC); |
rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TXFILTER_0); |
rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_BORDER_COLOR_0); |
rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TXFILTER_1); |
rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_BORDER_COLOR_1); |
rmesa->hw.tex[2].cmd[TEX_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TXFILTER_2); |
rmesa->hw.tex[2].cmd[TEX_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_BORDER_COLOR_2); |
rmesa->hw.cube[0].cmd[CUBE_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_FACES_0); |
rmesa->hw.cube[0].cmd[CUBE_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_OFFSETS_T0); |
rmesa->hw.cube[1].cmd[CUBE_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_FACES_1); |
rmesa->hw.cube[1].cmd[CUBE_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_OFFSETS_T1); |
rmesa->hw.cube[2].cmd[CUBE_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_FACES_2); |
rmesa->hw.cube[2].cmd[CUBE_CMD_1] = cmdpkt(rmesa, RADEON_EMIT_PP_CUBIC_OFFSETS_T2); |
rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_ZBIAS_FACTOR); |
rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT); |
rmesa->hw.mtl.cmd[MTL_CMD_0] = |
cmdpkt(rmesa, RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED); |
rmesa->hw.txr[0].cmd[TXR_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TEX_SIZE_0); |
rmesa->hw.txr[1].cmd[TXR_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TEX_SIZE_1); |
rmesa->hw.txr[2].cmd[TXR_CMD_0] = cmdpkt(rmesa, RADEON_EMIT_PP_TEX_SIZE_2); |
rmesa->hw.grd.cmd[GRD_CMD_0] = |
cmdscl( RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, 1, 4 ); |
rmesa->hw.fog.cmd[FOG_CMD_0] = |
cmdvec( RADEON_VS_FOG_PARAM_ADDR, 1, 4 ); |
rmesa->hw.glt.cmd[GLT_CMD_0] = |
cmdvec( RADEON_VS_GLOBAL_AMBIENT_ADDR, 1, 4 ); |
rmesa->hw.eye.cmd[EYE_CMD_0] = |
cmdvec( RADEON_VS_EYE_VECTOR_ADDR, 1, 4 ); |
for (i = 0 ; i < 6; i++) { |
rmesa->hw.mat[i].cmd[MAT_CMD_0] = |
cmdvec( RADEON_VS_MATRIX_0_ADDR + i*4, 1, 16); |
} |
for (i = 0 ; i < 8; i++) { |
rmesa->hw.lit[i].cmd[LIT_CMD_0] = |
cmdvec( RADEON_VS_LIGHT_AMBIENT_ADDR + i, 8, 24 ); |
rmesa->hw.lit[i].cmd[LIT_CMD_1] = |
cmdscl( RADEON_SS_LIGHT_DCD_ADDR + i, 8, 6 ); |
} |
for (i = 0 ; i < 6; i++) { |
rmesa->hw.ucp[i].cmd[UCP_CMD_0] = |
cmdvec( RADEON_VS_UCP_ADDR + i, 1, 4 ); |
} |
rmesa->hw.stp.cmd[STP_CMD_0] = CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0); |
rmesa->hw.stp.cmd[STP_DATA_0] = 0; |
rmesa->hw.stp.cmd[STP_CMD_1] = CP_PACKET0_ONE(RADEON_RE_STIPPLE_DATA, 31); |
rmesa->hw.grd.emit = scl_emit; |
rmesa->hw.fog.emit = vec_emit; |
rmesa->hw.glt.emit = vec_emit; |
rmesa->hw.eye.emit = vec_emit; |
for (i = 0; i < 6; i++) |
rmesa->hw.mat[i].emit = vec_emit; |
for (i = 0; i < 8; i++) |
rmesa->hw.lit[i].emit = lit_emit; |
for (i = 0; i < 6; i++) |
rmesa->hw.ucp[i].emit = vec_emit; |
rmesa->last_ReallyEnabled = -1; |
/* Initial Harware state: |
*/ |
rmesa->hw.ctx.cmd[CTX_PP_MISC] = (RADEON_ALPHA_TEST_PASS | |
RADEON_CHROMA_FUNC_FAIL | |
RADEON_CHROMA_KEY_NEAREST | |
RADEON_SHADOW_FUNC_EQUAL | |
RADEON_SHADOW_PASS_1 /*| |
RADEON_RIGHT_HAND_CUBE_OGL */); |
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (RADEON_FOG_VERTEX | |
/* this bit unused for vertex fog */ |
RADEON_FOG_USE_DEPTH); |
rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000; |
rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = (RADEON_COMB_FCN_ADD_CLAMP | |
RADEON_SRC_BLEND_GL_ONE | |
RADEON_DST_BLEND_GL_ZERO ); |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (RADEON_Z_TEST_LESS | |
RADEON_STENCIL_TEST_ALWAYS | |
RADEON_STENCIL_FAIL_KEEP | |
RADEON_STENCIL_ZPASS_KEEP | |
RADEON_STENCIL_ZFAIL_KEEP | |
RADEON_Z_WRITE_ENABLE); |
if (rmesa->using_hyperz) { |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_COMPRESSION_ENABLE | |
RADEON_Z_DECOMPRESSION_ENABLE; |
if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) { |
/* works for q3, but slight rendering errors with glxgears ? */ |
/* rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_HIERARCHY_ENABLE;*/ |
/* need this otherwise get lots of lockups with q3 ??? */ |
rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_FORCE_Z_DIRTY; |
} |
} |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] = (RADEON_SCISSOR_ENABLE | |
RADEON_ANTI_ALIAS_NONE); |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = (RADEON_PLANE_MASK_ENABLE | |
RADEON_ZBLOCK16); |
switch ( driQueryOptioni( &rmesa->radeon.optionCache, "dither_mode" ) ) { |
case DRI_CONF_DITHER_XERRORDIFFRESET: |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_INIT; |
break; |
case DRI_CONF_DITHER_ORDERED: |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_SCALE_DITHER_ENABLE; |
break; |
} |
if ( driQueryOptioni( &rmesa->radeon.optionCache, "round_mode" ) == |
DRI_CONF_ROUND_ROUND ) |
rmesa->radeon.state.color.roundEnable = RADEON_ROUND_ENABLE; |
else |
rmesa->radeon.state.color.roundEnable = 0; |
if ( driQueryOptioni (&rmesa->radeon.optionCache, "color_reduction" ) == |
DRI_CONF_COLOR_REDUCTION_DITHER ) |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE; |
else |
rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable; |
rmesa->hw.set.cmd[SET_SE_CNTL] = (RADEON_FFACE_CULL_CCW | |
RADEON_BFACE_SOLID | |
RADEON_FFACE_SOLID | |
/* RADEON_BADVTX_CULL_DISABLE | */ |
RADEON_FLAT_SHADE_VTX_LAST | |
RADEON_DIFFUSE_SHADE_GOURAUD | |
RADEON_ALPHA_SHADE_GOURAUD | |
RADEON_SPECULAR_SHADE_GOURAUD | |
RADEON_FOG_SHADE_GOURAUD | |
RADEON_VPORT_XY_XFORM_ENABLE | |
RADEON_VPORT_Z_XFORM_ENABLE | |
RADEON_VTX_PIX_CENTER_OGL | |
RADEON_ROUND_MODE_TRUNC | |
RADEON_ROUND_PREC_8TH_PIX); |
rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] = |
#ifdef MESA_BIG_ENDIAN |
RADEON_VC_32BIT_SWAP; |
#else |
RADEON_VC_NO_SWAP; |
#endif |
if (!(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) { |
rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] |= RADEON_TCL_BYPASS; |
} |
rmesa->hw.set.cmd[SET_SE_COORDFMT] = ( |
RADEON_VTX_W0_IS_NOT_1_OVER_W0 | |
RADEON_TEX1_W_ROUTING_USE_Q1); |
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = ((1 << 16) | 0xffff); |
rmesa->hw.lin.cmd[LIN_RE_LINE_STATE] = |
((0 << RADEON_LINE_CURRENT_PTR_SHIFT) | |
(1 << RADEON_LINE_CURRENT_COUNT_SHIFT)); |
rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (1 << 4); |
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] = |
((0x00 << RADEON_STENCIL_REF_SHIFT) | |
(0xff << RADEON_STENCIL_MASK_SHIFT) | |
(0xff << RADEON_STENCIL_WRITEMASK_SHIFT)); |
rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = RADEON_ROP_COPY; |
rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = 0xffffffff; |
rmesa->hw.msc.cmd[MSC_RE_MISC] = |
((0 << RADEON_STIPPLE_X_OFFSET_SHIFT) | |
(0 << RADEON_STIPPLE_Y_OFFSET_SHIFT) | |
RADEON_STIPPLE_BIG_BIT_ORDER); |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = 0x00000000; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = 0x00000000; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = 0x00000000; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = 0x00000000; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = 0x00000000; |
rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = 0x00000000; |
for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) { |
rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] = RADEON_BORDER_MODE_OGL; |
rmesa->hw.tex[i].cmd[TEX_PP_TXFORMAT] = |
(RADEON_TXFORMAT_ENDIAN_NO_SWAP | |
RADEON_TXFORMAT_PERSPECTIVE_ENABLE | |
(i << 24) | /* This is one of RADEON_TXFORMAT_ST_ROUTE_STQ[012] */ |
(2 << RADEON_TXFORMAT_WIDTH_SHIFT) | |
(2 << RADEON_TXFORMAT_HEIGHT_SHIFT)); |
/* Initialize the texture offset to the start of the card texture heap */ |
// rmesa->hw.tex[i].cmd[TEX_PP_TXOFFSET] = |
// rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
rmesa->hw.tex[i].cmd[TEX_PP_BORDER_COLOR] = 0; |
rmesa->hw.tex[i].cmd[TEX_PP_TXCBLEND] = |
(RADEON_COLOR_ARG_A_ZERO | |
RADEON_COLOR_ARG_B_ZERO | |
RADEON_COLOR_ARG_C_CURRENT_COLOR | |
RADEON_BLEND_CTL_ADD | |
RADEON_SCALE_1X | |
RADEON_CLAMP_TX); |
rmesa->hw.tex[i].cmd[TEX_PP_TXABLEND] = |
(RADEON_ALPHA_ARG_A_ZERO | |
RADEON_ALPHA_ARG_B_ZERO | |
RADEON_ALPHA_ARG_C_CURRENT_ALPHA | |
RADEON_BLEND_CTL_ADD | |
RADEON_SCALE_1X | |
RADEON_CLAMP_TX); |
rmesa->hw.tex[i].cmd[TEX_PP_TFACTOR] = 0; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_FACES] = 0; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_0] = |
rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_1] = |
rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_2] = |
rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_3] = |
rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_4] = |
rmesa->radeon.radeonScreen->texOffset[RADEON_LOCAL_TEX_HEAP]; |
} |
/* Can only add ST1 at the time of doing some multitex but can keep |
* it after that. Errors if DIFFUSE is missing. |
*/ |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = |
(RADEON_TCL_VTX_Z0 | |
RADEON_TCL_VTX_W0 | |
RADEON_TCL_VTX_PK_DIFFUSE |
); /* need to keep this uptodate */ |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = |
( RADEON_TCL_COMPUTE_XYZW | |
(RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) | |
(RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) | |
(RADEON_TCL_TEX_INPUT_TEX_2 << RADEON_TCL_TEX_2_OUTPUT_SHIFT)); |
/* XXX */ |
rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_0] = |
((MODEL << RADEON_MODELVIEW_0_SHIFT) | |
(MODEL_IT << RADEON_IT_MODELVIEW_0_SHIFT)); |
rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_1] = |
((MODEL_PROJ << RADEON_MODELPROJECT_0_SHIFT) | |
(TEXMAT_0 << RADEON_TEXMAT_0_SHIFT) | |
(TEXMAT_1 << RADEON_TEXMAT_1_SHIFT) | |
(TEXMAT_2 << RADEON_TEXMAT_2_SHIFT)); |
rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = |
(RADEON_UCP_IN_CLIP_SPACE | |
RADEON_CULL_FRONT_IS_CCW); |
rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = 0; |
rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = |
(RADEON_SPECULAR_LIGHTS | |
RADEON_DIFFUSE_SPECULAR_COMBINE | |
RADEON_LOCAL_LIGHT_VEC_GL | |
(RADEON_LM_SOURCE_STATE_MULT << RADEON_EMISSIVE_SOURCE_SHIFT) | |
(RADEON_LM_SOURCE_STATE_MULT << RADEON_AMBIENT_SOURCE_SHIFT) | |
(RADEON_LM_SOURCE_STATE_MULT << RADEON_DIFFUSE_SOURCE_SHIFT) | |
(RADEON_LM_SOURCE_STATE_MULT << RADEON_SPECULAR_SOURCE_SHIFT)); |
for (i = 0 ; i < 8; i++) { |
struct gl_light *l = &ctx->Light.Light[i]; |
GLenum p = GL_LIGHT0 + i; |
*(float *)&(rmesa->hw.lit[i].cmd[LIT_RANGE_CUTOFF]) = FLT_MAX; |
ctx->Driver.Lightfv( ctx, p, GL_AMBIENT, l->Ambient ); |
ctx->Driver.Lightfv( ctx, p, GL_DIFFUSE, l->Diffuse ); |
ctx->Driver.Lightfv( ctx, p, GL_SPECULAR, l->Specular ); |
ctx->Driver.Lightfv( ctx, p, GL_POSITION, NULL ); |
ctx->Driver.Lightfv( ctx, p, GL_SPOT_DIRECTION, NULL ); |
ctx->Driver.Lightfv( ctx, p, GL_SPOT_EXPONENT, &l->SpotExponent ); |
ctx->Driver.Lightfv( ctx, p, GL_SPOT_CUTOFF, &l->SpotCutoff ); |
ctx->Driver.Lightfv( ctx, p, GL_CONSTANT_ATTENUATION, |
&l->ConstantAttenuation ); |
ctx->Driver.Lightfv( ctx, p, GL_LINEAR_ATTENUATION, |
&l->LinearAttenuation ); |
ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION, |
&l->QuadraticAttenuation ); |
*(float *)&(rmesa->hw.lit[i].cmd[LIT_ATTEN_XXX]) = 0.0; |
} |
ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT, |
ctx->Light.Model.Ambient ); |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); |
for (i = 0 ; i < 6; i++) { |
ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, NULL ); |
} |
ctx->Driver.Fogfv( ctx, GL_FOG_MODE, NULL ); |
ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density ); |
ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start ); |
ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End ); |
ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color ); |
ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, NULL ); |
rmesa->hw.grd.cmd[GRD_VERT_GUARD_CLIP_ADJ] = IEEE_ONE; |
rmesa->hw.grd.cmd[GRD_VERT_GUARD_DISCARD_ADJ] = IEEE_ONE; |
rmesa->hw.grd.cmd[GRD_HORZ_GUARD_CLIP_ADJ] = IEEE_ONE; |
rmesa->hw.grd.cmd[GRD_HORZ_GUARD_DISCARD_ADJ] = IEEE_ONE; |
rmesa->hw.eye.cmd[EYE_X] = 0; |
rmesa->hw.eye.cmd[EYE_Y] = 0; |
rmesa->hw.eye.cmd[EYE_Z] = IEEE_ONE; |
rmesa->hw.eye.cmd[EYE_RESCALE_FACTOR] = IEEE_ONE; |
radeon_init_query_stateobj(&rmesa->radeon, R100_QUERYOBJ_CMDSIZE); |
rmesa->radeon.query.queryobj.cmd[R100_QUERYOBJ_CMD_0] = CP_PACKET0(RADEON_RB3D_ZPASS_DATA, 0); |
rmesa->radeon.query.queryobj.cmd[R100_QUERYOBJ_DATA_0] = 0; |
rmesa->radeon.hw.all_dirty = GL_TRUE; |
rcommonInitCmdBuf(&rmesa->radeon); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_swtcl.c |
---|
0,0 → 1,883 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
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, 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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/mtypes.h" |
#include "main/colormac.h" |
#include "main/enums.h" |
#include "main/imports.h" |
#include "main/macros.h" |
#include "main/simple_list.h" |
#include "math/m_xform.h" |
#include "swrast_setup/swrast_setup.h" |
#include "tnl/tnl.h" |
#include "tnl/t_context.h" |
#include "tnl/t_pipeline.h" |
#include "radeon_context.h" |
#include "radeon_ioctl.h" |
#include "radeon_state.h" |
#include "radeon_swtcl.h" |
#include "radeon_tcl.h" |
#include "radeon_debug.h" |
/* R100: xyzw, c0, c1/fog, stq[0..2] = 4+1+1+3*3 = 15 right? */ |
/* R200: xyzw, c0, c1/fog, strq[0..5] = 4+1+1+4*6 = 30 */ |
#define RADEON_MAX_TNL_VERTEX_SIZE (15 * sizeof(GLfloat)) /* for mesa _tnl stage */ |
/*********************************************************************** |
* Initialization |
***********************************************************************/ |
#define EMIT_ATTR( ATTR, STYLE, F0 ) \ |
do { \ |
rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = (ATTR); \ |
rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = (STYLE); \ |
rmesa->radeon.swtcl.vertex_attr_count++; \ |
fmt_0 |= F0; \ |
} while (0) |
#define EMIT_PAD( N ) \ |
do { \ |
rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = 0; \ |
rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = EMIT_PAD; \ |
rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].offset = (N); \ |
rmesa->radeon.swtcl.vertex_attr_count++; \ |
} while (0) |
static GLuint radeon_cp_vc_frmts[3][2] = |
{ |
{ RADEON_CP_VC_FRMT_ST0, RADEON_CP_VC_FRMT_ST0 | RADEON_CP_VC_FRMT_Q0 }, |
{ RADEON_CP_VC_FRMT_ST1, RADEON_CP_VC_FRMT_ST1 | RADEON_CP_VC_FRMT_Q1 }, |
{ RADEON_CP_VC_FRMT_ST2, RADEON_CP_VC_FRMT_ST2 | RADEON_CP_VC_FRMT_Q2 }, |
}; |
static void radeonSetVertexFormat( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT( ctx ); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLbitfield64 index_bitset = tnl->render_inputs_bitset; |
int fmt_0 = 0; |
int offset = 0; |
/* Important: |
*/ |
if ( VB->NdcPtr != NULL ) { |
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; |
} |
else { |
VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr; |
} |
assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL ); |
rmesa->radeon.swtcl.vertex_attr_count = 0; |
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to |
* build up a hardware vertex. |
*/ |
if ( !rmesa->swtcl.needproj || |
(index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX))) { |
/* for projtex */ |
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, |
RADEON_CP_VC_FRMT_XY | RADEON_CP_VC_FRMT_Z | RADEON_CP_VC_FRMT_W0 ); |
offset = 4; |
} |
else { |
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F, |
RADEON_CP_VC_FRMT_XY | RADEON_CP_VC_FRMT_Z ); |
offset = 3; |
} |
rmesa->swtcl.coloroffset = offset; |
#if MESA_LITTLE_ENDIAN |
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, |
RADEON_CP_VC_FRMT_PKCOLOR ); |
#else |
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ABGR, |
RADEON_CP_VC_FRMT_PKCOLOR ); |
#endif |
offset += 1; |
rmesa->swtcl.specoffset = 0; |
if (index_bitset & |
(BITFIELD64_BIT(_TNL_ATTRIB_COLOR1) | BITFIELD64_BIT(_TNL_ATTRIB_FOG))) { |
#if MESA_LITTLE_ENDIAN |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) { |
rmesa->swtcl.specoffset = offset; |
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, |
RADEON_CP_VC_FRMT_PKSPEC ); |
} |
else { |
EMIT_PAD( 3 ); |
} |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) { |
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, |
RADEON_CP_VC_FRMT_PKSPEC ); |
} |
else { |
EMIT_PAD( 1 ); |
} |
#else |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) { |
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, |
RADEON_CP_VC_FRMT_PKSPEC ); |
} |
else { |
EMIT_PAD( 1 ); |
} |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) { |
rmesa->swtcl.specoffset = offset; |
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, |
RADEON_CP_VC_FRMT_PKSPEC ); |
} |
else { |
EMIT_PAD( 3 ); |
} |
#endif |
} |
if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) { |
int i; |
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { |
if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) { |
GLuint sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size; |
switch (sz) { |
case 1: |
case 2: |
EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_2F, |
radeon_cp_vc_frmts[i][0] ); |
break; |
case 3: |
if (ctx->Texture.Unit[i]._ReallyEnabled & (TEXTURE_CUBE_BIT) ) { |
EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F, |
radeon_cp_vc_frmts[i][1] ); |
} else { |
EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_2F, |
radeon_cp_vc_frmts[i][0] ); |
} |
break; |
case 4: |
if (ctx->Texture.Unit[i]._ReallyEnabled & (TEXTURE_CUBE_BIT) ) { |
EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F, |
radeon_cp_vc_frmts[i][1] ); |
} else { |
EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F_XYW, |
radeon_cp_vc_frmts[i][1] ); |
} |
break; |
default: |
continue; |
}; |
} |
} |
} |
if (rmesa->radeon.tnl_index_bitset != index_bitset || |
fmt_0 != rmesa->swtcl.vertex_format) { |
RADEON_NEWPRIM(rmesa); |
rmesa->swtcl.vertex_format = fmt_0; |
rmesa->radeon.swtcl.vertex_size = |
_tnl_install_attrs( ctx, |
rmesa->radeon.swtcl.vertex_attrs, |
rmesa->radeon.swtcl.vertex_attr_count, |
NULL, 0 ); |
rmesa->radeon.swtcl.vertex_size /= 4; |
rmesa->radeon.tnl_index_bitset = index_bitset; |
radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, |
"%s: vertex_size= %d floats\n", __FUNCTION__, rmesa->radeon.swtcl.vertex_size); |
} |
} |
static void radeon_predict_emit_size( r100ContextPtr rmesa ) |
{ |
if (!rmesa->radeon.swtcl.emit_prediction) { |
const int state_size = radeonCountStateEmitSize( &rmesa->radeon ); |
const int scissor_size = 8; |
const int prims_size = 8; |
const int vertex_size = 7; |
if (rcommonEnsureCmdBufSpace(&rmesa->radeon, |
state_size + |
(scissor_size + prims_size + vertex_size), |
__FUNCTION__)) |
rmesa->radeon.swtcl.emit_prediction = radeonCountStateEmitSize( &rmesa->radeon ); |
else |
rmesa->radeon.swtcl.emit_prediction = state_size; |
rmesa->radeon.swtcl.emit_prediction += scissor_size + prims_size + vertex_size |
+ rmesa->radeon.cmdbuf.cs->cdw; |
} |
} |
static void radeonRenderStart( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT( ctx ); |
radeonSetVertexFormat( ctx ); |
if (rmesa->radeon.dma.flush != 0 && |
rmesa->radeon.dma.flush != rcommon_flush_last_swtcl_prim) |
rmesa->radeon.dma.flush( ctx ); |
} |
/** |
* Set vertex state for SW TCL. The primary purpose of this function is to |
* determine in advance whether or not the hardware can / should do the |
* projection divide or Mesa should do it. |
*/ |
void radeonChooseVertexState( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT( ctx ); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint se_coord_fmt = rmesa->hw.set.cmd[SET_SE_COORDFMT]; |
GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL); |
GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide; |
se_coord_fmt &= ~(RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | |
RADEON_VTX_Z_PRE_MULT_1_OVER_W0 | |
RADEON_VTX_W0_IS_NOT_1_OVER_W0); |
/* We must ensure that we don't do _tnl_need_projected_coords while in a |
* rasterization fallback. As this function will be called again when we |
* leave a rasterization fallback, we can just skip it for now. |
*/ |
if (rmesa->radeon.Fallback != 0) |
return; |
/* HW perspective divide is a win, but tiny vertex formats are a |
* bigger one. |
*/ |
if ((0 == (tnl->render_inputs_bitset & |
(BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX) |
| BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)))) |
|| twosided |
|| unfilled) { |
rmesa->swtcl.needproj = GL_TRUE; |
se_coord_fmt |= (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | |
RADEON_VTX_Z_PRE_MULT_1_OVER_W0); |
} |
else { |
rmesa->swtcl.needproj = GL_FALSE; |
se_coord_fmt |= (RADEON_VTX_W0_IS_NOT_1_OVER_W0); |
} |
_tnl_need_projected_coords( ctx, rmesa->swtcl.needproj ); |
if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) { |
RADEON_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt; |
} |
} |
void r100_swtcl_flush(struct gl_context *ctx, uint32_t current_offset) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
radeonEmitState(&rmesa->radeon); |
radeonEmitVertexAOS( rmesa, |
rmesa->radeon.swtcl.vertex_size, |
rmesa->radeon.swtcl.bo, |
current_offset); |
radeonEmitVbufPrim( rmesa, |
rmesa->swtcl.vertex_format, |
rmesa->radeon.swtcl.hw_primitive, |
rmesa->radeon.swtcl.numverts); |
if ( rmesa->radeon.swtcl.emit_prediction < rmesa->radeon.cmdbuf.cs->cdw ) |
WARN_ONCE("Rendering was %d commands larger than predicted size." |
" We might overflow command buffer.\n", |
rmesa->radeon.cmdbuf.cs->cdw - rmesa->radeon.swtcl.emit_prediction ); |
rmesa->radeon.swtcl.emit_prediction = 0; |
} |
/* |
* Render unclipped vertex buffers by emitting vertices directly to |
* dma buffers. Use strip/fan hardware primitives where possible. |
* Try to simulate missing primitives with indexed vertices. |
*/ |
#define HAVE_POINTS 1 |
#define HAVE_LINES 1 |
#define HAVE_LINE_STRIPS 1 |
#define HAVE_TRIANGLES 1 |
#define HAVE_TRI_STRIPS 1 |
#define HAVE_TRI_STRIP_1 0 |
#define HAVE_TRI_FANS 1 |
#define HAVE_QUADS 0 |
#define HAVE_QUAD_STRIPS 0 |
#define HAVE_POLYGONS 0 |
/* \todo: is it possible to make "ELTS" work with t_vertex code ? */ |
#define HAVE_ELTS 0 |
static const GLuint hw_prim[GL_POLYGON+1] = { |
RADEON_CP_VC_CNTL_PRIM_TYPE_POINT, |
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, |
0, |
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP, |
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, |
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP, |
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN, |
0, |
0, |
0 |
}; |
static INLINE void |
radeonDmaPrimitive( r100ContextPtr rmesa, GLenum prim ) |
{ |
RADEON_NEWPRIM( rmesa ); |
rmesa->radeon.swtcl.hw_primitive = hw_prim[prim]; |
// assert(rmesa->radeon.dma.current.ptr == rmesa->radeon.dma.current.start); |
} |
static void* radeon_alloc_verts( r100ContextPtr rmesa , GLuint nr, GLuint size ) |
{ |
void *rv; |
do { |
radeon_predict_emit_size( rmesa ); |
rv = rcommonAllocDmaLowVerts( &rmesa->radeon, nr, size ); |
} while (!rv); |
return rv; |
} |
#define LOCAL_VARS r100ContextPtr rmesa = R100_CONTEXT(ctx) |
#define INIT( prim ) radeonDmaPrimitive( rmesa, prim ) |
#define FLUSH() RADEON_NEWPRIM( rmesa ) |
#define GET_CURRENT_VB_MAX_VERTS() 10\ |
// (((int)rmesa->radeon.dma.current.end - (int)rmesa->radeon.dma.current.ptr) / (rmesa->radeon.swtcl.vertex_size*4)) |
#define GET_SUBSEQUENT_VB_MAX_VERTS() \ |
((RADEON_BUFFER_SIZE) / (rmesa->radeon.swtcl.vertex_size*4)) |
#define ALLOC_VERTS( nr ) radeon_alloc_verts( rmesa, nr, rmesa->radeon.swtcl.vertex_size * 4 ) |
#define EMIT_VERTS( ctx, j, nr, buf ) \ |
_tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf) |
#define TAG(x) radeon_dma_##x |
#include "tnl_dd/t_dd_dmatmp.h" |
/**********************************************************************/ |
/* Render pipeline stage */ |
/**********************************************************************/ |
static GLboolean radeon_run_render( struct gl_context *ctx, |
struct tnl_pipeline_stage *stage ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
tnl_render_func *tab = TAG(render_tab_verts); |
GLuint i; |
if (rmesa->radeon.swtcl.RenderIndex != 0 || |
!radeon_dma_validate_render( ctx, VB )) |
return GL_TRUE; |
radeon_prepare_render(&rmesa->radeon); |
if (rmesa->radeon.NewGLState) |
radeonValidateState( ctx ); |
tnl->Driver.Render.Start( ctx ); |
for (i = 0 ; i < VB->PrimitiveCount ; i++) |
{ |
GLuint prim = VB->Primitive[i].mode; |
GLuint start = VB->Primitive[i].start; |
GLuint length = VB->Primitive[i].count; |
if (!length) |
continue; |
radeon_print(RADEON_SWRENDER, RADEON_NORMAL, |
"radeon_render.c: prim %s %d..%d\n", |
_mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK), |
start, start+length); |
if (length) |
tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, prim ); |
} |
tnl->Driver.Render.Finish( ctx ); |
return GL_FALSE; /* finished the pipe */ |
} |
const struct tnl_pipeline_stage _radeon_render_stage = |
{ |
"radeon render", |
NULL, |
NULL, |
NULL, |
NULL, |
radeon_run_render /* run */ |
}; |
/**************************************************************************/ |
static const GLuint reduced_hw_prim[GL_POLYGON+1] = { |
RADEON_CP_VC_CNTL_PRIM_TYPE_POINT, |
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, |
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, |
RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, |
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, |
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, |
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, |
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, |
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, |
RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST |
}; |
static void radeonRasterPrimitive( struct gl_context *ctx, GLuint hwprim ); |
static void radeonRenderPrimitive( struct gl_context *ctx, GLenum prim ); |
static void radeonResetLineStipple( struct gl_context *ctx ); |
/*********************************************************************** |
* Emit primitives as inline vertices * |
***********************************************************************/ |
#undef LOCAL_VARS |
#undef ALLOC_VERTS |
#define CTX_ARG r100ContextPtr rmesa |
#define GET_VERTEX_DWORDS() rmesa->radeon.swtcl.vertex_size |
#define ALLOC_VERTS( n, size ) radeon_alloc_verts( rmesa, n, (size) * 4 ) |
#undef LOCAL_VARS |
#define LOCAL_VARS \ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); \ |
const char *radeonverts = (char *)rmesa->radeon.swtcl.verts; |
#define VERT(x) (radeonVertex *)(radeonverts + ((x) * (vertsize) * sizeof(int))) |
#define VERTEX radeonVertex |
#undef TAG |
#define TAG(x) radeon_##x |
#include "tnl_dd/t_dd_triemit.h" |
/*********************************************************************** |
* Macros for t_dd_tritmp.h to draw basic primitives * |
***********************************************************************/ |
#define QUAD( a, b, c, d ) radeon_quad( rmesa, a, b, c, d ) |
#define TRI( a, b, c ) radeon_triangle( rmesa, a, b, c ) |
#define LINE( a, b ) radeon_line( rmesa, a, b ) |
#define POINT( a ) radeon_point( rmesa, a ) |
/*********************************************************************** |
* Build render functions from dd templates * |
***********************************************************************/ |
#define RADEON_TWOSIDE_BIT 0x01 |
#define RADEON_UNFILLED_BIT 0x02 |
#define RADEON_MAX_TRIFUNC 0x04 |
static struct { |
tnl_points_func points; |
tnl_line_func line; |
tnl_triangle_func triangle; |
tnl_quad_func quad; |
} rast_tab[RADEON_MAX_TRIFUNC]; |
#define DO_FALLBACK 0 |
#define DO_OFFSET 0 |
#define DO_UNFILLED (IND & RADEON_UNFILLED_BIT) |
#define DO_TWOSIDE (IND & RADEON_TWOSIDE_BIT) |
#define DO_FLAT 0 |
#define DO_TRI 1 |
#define DO_QUAD 1 |
#define DO_LINE 1 |
#define DO_POINTS 1 |
#define DO_FULL_QUAD 1 |
#define HAVE_SPEC 1 |
#define HAVE_BACK_COLORS 0 |
#define HAVE_HW_FLATSHADE 1 |
#define TAB rast_tab |
#define DEPTH_SCALE 1.0 |
#define UNFILLED_TRI unfilled_tri |
#define UNFILLED_QUAD unfilled_quad |
#define VERT_X(_v) _v->v.x |
#define VERT_Y(_v) _v->v.y |
#define VERT_Z(_v) _v->v.z |
#define AREA_IS_CCW( a ) (a < 0) |
#define GET_VERTEX(e) (rmesa->radeon.swtcl.verts + ((e) * rmesa->radeon.swtcl.vertex_size * sizeof(int))) |
#define VERT_SET_RGBA( v, c ) \ |
do { \ |
radeon_color_t *color = (radeon_color_t *)&((v)->ui[coloroffset]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \ |
} while (0) |
#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset] |
#define VERT_SET_SPEC( v, c ) \ |
do { \ |
if (specoffset) { \ |
radeon_color_t *spec = (radeon_color_t *)&((v)->ui[specoffset]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \ |
UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \ |
} \ |
} while (0) |
#define VERT_COPY_SPEC( v0, v1 ) \ |
do { \ |
if (specoffset) { \ |
radeon_color_t *spec0 = (radeon_color_t *)&((v0)->ui[specoffset]); \ |
radeon_color_t *spec1 = (radeon_color_t *)&((v1)->ui[specoffset]); \ |
spec0->red = spec1->red; \ |
spec0->green = spec1->green; \ |
spec0->blue = spec1->blue; \ |
} \ |
} while (0) |
/* These don't need LE32_TO_CPU() as they used to save and restore |
* colors which are already in the correct format. |
*/ |
#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset] |
#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx] |
#define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset] |
#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] |
#undef LOCAL_VARS |
#undef TAG |
#undef INIT |
#define LOCAL_VARS(n) \ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); \ |
GLuint color[n] = {0}, spec[n] = {0}; \ |
GLuint coloroffset = rmesa->swtcl.coloroffset; \ |
GLuint specoffset = rmesa->swtcl.specoffset; \ |
(void) color; (void) spec; (void) coloroffset; (void) specoffset; |
/*********************************************************************** |
* Helpers for rendering unfilled primitives * |
***********************************************************************/ |
#define RASTERIZE(x) radeonRasterPrimitive( ctx, reduced_hw_prim[x] ) |
#define RENDER_PRIMITIVE rmesa->radeon.swtcl.render_primitive |
#undef TAG |
#define TAG(x) x |
#include "tnl_dd/t_dd_unfilled.h" |
#undef IND |
/*********************************************************************** |
* Generate GL render functions * |
***********************************************************************/ |
#define IND (0) |
#define TAG(x) x |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (RADEON_TWOSIDE_BIT) |
#define TAG(x) x##_twoside |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (RADEON_UNFILLED_BIT) |
#define TAG(x) x##_unfilled |
#include "tnl_dd/t_dd_tritmp.h" |
#define IND (RADEON_TWOSIDE_BIT|RADEON_UNFILLED_BIT) |
#define TAG(x) x##_twoside_unfilled |
#include "tnl_dd/t_dd_tritmp.h" |
static void init_rast_tab( void ) |
{ |
init(); |
init_twoside(); |
init_unfilled(); |
init_twoside_unfilled(); |
} |
/**********************************************************************/ |
/* Render unclipped begin/end objects */ |
/**********************************************************************/ |
#define RENDER_POINTS( start, count ) \ |
for ( ; start < count ; start++) \ |
radeon_point( rmesa, VERT(start) ) |
#define RENDER_LINE( v0, v1 ) \ |
radeon_line( rmesa, VERT(v0), VERT(v1) ) |
#define RENDER_TRI( v0, v1, v2 ) \ |
radeon_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) ) |
#define RENDER_QUAD( v0, v1, v2, v3 ) \ |
radeon_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) ) |
#undef INIT |
#define INIT(x) do { \ |
radeonRenderPrimitive( ctx, x ); \ |
} while (0) |
#undef LOCAL_VARS |
#define LOCAL_VARS \ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); \ |
const GLuint vertsize = rmesa->radeon.swtcl.vertex_size; \ |
const char *radeonverts = (char *)rmesa->radeon.swtcl.verts; \ |
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ |
const GLboolean stipple = ctx->Line.StippleFlag; \ |
(void) elt; (void) stipple; |
#define RESET_STIPPLE if ( stipple ) radeonResetLineStipple( ctx ); |
#define RESET_OCCLUSION |
#define PRESERVE_VB_DEFS |
#define ELT(x) (x) |
#define TAG(x) radeon_##x##_verts |
#include "tnl/t_vb_rendertmp.h" |
#undef ELT |
#undef TAG |
#define TAG(x) radeon_##x##_elts |
#define ELT(x) elt[x] |
#include "tnl/t_vb_rendertmp.h" |
/**********************************************************************/ |
/* Choose render functions */ |
/**********************************************************************/ |
void radeonChooseRenderState( struct gl_context *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint index = 0; |
GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL); |
GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide; |
if (!rmesa->radeon.TclFallback || rmesa->radeon.Fallback) |
return; |
if (twosided) |
index |= RADEON_TWOSIDE_BIT; |
if (unfilled) |
index |= RADEON_UNFILLED_BIT; |
if (index != rmesa->radeon.swtcl.RenderIndex) { |
tnl->Driver.Render.Points = rast_tab[index].points; |
tnl->Driver.Render.Line = rast_tab[index].line; |
tnl->Driver.Render.ClippedLine = rast_tab[index].line; |
tnl->Driver.Render.Triangle = rast_tab[index].triangle; |
tnl->Driver.Render.Quad = rast_tab[index].quad; |
if (index == 0) { |
tnl->Driver.Render.PrimTabVerts = radeon_render_tab_verts; |
tnl->Driver.Render.PrimTabElts = radeon_render_tab_elts; |
tnl->Driver.Render.ClippedPolygon = radeon_fast_clipped_poly; |
} else { |
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; |
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; |
tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; |
} |
rmesa->radeon.swtcl.RenderIndex = index; |
} |
} |
/**********************************************************************/ |
/* High level hooks for t_vb_render.c */ |
/**********************************************************************/ |
static void radeonRasterPrimitive( struct gl_context *ctx, GLuint hwprim ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
if (rmesa->radeon.swtcl.hw_primitive != hwprim) { |
RADEON_NEWPRIM( rmesa ); |
rmesa->radeon.swtcl.hw_primitive = hwprim; |
} |
} |
static void radeonRenderPrimitive( struct gl_context *ctx, GLenum prim ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || |
ctx->Polygon.BackMode != GL_FILL); |
rmesa->radeon.swtcl.render_primitive = prim; |
if (prim < GL_TRIANGLES || !unfilled) |
radeonRasterPrimitive( ctx, reduced_hw_prim[prim] ); |
} |
static void radeonRenderFinish( struct gl_context *ctx ) |
{ |
} |
static void radeonResetLineStipple( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
RADEON_STATECHANGE( rmesa, lin ); |
} |
/**********************************************************************/ |
/* Transition to/from hardware rasterization. */ |
/**********************************************************************/ |
static const char * const fallbackStrings[] = { |
"Texture mode", |
"glDrawBuffer(GL_FRONT_AND_BACK)", |
"glEnable(GL_STENCIL) without hw stencil buffer", |
"glRenderMode(selection or feedback)", |
"glBlendEquation", |
"glBlendFunc", |
"RADEON_NO_RAST", |
"Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)" |
}; |
static const char *getFallbackString(GLuint bit) |
{ |
int i = 0; |
while (bit > 1) { |
i++; |
bit >>= 1; |
} |
return fallbackStrings[i]; |
} |
void radeonFallback( struct gl_context *ctx, GLuint bit, GLboolean mode ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint oldfallback = rmesa->radeon.Fallback; |
if (mode) { |
rmesa->radeon.Fallback |= bit; |
if (oldfallback == 0) { |
radeon_firevertices(&rmesa->radeon); |
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_TRUE ); |
_swsetup_Wakeup( ctx ); |
rmesa->radeon.swtcl.RenderIndex = ~0; |
if (RADEON_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "Radeon begin rasterization fallback: 0x%x %s\n", |
bit, getFallbackString(bit)); |
} |
} |
} |
else { |
rmesa->radeon.Fallback &= ~bit; |
if (oldfallback == bit) { |
_swrast_flush( ctx ); |
tnl->Driver.Render.Start = radeonRenderStart; |
tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive; |
tnl->Driver.Render.Finish = radeonRenderFinish; |
tnl->Driver.Render.BuildVertices = _tnl_build_vertices; |
tnl->Driver.Render.CopyPV = _tnl_copy_pv; |
tnl->Driver.Render.Interp = _tnl_interp; |
tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple; |
TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_FALSE ); |
if (rmesa->radeon.TclFallback) { |
/* These are already done if rmesa->radeon.TclFallback goes to |
* zero above. But not if it doesn't (RADEON_NO_TCL for |
* example?) |
*/ |
_tnl_invalidate_vertex_state( ctx, ~0 ); |
_tnl_invalidate_vertices( ctx, ~0 ); |
rmesa->radeon.tnl_index_bitset = 0; |
radeonChooseVertexState( ctx ); |
radeonChooseRenderState( ctx ); |
} |
if (RADEON_DEBUG & RADEON_FALLBACKS) { |
fprintf(stderr, "Radeon end rasterization fallback: 0x%x %s\n", |
bit, getFallbackString(bit)); |
} |
} |
} |
} |
/**********************************************************************/ |
/* Initialization. */ |
/**********************************************************************/ |
void radeonInitSwtcl( struct gl_context *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
static int firsttime = 1; |
if (firsttime) { |
init_rast_tab(); |
firsttime = 0; |
} |
rmesa->radeon.swtcl.emit_prediction = 0; |
tnl->Driver.Render.Start = radeonRenderStart; |
tnl->Driver.Render.Finish = radeonRenderFinish; |
tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive; |
tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple; |
tnl->Driver.Render.BuildVertices = _tnl_build_vertices; |
tnl->Driver.Render.CopyPV = _tnl_copy_pv; |
tnl->Driver.Render.Interp = _tnl_interp; |
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, |
RADEON_MAX_TNL_VERTEX_SIZE); |
rmesa->radeon.swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf; |
rmesa->radeon.swtcl.RenderIndex = ~0; |
rmesa->radeon.swtcl.render_primitive = GL_TRIANGLES; |
rmesa->radeon.swtcl.hw_primitive = 0; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_swtcl.h |
---|
0,0 → 1,66 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
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 |
on 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 |
ATI, VA LINUX SYSTEMS AND/OR THEIR 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 __RADEON_TRIS_H__ |
#define __RADEON_TRIS_H__ |
#include "main/mtypes.h" |
#include "swrast/swrast.h" |
#include "radeon_context.h" |
extern void radeonInitSwtcl( struct gl_context *ctx ); |
extern void radeonChooseRenderState( struct gl_context *ctx ); |
extern void radeonChooseVertexState( struct gl_context *ctx ); |
extern void radeonCheckTexSizes( struct gl_context *ctx ); |
extern void radeonBuildVertices( struct gl_context *ctx, GLuint start, GLuint count, |
GLuint newinputs ); |
extern void radeonPrintSetupFlags(char *msg, GLuint flags ); |
extern void radeon_emit_indexed_verts( struct gl_context *ctx, |
GLuint start, |
GLuint count ); |
extern void radeon_translate_vertex( struct gl_context *ctx, |
const radeonVertex *src, |
SWvertex *dst ); |
extern void radeon_print_vertex( struct gl_context *ctx, const radeonVertex *v ); |
extern void r100_swtcl_flush(struct gl_context *ctx, uint32_t current_offset); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_tcl.c |
---|
0,0 → 1,565 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
Tungsten Graphics Inc., Austin, 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, 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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/imports.h" |
#include "main/mtypes.h" |
#include "main/light.h" |
#include "main/enums.h" |
#include "main/state.h" |
#include "vbo/vbo.h" |
#include "tnl/tnl.h" |
#include "tnl/t_pipeline.h" |
#include "radeon_common.h" |
#include "radeon_context.h" |
#include "radeon_state.h" |
#include "radeon_ioctl.h" |
#include "radeon_tcl.h" |
#include "radeon_swtcl.h" |
#include "radeon_maos.h" |
#include "radeon_common_context.h" |
/* |
* Render unclipped vertex buffers by emitting vertices directly to |
* dma buffers. Use strip/fan hardware primitives where possible. |
* Try to simulate missing primitives with indexed vertices. |
*/ |
#define HAVE_POINTS 1 |
#define HAVE_LINES 1 |
#define HAVE_LINE_LOOP 0 |
#define HAVE_LINE_STRIPS 1 |
#define HAVE_TRIANGLES 1 |
#define HAVE_TRI_STRIPS 1 |
#define HAVE_TRI_STRIP_1 0 |
#define HAVE_TRI_FANS 1 |
#define HAVE_QUADS 0 |
#define HAVE_QUAD_STRIPS 0 |
#define HAVE_POLYGONS 1 |
#define HAVE_ELTS 1 |
#define HW_POINTS RADEON_CP_VC_CNTL_PRIM_TYPE_POINT |
#define HW_LINES RADEON_CP_VC_CNTL_PRIM_TYPE_LINE |
#define HW_LINE_LOOP 0 |
#define HW_LINE_STRIP RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP |
#define HW_TRIANGLES RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST |
#define HW_TRIANGLE_STRIP_0 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP |
#define HW_TRIANGLE_STRIP_1 0 |
#define HW_TRIANGLE_FAN RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
#define HW_QUADS 0 |
#define HW_QUAD_STRIP 0 |
#define HW_POLYGON RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
static GLboolean discrete_prim[0x10] = { |
0, /* 0 none */ |
1, /* 1 points */ |
1, /* 2 lines */ |
0, /* 3 line_strip */ |
1, /* 4 tri_list */ |
0, /* 5 tri_fan */ |
0, /* 6 tri_type2 */ |
1, /* 7 rect list (unused) */ |
1, /* 8 3vert point */ |
1, /* 9 3vert line */ |
0, |
0, |
0, |
0, |
0, |
0, |
}; |
#define LOCAL_VARS r100ContextPtr rmesa = R100_CONTEXT(ctx) |
#define ELT_TYPE GLushort |
#define ELT_INIT(prim, hw_prim) \ |
radeonTclPrimitive( ctx, prim, hw_prim | RADEON_CP_VC_CNTL_PRIM_WALK_IND ) |
#define GET_MESA_ELTS() rmesa->tcl.Elts |
/* Don't really know how many elts will fit in what's left of cmdbuf, |
* as there is state to emit, etc: |
*/ |
/* Testing on isosurf shows a maximum around here. Don't know if it's |
* the card or driver or kernel module that is causing the behaviour. |
*/ |
#define GET_MAX_HW_ELTS() 300 |
#define RESET_STIPPLE() do { \ |
RADEON_STATECHANGE( rmesa, lin ); \ |
radeonEmitState(&rmesa->radeon); \ |
} while (0) |
#define AUTO_STIPPLE( mode ) do { \ |
RADEON_STATECHANGE( rmesa, lin ); \ |
if (mode) \ |
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \ |
RADEON_LINE_PATTERN_AUTO_RESET; \ |
else \ |
rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \ |
~RADEON_LINE_PATTERN_AUTO_RESET; \ |
radeonEmitState(&rmesa->radeon); \ |
} while (0) |
#define ALLOC_ELTS(nr) radeonAllocElts( rmesa, nr ) |
static GLushort *radeonAllocElts( r100ContextPtr rmesa, GLuint nr ) |
{ |
if (rmesa->radeon.dma.flush) |
rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); |
radeonEmitAOS( rmesa, |
rmesa->radeon.tcl.aos_count, 0 ); |
return radeonAllocEltsOpenEnded( rmesa, rmesa->tcl.vertex_format, |
rmesa->tcl.hw_primitive, nr ); |
} |
#define CLOSE_ELTS() if (0) RADEON_NEWPRIM( rmesa ) |
/* TODO: Try to extend existing primitive if both are identical, |
* discrete and there are no intervening state changes. (Somewhat |
* duplicates changes to DrawArrays code) |
*/ |
static void radeonEmitPrim( struct gl_context *ctx, |
GLenum prim, |
GLuint hwprim, |
GLuint start, |
GLuint count) |
{ |
r100ContextPtr rmesa = R100_CONTEXT( ctx ); |
radeonTclPrimitive( ctx, prim, hwprim ); |
radeonEmitAOS( rmesa, |
rmesa->radeon.tcl.aos_count, |
start ); |
/* Why couldn't this packet have taken an offset param? |
*/ |
radeonEmitVbufPrim( rmesa, |
rmesa->tcl.vertex_format, |
rmesa->tcl.hw_primitive, |
count - start ); |
} |
#define EMIT_PRIM( ctx, prim, hwprim, start, count ) do { \ |
radeonEmitPrim( ctx, prim, hwprim, start, count ); \ |
(void) rmesa; } while (0) |
#define MAX_CONVERSION_SIZE 40 |
/* Try & join small primitives |
*/ |
#if 0 |
#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) 0 |
#else |
#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) \ |
((NR) < 20 || \ |
((NR) < 40 && \ |
rmesa->tcl.hw_primitive == (PRIM| \ |
RADEON_CP_VC_CNTL_PRIM_WALK_IND| \ |
RADEON_CP_VC_CNTL_TCL_ENABLE))) |
#endif |
#ifdef MESA_BIG_ENDIAN |
/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */ |
#define EMIT_ELT(dest, offset, x) do { \ |
int off = offset + ( ( (uintptr_t)dest & 0x2 ) >> 1 ); \ |
GLushort *des = (GLushort *)( (uintptr_t)dest & ~0x2 ); \ |
(des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); \ |
(void)rmesa; } while (0) |
#else |
#define EMIT_ELT(dest, offset, x) do { \ |
(dest)[offset] = (GLushort) (x); \ |
(void)rmesa; } while (0) |
#endif |
#define EMIT_TWO_ELTS(dest, offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x); |
#define TAG(x) tcl_##x |
#include "tnl_dd/t_dd_dmatmp2.h" |
/**********************************************************************/ |
/* External entrypoints */ |
/**********************************************************************/ |
void radeonEmitPrimitive( struct gl_context *ctx, |
GLuint first, |
GLuint last, |
GLuint flags ) |
{ |
tcl_render_tab_verts[flags&PRIM_MODE_MASK]( ctx, first, last, flags ); |
} |
void radeonEmitEltPrimitive( struct gl_context *ctx, |
GLuint first, |
GLuint last, |
GLuint flags ) |
{ |
tcl_render_tab_elts[flags&PRIM_MODE_MASK]( ctx, first, last, flags ); |
} |
void radeonTclPrimitive( struct gl_context *ctx, |
GLenum prim, |
int hw_prim ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint se_cntl; |
GLuint newprim = hw_prim | RADEON_CP_VC_CNTL_TCL_ENABLE; |
radeon_prepare_render(&rmesa->radeon); |
if (rmesa->radeon.NewGLState) |
radeonValidateState( ctx ); |
if (newprim != rmesa->tcl.hw_primitive || |
!discrete_prim[hw_prim&0xf]) { |
RADEON_NEWPRIM( rmesa ); |
rmesa->tcl.hw_primitive = newprim; |
} |
se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL]; |
se_cntl &= ~RADEON_FLAT_SHADE_VTX_LAST; |
if (prim == GL_POLYGON && ctx->Light.ShadeModel == GL_FLAT) |
se_cntl |= RADEON_FLAT_SHADE_VTX_0; |
else |
se_cntl |= RADEON_FLAT_SHADE_VTX_LAST; |
if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) { |
RADEON_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl; |
} |
} |
/** |
* Predict total emit size for next rendering operation so there is no flush in middle of rendering |
* Prediction has to aim towards the best possible value that is worse than worst case scenario |
*/ |
static GLuint radeonEnsureEmitSize( struct gl_context * ctx , GLuint inputs ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLuint space_required; |
GLuint state_size; |
GLuint nr_aos = 1; /* radeonEmitArrays does always emit one */ |
int i; |
/* list of flags that are allocating aos object */ |
const GLuint flags_to_check[] = { |
VERT_BIT_NORMAL, |
VERT_BIT_COLOR0, |
VERT_BIT_COLOR1, |
VERT_BIT_FOG |
}; |
/* predict number of aos to emit */ |
for (i=0; i < sizeof(flags_to_check)/sizeof(flags_to_check[0]); ++i) |
{ |
if (inputs & flags_to_check[i]) |
++nr_aos; |
} |
for (i = 0; i < ctx->Const.MaxTextureUnits; ++i) |
{ |
if (inputs & VERT_BIT_TEX(i)) |
++nr_aos; |
} |
{ |
/* count the prediction for state size */ |
space_required = 0; |
state_size = radeonCountStateEmitSize( &rmesa->radeon ); |
/* tcl may be changed in radeonEmitArrays so account for it if not dirty */ |
if (!rmesa->hw.tcl.dirty) |
state_size += rmesa->hw.tcl.check( &rmesa->radeon.glCtx, &rmesa->hw.tcl ); |
/* predict size for elements */ |
for (i = 0; i < VB->PrimitiveCount; ++i) |
{ |
/* If primitive.count is less than MAX_CONVERSION_SIZE |
rendering code may decide convert to elts. |
In that case we have to make pessimistic prediction. |
and use larger of 2 paths. */ |
const GLuint elts = ELTS_BUFSZ(nr_aos); |
const GLuint index = INDEX_BUFSZ; |
const GLuint vbuf = VBUF_BUFSZ; |
if (!VB->Primitive[i].count) |
continue; |
if ( (!VB->Elts && VB->Primitive[i].count >= MAX_CONVERSION_SIZE) |
|| vbuf > index + elts) |
space_required += vbuf; |
else |
space_required += index + elts; |
space_required += VB->Primitive[i].count * 3; |
space_required += AOS_BUFSZ(nr_aos); |
} |
space_required += SCISSOR_BUFSZ; |
} |
/* flush the buffer in case we need more than is left. */ |
if (rcommonEnsureCmdBufSpace(&rmesa->radeon, space_required, __FUNCTION__)) |
return space_required + radeonCountStateEmitSize( &rmesa->radeon ); |
else |
return space_required + state_size; |
} |
/**********************************************************************/ |
/* Render pipeline stage */ |
/**********************************************************************/ |
/* TCL render. |
*/ |
static GLboolean radeon_run_tcl_render( struct gl_context *ctx, |
struct tnl_pipeline_stage *stage ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLuint inputs = VERT_BIT_POS | VERT_BIT_COLOR0; |
GLuint i; |
GLuint emit_end; |
/* TODO: separate this from the swtnl pipeline |
*/ |
if (rmesa->radeon.TclFallback) |
return GL_TRUE; /* fallback to software t&l */ |
if (VB->Count == 0) |
return GL_FALSE; |
/* NOTE: inputs != tnl->render_inputs - these are the untransformed |
* inputs. |
*/ |
if (ctx->Light.Enabled) { |
inputs |= VERT_BIT_NORMAL; |
} |
if (_mesa_need_secondary_color(ctx)) { |
inputs |= VERT_BIT_COLOR1; |
} |
if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) { |
inputs |= VERT_BIT_FOG; |
} |
for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) { |
if (ctx->Texture.Unit[i]._ReallyEnabled) { |
/* TODO: probably should not emit texture coords when texgen is enabled */ |
if (rmesa->TexGenNeedNormals[i]) { |
inputs |= VERT_BIT_NORMAL; |
} |
inputs |= VERT_BIT_TEX(i); |
} |
} |
radeonReleaseArrays( ctx, ~0 ); |
emit_end = radeonEnsureEmitSize( ctx, inputs ) |
+ rmesa->radeon.cmdbuf.cs->cdw; |
radeonEmitArrays( ctx, inputs ); |
rmesa->tcl.Elts = VB->Elts; |
for (i = 0 ; i < VB->PrimitiveCount ; i++) |
{ |
GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); |
GLuint start = VB->Primitive[i].start; |
GLuint length = VB->Primitive[i].count; |
if (!length) |
continue; |
if (rmesa->tcl.Elts) |
radeonEmitEltPrimitive( ctx, start, start+length, prim ); |
else |
radeonEmitPrimitive( ctx, start, start+length, prim ); |
} |
if (emit_end < rmesa->radeon.cmdbuf.cs->cdw) |
WARN_ONCE("Rendering was %d commands larger than predicted size." |
" We might overflow command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end); |
return GL_FALSE; /* finished the pipe */ |
} |
/* Initial state for tcl stage. |
*/ |
const struct tnl_pipeline_stage _radeon_tcl_stage = |
{ |
"radeon render", |
NULL, |
NULL, |
NULL, |
NULL, |
radeon_run_tcl_render /* run */ |
}; |
/**********************************************************************/ |
/* Validate state at pipeline start */ |
/**********************************************************************/ |
/*----------------------------------------------------------------------- |
* Manage TCL fallbacks |
*/ |
static void transition_to_swtnl( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint se_cntl; |
RADEON_NEWPRIM( rmesa ); |
rmesa->swtcl.vertex_format = 0; |
radeonChooseVertexState( ctx ); |
radeonChooseRenderState( ctx ); |
_tnl_validate_shine_tables( ctx ); |
tnl->Driver.NotifyMaterialChange = |
_tnl_validate_shine_tables; |
radeonReleaseArrays( ctx, ~0 ); |
se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL]; |
se_cntl |= RADEON_FLAT_SHADE_VTX_LAST; |
if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) { |
RADEON_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl; |
} |
} |
static void transition_to_hwtnl( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint se_coord_fmt = rmesa->hw.set.cmd[SET_SE_COORDFMT]; |
se_coord_fmt &= ~(RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | |
RADEON_VTX_Z_PRE_MULT_1_OVER_W0 | |
RADEON_VTX_W0_IS_NOT_1_OVER_W0); |
se_coord_fmt |= RADEON_VTX_W0_IS_NOT_1_OVER_W0; |
if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) { |
RADEON_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt; |
_tnl_need_projected_coords( ctx, GL_FALSE ); |
} |
radeonUpdateMaterial( ctx ); |
tnl->Driver.NotifyMaterialChange = radeonUpdateMaterial; |
if ( rmesa->radeon.dma.flush ) |
rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); |
rmesa->radeon.dma.flush = NULL; |
rmesa->swtcl.vertex_format = 0; |
// if (rmesa->swtcl.indexed_verts.buf) |
// radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, |
// __FUNCTION__ ); |
if (RADEON_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "Radeon end tcl fallback\n"); |
} |
static char *fallbackStrings[] = { |
"Rasterization fallback", |
"Unfilled triangles", |
"Twosided lighting, differing materials", |
"Materials in VB (maybe between begin/end)", |
"Texgen unit 0", |
"Texgen unit 1", |
"Texgen unit 2", |
"User disable", |
"Fogcoord with separate specular lighting" |
}; |
static char *getFallbackString(GLuint bit) |
{ |
int i = 0; |
while (bit > 1) { |
i++; |
bit >>= 1; |
} |
return fallbackStrings[i]; |
} |
void radeonTclFallback( struct gl_context *ctx, GLuint bit, GLboolean mode ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint oldfallback = rmesa->radeon.TclFallback; |
if (mode) { |
rmesa->radeon.TclFallback |= bit; |
if (oldfallback == 0) { |
if (RADEON_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "Radeon begin tcl fallback %s\n", |
getFallbackString( bit )); |
transition_to_swtnl( ctx ); |
} |
} |
else { |
rmesa->radeon.TclFallback &= ~bit; |
if (oldfallback == bit) { |
if (RADEON_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "Radeon end tcl fallback %s\n", |
getFallbackString( bit )); |
transition_to_hwtnl( ctx ); |
} |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_tcl.h |
---|
0,0 → 1,64 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
Tungsten Grahpics Inc., Austin, 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, 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 COPYRIGHT OWNER(S) 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 __RADEON_TCL_H__ |
#define __RADEON_TCL_H__ |
#include "radeon_context.h" |
extern void radeonTclPrimitive( struct gl_context *ctx, GLenum prim, int hw_prim ); |
extern void radeonEmitEltPrimitive( struct gl_context *ctx, GLuint first, GLuint last, |
GLuint flags ); |
extern void radeonEmitPrimitive( struct gl_context *ctx, GLuint first, GLuint last, |
GLuint flags ); |
extern void radeonTclFallback( struct gl_context *ctx, GLuint bit, GLboolean mode ); |
#define RADEON_TCL_FALLBACK_RASTER 0x1 /* rasterization */ |
#define RADEON_TCL_FALLBACK_UNFILLED 0x2 /* unfilled tris */ |
#define RADEON_TCL_FALLBACK_LIGHT_TWOSIDE 0x4 /* twoside tris */ |
#define RADEON_TCL_FALLBACK_MATERIAL 0x8 /* material in vb */ |
#define RADEON_TCL_FALLBACK_TEXGEN_0 0x10 /* texgen, unit 0 */ |
#define RADEON_TCL_FALLBACK_TEXGEN_1 0x20 /* texgen, unit 1 */ |
#define RADEON_TCL_FALLBACK_TEXGEN_2 0x40 /* texgen, unit 2 */ |
#define RADEON_TCL_FALLBACK_TCL_DISABLE 0x80 /* user disable */ |
#define RADEON_TCL_FALLBACK_FOGCOORDSPEC 0x100 /* fogcoord, sep. spec light */ |
/* max maos_verts vertex format has a size of 18 floats */ |
#define RADEON_MAX_TCL_VERTSIZE (18*4) |
#define TCL_FALLBACK( ctx, bit, mode ) radeonTclFallback( ctx, bit, mode ) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_tex.c |
---|
0,0 → 1,453 |
/* |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Gareth Hughes <gareth@valinux.com> |
* Brian Paul <brianp@valinux.com> |
*/ |
#include "main/glheader.h" |
#include "main/imports.h" |
#include "main/colormac.h" |
#include "main/context.h" |
#include "main/enums.h" |
#include "main/image.h" |
#include "main/simple_list.h" |
#include "main/teximage.h" |
#include "main/texobj.h" |
#include "radeon_context.h" |
#include "radeon_mipmap_tree.h" |
#include "radeon_ioctl.h" |
#include "radeon_tex.h" |
#include "xmlpool.h" |
/** |
* Set the texture wrap modes. |
* |
* \param t Texture object whose wrap modes are to be set |
* \param swrap Wrap mode for the \a s texture coordinate |
* \param twrap Wrap mode for the \a t texture coordinate |
*/ |
static void radeonSetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap ) |
{ |
GLboolean is_clamp = GL_FALSE; |
GLboolean is_clamp_to_border = GL_FALSE; |
t->pp_txfilter &= ~(RADEON_CLAMP_S_MASK | RADEON_CLAMP_T_MASK | RADEON_BORDER_MODE_D3D); |
switch ( swrap ) { |
case GL_REPEAT: |
t->pp_txfilter |= RADEON_CLAMP_S_WRAP; |
break; |
case GL_CLAMP: |
t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_GL; |
is_clamp = GL_TRUE; |
break; |
case GL_CLAMP_TO_EDGE: |
t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST; |
break; |
case GL_CLAMP_TO_BORDER: |
t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_GL; |
is_clamp_to_border = GL_TRUE; |
break; |
case GL_MIRRORED_REPEAT: |
t->pp_txfilter |= RADEON_CLAMP_S_MIRROR; |
break; |
case GL_MIRROR_CLAMP_EXT: |
t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_GL; |
is_clamp = GL_TRUE; |
break; |
case GL_MIRROR_CLAMP_TO_EDGE_EXT: |
t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_LAST; |
break; |
case GL_MIRROR_CLAMP_TO_BORDER_EXT: |
t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_GL; |
is_clamp_to_border = GL_TRUE; |
break; |
default: |
_mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__); |
} |
if (t->base.Target != GL_TEXTURE_1D) { |
switch ( twrap ) { |
case GL_REPEAT: |
t->pp_txfilter |= RADEON_CLAMP_T_WRAP; |
break; |
case GL_CLAMP: |
t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_GL; |
is_clamp = GL_TRUE; |
break; |
case GL_CLAMP_TO_EDGE: |
t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST; |
break; |
case GL_CLAMP_TO_BORDER: |
t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_GL; |
is_clamp_to_border = GL_TRUE; |
break; |
case GL_MIRRORED_REPEAT: |
t->pp_txfilter |= RADEON_CLAMP_T_MIRROR; |
break; |
case GL_MIRROR_CLAMP_EXT: |
t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_GL; |
is_clamp = GL_TRUE; |
break; |
case GL_MIRROR_CLAMP_TO_EDGE_EXT: |
t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_LAST; |
break; |
case GL_MIRROR_CLAMP_TO_BORDER_EXT: |
t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_GL; |
is_clamp_to_border = GL_TRUE; |
break; |
default: |
_mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__); |
} |
} |
if ( is_clamp_to_border ) { |
t->pp_txfilter |= RADEON_BORDER_MODE_D3D; |
} |
t->border_fallback = (is_clamp && is_clamp_to_border); |
} |
static void radeonSetTexMaxAnisotropy( radeonTexObjPtr t, GLfloat max ) |
{ |
t->pp_txfilter &= ~RADEON_MAX_ANISO_MASK; |
if ( max == 1.0 ) { |
t->pp_txfilter |= RADEON_MAX_ANISO_1_TO_1; |
} else if ( max <= 2.0 ) { |
t->pp_txfilter |= RADEON_MAX_ANISO_2_TO_1; |
} else if ( max <= 4.0 ) { |
t->pp_txfilter |= RADEON_MAX_ANISO_4_TO_1; |
} else if ( max <= 8.0 ) { |
t->pp_txfilter |= RADEON_MAX_ANISO_8_TO_1; |
} else { |
t->pp_txfilter |= RADEON_MAX_ANISO_16_TO_1; |
} |
} |
/** |
* Set the texture magnification and minification modes. |
* |
* \param t Texture whose filter modes are to be set |
* \param minf Texture minification mode |
* \param magf Texture magnification mode |
*/ |
static void radeonSetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf ) |
{ |
GLuint anisotropy = (t->pp_txfilter & RADEON_MAX_ANISO_MASK); |
/* Force revalidation to account for switches from/to mipmapping. */ |
t->validated = GL_FALSE; |
t->pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK); |
/* r100 chips can't handle mipmaps/aniso for cubemap/volume textures */ |
if ( t->base.Target == GL_TEXTURE_CUBE_MAP ) { |
switch ( minf ) { |
case GL_NEAREST: |
case GL_NEAREST_MIPMAP_NEAREST: |
case GL_NEAREST_MIPMAP_LINEAR: |
t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST; |
break; |
case GL_LINEAR: |
case GL_LINEAR_MIPMAP_NEAREST: |
case GL_LINEAR_MIPMAP_LINEAR: |
t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR; |
break; |
default: |
break; |
} |
} |
else if ( anisotropy == RADEON_MAX_ANISO_1_TO_1 ) { |
switch ( minf ) { |
case GL_NEAREST: |
t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST; |
break; |
case GL_LINEAR: |
t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR; |
break; |
case GL_NEAREST_MIPMAP_NEAREST: |
t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST; |
break; |
case GL_NEAREST_MIPMAP_LINEAR: |
t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST; |
break; |
case GL_LINEAR_MIPMAP_NEAREST: |
t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR; |
break; |
case GL_LINEAR_MIPMAP_LINEAR: |
t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR; |
break; |
} |
} else { |
switch ( minf ) { |
case GL_NEAREST: |
t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST; |
break; |
case GL_LINEAR: |
t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_LINEAR; |
break; |
case GL_NEAREST_MIPMAP_NEAREST: |
case GL_LINEAR_MIPMAP_NEAREST: |
t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST; |
break; |
case GL_NEAREST_MIPMAP_LINEAR: |
case GL_LINEAR_MIPMAP_LINEAR: |
t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR; |
break; |
} |
} |
switch ( magf ) { |
case GL_NEAREST: |
t->pp_txfilter |= RADEON_MAG_FILTER_NEAREST; |
break; |
case GL_LINEAR: |
t->pp_txfilter |= RADEON_MAG_FILTER_LINEAR; |
break; |
} |
} |
static void radeonSetTexBorderColor( radeonTexObjPtr t, const GLfloat color[4] ) |
{ |
GLubyte c[4]; |
CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); |
CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); |
CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); |
CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); |
t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] ); |
} |
#define SCALED_FLOAT_TO_BYTE( x, scale ) \ |
(((GLuint)((255.0F / scale) * (x))) / 2) |
static void radeonTexEnv( struct gl_context *ctx, GLenum target, |
GLenum pname, const GLfloat *param ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint unit = ctx->Texture.CurrentUnit; |
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
if ( RADEON_DEBUG & RADEON_STATE ) { |
fprintf( stderr, "%s( %s )\n", |
__FUNCTION__, _mesa_lookup_enum_by_nr( pname ) ); |
} |
switch ( pname ) { |
case GL_TEXTURE_ENV_COLOR: { |
GLubyte c[4]; |
GLuint envColor; |
_mesa_unclamped_float_rgba_to_ubyte(c, texUnit->EnvColor); |
envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] ); |
if ( rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] != envColor ) { |
RADEON_STATECHANGE( rmesa, tex[unit] ); |
rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] = envColor; |
} |
break; |
} |
case GL_TEXTURE_LOD_BIAS_EXT: { |
GLfloat bias, min; |
GLuint b; |
/* The Radeon's LOD bias is a signed 2's complement value with a |
* range of -1.0 <= bias < 4.0. We break this into two linear |
* functions, one mapping [-1.0,0.0] to [-128,0] and one mapping |
* [0.0,4.0] to [0,127]. |
*/ |
min = driQueryOptionb (&rmesa->radeon.optionCache, "no_neg_lod_bias") ? |
0.0 : -1.0; |
bias = CLAMP( *param, min, 4.0 ); |
if ( bias == 0 ) { |
b = 0; |
} else if ( bias > 0 ) { |
b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 4.0 )) << RADEON_LOD_BIAS_SHIFT; |
} else { |
b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 1.0 )) << RADEON_LOD_BIAS_SHIFT; |
} |
if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] & RADEON_LOD_BIAS_MASK) != b ) { |
RADEON_STATECHANGE( rmesa, tex[unit] ); |
rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] &= ~RADEON_LOD_BIAS_MASK; |
rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] |= (b & RADEON_LOD_BIAS_MASK); |
} |
break; |
} |
default: |
return; |
} |
} |
void radeonTexUpdateParameters(struct gl_context *ctx, GLuint unit) |
{ |
struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, unit); |
radeonTexObj* t = radeon_tex_obj(ctx->Texture.Unit[unit]._Current); |
radeonSetTexMaxAnisotropy(t , samp->MaxAnisotropy); |
radeonSetTexFilter(t, samp->MinFilter, samp->MagFilter); |
radeonSetTexWrap(t, samp->WrapS, samp->WrapT); |
radeonSetTexBorderColor(t, samp->BorderColor.f); |
} |
/** |
* Changes variables and flags for a state update, which will happen at the |
* next UpdateTextureState |
*/ |
static void radeonTexParameter( struct gl_context *ctx, GLenum target, |
struct gl_texture_object *texObj, |
GLenum pname, const GLfloat *params ) |
{ |
radeonTexObj* t = radeon_tex_obj(texObj); |
radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, "%s( %s )\n", __FUNCTION__, |
_mesa_lookup_enum_by_nr( pname ) ); |
switch ( pname ) { |
case GL_TEXTURE_BASE_LEVEL: |
case GL_TEXTURE_MAX_LEVEL: |
case GL_TEXTURE_MIN_LOD: |
case GL_TEXTURE_MAX_LOD: |
t->validated = GL_FALSE; |
break; |
default: |
return; |
} |
} |
static void radeonDeleteTexture( struct gl_context *ctx, |
struct gl_texture_object *texObj ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
radeonTexObj* t = radeon_tex_obj(texObj); |
int i; |
radeon_print(RADEON_TEXTURE, RADEON_NORMAL, |
"%s( %p (target = %s) )\n", __FUNCTION__, (void *)texObj, |
_mesa_lookup_enum_by_nr( texObj->Target ) ); |
if ( rmesa ) { |
radeon_firevertices(&rmesa->radeon); |
for ( i = 0 ; i < rmesa->radeon.glCtx.Const.MaxTextureUnits ; i++ ) { |
if ( t == rmesa->state.texture.unit[i].texobj ) { |
rmesa->state.texture.unit[i].texobj = NULL; |
rmesa->hw.tex[i].dirty = GL_FALSE; |
rmesa->hw.cube[i].dirty = GL_FALSE; |
} |
} |
} |
radeon_miptree_unreference(&t->mt); |
/* Free mipmap images and the texture object itself */ |
_mesa_delete_texture_object(ctx, texObj); |
} |
/* Need: |
* - Same GEN_MODE for all active bits |
* - Same EyePlane/ObjPlane for all active bits when using Eye/Obj |
* - STRQ presumably all supported (matrix means incoming R values |
* can end up in STQ, this has implications for vertex support, |
* presumably ok if maos is used, though?) |
* |
* Basically impossible to do this on the fly - just collect some |
* basic info & do the checks from ValidateState(). |
*/ |
static void radeonTexGen( struct gl_context *ctx, |
GLenum coord, |
GLenum pname, |
const GLfloat *params ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLuint unit = ctx->Texture.CurrentUnit; |
rmesa->recheck_texgen[unit] = GL_TRUE; |
} |
/** |
* Allocate a new texture object. |
* Called via ctx->Driver.NewTextureObject. |
* Note: we could use containment here to 'derive' the driver-specific |
* texture object from the core mesa gl_texture_object. Not done at this time. |
*/ |
static struct gl_texture_object * |
radeonNewTextureObject( struct gl_context *ctx, GLuint name, GLenum target ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
radeonTexObj* t = CALLOC_STRUCT(radeon_tex_obj); |
_mesa_initialize_texture_object(ctx, &t->base, name, target); |
t->base.Sampler.MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy; |
t->border_fallback = GL_FALSE; |
t->pp_txfilter = RADEON_BORDER_MODE_OGL; |
t->pp_txformat = (RADEON_TXFORMAT_ENDIAN_NO_SWAP | |
RADEON_TXFORMAT_PERSPECTIVE_ENABLE); |
radeonSetTexWrap( t, t->base.Sampler.WrapS, t->base.Sampler.WrapT ); |
radeonSetTexMaxAnisotropy( t, t->base.Sampler.MaxAnisotropy ); |
radeonSetTexFilter( t, t->base.Sampler.MinFilter, t->base.Sampler.MagFilter ); |
radeonSetTexBorderColor( t, t->base.Sampler.BorderColor.f ); |
return &t->base; |
} |
static struct gl_sampler_object * |
radeonNewSamplerObject(struct gl_context *ctx, GLuint name) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
struct gl_sampler_object *samp = _mesa_new_sampler_object(ctx, name); |
if (samp) |
samp->MaxAnisotropy = rmesa->radeon.initialMaxAnisotropy; |
return samp; |
} |
void radeonInitTextureFuncs( radeonContextPtr radeon, struct dd_function_table *functions ) |
{ |
radeon_init_common_texture_funcs(radeon, functions); |
functions->NewTextureObject = radeonNewTextureObject; |
// functions->BindTexture = radeonBindTexture; |
functions->DeleteTexture = radeonDeleteTexture; |
functions->TexEnv = radeonTexEnv; |
functions->TexParameter = radeonTexParameter; |
functions->TexGen = radeonTexGen; |
functions->NewSamplerObject = radeonNewSamplerObject; |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_tex.h |
---|
0,0 → 1,54 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Kevin E. Martin <martin@valinux.com> |
* Gareth Hughes <gareth@valinux.com> |
* |
*/ |
#ifndef __RADEON_TEX_H__ |
#define __RADEON_TEX_H__ |
extern void radeonSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv); |
extern void radeonSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_format, |
__DRIdrawable *dPriv); |
extern void radeonUpdateTextureState( struct gl_context *ctx ); |
extern int radeonUploadTexImages( r100ContextPtr rmesa, radeonTexObjPtr t, |
GLuint face ); |
extern void radeonDestroyTexObj( r100ContextPtr rmesa, radeonTexObjPtr t ); |
extern void radeonTexUpdateParameters(struct gl_context *ctx, GLuint unit); |
extern void radeonInitTextureFuncs( radeonContextPtr radeon, struct dd_function_table *functions ); |
#endif /* __RADEON_TEX_H__ */ |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_tex_copy.c |
---|
0,0 → 1,160 |
/* |
* Copyright (C) 2009 Maciej Cencora <m.cencora@gmail.com> |
* |
* 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, 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 COPYRIGHT OWNER(S) 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 "radeon_common.h" |
#include "radeon_texture.h" |
#include "main/enums.h" |
#include "main/image.h" |
#include "main/teximage.h" |
#include "main/texstate.h" |
#include "drivers/common/meta.h" |
#include "radeon_mipmap_tree.h" |
static GLboolean |
do_copy_texsubimage(struct gl_context *ctx, |
struct radeon_tex_obj *tobj, |
radeon_texture_image *timg, |
GLint dstx, GLint dsty, |
struct radeon_renderbuffer *rrb, |
GLint x, GLint y, |
GLsizei width, GLsizei height) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
const GLuint face = timg->base.Base.Face; |
const GLuint level = timg->base.Base.Level; |
unsigned src_bpp; |
unsigned dst_bpp; |
gl_format src_mesaformat; |
gl_format dst_mesaformat; |
unsigned flip_y; |
if (!radeon->vtbl.blit) { |
return GL_FALSE; |
} |
// This is software renderbuffer, fallback to swrast |
if (!rrb) { |
return GL_FALSE; |
} |
if (_mesa_get_format_bits(timg->base.Base.TexFormat, GL_DEPTH_BITS) > 0) { |
/* copying depth values */ |
flip_y = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Type == GL_NONE; |
} else { |
/* copying color */ |
flip_y = ctx->ReadBuffer->Attachment[BUFFER_COLOR0].Type == GL_NONE; |
} |
if (!timg->mt) { |
radeon_validate_texture_miptree(ctx, &tobj->base.Sampler, &tobj->base); |
} |
assert(rrb->bo); |
assert(timg->mt); |
assert(timg->mt->bo); |
assert(timg->base.Base.Width >= dstx + width); |
assert(timg->base.Base.Height >= dsty + height); |
intptr_t src_offset = rrb->draw_offset; |
intptr_t dst_offset = radeon_miptree_image_offset(timg->mt, face, level); |
if (0) { |
fprintf(stderr, "%s: copying to face %d, level %d\n", |
__FUNCTION__, face, level); |
fprintf(stderr, "to: x %d, y %d, offset %d\n", dstx, dsty, (uint32_t) dst_offset); |
fprintf(stderr, "from (%dx%d) width %d, height %d, offset %d, pitch %d\n", |
x, y, rrb->base.Base.Width, rrb->base.Base.Height, (uint32_t) src_offset, rrb->pitch/rrb->cpp); |
fprintf(stderr, "src size %d, dst size %d\n", rrb->bo->size, timg->mt->bo->size); |
} |
src_mesaformat = rrb->base.Base.Format; |
dst_mesaformat = timg->base.Base.TexFormat; |
src_bpp = _mesa_get_format_bytes(src_mesaformat); |
dst_bpp = _mesa_get_format_bytes(dst_mesaformat); |
if (!radeon->vtbl.check_blit(dst_mesaformat, rrb->pitch / rrb->cpp)) { |
/* depth formats tend to be special */ |
if (_mesa_get_format_bits(dst_mesaformat, GL_DEPTH_BITS) > 0) |
return GL_FALSE; |
if (src_bpp != dst_bpp) |
return GL_FALSE; |
switch (dst_bpp) { |
case 2: |
src_mesaformat = MESA_FORMAT_RGB565; |
dst_mesaformat = MESA_FORMAT_RGB565; |
break; |
case 4: |
src_mesaformat = MESA_FORMAT_ARGB8888; |
dst_mesaformat = MESA_FORMAT_ARGB8888; |
break; |
case 1: |
src_mesaformat = MESA_FORMAT_A8; |
dst_mesaformat = MESA_FORMAT_A8; |
break; |
default: |
return GL_FALSE; |
} |
} |
/* blit from src buffer to texture */ |
return radeon->vtbl.blit(ctx, rrb->bo, src_offset, src_mesaformat, rrb->pitch/rrb->cpp, |
rrb->base.Base.Width, rrb->base.Base.Height, x, y, |
timg->mt->bo, dst_offset, dst_mesaformat, |
timg->mt->levels[level].rowstride / dst_bpp, |
timg->base.Base.Width, timg->base.Base.Height, |
dstx, dsty, width, height, flip_y); |
} |
void |
radeonCopyTexSubImage(struct gl_context *ctx, GLuint dims, |
struct gl_texture_image *texImage, |
GLint xoffset, GLint yoffset, GLint slice, |
struct gl_renderbuffer *rb, |
GLint x, GLint y, |
GLsizei width, GLsizei height) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
radeon_prepare_render(radeon); |
if (slice != 0 || !do_copy_texsubimage(ctx, |
radeon_tex_obj(texImage->TexObject), |
(radeon_texture_image *)texImage, |
xoffset, yoffset, |
radeon_renderbuffer(rb), x, y, width, height)) { |
radeon_print(RADEON_FALLBACKS, RADEON_NORMAL, |
"Falling back to sw for glCopyTexSubImage2D\n"); |
_mesa_meta_CopyTexSubImage(ctx, dims, texImage, |
xoffset, yoffset, slice, |
rb, x, y, width, height); |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_texstate.c |
---|
0,0 → 1,1144 |
/************************************************************************** |
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and |
VA Linux Systems Inc., Fremont, California. |
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, 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 COPYRIGHT OWNER(S) 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: |
* Kevin E. Martin <martin@valinux.com> |
* Gareth Hughes <gareth@valinux.com> |
*/ |
#include "main/glheader.h" |
#include "main/imports.h" |
#include "main/colormac.h" |
#include "main/context.h" |
#include "main/macros.h" |
#include "main/teximage.h" |
#include "main/texstate.h" |
#include "main/texobj.h" |
#include "main/enums.h" |
#include "main/samplerobj.h" |
#include "radeon_context.h" |
#include "radeon_mipmap_tree.h" |
#include "radeon_state.h" |
#include "radeon_ioctl.h" |
#include "radeon_swtcl.h" |
#include "radeon_tex.h" |
#include "radeon_tcl.h" |
#define RADEON_TXFORMAT_A8 RADEON_TXFORMAT_I8 |
#define RADEON_TXFORMAT_L8 RADEON_TXFORMAT_I8 |
#define RADEON_TXFORMAT_AL88 RADEON_TXFORMAT_AI88 |
#define RADEON_TXFORMAT_YCBCR RADEON_TXFORMAT_YVYU422 |
#define RADEON_TXFORMAT_YCBCR_REV RADEON_TXFORMAT_VYUY422 |
#define RADEON_TXFORMAT_RGB_DXT1 RADEON_TXFORMAT_DXT1 |
#define RADEON_TXFORMAT_RGBA_DXT1 RADEON_TXFORMAT_DXT1 |
#define RADEON_TXFORMAT_RGBA_DXT3 RADEON_TXFORMAT_DXT23 |
#define RADEON_TXFORMAT_RGBA_DXT5 RADEON_TXFORMAT_DXT45 |
#define _COLOR(f) \ |
[ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, 0 } |
#define _COLOR_REV(f) \ |
[ MESA_FORMAT_ ## f ## _REV ] = { RADEON_TXFORMAT_ ## f, 0 } |
#define _ALPHA(f) \ |
[ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f | RADEON_TXFORMAT_ALPHA_IN_MAP, 0 } |
#define _ALPHA_REV(f) \ |
[ MESA_FORMAT_ ## f ## _REV ] = { RADEON_TXFORMAT_ ## f | RADEON_TXFORMAT_ALPHA_IN_MAP, 0 } |
#define _YUV(f) \ |
[ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, RADEON_YUV_TO_RGB } |
#define _INVALID(f) \ |
[ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 } |
#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \ |
&& (tx_table[f].format != 0xffffffff) ) |
struct tx_table { |
GLuint format, filter; |
}; |
/* XXX verify this table against MESA_FORMAT_x values */ |
static const struct tx_table tx_table[] = |
{ |
_INVALID(NONE), /* MESA_FORMAT_NONE */ |
_ALPHA(RGBA8888), |
_ALPHA_REV(RGBA8888), |
_ALPHA(ARGB8888), |
_ALPHA_REV(ARGB8888), |
[ MESA_FORMAT_RGB888 ] = { RADEON_TXFORMAT_ARGB8888, 0 }, |
_COLOR(RGB565), |
_COLOR_REV(RGB565), |
_ALPHA(ARGB4444), |
_ALPHA_REV(ARGB4444), |
_ALPHA(ARGB1555), |
_ALPHA_REV(ARGB1555), |
_ALPHA(AL88), |
_ALPHA_REV(AL88), |
_ALPHA(A8), |
_COLOR(L8), |
_ALPHA(I8), |
_YUV(YCBCR), |
_YUV(YCBCR_REV), |
_INVALID(RGB_FXT1), |
_INVALID(RGBA_FXT1), |
_COLOR(RGB_DXT1), |
_ALPHA(RGBA_DXT1), |
_ALPHA(RGBA_DXT3), |
_ALPHA(RGBA_DXT5), |
}; |
#undef _COLOR |
#undef _ALPHA |
#undef _INVALID |
/* ================================================================ |
* Texture combine functions |
*/ |
/* GL_ARB_texture_env_combine support |
*/ |
/* The color tables have combine functions for GL_SRC_COLOR, |
* GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA. |
*/ |
static GLuint radeon_texture_color[][RADEON_MAX_TEXTURE_UNITS] = |
{ |
{ |
RADEON_COLOR_ARG_A_T0_COLOR, |
RADEON_COLOR_ARG_A_T1_COLOR, |
RADEON_COLOR_ARG_A_T2_COLOR |
}, |
{ |
RADEON_COLOR_ARG_A_T0_COLOR | RADEON_COMP_ARG_A, |
RADEON_COLOR_ARG_A_T1_COLOR | RADEON_COMP_ARG_A, |
RADEON_COLOR_ARG_A_T2_COLOR | RADEON_COMP_ARG_A |
}, |
{ |
RADEON_COLOR_ARG_A_T0_ALPHA, |
RADEON_COLOR_ARG_A_T1_ALPHA, |
RADEON_COLOR_ARG_A_T2_ALPHA |
}, |
{ |
RADEON_COLOR_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A, |
RADEON_COLOR_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A, |
RADEON_COLOR_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A |
}, |
}; |
static GLuint radeon_tfactor_color[] = |
{ |
RADEON_COLOR_ARG_A_TFACTOR_COLOR, |
RADEON_COLOR_ARG_A_TFACTOR_COLOR | RADEON_COMP_ARG_A, |
RADEON_COLOR_ARG_A_TFACTOR_ALPHA, |
RADEON_COLOR_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A |
}; |
static GLuint radeon_primary_color[] = |
{ |
RADEON_COLOR_ARG_A_DIFFUSE_COLOR, |
RADEON_COLOR_ARG_A_DIFFUSE_COLOR | RADEON_COMP_ARG_A, |
RADEON_COLOR_ARG_A_DIFFUSE_ALPHA, |
RADEON_COLOR_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A |
}; |
static GLuint radeon_previous_color[] = |
{ |
RADEON_COLOR_ARG_A_CURRENT_COLOR, |
RADEON_COLOR_ARG_A_CURRENT_COLOR | RADEON_COMP_ARG_A, |
RADEON_COLOR_ARG_A_CURRENT_ALPHA, |
RADEON_COLOR_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A |
}; |
/* GL_ZERO table - indices 0-3 |
* GL_ONE table - indices 1-4 |
*/ |
static GLuint radeon_zero_color[] = |
{ |
RADEON_COLOR_ARG_A_ZERO, |
RADEON_COLOR_ARG_A_ZERO | RADEON_COMP_ARG_A, |
RADEON_COLOR_ARG_A_ZERO, |
RADEON_COLOR_ARG_A_ZERO | RADEON_COMP_ARG_A, |
RADEON_COLOR_ARG_A_ZERO |
}; |
/* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA. |
*/ |
static GLuint radeon_texture_alpha[][RADEON_MAX_TEXTURE_UNITS] = |
{ |
{ |
RADEON_ALPHA_ARG_A_T0_ALPHA, |
RADEON_ALPHA_ARG_A_T1_ALPHA, |
RADEON_ALPHA_ARG_A_T2_ALPHA |
}, |
{ |
RADEON_ALPHA_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A, |
RADEON_ALPHA_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A, |
RADEON_ALPHA_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A |
}, |
}; |
static GLuint radeon_tfactor_alpha[] = |
{ |
RADEON_ALPHA_ARG_A_TFACTOR_ALPHA, |
RADEON_ALPHA_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A |
}; |
static GLuint radeon_primary_alpha[] = |
{ |
RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA, |
RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A |
}; |
static GLuint radeon_previous_alpha[] = |
{ |
RADEON_ALPHA_ARG_A_CURRENT_ALPHA, |
RADEON_ALPHA_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A |
}; |
/* GL_ZERO table - indices 0-1 |
* GL_ONE table - indices 1-2 |
*/ |
static GLuint radeon_zero_alpha[] = |
{ |
RADEON_ALPHA_ARG_A_ZERO, |
RADEON_ALPHA_ARG_A_ZERO | RADEON_COMP_ARG_A, |
RADEON_ALPHA_ARG_A_ZERO |
}; |
/* Extract the arg from slot A, shift it into the correct argument slot |
* and set the corresponding complement bit. |
*/ |
#define RADEON_COLOR_ARG( n, arg ) \ |
do { \ |
color_combine |= \ |
((color_arg[n] & RADEON_COLOR_ARG_MASK) \ |
<< RADEON_COLOR_ARG_##arg##_SHIFT); \ |
color_combine |= \ |
((color_arg[n] >> RADEON_COMP_ARG_SHIFT) \ |
<< RADEON_COMP_ARG_##arg##_SHIFT); \ |
} while (0) |
#define RADEON_ALPHA_ARG( n, arg ) \ |
do { \ |
alpha_combine |= \ |
((alpha_arg[n] & RADEON_ALPHA_ARG_MASK) \ |
<< RADEON_ALPHA_ARG_##arg##_SHIFT); \ |
alpha_combine |= \ |
((alpha_arg[n] >> RADEON_COMP_ARG_SHIFT) \ |
<< RADEON_COMP_ARG_##arg##_SHIFT); \ |
} while (0) |
/* ================================================================ |
* Texture unit state management |
*/ |
static GLboolean radeonUpdateTextureEnv( struct gl_context *ctx, int unit ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
GLuint color_combine, alpha_combine; |
const GLuint color_combine0 = RADEON_COLOR_ARG_A_ZERO | RADEON_COLOR_ARG_B_ZERO |
| RADEON_COLOR_ARG_C_CURRENT_COLOR | RADEON_BLEND_CTL_ADD |
| RADEON_SCALE_1X | RADEON_CLAMP_TX; |
const GLuint alpha_combine0 = RADEON_ALPHA_ARG_A_ZERO | RADEON_ALPHA_ARG_B_ZERO |
| RADEON_ALPHA_ARG_C_CURRENT_ALPHA | RADEON_BLEND_CTL_ADD |
| RADEON_SCALE_1X | RADEON_CLAMP_TX; |
/* texUnit->_Current can be NULL if and only if the texture unit is |
* not actually enabled. |
*/ |
assert( (texUnit->_ReallyEnabled == 0) |
|| (texUnit->_Current != NULL) ); |
if ( RADEON_DEBUG & RADEON_TEXTURE ) { |
fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, (void *)ctx, unit ); |
} |
/* Set the texture environment state. Isn't this nice and clean? |
* The chip will automagically set the texture alpha to 0xff when |
* the texture format does not include an alpha component. This |
* reduces the amount of special-casing we have to do, alpha-only |
* textures being a notable exception. Doesn't work for luminance |
* textures realized with I8 and ALPHA_IN_MAP not set neither (on r100). |
*/ |
/* Don't cache these results. |
*/ |
rmesa->state.texture.unit[unit].format = 0; |
rmesa->state.texture.unit[unit].envMode = 0; |
if ( !texUnit->_ReallyEnabled ) { |
color_combine = color_combine0; |
alpha_combine = alpha_combine0; |
} |
else { |
GLuint color_arg[3], alpha_arg[3]; |
GLuint i; |
const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB; |
const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA; |
GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB; |
GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA; |
/* Step 1: |
* Extract the color and alpha combine function arguments. |
*/ |
for ( i = 0 ; i < numColorArgs ; i++ ) { |
const GLint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR; |
const GLuint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i]; |
assert(op >= 0); |
assert(op <= 3); |
switch ( srcRGBi ) { |
case GL_TEXTURE: |
if (texUnit->_Current->Image[0][0]->_BaseFormat == GL_ALPHA) |
color_arg[i] = radeon_zero_color[op]; |
else |
color_arg[i] = radeon_texture_color[op][unit]; |
break; |
case GL_CONSTANT: |
color_arg[i] = radeon_tfactor_color[op]; |
break; |
case GL_PRIMARY_COLOR: |
color_arg[i] = radeon_primary_color[op]; |
break; |
case GL_PREVIOUS: |
color_arg[i] = radeon_previous_color[op]; |
break; |
case GL_ZERO: |
color_arg[i] = radeon_zero_color[op]; |
break; |
case GL_ONE: |
color_arg[i] = radeon_zero_color[op+1]; |
break; |
case GL_TEXTURE0: |
case GL_TEXTURE1: |
case GL_TEXTURE2: { |
GLuint txunit = srcRGBi - GL_TEXTURE0; |
if (ctx->Texture.Unit[txunit]._Current->Image[0][0]->_BaseFormat == GL_ALPHA) |
color_arg[i] = radeon_zero_color[op]; |
else |
/* implement ogl 1.4/1.5 core spec here, not specification of |
* GL_ARB_texture_env_crossbar (which would require disabling blending |
* instead of undefined results when referencing not enabled texunit) */ |
color_arg[i] = radeon_texture_color[op][txunit]; |
} |
break; |
default: |
return GL_FALSE; |
} |
} |
for ( i = 0 ; i < numAlphaArgs ; i++ ) { |
const GLint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA; |
const GLuint srcAi = texUnit->_CurrentCombine->SourceA[i]; |
assert(op >= 0); |
assert(op <= 1); |
switch ( srcAi ) { |
case GL_TEXTURE: |
if (texUnit->_Current->Image[0][0]->_BaseFormat == GL_LUMINANCE) |
alpha_arg[i] = radeon_zero_alpha[op+1]; |
else |
alpha_arg[i] = radeon_texture_alpha[op][unit]; |
break; |
case GL_CONSTANT: |
alpha_arg[i] = radeon_tfactor_alpha[op]; |
break; |
case GL_PRIMARY_COLOR: |
alpha_arg[i] = radeon_primary_alpha[op]; |
break; |
case GL_PREVIOUS: |
alpha_arg[i] = radeon_previous_alpha[op]; |
break; |
case GL_ZERO: |
alpha_arg[i] = radeon_zero_alpha[op]; |
break; |
case GL_ONE: |
alpha_arg[i] = radeon_zero_alpha[op+1]; |
break; |
case GL_TEXTURE0: |
case GL_TEXTURE1: |
case GL_TEXTURE2: { |
GLuint txunit = srcAi - GL_TEXTURE0; |
if (ctx->Texture.Unit[txunit]._Current->Image[0][0]->_BaseFormat == GL_LUMINANCE) |
alpha_arg[i] = radeon_zero_alpha[op+1]; |
else |
alpha_arg[i] = radeon_texture_alpha[op][txunit]; |
} |
break; |
default: |
return GL_FALSE; |
} |
} |
/* Step 2: |
* Build up the color and alpha combine functions. |
*/ |
switch ( texUnit->_CurrentCombine->ModeRGB ) { |
case GL_REPLACE: |
color_combine = (RADEON_COLOR_ARG_A_ZERO | |
RADEON_COLOR_ARG_B_ZERO | |
RADEON_BLEND_CTL_ADD | |
RADEON_CLAMP_TX); |
RADEON_COLOR_ARG( 0, C ); |
break; |
case GL_MODULATE: |
color_combine = (RADEON_COLOR_ARG_C_ZERO | |
RADEON_BLEND_CTL_ADD | |
RADEON_CLAMP_TX); |
RADEON_COLOR_ARG( 0, A ); |
RADEON_COLOR_ARG( 1, B ); |
break; |
case GL_ADD: |
color_combine = (RADEON_COLOR_ARG_B_ZERO | |
RADEON_COMP_ARG_B | |
RADEON_BLEND_CTL_ADD | |
RADEON_CLAMP_TX); |
RADEON_COLOR_ARG( 0, A ); |
RADEON_COLOR_ARG( 1, C ); |
break; |
case GL_ADD_SIGNED: |
color_combine = (RADEON_COLOR_ARG_B_ZERO | |
RADEON_COMP_ARG_B | |
RADEON_BLEND_CTL_ADDSIGNED | |
RADEON_CLAMP_TX); |
RADEON_COLOR_ARG( 0, A ); |
RADEON_COLOR_ARG( 1, C ); |
break; |
case GL_SUBTRACT: |
color_combine = (RADEON_COLOR_ARG_B_ZERO | |
RADEON_COMP_ARG_B | |
RADEON_BLEND_CTL_SUBTRACT | |
RADEON_CLAMP_TX); |
RADEON_COLOR_ARG( 0, A ); |
RADEON_COLOR_ARG( 1, C ); |
break; |
case GL_INTERPOLATE: |
color_combine = (RADEON_BLEND_CTL_BLEND | |
RADEON_CLAMP_TX); |
RADEON_COLOR_ARG( 0, B ); |
RADEON_COLOR_ARG( 1, A ); |
RADEON_COLOR_ARG( 2, C ); |
break; |
case GL_DOT3_RGB_EXT: |
case GL_DOT3_RGBA_EXT: |
/* The EXT version of the DOT3 extension does not support the |
* scale factor, but the ARB version (and the version in OpenGL |
* 1.3) does. |
*/ |
RGBshift = 0; |
/* FALLTHROUGH */ |
case GL_DOT3_RGB: |
case GL_DOT3_RGBA: |
/* The R100 / RV200 only support a 1X multiplier in hardware |
* w/the ARB version. |
*/ |
if ( RGBshift != (RADEON_SCALE_1X >> RADEON_SCALE_SHIFT) ) { |
return GL_FALSE; |
} |
RGBshift += 2; |
if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT) |
|| (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) { |
/* is it necessary to set this or will it be ignored anyway? */ |
Ashift = RGBshift; |
} |
color_combine = (RADEON_COLOR_ARG_C_ZERO | |
RADEON_BLEND_CTL_DOT3 | |
RADEON_CLAMP_TX); |
RADEON_COLOR_ARG( 0, A ); |
RADEON_COLOR_ARG( 1, B ); |
break; |
case GL_MODULATE_ADD_ATI: |
color_combine = (RADEON_BLEND_CTL_ADD | |
RADEON_CLAMP_TX); |
RADEON_COLOR_ARG( 0, A ); |
RADEON_COLOR_ARG( 1, C ); |
RADEON_COLOR_ARG( 2, B ); |
break; |
case GL_MODULATE_SIGNED_ADD_ATI: |
color_combine = (RADEON_BLEND_CTL_ADDSIGNED | |
RADEON_CLAMP_TX); |
RADEON_COLOR_ARG( 0, A ); |
RADEON_COLOR_ARG( 1, C ); |
RADEON_COLOR_ARG( 2, B ); |
break; |
case GL_MODULATE_SUBTRACT_ATI: |
color_combine = (RADEON_BLEND_CTL_SUBTRACT | |
RADEON_CLAMP_TX); |
RADEON_COLOR_ARG( 0, A ); |
RADEON_COLOR_ARG( 1, C ); |
RADEON_COLOR_ARG( 2, B ); |
break; |
default: |
return GL_FALSE; |
} |
switch ( texUnit->_CurrentCombine->ModeA ) { |
case GL_REPLACE: |
alpha_combine = (RADEON_ALPHA_ARG_A_ZERO | |
RADEON_ALPHA_ARG_B_ZERO | |
RADEON_BLEND_CTL_ADD | |
RADEON_CLAMP_TX); |
RADEON_ALPHA_ARG( 0, C ); |
break; |
case GL_MODULATE: |
alpha_combine = (RADEON_ALPHA_ARG_C_ZERO | |
RADEON_BLEND_CTL_ADD | |
RADEON_CLAMP_TX); |
RADEON_ALPHA_ARG( 0, A ); |
RADEON_ALPHA_ARG( 1, B ); |
break; |
case GL_ADD: |
alpha_combine = (RADEON_ALPHA_ARG_B_ZERO | |
RADEON_COMP_ARG_B | |
RADEON_BLEND_CTL_ADD | |
RADEON_CLAMP_TX); |
RADEON_ALPHA_ARG( 0, A ); |
RADEON_ALPHA_ARG( 1, C ); |
break; |
case GL_ADD_SIGNED: |
alpha_combine = (RADEON_ALPHA_ARG_B_ZERO | |
RADEON_COMP_ARG_B | |
RADEON_BLEND_CTL_ADDSIGNED | |
RADEON_CLAMP_TX); |
RADEON_ALPHA_ARG( 0, A ); |
RADEON_ALPHA_ARG( 1, C ); |
break; |
case GL_SUBTRACT: |
alpha_combine = (RADEON_COLOR_ARG_B_ZERO | |
RADEON_COMP_ARG_B | |
RADEON_BLEND_CTL_SUBTRACT | |
RADEON_CLAMP_TX); |
RADEON_ALPHA_ARG( 0, A ); |
RADEON_ALPHA_ARG( 1, C ); |
break; |
case GL_INTERPOLATE: |
alpha_combine = (RADEON_BLEND_CTL_BLEND | |
RADEON_CLAMP_TX); |
RADEON_ALPHA_ARG( 0, B ); |
RADEON_ALPHA_ARG( 1, A ); |
RADEON_ALPHA_ARG( 2, C ); |
break; |
case GL_MODULATE_ADD_ATI: |
alpha_combine = (RADEON_BLEND_CTL_ADD | |
RADEON_CLAMP_TX); |
RADEON_ALPHA_ARG( 0, A ); |
RADEON_ALPHA_ARG( 1, C ); |
RADEON_ALPHA_ARG( 2, B ); |
break; |
case GL_MODULATE_SIGNED_ADD_ATI: |
alpha_combine = (RADEON_BLEND_CTL_ADDSIGNED | |
RADEON_CLAMP_TX); |
RADEON_ALPHA_ARG( 0, A ); |
RADEON_ALPHA_ARG( 1, C ); |
RADEON_ALPHA_ARG( 2, B ); |
break; |
case GL_MODULATE_SUBTRACT_ATI: |
alpha_combine = (RADEON_BLEND_CTL_SUBTRACT | |
RADEON_CLAMP_TX); |
RADEON_ALPHA_ARG( 0, A ); |
RADEON_ALPHA_ARG( 1, C ); |
RADEON_ALPHA_ARG( 2, B ); |
break; |
default: |
return GL_FALSE; |
} |
if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGB_EXT) |
|| (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGB) ) { |
alpha_combine |= RADEON_DOT_ALPHA_DONT_REPLICATE; |
} |
/* Step 3: |
* Apply the scale factor. |
*/ |
color_combine |= (RGBshift << RADEON_SCALE_SHIFT); |
alpha_combine |= (Ashift << RADEON_SCALE_SHIFT); |
/* All done! |
*/ |
} |
if ( rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] != color_combine || |
rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] != alpha_combine ) { |
RADEON_STATECHANGE( rmesa, tex[unit] ); |
rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] = color_combine; |
rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] = alpha_combine; |
} |
return GL_TRUE; |
} |
void radeonSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint texture_format, |
__DRIdrawable *dPriv) |
{ |
struct gl_texture_unit *texUnit; |
struct gl_texture_object *texObj; |
struct gl_texture_image *texImage; |
struct radeon_renderbuffer *rb; |
radeon_texture_image *rImage; |
radeonContextPtr radeon; |
struct radeon_framebuffer *rfb; |
radeonTexObjPtr t; |
uint32_t pitch_val; |
gl_format texFormat; |
radeon = pDRICtx->driverPrivate; |
rfb = dPriv->driverPrivate; |
texUnit = _mesa_get_current_tex_unit(&radeon->glCtx); |
texObj = _mesa_select_tex_object(&radeon->glCtx, texUnit, target); |
texImage = _mesa_get_tex_image(&radeon->glCtx, texObj, target, 0); |
rImage = get_radeon_texture_image(texImage); |
t = radeon_tex_obj(texObj); |
if (t == NULL) { |
return; |
} |
radeon_update_renderbuffers(pDRICtx, dPriv, GL_TRUE); |
rb = rfb->color_rb[0]; |
if (rb->bo == NULL) { |
/* Failed to BO for the buffer */ |
return; |
} |
_mesa_lock_texture(&radeon->glCtx, texObj); |
if (t->bo) { |
radeon_bo_unref(t->bo); |
t->bo = NULL; |
} |
if (rImage->bo) { |
radeon_bo_unref(rImage->bo); |
rImage->bo = NULL; |
} |
radeon_miptree_unreference(&t->mt); |
radeon_miptree_unreference(&rImage->mt); |
rImage->bo = rb->bo; |
radeon_bo_ref(rImage->bo); |
t->bo = rb->bo; |
radeon_bo_ref(t->bo); |
t->tile_bits = 0; |
t->image_override = GL_TRUE; |
t->override_offset = 0; |
switch (rb->cpp) { |
case 4: |
if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { |
t->pp_txformat = tx_table[MESA_FORMAT_RGB888].format; |
texFormat = MESA_FORMAT_RGB888; |
} |
else { |
t->pp_txformat = tx_table[MESA_FORMAT_ARGB8888].format; |
texFormat = MESA_FORMAT_ARGB8888; |
} |
t->pp_txfilter |= tx_table[MESA_FORMAT_ARGB8888].filter; |
break; |
case 3: |
default: |
texFormat = MESA_FORMAT_RGB888; |
t->pp_txformat = tx_table[MESA_FORMAT_RGB888].format; |
t->pp_txfilter |= tx_table[MESA_FORMAT_RGB888].filter; |
break; |
case 2: |
texFormat = MESA_FORMAT_RGB565; |
t->pp_txformat = tx_table[MESA_FORMAT_RGB565].format; |
t->pp_txfilter |= tx_table[MESA_FORMAT_RGB565].filter; |
break; |
} |
_mesa_init_teximage_fields(&radeon->glCtx, texImage, |
rb->base.Base.Width, rb->base.Base.Height, |
1, 0, |
rb->cpp, texFormat); |
rImage->base.RowStride = rb->pitch / rb->cpp; |
t->pp_txpitch &= (1 << 13) -1; |
pitch_val = rb->pitch; |
t->pp_txsize = ((rb->base.Base.Width - 1) << RADEON_TEX_USIZE_SHIFT) |
| ((rb->base.Base.Height - 1) << RADEON_TEX_VSIZE_SHIFT); |
if (target == GL_TEXTURE_RECTANGLE_NV) { |
t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2; |
t->pp_txpitch = pitch_val; |
t->pp_txpitch -= 32; |
} else { |
t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK | |
RADEON_TXFORMAT_HEIGHT_MASK | |
RADEON_TXFORMAT_CUBIC_MAP_ENABLE | |
RADEON_TXFORMAT_F5_WIDTH_MASK | |
RADEON_TXFORMAT_F5_HEIGHT_MASK); |
t->pp_txformat |= ((texImage->WidthLog2 << RADEON_TXFORMAT_WIDTH_SHIFT) | |
(texImage->HeightLog2 << RADEON_TXFORMAT_HEIGHT_SHIFT)); |
} |
t->validated = GL_TRUE; |
_mesa_unlock_texture(&radeon->glCtx, texObj); |
return; |
} |
void radeonSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv) |
{ |
radeonSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); |
} |
#define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \ |
RADEON_MIN_FILTER_MASK | \ |
RADEON_MAG_FILTER_MASK | \ |
RADEON_MAX_ANISO_MASK | \ |
RADEON_YUV_TO_RGB | \ |
RADEON_YUV_TEMPERATURE_MASK | \ |
RADEON_CLAMP_S_MASK | \ |
RADEON_CLAMP_T_MASK | \ |
RADEON_BORDER_MODE_D3D ) |
#define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK | \ |
RADEON_TXFORMAT_HEIGHT_MASK | \ |
RADEON_TXFORMAT_FORMAT_MASK | \ |
RADEON_TXFORMAT_F5_WIDTH_MASK | \ |
RADEON_TXFORMAT_F5_HEIGHT_MASK | \ |
RADEON_TXFORMAT_ALPHA_IN_MAP | \ |
RADEON_TXFORMAT_CUBIC_MAP_ENABLE | \ |
RADEON_TXFORMAT_NON_POWER2) |
static void disable_tex_obj_state( r100ContextPtr rmesa, |
int unit ) |
{ |
RADEON_STATECHANGE( rmesa, tex[unit] ); |
RADEON_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_ST_BIT(unit) | |
RADEON_Q_BIT(unit)); |
if (rmesa->radeon.TclFallback & (RADEON_TCL_FALLBACK_TEXGEN_0<<unit)) { |
TCL_FALLBACK( &rmesa->radeon.glCtx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE); |
rmesa->recheck_texgen[unit] = GL_TRUE; |
} |
if (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) { |
/* this seems to be a genuine (r100 only?) hw bug. Need to remove the |
cubic_map bit on unit 2 when the unit is disabled, otherwise every |
2nd (2d) mipmap on unit 0 will be broken (may not be needed for other |
units, better be safe than sorry though).*/ |
RADEON_STATECHANGE( rmesa, tex[unit] ); |
rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= ~RADEON_TXFORMAT_CUBIC_MAP_ENABLE; |
} |
{ |
GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4; |
GLuint tmp = rmesa->TexGenEnabled; |
rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit); |
rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit); |
rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift); |
rmesa->TexGenNeedNormals[unit] = 0; |
rmesa->TexGenEnabled |= |
(RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift; |
if (tmp != rmesa->TexGenEnabled) { |
rmesa->recheck_texgen[unit] = GL_TRUE; |
rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX; |
} |
} |
} |
static void import_tex_obj_state( r100ContextPtr rmesa, |
int unit, |
radeonTexObjPtr texobj ) |
{ |
/* do not use RADEON_DB_STATE to avoid stale texture caches */ |
uint32_t *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0]; |
GLuint se_coord_fmt = rmesa->hw.set.cmd[SET_SE_COORDFMT]; |
RADEON_STATECHANGE( rmesa, tex[unit] ); |
cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK; |
cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK; |
cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; |
cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK; |
cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color; |
if (texobj->pp_txformat & RADEON_TXFORMAT_NON_POWER2) { |
uint32_t *txr_cmd = &rmesa->hw.txr[unit].cmd[TXR_CMD_0]; |
txr_cmd[TXR_PP_TEX_SIZE] = texobj->pp_txsize; /* NPOT only! */ |
txr_cmd[TXR_PP_TEX_PITCH] = texobj->pp_txpitch; /* NPOT only! */ |
RADEON_STATECHANGE( rmesa, txr[unit] ); |
} |
if (texobj->base.Target == GL_TEXTURE_RECTANGLE_NV) { |
se_coord_fmt |= RADEON_VTX_ST0_NONPARAMETRIC << unit; |
} |
else { |
se_coord_fmt &= ~(RADEON_VTX_ST0_NONPARAMETRIC << unit); |
if (texobj->base.Target == GL_TEXTURE_CUBE_MAP) { |
uint32_t *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0]; |
RADEON_STATECHANGE( rmesa, cube[unit] ); |
cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces; |
/* state filled out in the cube_emit */ |
} |
} |
if (se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT]) { |
RADEON_STATECHANGE( rmesa, set ); |
rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt; |
} |
rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX; |
} |
static void set_texgen_matrix( r100ContextPtr rmesa, |
GLuint unit, |
const GLfloat *s_plane, |
const GLfloat *t_plane, |
const GLfloat *r_plane, |
const GLfloat *q_plane ) |
{ |
rmesa->TexGenMatrix[unit].m[0] = s_plane[0]; |
rmesa->TexGenMatrix[unit].m[4] = s_plane[1]; |
rmesa->TexGenMatrix[unit].m[8] = s_plane[2]; |
rmesa->TexGenMatrix[unit].m[12] = s_plane[3]; |
rmesa->TexGenMatrix[unit].m[1] = t_plane[0]; |
rmesa->TexGenMatrix[unit].m[5] = t_plane[1]; |
rmesa->TexGenMatrix[unit].m[9] = t_plane[2]; |
rmesa->TexGenMatrix[unit].m[13] = t_plane[3]; |
rmesa->TexGenMatrix[unit].m[2] = r_plane[0]; |
rmesa->TexGenMatrix[unit].m[6] = r_plane[1]; |
rmesa->TexGenMatrix[unit].m[10] = r_plane[2]; |
rmesa->TexGenMatrix[unit].m[14] = r_plane[3]; |
rmesa->TexGenMatrix[unit].m[3] = q_plane[0]; |
rmesa->TexGenMatrix[unit].m[7] = q_plane[1]; |
rmesa->TexGenMatrix[unit].m[11] = q_plane[2]; |
rmesa->TexGenMatrix[unit].m[15] = q_plane[3]; |
rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE << unit; |
rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX; |
} |
/* Returns GL_FALSE if fallback required. |
*/ |
static GLboolean radeon_validate_texgen( struct gl_context *ctx, GLuint unit ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4; |
GLuint tmp = rmesa->TexGenEnabled; |
static const GLfloat reflect[16] = { |
-1, 0, 0, 0, |
0, -1, 0, 0, |
0, 0, -1, 0, |
0, 0, 0, 1 }; |
rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE << unit); |
rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE << unit); |
rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK << inputshift); |
rmesa->TexGenNeedNormals[unit] = 0; |
if ((texUnit->TexGenEnabled & (S_BIT|T_BIT|R_BIT|Q_BIT)) == 0) { |
/* Disabled, no fallback: |
*/ |
rmesa->TexGenEnabled |= |
(RADEON_TEXGEN_INPUT_TEXCOORD_0 + unit) << inputshift; |
return GL_TRUE; |
} |
/* the r100 cannot do texgen for some coords and not for others |
* we do not detect such cases (certainly can't do it here) and just |
* ASSUME that when S and T are texgen enabled we do not need other |
* non-texgen enabled coords, no matter if the R and Q bits are texgen |
* enabled. Still check for mixed mode texgen for all coords. |
*/ |
else if ( (texUnit->TexGenEnabled & S_BIT) && |
(texUnit->TexGenEnabled & T_BIT) && |
(texUnit->GenS.Mode == texUnit->GenT.Mode) ) { |
if ( ((texUnit->TexGenEnabled & R_BIT) && |
(texUnit->GenS.Mode != texUnit->GenR.Mode)) || |
((texUnit->TexGenEnabled & Q_BIT) && |
(texUnit->GenS.Mode != texUnit->GenQ.Mode)) ) { |
/* Mixed modes, fallback: |
*/ |
if (RADEON_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "fallback mixed texgen\n"); |
return GL_FALSE; |
} |
rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit; |
} |
else { |
/* some texgen mode not including both S and T bits */ |
if (RADEON_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "fallback mixed texgen/nontexgen\n"); |
return GL_FALSE; |
} |
if ((texUnit->TexGenEnabled & (R_BIT | Q_BIT)) != 0) { |
/* need this here for vtxfmt presumably. Argh we need to set |
this from way too many places, would be much easier if we could leave |
tcl q coord always enabled as on r200) */ |
RADEON_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_Q_BIT(unit); |
} |
switch (texUnit->GenS.Mode) { |
case GL_OBJECT_LINEAR: |
rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_OBJ << inputshift; |
set_texgen_matrix( rmesa, unit, |
texUnit->GenS.ObjectPlane, |
texUnit->GenT.ObjectPlane, |
texUnit->GenR.ObjectPlane, |
texUnit->GenQ.ObjectPlane); |
break; |
case GL_EYE_LINEAR: |
rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE << inputshift; |
set_texgen_matrix( rmesa, unit, |
texUnit->GenS.EyePlane, |
texUnit->GenT.EyePlane, |
texUnit->GenR.EyePlane, |
texUnit->GenQ.EyePlane); |
break; |
case GL_REFLECTION_MAP_NV: |
rmesa->TexGenNeedNormals[unit] = GL_TRUE; |
rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_REFLECT << inputshift; |
/* TODO: unknown if this is needed/correct */ |
set_texgen_matrix( rmesa, unit, reflect, reflect + 4, |
reflect + 8, reflect + 12 ); |
break; |
case GL_NORMAL_MAP_NV: |
rmesa->TexGenNeedNormals[unit] = GL_TRUE; |
rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_NORMAL << inputshift; |
break; |
case GL_SPHERE_MAP: |
/* the mode which everyone uses :-( */ |
default: |
/* Unsupported mode, fallback: |
*/ |
if (RADEON_DEBUG & RADEON_FALLBACKS) |
fprintf(stderr, "fallback GL_SPHERE_MAP\n"); |
return GL_FALSE; |
} |
if (tmp != rmesa->TexGenEnabled) { |
rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX; |
} |
return GL_TRUE; |
} |
/** |
* Compute the cached hardware register values for the given texture object. |
* |
* \param rmesa Context pointer |
* \param t the r300 texture object |
*/ |
static GLboolean setup_hardware_state(r100ContextPtr rmesa, radeonTexObj *t, int unit) |
{ |
const struct gl_texture_image *firstImage; |
GLint log2Width, log2Height, texelBytes; |
if ( t->bo ) { |
return GL_TRUE; |
} |
firstImage = t->base.Image[0][t->minLod]; |
log2Width = firstImage->WidthLog2; |
log2Height = firstImage->HeightLog2; |
texelBytes = _mesa_get_format_bytes(firstImage->TexFormat); |
if (!t->image_override) { |
if (VALID_FORMAT(firstImage->TexFormat)) { |
const struct tx_table *table = tx_table; |
t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK | |
RADEON_TXFORMAT_ALPHA_IN_MAP); |
t->pp_txfilter &= ~RADEON_YUV_TO_RGB; |
t->pp_txformat |= table[ firstImage->TexFormat ].format; |
t->pp_txfilter |= table[ firstImage->TexFormat ].filter; |
} else { |
_mesa_problem(NULL, "unexpected texture format in %s", |
__FUNCTION__); |
return GL_FALSE; |
} |
} |
t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK; |
t->pp_txfilter |= (t->maxLod - t->minLod) << RADEON_MAX_MIP_LEVEL_SHIFT; |
t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK | |
RADEON_TXFORMAT_HEIGHT_MASK | |
RADEON_TXFORMAT_CUBIC_MAP_ENABLE | |
RADEON_TXFORMAT_F5_WIDTH_MASK | |
RADEON_TXFORMAT_F5_HEIGHT_MASK); |
t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) | |
(log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT)); |
t->tile_bits = 0; |
if (t->base.Target == GL_TEXTURE_CUBE_MAP) { |
ASSERT(log2Width == log2Height); |
t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_F5_WIDTH_SHIFT) | |
(log2Height << RADEON_TXFORMAT_F5_HEIGHT_SHIFT) | |
/* don't think we need this bit, if it exists at all - fglrx does not set it */ |
(RADEON_TXFORMAT_CUBIC_MAP_ENABLE)); |
t->pp_cubic_faces = ((log2Width << RADEON_FACE_WIDTH_1_SHIFT) | |
(log2Height << RADEON_FACE_HEIGHT_1_SHIFT) | |
(log2Width << RADEON_FACE_WIDTH_2_SHIFT) | |
(log2Height << RADEON_FACE_HEIGHT_2_SHIFT) | |
(log2Width << RADEON_FACE_WIDTH_3_SHIFT) | |
(log2Height << RADEON_FACE_HEIGHT_3_SHIFT) | |
(log2Width << RADEON_FACE_WIDTH_4_SHIFT) | |
(log2Height << RADEON_FACE_HEIGHT_4_SHIFT)); |
} |
t->pp_txsize = (((firstImage->Width - 1) << RADEON_TEX_USIZE_SHIFT) |
| ((firstImage->Height - 1) << RADEON_TEX_VSIZE_SHIFT)); |
if ( !t->image_override ) { |
if (_mesa_is_format_compressed(firstImage->TexFormat)) |
t->pp_txpitch = (firstImage->Width + 63) & ~(63); |
else |
t->pp_txpitch = ((firstImage->Width * texelBytes) + 63) & ~(63); |
t->pp_txpitch -= 32; |
} |
if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) { |
t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2; |
} |
return GL_TRUE; |
} |
static GLboolean radeon_validate_texture(struct gl_context *ctx, struct gl_texture_object *texObj, int unit) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
radeonTexObj *t = radeon_tex_obj(texObj); |
int ret; |
if (!radeon_validate_texture_miptree(ctx, _mesa_get_samplerobj(ctx, unit), texObj)) |
return GL_FALSE; |
ret = setup_hardware_state(rmesa, t, unit); |
if (ret == GL_FALSE) |
return GL_FALSE; |
/* yuv conversion only works in first unit */ |
if (unit != 0 && (t->pp_txfilter & RADEON_YUV_TO_RGB)) |
return GL_FALSE; |
RADEON_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= |
(RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit; |
RADEON_STATECHANGE( rmesa, tcl ); |
rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_ST_BIT(unit); |
rmesa->recheck_texgen[unit] = GL_TRUE; |
radeonTexUpdateParameters(ctx, unit); |
import_tex_obj_state( rmesa, unit, t ); |
if (rmesa->recheck_texgen[unit]) { |
GLboolean fallback = !radeon_validate_texgen( ctx, unit ); |
TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), fallback); |
rmesa->recheck_texgen[unit] = 0; |
rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX; |
} |
if ( ! radeonUpdateTextureEnv( ctx, unit ) ) { |
return GL_FALSE; |
} |
FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback ); |
t->validated = GL_TRUE; |
return !t->border_fallback; |
} |
static GLboolean radeonUpdateTextureUnit( struct gl_context *ctx, int unit ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
if (ctx->Texture.Unit[unit]._ReallyEnabled & TEXTURE_3D_BIT) { |
disable_tex_obj_state(rmesa, unit); |
rmesa->state.texture.unit[unit].texobj = NULL; |
return GL_FALSE; |
} |
if (!ctx->Texture.Unit[unit]._ReallyEnabled) { |
/* disable the unit */ |
disable_tex_obj_state(rmesa, unit); |
rmesa->state.texture.unit[unit].texobj = NULL; |
return GL_TRUE; |
} |
if (!radeon_validate_texture(ctx, ctx->Texture.Unit[unit]._Current, unit)) { |
_mesa_warning(ctx, |
"failed to validate texture for unit %d.\n", |
unit); |
rmesa->state.texture.unit[unit].texobj = NULL; |
return GL_FALSE; |
} |
rmesa->state.texture.unit[unit].texobj = radeon_tex_obj(ctx->Texture.Unit[unit]._Current); |
return GL_TRUE; |
} |
void radeonUpdateTextureState( struct gl_context *ctx ) |
{ |
r100ContextPtr rmesa = R100_CONTEXT(ctx); |
GLboolean ok; |
/* set the ctx all textures off */ |
RADEON_STATECHANGE( rmesa, ctx ); |
rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~((RADEON_TEX_ENABLE_MASK) | (RADEON_TEX_BLEND_ENABLE_MASK)); |
ok = (radeonUpdateTextureUnit( ctx, 0 ) && |
radeonUpdateTextureUnit( ctx, 1 ) && |
radeonUpdateTextureUnit( ctx, 2 )); |
FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, !ok ); |
if (rmesa->radeon.TclFallback) |
radeonChooseVertexState( ctx ); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_texture.c |
---|
0,0 → 1,684 |
/* |
* Copyright (C) 2009 Maciej Cencora. |
* Copyright (C) 2008 Nicolai Haehnle. |
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
* |
* The Weather Channel (TM) funded Tungsten Graphics to develop the |
* initial release of the Radeon 8500 driver under the XFree86 license. |
* This notice must be preserved. |
* |
* 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 COPYRIGHT OWNER(S) 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 "main/glheader.h" |
#include "main/imports.h" |
#include "main/context.h" |
#include "main/enums.h" |
#include "main/mipmap.h" |
#include "main/pbo.h" |
#include "main/texcompress.h" |
#include "main/texstore.h" |
#include "main/teximage.h" |
#include "main/texobj.h" |
#include "drivers/common/meta.h" |
#include "xmlpool.h" /* for symbolic values of enum-type options */ |
#include "radeon_common.h" |
#include "radeon_mipmap_tree.h" |
static void teximage_assign_miptree(radeonContextPtr rmesa, |
struct gl_texture_object *texObj, |
struct gl_texture_image *texImage); |
static radeon_mipmap_tree *radeon_miptree_create_for_teximage(radeonContextPtr rmesa, |
struct gl_texture_object *texObj, |
struct gl_texture_image *texImage); |
void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride, |
GLuint numrows, GLuint rowsize) |
{ |
assert(rowsize <= dststride); |
assert(rowsize <= srcstride); |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s dst %p, stride %u, src %p, stride %u, " |
"numrows %u, rowsize %u.\n", |
__func__, dst, dststride, |
src, srcstride, |
numrows, rowsize); |
if (rowsize == srcstride && rowsize == dststride) { |
memcpy(dst, src, numrows*rowsize); |
} else { |
GLuint i; |
for(i = 0; i < numrows; ++i) { |
memcpy(dst, src, rowsize); |
dst += dststride; |
src += srcstride; |
} |
} |
} |
/* textures */ |
/** |
* Allocate an empty texture image object. |
*/ |
struct gl_texture_image *radeonNewTextureImage(struct gl_context *ctx) |
{ |
return calloc(1, sizeof(radeon_texture_image)); |
} |
/** |
* Delete a texture image object. |
*/ |
static void |
radeonDeleteTextureImage(struct gl_context *ctx, struct gl_texture_image *img) |
{ |
/* nothing special (yet) for radeon_texture_image */ |
_mesa_delete_texture_image(ctx, img); |
} |
static GLboolean |
radeonAllocTextureImageBuffer(struct gl_context *ctx, |
struct gl_texture_image *timage) |
{ |
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
struct gl_texture_object *texobj = timage->TexObject; |
ctx->Driver.FreeTextureImageBuffer(ctx, timage); |
if (!_swrast_init_texture_image(timage)) |
return GL_FALSE; |
teximage_assign_miptree(rmesa, texobj, timage); |
return GL_TRUE; |
} |
/** |
* Free memory associated with this texture image. |
*/ |
void radeonFreeTextureImageBuffer(struct gl_context *ctx, struct gl_texture_image *timage) |
{ |
radeon_texture_image* image = get_radeon_texture_image(timage); |
if (image->mt) { |
radeon_miptree_unreference(&image->mt); |
} |
if (image->bo) { |
radeon_bo_unref(image->bo); |
image->bo = NULL; |
} |
_swrast_free_texture_image_buffer(ctx, timage); |
} |
/** |
* Map texture memory/buffer into user space. |
* Note: the region of interest parameters are ignored here. |
* \param mapOut returns start of mapping of region of interest |
* \param rowStrideOut returns row stride in bytes |
*/ |
static void |
radeon_map_texture_image(struct gl_context *ctx, |
struct gl_texture_image *texImage, |
GLuint slice, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **map, |
GLint *stride) |
{ |
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
radeon_texture_image *image = get_radeon_texture_image(texImage); |
radeon_mipmap_tree *mt = image->mt; |
GLuint texel_size = _mesa_get_format_bytes(texImage->TexFormat); |
GLuint width = texImage->Width; |
GLuint height = texImage->Height; |
struct radeon_bo *bo = !image->mt ? image->bo : image->mt->bo; |
unsigned int bw, bh; |
GLboolean write = (mode & GL_MAP_WRITE_BIT) != 0; |
_mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); |
assert(y % bh == 0); |
y /= bh; |
texel_size /= bw; |
if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) { |
radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, |
"%s for texture that is " |
"queued for GPU processing.\n", |
__func__); |
radeon_firevertices(rmesa); |
} |
if (image->bo) { |
/* TFP case */ |
radeon_bo_map(image->bo, write); |
*stride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0, texImage->TexObject->Target); |
*map = bo->ptr; |
} else if (likely(mt)) { |
void *base; |
radeon_mipmap_level *lvl = &image->mt->levels[texImage->Level]; |
radeon_bo_map(mt->bo, write); |
base = mt->bo->ptr + lvl->faces[image->base.Base.Face].offset; |
*stride = lvl->rowstride; |
*map = base + (slice * height) * *stride; |
} else { |
/* texture data is in malloc'd memory */ |
assert(map); |
*stride = _mesa_format_row_stride(texImage->TexFormat, width); |
*map = image->base.Buffer + (slice * height) * *stride; |
} |
*map += y * *stride + x * texel_size; |
} |
static void |
radeon_unmap_texture_image(struct gl_context *ctx, |
struct gl_texture_image *texImage, GLuint slice) |
{ |
radeon_texture_image *image = get_radeon_texture_image(texImage); |
if (image->bo) |
radeon_bo_unmap(image->bo); |
else if (image->mt) |
radeon_bo_unmap(image->mt->bo); |
} |
/* try to find a format which will only need a memcopy */ |
static gl_format radeonChoose8888TexFormat(radeonContextPtr rmesa, |
GLenum srcFormat, |
GLenum srcType, GLboolean fbo) |
{ |
#if defined(RADEON_R100) |
/* r100 can only do this */ |
return _radeon_texformat_argb8888; |
#elif defined(RADEON_R200) |
const GLuint ui = 1; |
const GLubyte littleEndian = *((const GLubyte *)&ui); |
if (fbo) |
return _radeon_texformat_argb8888; |
if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) || |
(srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) || |
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || |
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian)) { |
return MESA_FORMAT_RGBA8888; |
} else if ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || |
(srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) || |
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) || |
(srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian)) { |
return MESA_FORMAT_RGBA8888_REV; |
} else |
return _radeon_texformat_argb8888; |
#endif |
} |
gl_format radeonChooseTextureFormat_mesa(struct gl_context * ctx, |
GLenum target, |
GLint internalFormat, |
GLenum format, |
GLenum type) |
{ |
return radeonChooseTextureFormat(ctx, internalFormat, format, |
type, 0); |
} |
gl_format radeonChooseTextureFormat(struct gl_context * ctx, |
GLint internalFormat, |
GLenum format, |
GLenum type, GLboolean fbo) |
{ |
radeonContextPtr rmesa = RADEON_CONTEXT(ctx); |
const GLboolean do32bpt = |
(rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_32); |
const GLboolean force16bpt = |
(rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16); |
(void)format; |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s InternalFormat=%s(%d) type=%s format=%s\n", |
__func__, |
_mesa_lookup_enum_by_nr(internalFormat), internalFormat, |
_mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format)); |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"%s do32bpt=%d force16bpt=%d\n", |
__func__, do32bpt, force16bpt); |
switch (internalFormat) { |
case 4: |
case GL_RGBA: |
case GL_COMPRESSED_RGBA: |
switch (type) { |
case GL_UNSIGNED_INT_10_10_10_2: |
case GL_UNSIGNED_INT_2_10_10_10_REV: |
return do32bpt ? _radeon_texformat_argb8888 : |
_radeon_texformat_argb1555; |
case GL_UNSIGNED_SHORT_4_4_4_4: |
case GL_UNSIGNED_SHORT_4_4_4_4_REV: |
return _radeon_texformat_argb4444; |
case GL_UNSIGNED_SHORT_5_5_5_1: |
case GL_UNSIGNED_SHORT_1_5_5_5_REV: |
return _radeon_texformat_argb1555; |
default: |
return do32bpt ? radeonChoose8888TexFormat(rmesa, format, type, fbo) : |
_radeon_texformat_argb4444; |
} |
case 3: |
case GL_RGB: |
case GL_COMPRESSED_RGB: |
switch (type) { |
case GL_UNSIGNED_SHORT_4_4_4_4: |
case GL_UNSIGNED_SHORT_4_4_4_4_REV: |
return _radeon_texformat_argb4444; |
case GL_UNSIGNED_SHORT_5_5_5_1: |
case GL_UNSIGNED_SHORT_1_5_5_5_REV: |
return _radeon_texformat_argb1555; |
case GL_UNSIGNED_SHORT_5_6_5: |
case GL_UNSIGNED_SHORT_5_6_5_REV: |
return _radeon_texformat_rgb565; |
default: |
return do32bpt ? _radeon_texformat_argb8888 : |
_radeon_texformat_rgb565; |
} |
case GL_RGBA8: |
case GL_RGB10_A2: |
case GL_RGBA12: |
case GL_RGBA16: |
return !force16bpt ? |
radeonChoose8888TexFormat(rmesa, format, type, fbo) : |
_radeon_texformat_argb4444; |
case GL_RGBA4: |
case GL_RGBA2: |
return _radeon_texformat_argb4444; |
case GL_RGB5_A1: |
return _radeon_texformat_argb1555; |
case GL_RGB8: |
case GL_RGB10: |
case GL_RGB12: |
case GL_RGB16: |
return !force16bpt ? _radeon_texformat_argb8888 : |
_radeon_texformat_rgb565; |
case GL_RGB5: |
case GL_RGB4: |
case GL_R3_G3_B2: |
return _radeon_texformat_rgb565; |
case GL_ALPHA: |
case GL_ALPHA4: |
case GL_ALPHA8: |
case GL_ALPHA12: |
case GL_ALPHA16: |
case GL_COMPRESSED_ALPHA: |
#if defined(RADEON_R200) |
/* r200: can't use a8 format since interpreting hw I8 as a8 would result |
in wrong rgb values (same as alpha value instead of 0). */ |
return _radeon_texformat_al88; |
#else |
return MESA_FORMAT_A8; |
#endif |
case 1: |
case GL_LUMINANCE: |
case GL_LUMINANCE4: |
case GL_LUMINANCE8: |
case GL_LUMINANCE12: |
case GL_LUMINANCE16: |
case GL_COMPRESSED_LUMINANCE: |
return MESA_FORMAT_L8; |
case 2: |
case GL_LUMINANCE_ALPHA: |
case GL_LUMINANCE4_ALPHA4: |
case GL_LUMINANCE6_ALPHA2: |
case GL_LUMINANCE8_ALPHA8: |
case GL_LUMINANCE12_ALPHA4: |
case GL_LUMINANCE12_ALPHA12: |
case GL_LUMINANCE16_ALPHA16: |
case GL_COMPRESSED_LUMINANCE_ALPHA: |
return _radeon_texformat_al88; |
case GL_INTENSITY: |
case GL_INTENSITY4: |
case GL_INTENSITY8: |
case GL_INTENSITY12: |
case GL_INTENSITY16: |
case GL_COMPRESSED_INTENSITY: |
return MESA_FORMAT_I8; |
case GL_YCBCR_MESA: |
if (type == GL_UNSIGNED_SHORT_8_8_APPLE || |
type == GL_UNSIGNED_BYTE) |
return MESA_FORMAT_YCBCR; |
else |
return MESA_FORMAT_YCBCR_REV; |
case GL_RGB_S3TC: |
case GL_RGB4_S3TC: |
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: |
return MESA_FORMAT_RGB_DXT1; |
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: |
return MESA_FORMAT_RGBA_DXT1; |
case GL_RGBA_S3TC: |
case GL_RGBA4_S3TC: |
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: |
return MESA_FORMAT_RGBA_DXT3; |
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: |
return MESA_FORMAT_RGBA_DXT5; |
case GL_ALPHA16F_ARB: |
return MESA_FORMAT_ALPHA_FLOAT16; |
case GL_ALPHA32F_ARB: |
return MESA_FORMAT_ALPHA_FLOAT32; |
case GL_LUMINANCE16F_ARB: |
return MESA_FORMAT_LUMINANCE_FLOAT16; |
case GL_LUMINANCE32F_ARB: |
return MESA_FORMAT_LUMINANCE_FLOAT32; |
case GL_LUMINANCE_ALPHA16F_ARB: |
return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16; |
case GL_LUMINANCE_ALPHA32F_ARB: |
return MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32; |
case GL_INTENSITY16F_ARB: |
return MESA_FORMAT_INTENSITY_FLOAT16; |
case GL_INTENSITY32F_ARB: |
return MESA_FORMAT_INTENSITY_FLOAT32; |
case GL_RGB16F_ARB: |
return MESA_FORMAT_RGBA_FLOAT16; |
case GL_RGB32F_ARB: |
return MESA_FORMAT_RGBA_FLOAT32; |
case GL_RGBA16F_ARB: |
return MESA_FORMAT_RGBA_FLOAT16; |
case GL_RGBA32F_ARB: |
return MESA_FORMAT_RGBA_FLOAT32; |
case GL_DEPTH_COMPONENT: |
case GL_DEPTH_COMPONENT16: |
case GL_DEPTH_COMPONENT24: |
case GL_DEPTH_COMPONENT32: |
case GL_DEPTH_STENCIL_EXT: |
case GL_DEPTH24_STENCIL8_EXT: |
return MESA_FORMAT_S8_Z24; |
/* EXT_texture_sRGB */ |
case GL_SRGB: |
case GL_SRGB8: |
case GL_SRGB_ALPHA: |
case GL_SRGB8_ALPHA8: |
case GL_COMPRESSED_SRGB: |
case GL_COMPRESSED_SRGB_ALPHA: |
return MESA_FORMAT_SARGB8; |
case GL_SLUMINANCE: |
case GL_SLUMINANCE8: |
case GL_COMPRESSED_SLUMINANCE: |
return MESA_FORMAT_SL8; |
case GL_SLUMINANCE_ALPHA: |
case GL_SLUMINANCE8_ALPHA8: |
case GL_COMPRESSED_SLUMINANCE_ALPHA: |
return MESA_FORMAT_SLA8; |
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: |
return MESA_FORMAT_SRGB_DXT1; |
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: |
return MESA_FORMAT_SRGBA_DXT1; |
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: |
return MESA_FORMAT_SRGBA_DXT3; |
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: |
return MESA_FORMAT_SRGBA_DXT5; |
default: |
_mesa_problem(ctx, |
"unexpected internalFormat 0x%x in %s", |
(int)internalFormat, __func__); |
return MESA_FORMAT_NONE; |
} |
return MESA_FORMAT_NONE; /* never get here */ |
} |
/** Check if given image is valid within current texture object. |
*/ |
static void teximage_assign_miptree(radeonContextPtr rmesa, |
struct gl_texture_object *texObj, |
struct gl_texture_image *texImage) |
{ |
radeonTexObj *t = radeon_tex_obj(texObj); |
radeon_texture_image* image = get_radeon_texture_image(texImage); |
/* Try using current miptree, or create new if there isn't any */ |
if (!t->mt || !radeon_miptree_matches_image(t->mt, texImage)) { |
radeon_miptree_unreference(&t->mt); |
t->mt = radeon_miptree_create_for_teximage(rmesa, |
texObj, |
texImage); |
radeon_print(RADEON_TEXTURE, RADEON_NORMAL, |
"%s: texObj %p, texImage %p, " |
"texObj miptree doesn't match, allocated new miptree %p\n", |
__FUNCTION__, texObj, texImage, t->mt); |
} |
/* Miptree alocation may have failed, |
* when there was no image for baselevel specified */ |
if (t->mt) { |
radeon_miptree_reference(t->mt, &image->mt); |
} else |
radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, |
"%s Failed to allocate miptree.\n", __func__); |
} |
unsigned radeonIsFormatRenderable(gl_format mesa_format) |
{ |
if (mesa_format == _radeon_texformat_argb8888 || mesa_format == _radeon_texformat_rgb565 || |
mesa_format == _radeon_texformat_argb1555 || mesa_format == _radeon_texformat_argb4444) |
return 1; |
switch (mesa_format) |
{ |
case MESA_FORMAT_Z16: |
case MESA_FORMAT_S8_Z24: |
return 1; |
default: |
return 0; |
} |
} |
void radeon_image_target_texture_2d(struct gl_context *ctx, GLenum target, |
struct gl_texture_object *texObj, |
struct gl_texture_image *texImage, |
GLeglImageOES image_handle) |
{ |
radeonContextPtr radeon = RADEON_CONTEXT(ctx); |
radeonTexObj *t = radeon_tex_obj(texObj); |
radeon_texture_image *radeonImage = get_radeon_texture_image(texImage); |
__DRIscreen *screen; |
__DRIimage *image; |
screen = radeon->dri.screen; |
image = screen->dri2.image->lookupEGLImage(screen, image_handle, |
screen->loaderPrivate); |
if (image == NULL) |
return; |
radeonFreeTextureImageBuffer(ctx, texImage); |
texImage->Width = image->width; |
texImage->Height = image->height; |
texImage->Depth = 1; |
texImage->_BaseFormat = GL_RGBA; |
texImage->TexFormat = image->format; |
radeonImage->base.RowStride = image->pitch; |
texImage->InternalFormat = image->internal_format; |
if(t->mt) |
{ |
radeon_miptree_unreference(&t->mt); |
t->mt = NULL; |
} |
/* NOTE: The following is *very* ugly and will probably break. But |
I don't know how to deal with it, without creating a whole new |
function like radeon_miptree_from_bo() so I'm going with the |
easy but error-prone way. */ |
radeon_try_alloc_miptree(radeon, t); |
radeon_miptree_reference(t->mt, &radeonImage->mt); |
if (t->mt == NULL) |
{ |
radeon_print(RADEON_TEXTURE, RADEON_VERBOSE, |
"%s Failed to allocate miptree.\n", __func__); |
return; |
} |
/* Particularly ugly: this is guaranteed to break, if image->bo is |
not of the required size for a miptree. */ |
radeon_bo_unref(t->mt->bo); |
radeon_bo_ref(image->bo); |
t->mt->bo = image->bo; |
if (!radeon_miptree_matches_image(t->mt, &radeonImage->base.Base)) |
fprintf(stderr, "miptree doesn't match image\n"); |
} |
gl_format _radeon_texformat_rgba8888 = MESA_FORMAT_NONE; |
gl_format _radeon_texformat_argb8888 = MESA_FORMAT_NONE; |
gl_format _radeon_texformat_rgb565 = MESA_FORMAT_NONE; |
gl_format _radeon_texformat_argb4444 = MESA_FORMAT_NONE; |
gl_format _radeon_texformat_argb1555 = MESA_FORMAT_NONE; |
gl_format _radeon_texformat_al88 = MESA_FORMAT_NONE; |
/*@}*/ |
static void |
radeonInitTextureFormats(void) |
{ |
if (_mesa_little_endian()) { |
_radeon_texformat_rgba8888 = MESA_FORMAT_RGBA8888; |
_radeon_texformat_argb8888 = MESA_FORMAT_ARGB8888; |
_radeon_texformat_rgb565 = MESA_FORMAT_RGB565; |
_radeon_texformat_argb4444 = MESA_FORMAT_ARGB4444; |
_radeon_texformat_argb1555 = MESA_FORMAT_ARGB1555; |
_radeon_texformat_al88 = MESA_FORMAT_AL88; |
} |
else { |
_radeon_texformat_rgba8888 = MESA_FORMAT_RGBA8888_REV; |
_radeon_texformat_argb8888 = MESA_FORMAT_ARGB8888_REV; |
_radeon_texformat_rgb565 = MESA_FORMAT_RGB565_REV; |
_radeon_texformat_argb4444 = MESA_FORMAT_ARGB4444_REV; |
_radeon_texformat_argb1555 = MESA_FORMAT_ARGB1555_REV; |
_radeon_texformat_al88 = MESA_FORMAT_AL88_REV; |
} |
} |
void |
radeon_init_common_texture_funcs(radeonContextPtr radeon, |
struct dd_function_table *functions) |
{ |
functions->NewTextureImage = radeonNewTextureImage; |
functions->DeleteTextureImage = radeonDeleteTextureImage; |
functions->AllocTextureImageBuffer = radeonAllocTextureImageBuffer; |
functions->FreeTextureImageBuffer = radeonFreeTextureImageBuffer; |
functions->MapTextureImage = radeon_map_texture_image; |
functions->UnmapTextureImage = radeon_unmap_texture_image; |
functions->ChooseTextureFormat = radeonChooseTextureFormat_mesa; |
functions->CopyTexSubImage = radeonCopyTexSubImage; |
functions->Bitmap = _mesa_meta_Bitmap; |
functions->EGLImageTargetTexture2D = radeon_image_target_texture_2d; |
radeonInitTextureFormats(); |
} |
static radeon_mipmap_tree *radeon_miptree_create_for_teximage(radeonContextPtr rmesa, |
struct gl_texture_object *texObj, |
struct gl_texture_image *texImage) |
{ |
radeonTexObj *t = radeon_tex_obj(texObj); |
GLuint firstLevel; |
GLuint lastLevel; |
int width, height, depth; |
int i; |
width = texImage->Width; |
height = texImage->Height; |
depth = texImage->Depth; |
if (texImage->Level > texObj->BaseLevel && |
(width == 1 || |
(texObj->Target != GL_TEXTURE_1D && height == 1) || |
(texObj->Target == GL_TEXTURE_3D && depth == 1))) { |
/* For this combination, we're at some lower mipmap level and |
* some important dimension is 1. We can't extrapolate up to a |
* likely base level width/height/depth for a full mipmap stack |
* from this info, so just allocate this one level. |
*/ |
firstLevel = texImage->Level; |
lastLevel = texImage->Level; |
} else { |
if (texImage->Level < texObj->BaseLevel) |
firstLevel = 0; |
else |
firstLevel = texObj->BaseLevel; |
for (i = texImage->Level; i > firstLevel; i--) { |
width <<= 1; |
if (height != 1) |
height <<= 1; |
if (depth != 1) |
depth <<= 1; |
} |
if ((texObj->Sampler.MinFilter == GL_NEAREST || |
texObj->Sampler.MinFilter == GL_LINEAR) && |
texImage->Level == firstLevel) { |
lastLevel = firstLevel; |
} else { |
lastLevel = firstLevel + _mesa_logbase2(MAX2(MAX2(width, height), depth)); |
} |
} |
return radeon_miptree_create(rmesa, texObj->Target, |
texImage->TexFormat, firstLevel, lastLevel - firstLevel + 1, |
width, height, depth, |
t->tile_bits); |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_texture.h |
---|
0,0 → 1,83 |
/* |
* Copyright (C) 2008 Nicolai Haehnle. |
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
* |
* The Weather Channel (TM) funded Tungsten Graphics to develop the |
* initial release of the Radeon 8500 driver under the XFree86 license. |
* This notice must be preserved. |
* |
* 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 COPYRIGHT OWNER(S) 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 RADEON_TEXTURE_H |
#define RADEON_TEXTURE_H |
#include "main/formats.h" |
extern gl_format _radeon_texformat_rgba8888; |
extern gl_format _radeon_texformat_argb8888; |
extern gl_format _radeon_texformat_rgb565; |
extern gl_format _radeon_texformat_argb4444; |
extern gl_format _radeon_texformat_argb1555; |
extern gl_format _radeon_texformat_al88; |
extern |
void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride, |
GLuint numrows, GLuint rowsize); |
struct gl_texture_image *radeonNewTextureImage(struct gl_context *ctx); |
void radeonFreeTextureImageBuffer(struct gl_context *ctx, struct gl_texture_image *timage); |
int radeon_validate_texture_miptree(struct gl_context * ctx, |
struct gl_sampler_object *samp, |
struct gl_texture_object *texObj); |
gl_format radeonChooseTextureFormat_mesa(struct gl_context * ctx, |
GLenum target, |
GLint internalFormat, |
GLenum format, |
GLenum type); |
gl_format radeonChooseTextureFormat(struct gl_context * ctx, |
GLint internalFormat, |
GLenum format, |
GLenum type, GLboolean fbo); |
void radeonCopyTexSubImage(struct gl_context *ctx, GLuint dims, |
struct gl_texture_image *texImage, |
GLint xoffset, GLint yoffset, GLint zoffset, |
struct gl_renderbuffer *rb, |
GLint x, GLint y, |
GLsizei width, GLsizei height); |
unsigned radeonIsFormatRenderable(gl_format mesa_format); |
void radeon_image_target_texture_2d(struct gl_context *ctx, GLenum target, |
struct gl_texture_object *texObj, |
struct gl_texture_image *texImage, |
GLeglImageOES image_handle); |
void |
radeon_init_common_texture_funcs(radeonContextPtr radeon, |
struct dd_function_table *functions); |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_tile.c |
---|
0,0 → 1,512 |
/* |
* Copyright (C) 2010 Maciej Cencora <m.cencora@gmail.com> |
* |
* 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, 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 COPYRIGHT OWNER(S) 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 "radeon_tile.h" |
#include <stdint.h> |
#include <string.h> |
#include "main/macros.h" |
#include "radeon_debug.h" |
#define MICRO_TILE_SIZE 32 |
static void micro_tile_8_x_4_8bit(const void * const src, unsigned src_pitch, |
void * const dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned row; /* current source row */ |
unsigned col; /* current source column */ |
unsigned k; /* number of processed tiles */ |
const unsigned tile_width = 8, tile_height = 4; |
const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; |
k = 0; |
for (row = 0; row < height; row += tile_height) |
{ |
for (col = 0; col < width; col += tile_width, ++k) |
{ |
uint8_t *src2 = (uint8_t *)src + src_pitch * row + col; |
uint8_t *dst2 = (uint8_t *)dst + row * dst_pitch + |
(k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint8_t); |
unsigned j; |
for (j = 0; j < MIN2(tile_height, height - row); ++j) |
{ |
unsigned columns = MIN2(tile_width, width - col); |
memcpy(dst2, src2, columns * sizeof(uint8_t)); |
dst2 += tile_width; |
src2 += src_pitch; |
} |
} |
} |
} |
static void micro_tile_4_x_4_16bit(const void * const src, unsigned src_pitch, |
void * const dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned row; /* current source row */ |
unsigned col; /* current source column */ |
unsigned k; /* number of processed tiles */ |
const unsigned tile_width = 4, tile_height = 4; |
const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; |
k = 0; |
for (row = 0; row < height; row += tile_height) |
{ |
for (col = 0; col < width; col += tile_width, ++k) |
{ |
uint16_t *src2 = (uint16_t *)src + src_pitch * row + col; |
uint16_t *dst2 = (uint16_t *)dst + row * dst_pitch + |
(k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint16_t); |
unsigned j; |
for (j = 0; j < MIN2(tile_height, height - row); ++j) |
{ |
unsigned columns = MIN2(tile_width, width - col); |
memcpy(dst2, src2, columns * sizeof(uint16_t)); |
dst2 += tile_width; |
src2 += src_pitch; |
} |
} |
} |
} |
static void micro_tile_8_x_2_16bit(const void * const src, unsigned src_pitch, |
void * const dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned row; /* current source row */ |
unsigned col; /* current source column */ |
unsigned k; /* number of processed tiles */ |
const unsigned tile_width = 8, tile_height = 2; |
const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; |
k = 0; |
for (row = 0; row < height; row += tile_height) |
{ |
for (col = 0; col < width; col += tile_width, ++k) |
{ |
uint16_t *src2 = (uint16_t *)src + src_pitch * row + col; |
uint16_t *dst2 = (uint16_t *)dst + row * dst_pitch + |
(k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint16_t); |
unsigned j; |
for (j = 0; j < MIN2(tile_height, height - row); ++j) |
{ |
unsigned columns = MIN2(tile_width, width - col); |
memcpy(dst2, src2, columns * sizeof(uint16_t)); |
dst2 += tile_width; |
src2 += src_pitch; |
} |
} |
} |
} |
static void micro_tile_4_x_2_32bit(const void * const src, unsigned src_pitch, |
void * const dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned row; /* current source row */ |
unsigned col; /* current source column */ |
unsigned k; /* number of processed tiles */ |
const unsigned tile_width = 4, tile_height = 2; |
const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; |
k = 0; |
for (row = 0; row < height; row += tile_height) |
{ |
for (col = 0; col < width; col += tile_width, ++k) |
{ |
uint32_t *src2 = (uint32_t *)src + src_pitch * row + col; |
uint32_t *dst2 = (uint32_t *)dst + row * dst_pitch + |
(k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint32_t); |
unsigned j; |
for (j = 0; j < MIN2(tile_height, height - row); ++j) |
{ |
unsigned columns = MIN2(tile_width, width - col); |
memcpy(dst2, src2, columns * sizeof(uint32_t)); |
dst2 += tile_width; |
src2 += src_pitch; |
} |
} |
} |
} |
static void micro_tile_2_x_2_64bit(const void * const src, unsigned src_pitch, |
void * const dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned row; /* current source row */ |
unsigned col; /* current source column */ |
unsigned k; /* number of processed tiles */ |
const unsigned tile_width = 2, tile_height = 2; |
const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; |
k = 0; |
for (row = 0; row < height; row += tile_height) |
{ |
for (col = 0; col < width; col += tile_width, ++k) |
{ |
uint64_t *src2 = (uint64_t *)src + src_pitch * row + col; |
uint64_t *dst2 = (uint64_t *)dst + row * dst_pitch + |
(k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint64_t); |
unsigned j; |
for (j = 0; j < MIN2(tile_height, height - row); ++j) |
{ |
unsigned columns = MIN2(tile_width, width - col); |
memcpy(dst2, src2, columns * sizeof(uint64_t)); |
dst2 += tile_width; |
src2 += src_pitch; |
} |
} |
} |
} |
static void micro_tile_1_x_1_128bit(const void * src, unsigned src_pitch, |
void * dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned i, j; |
const unsigned elem_size = 16; /* sizeof(uint128_t) */ |
for (j = 0; j < height; ++j) |
{ |
for (i = 0; i < width; ++i) |
{ |
memcpy(dst, src, width * elem_size); |
dst += dst_pitch * elem_size; |
src += src_pitch * elem_size; |
} |
} |
} |
void tile_image(const void * src, unsigned src_pitch, |
void *dst, unsigned dst_pitch, |
gl_format format, unsigned width, unsigned height) |
{ |
assert(src_pitch >= width); |
assert(dst_pitch >= width); |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"Software tiling: src_pitch %d, dst_pitch %d, width %d, height %d, bpp %d\n", |
src_pitch, dst_pitch, width, height, _mesa_get_format_bytes(format)); |
switch (_mesa_get_format_bytes(format)) |
{ |
case 16: |
micro_tile_1_x_1_128bit(src, src_pitch, dst, dst_pitch, width, height); |
break; |
case 8: |
micro_tile_2_x_2_64bit(src, src_pitch, dst, dst_pitch, width, height); |
break; |
case 4: |
micro_tile_4_x_2_32bit(src, src_pitch, dst, dst_pitch, width, height); |
break; |
case 2: |
if (_mesa_get_format_bits(format, GL_DEPTH_BITS)) |
{ |
micro_tile_4_x_4_16bit(src, src_pitch, dst, dst_pitch, width, height); |
} |
else |
{ |
micro_tile_8_x_2_16bit(src, src_pitch, dst, dst_pitch, width, height); |
} |
break; |
case 1: |
micro_tile_8_x_4_8bit(src, src_pitch, dst, dst_pitch, width, height); |
break; |
default: |
assert(0); |
break; |
} |
} |
static void micro_untile_8_x_4_8bit(const void * const src, unsigned src_pitch, |
void * const dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned row; /* current destination row */ |
unsigned col; /* current destination column */ |
unsigned k; /* current tile number */ |
const unsigned tile_width = 8, tile_height = 4; |
const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; |
assert(src_pitch % tile_width == 0); |
k = 0; |
for (row = 0; row < height; row += tile_height) |
{ |
for (col = 0; col < width; col += tile_width, ++k) |
{ |
uint8_t *src2 = (uint8_t *)src + row * src_pitch + |
(k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint8_t); |
uint8_t *dst2 = (uint8_t *)dst + dst_pitch * row + col; |
unsigned j; |
for (j = 0; j < MIN2(tile_height, height - row); ++j) |
{ |
unsigned columns = MIN2(tile_width, width - col); |
memcpy(dst2, src2, columns * sizeof(uint8_t)); |
dst2 += dst_pitch; |
src2 += tile_width; |
} |
} |
} |
} |
static void micro_untile_8_x_2_16bit(const void * const src, unsigned src_pitch, |
void * const dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned row; /* current destination row */ |
unsigned col; /* current destination column */ |
unsigned k; /* current tile number */ |
const unsigned tile_width = 8, tile_height = 2; |
const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; |
assert(src_pitch % tile_width == 0); |
k = 0; |
for (row = 0; row < height; row += tile_height) |
{ |
for (col = 0; col < width; col += tile_width, ++k) |
{ |
uint16_t *src2 = (uint16_t *)src + row * src_pitch + |
(k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint16_t); |
uint16_t *dst2 = (uint16_t *)dst + dst_pitch * row + col; |
unsigned j; |
for (j = 0; j < MIN2(tile_height, height - row); ++j) |
{ |
unsigned columns = MIN2(tile_width, width - col); |
memcpy(dst2, src2, columns * sizeof(uint16_t)); |
dst2 += dst_pitch; |
src2 += tile_width; |
} |
} |
} |
} |
static void micro_untile_4_x_4_16bit(const void * const src, unsigned src_pitch, |
void * const dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned row; /* current destination row */ |
unsigned col; /* current destination column */ |
unsigned k; /* current tile number */ |
const unsigned tile_width = 4, tile_height = 4; |
const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; |
assert(src_pitch % tile_width == 0); |
k = 0; |
for (row = 0; row < height; row += tile_height) |
{ |
for (col = 0; col < width; col += tile_width, ++k) |
{ |
uint16_t *src2 = (uint16_t *)src + row * src_pitch + |
(k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint16_t); |
uint16_t *dst2 = (uint16_t *)dst + dst_pitch * row + col; |
unsigned j; |
for (j = 0; j < MIN2(tile_height, height - row); ++j) |
{ |
unsigned columns = MIN2(tile_width, width - col); |
memcpy(dst2, src2, columns * sizeof(uint16_t)); |
dst2 += dst_pitch; |
src2 += tile_width; |
} |
} |
} |
} |
static void micro_untile_4_x_2_32bit(const void * const src, unsigned src_pitch, |
void * const dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned row; /* current destination row */ |
unsigned col; /* current destination column */ |
unsigned k; /* current tile number */ |
const unsigned tile_width = 4, tile_height = 2; |
const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; |
assert(src_pitch % tile_width == 0); |
k = 0; |
for (row = 0; row < height; row += tile_height) |
{ |
for (col = 0; col < width; col += tile_width, ++k) |
{ |
uint32_t *src2 = (uint32_t *)src + row * src_pitch + |
(k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint32_t); |
uint32_t *dst2 = (uint32_t *)dst + dst_pitch * row + col; |
unsigned j; |
for (j = 0; j < MIN2(tile_height, height - row); ++j) |
{ |
unsigned columns = MIN2(tile_width, width - col); |
memcpy(dst2, src2, columns * sizeof(uint32_t)); |
dst2 += dst_pitch; |
src2 += tile_width; |
} |
} |
} |
} |
static void micro_untile_2_x_2_64bit(const void * const src, unsigned src_pitch, |
void * const dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned row; /* current destination row */ |
unsigned col; /* current destination column */ |
unsigned k; /* current tile number */ |
const unsigned tile_width = 2, tile_height = 2; |
const unsigned tiles_in_row = (width + (tile_width - 1)) / tile_width; |
assert(src_pitch % tile_width == 0); |
k = 0; |
for (row = 0; row < height; row += tile_height) |
{ |
for (col = 0; col < width; col += tile_width, ++k) |
{ |
uint64_t *src2 = (uint64_t *)src + row * src_pitch + |
(k % tiles_in_row) * MICRO_TILE_SIZE / sizeof(uint64_t); |
uint64_t *dst2 = (uint64_t *)dst + dst_pitch * row + col; |
unsigned j; |
for (j = 0; j < MIN2(tile_height, height - row); ++j) |
{ |
unsigned columns = MIN2(tile_width, width - col); |
memcpy(dst2, src2, columns * sizeof(uint64_t)); |
dst2 += dst_pitch; |
src2 += tile_width; |
} |
} |
} |
} |
static void micro_untile_1_x_1_128bit(const void * src, unsigned src_pitch, |
void * dst, unsigned dst_pitch, |
unsigned width, unsigned height) |
{ |
unsigned i, j; |
const unsigned elem_size = 16; /* sizeof(uint128_t) */ |
for (j = 0; j < height; ++j) |
{ |
for (i = 0; i < width; ++i) |
{ |
memcpy(dst, src, width * elem_size); |
dst += dst_pitch * elem_size; |
src += src_pitch * elem_size; |
} |
} |
} |
void untile_image(const void * src, unsigned src_pitch, |
void *dst, unsigned dst_pitch, |
gl_format format, unsigned width, unsigned height) |
{ |
assert(src_pitch >= width); |
assert(dst_pitch >= width); |
radeon_print(RADEON_TEXTURE, RADEON_TRACE, |
"Software untiling: src_pitch %d, dst_pitch %d, width %d, height %d, bpp %d\n", |
src_pitch, dst_pitch, width, height, _mesa_get_format_bytes(format)); |
switch (_mesa_get_format_bytes(format)) |
{ |
case 16: |
micro_untile_1_x_1_128bit(src, src_pitch, dst, dst_pitch, width, height); |
break; |
case 8: |
micro_untile_2_x_2_64bit(src, src_pitch, dst, dst_pitch, width, height); |
break; |
case 4: |
micro_untile_4_x_2_32bit(src, src_pitch, dst, dst_pitch, width, height); |
break; |
case 2: |
if (_mesa_get_format_bits(format, GL_DEPTH_BITS)) |
{ |
micro_untile_4_x_4_16bit(src, src_pitch, dst, dst_pitch, width, height); |
} |
else |
{ |
micro_untile_8_x_2_16bit(src, src_pitch, dst, dst_pitch, width, height); |
} |
break; |
case 1: |
micro_untile_8_x_4_8bit(src, src_pitch, dst, dst_pitch, width, height); |
break; |
default: |
assert(0); |
break; |
} |
} |
void get_tile_size(gl_format format, unsigned *block_width, unsigned *block_height) |
{ |
switch (_mesa_get_format_bytes(format)) |
{ |
case 16: |
*block_width = 1; |
*block_height = 1; |
break; |
case 8: |
*block_width = 2; |
*block_height = 2; |
break; |
case 4: |
*block_width = 4; |
*block_height = 2; |
break; |
case 2: |
if (_mesa_get_format_bits(format, GL_DEPTH_BITS)) |
{ |
*block_width = 4; |
*block_height = 4; |
} |
else |
{ |
*block_width = 8; |
*block_height = 2; |
} |
break; |
case 1: |
*block_width = 8; |
*block_height = 4; |
break; |
default: |
assert(0); |
break; |
} |
} |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/radeon_tile.h |
---|
0,0 → 1,38 |
/* |
* Copyright (C) 2010 Maciej Cencora <m.cencora@gmail.com> |
* |
* 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, 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 COPYRIGHT OWNER(S) 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 <main/formats.h> |
void tile_image(const void * src, unsigned src_pitch, |
void *dst, unsigned dst_pitch, |
gl_format format, unsigned width, unsigned height); |
void untile_image(const void * src, unsigned src_pitch, |
void *dst, unsigned dst_pitch, |
gl_format format, unsigned width, unsigned height); |
void get_tile_size(gl_format format, unsigned *block_width, unsigned *block_height); |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/server/radeon_dri.h |
---|
0,0 → 1,115 |
/** |
* \file server/radeon_dri.h |
* \brief Radeon server-side structures. |
* |
* \author Kevin E. Martin <martin@xfree86.org> |
* \author Rickard E. Faith <faith@valinux.com> |
*/ |
/* |
* Copyright 2000 ATI Technologies Inc., Markham, Ontario, |
* VA Linux Systems Inc., Fremont, California. |
* |
* 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 on 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 |
* NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR |
* THEIR 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 _RADEON_DRI_ |
#define _RADEON_DRI_ |
#include "xf86drm.h" |
#include "drm.h" |
#include "radeon_drm.h" |
/* DRI Driver defaults */ |
#define RADEON_DEFAULT_CP_PIO_MODE RADEON_CSQ_PRIPIO_INDPIO |
#define RADEON_DEFAULT_CP_BM_MODE RADEON_CSQ_PRIBM_INDBM |
#define RADEON_DEFAULT_AGP_MODE 1 |
#define RADEON_DEFAULT_AGP_FAST_WRITE 0 |
#define RADEON_DEFAULT_AGP_SIZE 8 /* MB (must be 2^n and > 4MB) */ |
#define RADEON_DEFAULT_RING_SIZE 1 /* MB (must be page aligned) */ |
#define RADEON_DEFAULT_BUFFER_SIZE 2 /* MB (must be page aligned) */ |
#define RADEON_DEFAULT_AGP_TEX_SIZE 1 /* MB (must be page aligned) */ |
#define RADEON_DEFAULT_CP_TIMEOUT 10000 /* usecs */ |
#define RADEON_DEFAULT_PAGE_FLIP 0 /* page flipping diabled */ |
#define RADEON_BUFFER_ALIGN 0x00000fff |
/** |
* \brief Radeon DRI driver private data. |
*/ |
typedef struct { |
/** |
* \name DRI screen private data |
*/ |
/*@{*/ |
int deviceID; /**< \brief PCI device ID */ |
int width; /**< \brief width in pixels of display */ |
int height; /**< \brief height in scanlines of display */ |
int depth; /**< \brief depth of display (8, 15, 16, 24) */ |
int bpp; /**< \brief bit depth of display (8, 16, 24, 32) */ |
int IsPCI; /**< \brief is current card a PCI card? */ |
int AGPMode; /**< \brief AGP mode */ |
int frontOffset; /**< \brief front buffer offset */ |
int frontPitch; /**< \brief front buffer pitch */ |
int backOffset; /**< \brief shared back buffer offset */ |
int backPitch; /**< \brief shared back buffer pitch */ |
int depthOffset; /**< \brief shared depth buffer offset */ |
int depthPitch; /**< \brief shared depth buffer pitch */ |
int textureOffset; /**< \brief start of texture data in frame buffer */ |
int textureSize; /**< \brief size of texture date */ |
int log2TexGran; /**< \brief log2 texture granularity */ |
/*@}*/ |
/** |
* \name MMIO register data |
*/ |
/*@{*/ |
drm_handle_t registerHandle; /**< \brief MMIO register map size */ |
drmSize registerSize; /**< \brief MMIO register map handle */ |
/*@}*/ |
/** |
* \name CP in-memory status information |
*/ |
/*@{*/ |
drm_handle_t statusHandle; /**< \brief status map handle */ |
drmSize statusSize; /**< \brief status map size */ |
/*@}*/ |
/** |
* \name CP AGP Texture data |
*/ |
/*@{*/ |
drm_handle_t gartTexHandle; /**< \brief AGP texture area map handle */ |
drmSize gartTexMapSize; /**< \brief AGP texture area map size */ |
int log2GARTTexGran; /**< \brief AGP texture granularity in log base 2 */ |
int gartTexOffset; /**< \brief AGP texture area offset in AGP space */ |
/*@}*/ |
unsigned int sarea_priv_offset; /**< \brief offset of the private SAREA data*/ |
} RADEONDRIRec, *RADEONDRIPtr; |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/server/radeon_macros.h |
---|
0,0 → 1,128 |
/** |
* \file server/radeon_macros.h |
* \brief Macros for Radeon MMIO operation. |
* |
* \authors Kevin E. Martin <martin@xfree86.org> |
* \authors Rickard E. Faith <faith@valinux.com> |
* \authors Alan Hourihane <alanh@fairlite.demon.co.uk> |
*/ |
/* |
* Copyright 2000 ATI Technologies Inc., Markham, Ontario, and |
* VA Linux Systems Inc., Fremont, California. |
* |
* 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 on 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 |
* NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR |
* THEIR 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 _RADEON_MACROS_H_ |
#define _RADEON_MACROS_H_ |
#include <mmio.h> |
# define MMIO_IN8(base, offset) \ |
*(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) |
# define MMIO_IN32(base, offset) \ |
read_MMIO_LE32(base, offset) |
# define MMIO_OUT8(base, offset, val) \ |
*(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) = (val) |
# define MMIO_OUT32(base, offset, val) \ |
*(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset)) = CPU_TO_LE32(val) |
/* Memory mapped register access macros */ |
#define INREG8(addr) MMIO_IN8(RADEONMMIO, addr) |
#define INREG(addr) MMIO_IN32(RADEONMMIO, addr) |
#define OUTREG8(addr, val) MMIO_OUT8(RADEONMMIO, addr, val) |
#define OUTREG(addr, val) MMIO_OUT32(RADEONMMIO, addr, val) |
#define ADDRREG(addr) ((volatile GLuint *)(pointer)(RADEONMMIO + (addr))) |
#define OUTREGP(addr, val, mask) \ |
do { \ |
GLuint tmp = INREG(addr); \ |
tmp &= (mask); \ |
tmp |= (val); \ |
OUTREG(addr, tmp); \ |
} while (0) |
#define INPLL(dpy, addr) RADEONINPLL(dpy, addr) |
#define OUTPLL(addr, val) \ |
do { \ |
OUTREG8(RADEON_CLOCK_CNTL_INDEX, (((addr) & 0x3f) | \ |
RADEON_PLL_WR_EN)); \ |
OUTREG(RADEON_CLOCK_CNTL_DATA, val); \ |
} while (0) |
#define OUTPLLP(dpy, addr, val, mask) \ |
do { \ |
GLuint tmp = INPLL(dpy, addr); \ |
tmp &= (mask); \ |
tmp |= (val); \ |
OUTPLL(addr, tmp); \ |
} while (0) |
#define OUTPAL_START(idx) \ |
do { \ |
OUTREG8(RADEON_PALETTE_INDEX, (idx)); \ |
} while (0) |
#define OUTPAL_NEXT(r, g, b) \ |
do { \ |
OUTREG(RADEON_PALETTE_DATA, ((r) << 16) | ((g) << 8) | (b)); \ |
} while (0) |
#define OUTPAL_NEXT_CARD32(v) \ |
do { \ |
OUTREG(RADEON_PALETTE_DATA, (v & 0x00ffffff)); \ |
} while (0) |
#define OUTPAL(idx, r, g, b) \ |
do { \ |
OUTPAL_START((idx)); \ |
OUTPAL_NEXT((r), (g), (b)); \ |
} while (0) |
#define INPAL_START(idx) \ |
do { \ |
OUTREG(RADEON_PALETTE_INDEX, (idx) << 16); \ |
} while (0) |
#define INPAL_NEXT() INREG(RADEON_PALETTE_DATA) |
#define PAL_SELECT(idx) \ |
do { \ |
if (!idx) { \ |
OUTREG(RADEON_DAC_CNTL2, INREG(RADEON_DAC_CNTL2) & \ |
(GLuint)~RADEON_DAC2_PALETTE_ACC_CTL); \ |
} else { \ |
OUTREG(RADEON_DAC_CNTL2, INREG(RADEON_DAC_CNTL2) | \ |
RADEON_DAC2_PALETTE_ACC_CTL); \ |
} \ |
} while (0) |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/radeon/server/radeon_reg.h |
---|
0,0 → 1,2163 |
/* |
* Copyright 2000 ATI Technologies Inc., Markham, Ontario, and |
* VA Linux Systems Inc., Fremont, California. |
* |
* 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 on 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 |
* NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR |
* THEIR 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: |
* Kevin E. Martin <martin@xfree86.org> |
* Rickard E. Faith <faith@valinux.com> |
* Alan Hourihane <alanh@fairlite.demon.co.uk> |
* |
* References: |
* |
* !!!! FIXME !!!! |
* RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical |
* Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April |
* 1999. |
* |
* !!!! FIXME !!!! |
* RAGE 128 Software Development Manual (Technical Reference Manual P/N |
* SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. |
* |
*/ |
/* !!!! FIXME !!!! NOTE: THIS FILE HAS BEEN CONVERTED FROM r128_reg.h |
* AND CONTAINS REGISTERS AND REGISTER DEFINITIONS THAT ARE NOT CORRECT |
* ON THE RADEON. A FULL AUDIT OF THIS CODE IS NEEDED! */ |
#ifndef _RADEON_REG_H_ |
#define _RADEON_REG_H_ |
/* Registers for 2D/Video/Overlay */ |
#define RADEON_ADAPTER_ID 0x0f2c /* PCI */ |
#define RADEON_AGP_BASE 0x0170 |
#define RADEON_AGP_CNTL 0x0174 |
# define RADEON_AGP_APER_SIZE_256MB (0x00 << 0) |
# define RADEON_AGP_APER_SIZE_128MB (0x20 << 0) |
# define RADEON_AGP_APER_SIZE_64MB (0x30 << 0) |
# define RADEON_AGP_APER_SIZE_32MB (0x38 << 0) |
# define RADEON_AGP_APER_SIZE_16MB (0x3c << 0) |
# define RADEON_AGP_APER_SIZE_8MB (0x3e << 0) |
# define RADEON_AGP_APER_SIZE_4MB (0x3f << 0) |
# define RADEON_AGP_APER_SIZE_MASK (0x3f << 0) |
#define RADEON_AGP_COMMAND 0x0f60 /* PCI */ |
#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config*/ |
# define RADEON_AGP_ENABLE (1<<8) |
#define RADEON_AGP_PLL_CNTL 0x000b /* PLL */ |
#define RADEON_AGP_STATUS 0x0f5c /* PCI */ |
# define RADEON_AGP_1X_MODE 0x01 |
# define RADEON_AGP_2X_MODE 0x02 |
# define RADEON_AGP_4X_MODE 0x04 |
# define RADEON_AGP_FW_MODE 0x10 |
# define RADEON_AGP_MODE_MASK 0x17 |
#define RADEON_ATTRDR 0x03c1 /* VGA */ |
#define RADEON_ATTRDW 0x03c0 /* VGA */ |
#define RADEON_ATTRX 0x03c0 /* VGA */ |
#define RADEON_AUX_SC_CNTL 0x1660 |
# define RADEON_AUX1_SC_EN (1 << 0) |
# define RADEON_AUX1_SC_MODE_OR (0 << 1) |
# define RADEON_AUX1_SC_MODE_NAND (1 << 1) |
# define RADEON_AUX2_SC_EN (1 << 2) |
# define RADEON_AUX2_SC_MODE_OR (0 << 3) |
# define RADEON_AUX2_SC_MODE_NAND (1 << 3) |
# define RADEON_AUX3_SC_EN (1 << 4) |
# define RADEON_AUX3_SC_MODE_OR (0 << 5) |
# define RADEON_AUX3_SC_MODE_NAND (1 << 5) |
#define RADEON_AUX1_SC_BOTTOM 0x1670 |
#define RADEON_AUX1_SC_LEFT 0x1664 |
#define RADEON_AUX1_SC_RIGHT 0x1668 |
#define RADEON_AUX1_SC_TOP 0x166c |
#define RADEON_AUX2_SC_BOTTOM 0x1680 |
#define RADEON_AUX2_SC_LEFT 0x1674 |
#define RADEON_AUX2_SC_RIGHT 0x1678 |
#define RADEON_AUX2_SC_TOP 0x167c |
#define RADEON_AUX3_SC_BOTTOM 0x1690 |
#define RADEON_AUX3_SC_LEFT 0x1684 |
#define RADEON_AUX3_SC_RIGHT 0x1688 |
#define RADEON_AUX3_SC_TOP 0x168c |
#define RADEON_AUX_WINDOW_HORZ_CNTL 0x02d8 |
#define RADEON_AUX_WINDOW_VERT_CNTL 0x02dc |
#define RADEON_BASE_CODE 0x0f0b |
#define RADEON_BIOS_0_SCRATCH 0x0010 |
#define RADEON_BIOS_1_SCRATCH 0x0014 |
#define RADEON_BIOS_2_SCRATCH 0x0018 |
#define RADEON_BIOS_3_SCRATCH 0x001c |
#define RADEON_BIOS_4_SCRATCH 0x0020 |
#define RADEON_BIOS_5_SCRATCH 0x0024 |
#define RADEON_BIOS_6_SCRATCH 0x0028 |
#define RADEON_BIOS_7_SCRATCH 0x002c |
#define RADEON_BIOS_ROM 0x0f30 /* PCI */ |
#define RADEON_BIST 0x0f0f /* PCI */ |
#define RADEON_BRUSH_DATA0 0x1480 |
#define RADEON_BRUSH_DATA1 0x1484 |
#define RADEON_BRUSH_DATA10 0x14a8 |
#define RADEON_BRUSH_DATA11 0x14ac |
#define RADEON_BRUSH_DATA12 0x14b0 |
#define RADEON_BRUSH_DATA13 0x14b4 |
#define RADEON_BRUSH_DATA14 0x14b8 |
#define RADEON_BRUSH_DATA15 0x14bc |
#define RADEON_BRUSH_DATA16 0x14c0 |
#define RADEON_BRUSH_DATA17 0x14c4 |
#define RADEON_BRUSH_DATA18 0x14c8 |
#define RADEON_BRUSH_DATA19 0x14cc |
#define RADEON_BRUSH_DATA2 0x1488 |
#define RADEON_BRUSH_DATA20 0x14d0 |
#define RADEON_BRUSH_DATA21 0x14d4 |
#define RADEON_BRUSH_DATA22 0x14d8 |
#define RADEON_BRUSH_DATA23 0x14dc |
#define RADEON_BRUSH_DATA24 0x14e0 |
#define RADEON_BRUSH_DATA25 0x14e4 |
#define RADEON_BRUSH_DATA26 0x14e8 |
#define RADEON_BRUSH_DATA27 0x14ec |
#define RADEON_BRUSH_DATA28 0x14f0 |
#define RADEON_BRUSH_DATA29 0x14f4 |
#define RADEON_BRUSH_DATA3 0x148c |
#define RADEON_BRUSH_DATA30 0x14f8 |
#define RADEON_BRUSH_DATA31 0x14fc |
#define RADEON_BRUSH_DATA32 0x1500 |
#define RADEON_BRUSH_DATA33 0x1504 |
#define RADEON_BRUSH_DATA34 0x1508 |
#define RADEON_BRUSH_DATA35 0x150c |
#define RADEON_BRUSH_DATA36 0x1510 |
#define RADEON_BRUSH_DATA37 0x1514 |
#define RADEON_BRUSH_DATA38 0x1518 |
#define RADEON_BRUSH_DATA39 0x151c |
#define RADEON_BRUSH_DATA4 0x1490 |
#define RADEON_BRUSH_DATA40 0x1520 |
#define RADEON_BRUSH_DATA41 0x1524 |
#define RADEON_BRUSH_DATA42 0x1528 |
#define RADEON_BRUSH_DATA43 0x152c |
#define RADEON_BRUSH_DATA44 0x1530 |
#define RADEON_BRUSH_DATA45 0x1534 |
#define RADEON_BRUSH_DATA46 0x1538 |
#define RADEON_BRUSH_DATA47 0x153c |
#define RADEON_BRUSH_DATA48 0x1540 |
#define RADEON_BRUSH_DATA49 0x1544 |
#define RADEON_BRUSH_DATA5 0x1494 |
#define RADEON_BRUSH_DATA50 0x1548 |
#define RADEON_BRUSH_DATA51 0x154c |
#define RADEON_BRUSH_DATA52 0x1550 |
#define RADEON_BRUSH_DATA53 0x1554 |
#define RADEON_BRUSH_DATA54 0x1558 |
#define RADEON_BRUSH_DATA55 0x155c |
#define RADEON_BRUSH_DATA56 0x1560 |
#define RADEON_BRUSH_DATA57 0x1564 |
#define RADEON_BRUSH_DATA58 0x1568 |
#define RADEON_BRUSH_DATA59 0x156c |
#define RADEON_BRUSH_DATA6 0x1498 |
#define RADEON_BRUSH_DATA60 0x1570 |
#define RADEON_BRUSH_DATA61 0x1574 |
#define RADEON_BRUSH_DATA62 0x1578 |
#define RADEON_BRUSH_DATA63 0x157c |
#define RADEON_BRUSH_DATA7 0x149c |
#define RADEON_BRUSH_DATA8 0x14a0 |
#define RADEON_BRUSH_DATA9 0x14a4 |
#define RADEON_BRUSH_SCALE 0x1470 |
#define RADEON_BRUSH_Y_X 0x1474 |
#define RADEON_BUS_CNTL 0x0030 |
# define RADEON_BUS_MASTER_DIS (1 << 6) |
# define RADEON_BUS_RD_DISCARD_EN (1 << 24) |
# define RADEON_BUS_RD_ABORT_EN (1 << 25) |
# define RADEON_BUS_MSTR_DISCONNECT_EN (1 << 28) |
# define RADEON_BUS_WRT_BURST (1 << 29) |
# define RADEON_BUS_READ_BURST (1 << 30) |
#define RADEON_BUS_CNTL1 0x0034 |
# define RADEON_BUS_WAIT_ON_LOCK_EN (1 << 4) |
#define RADEON_CACHE_CNTL 0x1724 |
#define RADEON_CACHE_LINE 0x0f0c /* PCI */ |
#define RADEON_CAP0_TRIG_CNTL 0x0950 /* ? */ |
#define RADEON_CAP1_TRIG_CNTL 0x09c0 /* ? */ |
#define RADEON_CAPABILITIES_ID 0x0f50 /* PCI */ |
#define RADEON_CAPABILITIES_PTR 0x0f34 /* PCI */ |
#define RADEON_CLK_PIN_CNTL 0x0001 /* PLL */ |
#define RADEON_CLOCK_CNTL_DATA 0x000c |
#define RADEON_CLOCK_CNTL_INDEX 0x0008 |
# define RADEON_PLL_WR_EN (1 << 7) |
# define RADEON_PLL_DIV_SEL (3 << 8) |
# define RADEON_PLL2_DIV_SEL_MASK ~(3 << 8) |
#define RADEON_CLR_CMP_CLR_3D 0x1a24 |
#define RADEON_CLR_CMP_CLR_DST 0x15c8 |
#define RADEON_CLR_CMP_CLR_SRC 0x15c4 |
#define RADEON_CLR_CMP_CNTL 0x15c0 |
# define RADEON_SRC_CMP_EQ_COLOR (4 << 0) |
# define RADEON_SRC_CMP_NEQ_COLOR (5 << 0) |
# define RADEON_CLR_CMP_SRC_SOURCE (1 << 24) |
#define RADEON_CLR_CMP_MASK 0x15cc |
# define RADEON_CLR_CMP_MSK 0xffffffff |
#define RADEON_CLR_CMP_MASK_3D 0x1A28 |
#define RADEON_COMMAND 0x0f04 /* PCI */ |
#define RADEON_COMPOSITE_SHADOW_ID 0x1a0c |
#define RADEON_CONFIG_APER_0_BASE 0x0100 |
#define RADEON_CONFIG_APER_1_BASE 0x0104 |
#define RADEON_CONFIG_APER_SIZE 0x0108 |
#define RADEON_CONFIG_BONDS 0x00e8 |
#define RADEON_CONFIG_CNTL 0x00e0 |
# define RADEON_CFG_ATI_REV_A11 (0 << 16) |
# define RADEON_CFG_ATI_REV_A12 (1 << 16) |
# define RADEON_CFG_ATI_REV_A13 (2 << 16) |
# define RADEON_CFG_ATI_REV_ID_MASK (0xf << 16) |
#define RADEON_CONFIG_MEMSIZE 0x00f8 |
#define RADEON_CONFIG_MEMSIZE_EMBEDDED 0x0114 |
#define RADEON_CONFIG_REG_1_BASE 0x010c |
#define RADEON_CONFIG_REG_APER_SIZE 0x0110 |
#define RADEON_CONFIG_XSTRAP 0x00e4 |
#define RADEON_CONSTANT_COLOR_C 0x1d34 |
# define RADEON_CONSTANT_COLOR_MASK 0x00ffffff |
# define RADEON_CONSTANT_COLOR_ONE 0x00ffffff |
# define RADEON_CONSTANT_COLOR_ZERO 0x00000000 |
#define RADEON_CRC_CMDFIFO_ADDR 0x0740 |
#define RADEON_CRC_CMDFIFO_DOUT 0x0744 |
#define RADEON_GRPH_BUFFER_CNTL 0x02f0 |
# define RADEON_GRPH_START_REQ_MASK (0x7f) |
# define RADEON_GRPH_START_REQ_SHIFT 0 |
# define RADEON_GRPH_STOP_REQ_MASK (0x7f<<8) |
# define RADEON_GRPH_STOP_REQ_SHIFT 8 |
# define RADEON_GRPH_CRITICAL_POINT_MASK (0x7f<<16) |
# define RADEON_GRPH_CRITICAL_POINT_SHIFT 16 |
# define RADEON_GRPH_CRITICAL_CNTL (1<<28) |
# define RADEON_GRPH_BUFFER_SIZE (1<<29) |
# define RADEON_GRPH_CRITICAL_AT_SOF (1<<30) |
# define RADEON_GRPH_STOP_CNTL (1<<31) |
#define RADEON_GRPH2_BUFFER_CNTL 0x03f0 |
# define RADEON_GRPH2_START_REQ_MASK (0x7f) |
# define RADEON_GRPH2_START_REQ_SHIFT 0 |
# define RADEON_GRPH2_STOP_REQ_MASK (0x7f<<8) |
# define RADEON_GRPH2_STOP_REQ_SHIFT 8 |
# define RADEON_GRPH2_CRITICAL_POINT_MASK (0x7f<<16) |
# define RADEON_GRPH2_CRITICAL_POINT_SHIFT 16 |
# define RADEON_GRPH2_CRITICAL_CNTL (1<<28) |
# define RADEON_GRPH2_BUFFER_SIZE (1<<29) |
# define RADEON_GRPH2_CRITICAL_AT_SOF (1<<30) |
# define RADEON_GRPH2_STOP_CNTL (1<<31) |
#define RADEON_CRTC_CRNT_FRAME 0x0214 |
#define RADEON_CRTC_EXT_CNTL 0x0054 |
# define RADEON_CRTC_VGA_XOVERSCAN (1 << 0) |
# define RADEON_VGA_ATI_LINEAR (1 << 3) |
# define RADEON_XCRT_CNT_EN (1 << 6) |
# define RADEON_CRTC_HSYNC_DIS (1 << 8) |
# define RADEON_CRTC_VSYNC_DIS (1 << 9) |
# define RADEON_CRTC_DISPLAY_DIS (1 << 10) |
# define RADEON_CRTC_SYNC_TRISTAT (1 << 11) |
# define RADEON_CRTC_CRT_ON (1 << 15) |
#define RADEON_CRTC_EXT_CNTL_DPMS_BYTE 0x0055 |
# define RADEON_CRTC_HSYNC_DIS_BYTE (1 << 0) |
# define RADEON_CRTC_VSYNC_DIS_BYTE (1 << 1) |
# define RADEON_CRTC_DISPLAY_DIS_BYTE (1 << 2) |
#define RADEON_CRTC_GEN_CNTL 0x0050 |
# define RADEON_CRTC_DBL_SCAN_EN (1 << 0) |
# define RADEON_CRTC_INTERLACE_EN (1 << 1) |
# define RADEON_CRTC_CSYNC_EN (1 << 4) |
# define RADEON_CRTC_CUR_EN (1 << 16) |
# define RADEON_CRTC_CUR_MODE_MASK (7 << 17) |
# define RADEON_CRTC_ICON_EN (1 << 20) |
# define RADEON_CRTC_EXT_DISP_EN (1 << 24) |
# define RADEON_CRTC_EN (1 << 25) |
# define RADEON_CRTC_DISP_REQ_EN_B (1 << 26) |
#define RADEON_CRTC2_GEN_CNTL 0x03f8 |
# define RADEON_CRTC2_DBL_SCAN_EN (1 << 0) |
# define RADEON_CRTC2_INTERLACE_EN (1 << 1) |
# define RADEON_CRTC2_SYNC_TRISTAT (1 << 4) |
# define RADEON_CRTC2_HSYNC_TRISTAT (1 << 5) |
# define RADEON_CRTC2_VSYNC_TRISTAT (1 << 6) |
# define RADEON_CRTC2_CRT2_ON (1 << 7) |
# define RADEON_CRTC2_ICON_EN (1 << 15) |
# define RADEON_CRTC2_CUR_EN (1 << 16) |
# define RADEON_CRTC2_CUR_MODE_MASK (7 << 20) |
# define RADEON_CRTC2_DISP_DIS (1 << 23) |
# define RADEON_CRTC2_EN (1 << 25) |
# define RADEON_CRTC2_DISP_REQ_EN_B (1 << 26) |
# define RADEON_CRTC2_CSYNC_EN (1 << 27) |
# define RADEON_CRTC2_HSYNC_DIS (1 << 28) |
# define RADEON_CRTC2_VSYNC_DIS (1 << 29) |
#define RADEON_CRTC_MORE_CNTL 0x27c |
# define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4) |
# define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5) |
#define RADEON_CRTC_GUI_TRIG_VLINE 0x0218 |
#define RADEON_CRTC_H_SYNC_STRT_WID 0x0204 |
# define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0) |
# define RADEON_CRTC_H_SYNC_STRT_CHAR (0x3ff << 3) |
# define RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT 3 |
# define RADEON_CRTC_H_SYNC_WID (0x3f << 16) |
# define RADEON_CRTC_H_SYNC_WID_SHIFT 16 |
# define RADEON_CRTC_H_SYNC_POL (1 << 23) |
#define RADEON_CRTC2_H_SYNC_STRT_WID 0x0304 |
# define RADEON_CRTC2_H_SYNC_STRT_PIX (0x07 << 0) |
# define RADEON_CRTC2_H_SYNC_STRT_CHAR (0x3ff << 3) |
# define RADEON_CRTC2_H_SYNC_STRT_CHAR_SHIFT 3 |
# define RADEON_CRTC2_H_SYNC_WID (0x3f << 16) |
# define RADEON_CRTC2_H_SYNC_WID_SHIFT 16 |
# define RADEON_CRTC2_H_SYNC_POL (1 << 23) |
#define RADEON_CRTC_H_TOTAL_DISP 0x0200 |
# define RADEON_CRTC_H_TOTAL (0x03ff << 0) |
# define RADEON_CRTC_H_TOTAL_SHIFT 0 |
# define RADEON_CRTC_H_DISP (0x01ff << 16) |
# define RADEON_CRTC_H_DISP_SHIFT 16 |
#define RADEON_CRTC2_H_TOTAL_DISP 0x0300 |
# define RADEON_CRTC2_H_TOTAL (0x03ff << 0) |
# define RADEON_CRTC2_H_TOTAL_SHIFT 0 |
# define RADEON_CRTC2_H_DISP (0x01ff << 16) |
# define RADEON_CRTC2_H_DISP_SHIFT 16 |
#define RADEON_CRTC_OFFSET 0x0224 |
#define RADEON_CRTC2_OFFSET 0x0324 |
#define RADEON_CRTC_OFFSET_CNTL 0x0228 |
# define RADEON_CRTC_TILE_EN (1 << 15) |
#define RADEON_CRTC2_OFFSET_CNTL 0x0328 |
# define RADEON_CRTC2_TILE_EN (1 << 15) |
#define RADEON_CRTC_PITCH 0x022c |
#define RADEON_CRTC2_PITCH 0x032c |
#define RADEON_CRTC_STATUS 0x005c |
# define RADEON_CRTC_VBLANK_SAVE (1 << 1) |
# define RADEON_CRTC_VBLANK_SAVE_CLEAR (1 << 1) |
#define RADEON_CRTC2_STATUS 0x03fc |
# define RADEON_CRTC2_VBLANK_SAVE (1 << 1) |
# define RADEON_CRTC2_VBLANK_SAVE_CLEAR (1 << 1) |
#define RADEON_CRTC_V_SYNC_STRT_WID 0x020c |
# define RADEON_CRTC_V_SYNC_STRT (0x7ff << 0) |
# define RADEON_CRTC_V_SYNC_STRT_SHIFT 0 |
# define RADEON_CRTC_V_SYNC_WID (0x1f << 16) |
# define RADEON_CRTC_V_SYNC_WID_SHIFT 16 |
# define RADEON_CRTC_V_SYNC_POL (1 << 23) |
#define RADEON_CRTC2_V_SYNC_STRT_WID 0x030c |
# define RADEON_CRTC2_V_SYNC_STRT (0x7ff << 0) |
# define RADEON_CRTC2_V_SYNC_STRT_SHIFT 0 |
# define RADEON_CRTC2_V_SYNC_WID (0x1f << 16) |
# define RADEON_CRTC2_V_SYNC_WID_SHIFT 16 |
# define RADEON_CRTC2_V_SYNC_POL (1 << 23) |
#define RADEON_CRTC_V_TOTAL_DISP 0x0208 |
# define RADEON_CRTC_V_TOTAL (0x07ff << 0) |
# define RADEON_CRTC_V_TOTAL_SHIFT 0 |
# define RADEON_CRTC_V_DISP (0x07ff << 16) |
# define RADEON_CRTC_V_DISP_SHIFT 16 |
#define RADEON_CRTC2_V_TOTAL_DISP 0x0308 |
# define RADEON_CRTC2_V_TOTAL (0x07ff << 0) |
# define RADEON_CRTC2_V_TOTAL_SHIFT 0 |
# define RADEON_CRTC2_V_DISP (0x07ff << 16) |
# define RADEON_CRTC2_V_DISP_SHIFT 16 |
#define RADEON_CRTC_VLINE_CRNT_VLINE 0x0210 |
# define RADEON_CRTC_CRNT_VLINE_MASK (0x7ff << 16) |
#define RADEON_CRTC2_CRNT_FRAME 0x0314 |
#define RADEON_CRTC2_GUI_TRIG_VLINE 0x0318 |
#define RADEON_CRTC2_STATUS 0x03fc |
#define RADEON_CRTC2_VLINE_CRNT_VLINE 0x0310 |
#define RADEON_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */ |
#define RADEON_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */ |
#define RADEON_CUR_CLR0 0x026c |
#define RADEON_CUR_CLR1 0x0270 |
#define RADEON_CUR_HORZ_VERT_OFF 0x0268 |
#define RADEON_CUR_HORZ_VERT_POSN 0x0264 |
#define RADEON_CUR_OFFSET 0x0260 |
# define RADEON_CUR_LOCK (1 << 31) |
#define RADEON_CUR2_CLR0 0x036c |
#define RADEON_CUR2_CLR1 0x0370 |
#define RADEON_CUR2_HORZ_VERT_OFF 0x0368 |
#define RADEON_CUR2_HORZ_VERT_POSN 0x0364 |
#define RADEON_CUR2_OFFSET 0x0360 |
# define RADEON_CUR2_LOCK (1 << 31) |
#define RADEON_DAC_CNTL 0x0058 |
# define RADEON_DAC_RANGE_CNTL (3 << 0) |
# define RADEON_DAC_RANGE_CNTL_MASK 0x03 |
# define RADEON_DAC_BLANKING (1 << 2) |
# define RADEON_DAC_CMP_EN (1 << 3) |
# define RADEON_DAC_CMP_OUTPUT (1 << 7) |
# define RADEON_DAC_8BIT_EN (1 << 8) |
# define RADEON_DAC_VGA_ADR_EN (1 << 13) |
# define RADEON_DAC_PDWN (1 << 15) |
# define RADEON_DAC_MASK_ALL (0xff << 24) |
#define RADEON_DAC_CNTL2 0x007c |
# define RADEON_DAC2_DAC_CLK_SEL (1 << 0) |
# define RADEON_DAC2_DAC2_CLK_SEL (1 << 1) |
# define RADEON_DAC2_PALETTE_ACC_CTL (1 << 5) |
#define RADEON_DAC_EXT_CNTL 0x0280 |
# define RADEON_DAC_FORCE_BLANK_OFF_EN (1 << 4) |
# define RADEON_DAC_FORCE_DATA_EN (1 << 5) |
# define RADEON_DAC_FORCE_DATA_SEL_MASK (3 << 6) |
# define RADEON_DAC_FORCE_DATA_MASK 0x0003ff00 |
# define RADEON_DAC_FORCE_DATA_SHIFT 8 |
#define RADEON_TV_DAC_CNTL 0x088c |
# define RADEON_TV_DAC_STD_MASK 0x0300 |
# define RADEON_TV_DAC_RDACPD (1 << 24) |
# define RADEON_TV_DAC_GDACPD (1 << 25) |
# define RADEON_TV_DAC_BDACPD (1 << 26) |
#define RADEON_DISP_HW_DEBUG 0x0d14 |
# define RADEON_CRT2_DISP1_SEL (1 << 5) |
#define RADEON_DISP_OUTPUT_CNTL 0x0d64 |
# define RADEON_DISP_DAC_SOURCE_MASK 0x03 |
# define RADEON_DISP_DAC2_SOURCE_MASK 0x0c |
# define RADEON_DISP_DAC_SOURCE_CRTC2 0x01 |
# define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04 |
#define RADEON_DAC_CRC_SIG 0x02cc |
#define RADEON_DAC_DATA 0x03c9 /* VGA */ |
#define RADEON_DAC_MASK 0x03c6 /* VGA */ |
#define RADEON_DAC_R_INDEX 0x03c7 /* VGA */ |
#define RADEON_DAC_W_INDEX 0x03c8 /* VGA */ |
#define RADEON_DDA_CONFIG 0x02e0 |
#define RADEON_DDA_ON_OFF 0x02e4 |
#define RADEON_DEFAULT_OFFSET 0x16e0 |
#define RADEON_DEFAULT_PITCH 0x16e4 |
#define RADEON_DEFAULT_SC_BOTTOM_RIGHT 0x16e8 |
# define RADEON_DEFAULT_SC_RIGHT_MAX (0x1fff << 0) |
# define RADEON_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16) |
#define RADEON_DESTINATION_3D_CLR_CMP_VAL 0x1820 |
#define RADEON_DESTINATION_3D_CLR_CMP_MSK 0x1824 |
#define RADEON_DEVICE_ID 0x0f02 /* PCI */ |
#define RADEON_DISP_MISC_CNTL 0x0d00 |
# define RADEON_SOFT_RESET_GRPH_PP (1 << 0) |
#define RADEON_DISP_MERGE_CNTL 0x0d60 |
# define RADEON_DISP_ALPHA_MODE_MASK 0x03 |
# define RADEON_DISP_ALPHA_MODE_KEY 0 |
# define RADEON_DISP_ALPHA_MODE_PER_PIXEL 1 |
# define RADEON_DISP_ALPHA_MODE_GLOBAL 2 |
# define RADEON_DISP_RGB_OFFSET_EN (1<<8) |
# define RADEON_DISP_GRPH_ALPHA_MASK (0xff << 16) |
# define RADEON_DISP_OV0_ALPHA_MASK (0xff << 24) |
# define RADEON_DISP_LIN_TRANS_BYPASS (0x01 << 9) |
#define RADEON_DISP2_MERGE_CNTL 0x0d68 |
# define RADEON_DISP2_RGB_OFFSET_EN (1<<8) |
#define RADEON_DISP_LIN_TRANS_GRPH_A 0x0d80 |
#define RADEON_DISP_LIN_TRANS_GRPH_B 0x0d84 |
#define RADEON_DISP_LIN_TRANS_GRPH_C 0x0d88 |
#define RADEON_DISP_LIN_TRANS_GRPH_D 0x0d8c |
#define RADEON_DISP_LIN_TRANS_GRPH_E 0x0d90 |
#define RADEON_DISP_LIN_TRANS_GRPH_F 0x0d98 |
#define RADEON_DP_BRUSH_BKGD_CLR 0x1478 |
#define RADEON_DP_BRUSH_FRGD_CLR 0x147c |
#define RADEON_DP_CNTL 0x16c0 |
# define RADEON_DST_X_LEFT_TO_RIGHT (1 << 0) |
# define RADEON_DST_Y_TOP_TO_BOTTOM (1 << 1) |
#define RADEON_DP_CNTL_XDIR_YDIR_YMAJOR 0x16d0 |
# define RADEON_DST_Y_MAJOR (1 << 2) |
# define RADEON_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15) |
# define RADEON_DST_X_DIR_LEFT_TO_RIGHT (1 << 31) |
#define RADEON_DP_DATATYPE 0x16c4 |
# define RADEON_HOST_BIG_ENDIAN_EN (1 << 29) |
#define RADEON_DP_GUI_MASTER_CNTL 0x146c |
# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) |
# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) |
# define RADEON_GMC_SRC_CLIPPING (1 << 2) |
# define RADEON_GMC_DST_CLIPPING (1 << 3) |
# define RADEON_GMC_BRUSH_DATATYPE_MASK (0x0f << 4) |
# define RADEON_GMC_BRUSH_8X8_MONO_FG_BG (0 << 4) |
# define RADEON_GMC_BRUSH_8X8_MONO_FG_LA (1 << 4) |
# define RADEON_GMC_BRUSH_1X8_MONO_FG_BG (4 << 4) |
# define RADEON_GMC_BRUSH_1X8_MONO_FG_LA (5 << 4) |
# define RADEON_GMC_BRUSH_32x1_MONO_FG_BG (6 << 4) |
# define RADEON_GMC_BRUSH_32x1_MONO_FG_LA (7 << 4) |
# define RADEON_GMC_BRUSH_32x32_MONO_FG_BG (8 << 4) |
# define RADEON_GMC_BRUSH_32x32_MONO_FG_LA (9 << 4) |
# define RADEON_GMC_BRUSH_8x8_COLOR (10 << 4) |
# define RADEON_GMC_BRUSH_1X8_COLOR (12 << 4) |
# define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4) |
# define RADEON_GMC_BRUSH_NONE (15 << 4) |
# define RADEON_GMC_DST_8BPP_CI (2 << 8) |
# define RADEON_GMC_DST_15BPP (3 << 8) |
# define RADEON_GMC_DST_16BPP (4 << 8) |
# define RADEON_GMC_DST_24BPP (5 << 8) |
# define RADEON_GMC_DST_32BPP (6 << 8) |
# define RADEON_GMC_DST_8BPP_RGB (7 << 8) |
# define RADEON_GMC_DST_Y8 (8 << 8) |
# define RADEON_GMC_DST_RGB8 (9 << 8) |
# define RADEON_GMC_DST_VYUY (11 << 8) |
# define RADEON_GMC_DST_YVYU (12 << 8) |
# define RADEON_GMC_DST_AYUV444 (14 << 8) |
# define RADEON_GMC_DST_ARGB4444 (15 << 8) |
# define RADEON_GMC_DST_DATATYPE_MASK (0x0f << 8) |
# define RADEON_GMC_DST_DATATYPE_SHIFT 8 |
# define RADEON_GMC_SRC_DATATYPE_MASK (3 << 12) |
# define RADEON_GMC_SRC_DATATYPE_MONO_FG_BG (0 << 12) |
# define RADEON_GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12) |
# define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12) |
# define RADEON_GMC_BYTE_PIX_ORDER (1 << 14) |
# define RADEON_GMC_BYTE_MSB_TO_LSB (0 << 14) |
# define RADEON_GMC_BYTE_LSB_TO_MSB (1 << 14) |
# define RADEON_GMC_CONVERSION_TEMP (1 << 15) |
# define RADEON_GMC_CONVERSION_TEMP_6500 (0 << 15) |
# define RADEON_GMC_CONVERSION_TEMP_9300 (1 << 15) |
# define RADEON_GMC_ROP3_MASK (0xff << 16) |
# define RADEON_DP_SRC_SOURCE_MASK (7 << 24) |
# define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24) |
# define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24) |
# define RADEON_GMC_3D_FCN_EN (1 << 27) |
# define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28) |
# define RADEON_GMC_AUX_CLIP_DIS (1 << 29) |
# define RADEON_GMC_WR_MSK_DIS (1 << 30) |
# define RADEON_GMC_LD_BRUSH_Y_X (1 << 31) |
# define RADEON_ROP3_ZERO 0x00000000 |
# define RADEON_ROP3_DSa 0x00880000 |
# define RADEON_ROP3_SDna 0x00440000 |
# define RADEON_ROP3_S 0x00cc0000 |
# define RADEON_ROP3_DSna 0x00220000 |
# define RADEON_ROP3_D 0x00aa0000 |
# define RADEON_ROP3_DSx 0x00660000 |
# define RADEON_ROP3_DSo 0x00ee0000 |
# define RADEON_ROP3_DSon 0x00110000 |
# define RADEON_ROP3_DSxn 0x00990000 |
# define RADEON_ROP3_Dn 0x00550000 |
# define RADEON_ROP3_SDno 0x00dd0000 |
# define RADEON_ROP3_Sn 0x00330000 |
# define RADEON_ROP3_DSno 0x00bb0000 |
# define RADEON_ROP3_DSan 0x00770000 |
# define RADEON_ROP3_ONE 0x00ff0000 |
# define RADEON_ROP3_DPa 0x00a00000 |
# define RADEON_ROP3_PDna 0x00500000 |
# define RADEON_ROP3_P 0x00f00000 |
# define RADEON_ROP3_DPna 0x000a0000 |
# define RADEON_ROP3_D 0x00aa0000 |
# define RADEON_ROP3_DPx 0x005a0000 |
# define RADEON_ROP3_DPo 0x00fa0000 |
# define RADEON_ROP3_DPon 0x00050000 |
# define RADEON_ROP3_PDxn 0x00a50000 |
# define RADEON_ROP3_PDno 0x00f50000 |
# define RADEON_ROP3_Pn 0x000f0000 |
# define RADEON_ROP3_DPno 0x00af0000 |
# define RADEON_ROP3_DPan 0x005f0000 |
#define RADEON_DP_GUI_MASTER_CNTL_C 0x1c84 |
#define RADEON_DP_MIX 0x16c8 |
#define RADEON_DP_SRC_BKGD_CLR 0x15dc |
#define RADEON_DP_SRC_FRGD_CLR 0x15d8 |
#define RADEON_DP_WRITE_MASK 0x16cc |
#define RADEON_DST_BRES_DEC 0x1630 |
#define RADEON_DST_BRES_ERR 0x1628 |
#define RADEON_DST_BRES_INC 0x162c |
#define RADEON_DST_BRES_LNTH 0x1634 |
#define RADEON_DST_BRES_LNTH_SUB 0x1638 |
#define RADEON_DST_HEIGHT 0x1410 |
#define RADEON_DST_HEIGHT_WIDTH 0x143c |
#define RADEON_DST_HEIGHT_WIDTH_8 0x158c |
#define RADEON_DST_HEIGHT_WIDTH_BW 0x15b4 |
#define RADEON_DST_HEIGHT_Y 0x15a0 |
#define RADEON_DST_LINE_START 0x1600 |
#define RADEON_DST_LINE_END 0x1604 |
#define RADEON_DST_LINE_PATCOUNT 0x1608 |
# define RADEON_BRES_CNTL_SHIFT 8 |
#define RADEON_DST_OFFSET 0x1404 |
#define RADEON_DST_PITCH 0x1408 |
#define RADEON_DST_PITCH_OFFSET 0x142c |
#define RADEON_DST_PITCH_OFFSET_C 0x1c80 |
# define RADEON_PITCH_SHIFT 21 |
# define RADEON_DST_TILE_LINEAR (0 << 30) |
# define RADEON_DST_TILE_MACRO (1 << 30) |
# define RADEON_DST_TILE_MICRO (2 << 30) |
# define RADEON_DST_TILE_BOTH (3 << 30) |
#define RADEON_DST_WIDTH 0x140c |
#define RADEON_DST_WIDTH_HEIGHT 0x1598 |
#define RADEON_DST_WIDTH_X 0x1588 |
#define RADEON_DST_WIDTH_X_INCY 0x159c |
#define RADEON_DST_X 0x141c |
#define RADEON_DST_X_SUB 0x15a4 |
#define RADEON_DST_X_Y 0x1594 |
#define RADEON_DST_Y 0x1420 |
#define RADEON_DST_Y_SUB 0x15a8 |
#define RADEON_DST_Y_X 0x1438 |
#define RADEON_FCP_CNTL 0x0910 |
# define RADEON_FCP0_SRC_PCICLK 0 |
# define RADEON_FCP0_SRC_PCLK 1 |
# define RADEON_FCP0_SRC_PCLKb 2 |
# define RADEON_FCP0_SRC_HREF 3 |
# define RADEON_FCP0_SRC_GND 4 |
# define RADEON_FCP0_SRC_HREFb 5 |
#define RADEON_FLUSH_1 0x1704 |
#define RADEON_FLUSH_2 0x1708 |
#define RADEON_FLUSH_3 0x170c |
#define RADEON_FLUSH_4 0x1710 |
#define RADEON_FLUSH_5 0x1714 |
#define RADEON_FLUSH_6 0x1718 |
#define RADEON_FLUSH_7 0x171c |
#define RADEON_FOG_3D_TABLE_START 0x1810 |
#define RADEON_FOG_3D_TABLE_END 0x1814 |
#define RADEON_FOG_3D_TABLE_DENSITY 0x181c |
#define RADEON_FOG_TABLE_INDEX 0x1a14 |
#define RADEON_FOG_TABLE_DATA 0x1a18 |
#define RADEON_FP_CRTC_H_TOTAL_DISP 0x0250 |
#define RADEON_FP_CRTC_V_TOTAL_DISP 0x0254 |
#define RADEON_FP_CRTC2_H_TOTAL_DISP 0x0350 |
#define RADEON_FP_CRTC2_V_TOTAL_DISP 0x0354 |
# define RADEON_FP_CRTC_H_TOTAL_MASK 0x000003ff |
# define RADEON_FP_CRTC_H_DISP_MASK 0x01ff0000 |
# define RADEON_FP_CRTC_V_TOTAL_MASK 0x00000fff |
# define RADEON_FP_CRTC_V_DISP_MASK 0x0fff0000 |
# define RADEON_FP_H_SYNC_STRT_CHAR_MASK 0x00001ff8 |
# define RADEON_FP_H_SYNC_WID_MASK 0x003f0000 |
# define RADEON_FP_V_SYNC_STRT_MASK 0x00000fff |
# define RADEON_FP_V_SYNC_WID_MASK 0x001f0000 |
# define RADEON_FP_CRTC_H_TOTAL_SHIFT 0x00000000 |
# define RADEON_FP_CRTC_H_DISP_SHIFT 0x00000010 |
# define RADEON_FP_CRTC_V_TOTAL_SHIFT 0x00000000 |
# define RADEON_FP_CRTC_V_DISP_SHIFT 0x00000010 |
# define RADEON_FP_H_SYNC_STRT_CHAR_SHIFT 0x00000003 |
# define RADEON_FP_H_SYNC_WID_SHIFT 0x00000010 |
# define RADEON_FP_V_SYNC_STRT_SHIFT 0x00000000 |
# define RADEON_FP_V_SYNC_WID_SHIFT 0x00000010 |
#define RADEON_FP_GEN_CNTL 0x0284 |
# define RADEON_FP_FPON (1 << 0) |
# define RADEON_FP_TMDS_EN (1 << 2) |
# define RADEON_FP_PANEL_FORMAT (1 << 3) |
# define RADEON_FP_EN_TMDS (1 << 7) |
# define RADEON_FP_DETECT_SENSE (1 << 8) |
# define RADEON_FP_SEL_CRTC2 (1 << 13) |
# define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15) |
# define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16) |
# define RADEON_FP_CRTC_DONT_SHADOW_HEND (1 << 17) |
# define RADEON_FP_CRTC_USE_SHADOW_VEND (1 << 18) |
# define RADEON_FP_RMX_HVSYNC_CONTROL_EN (1 << 20) |
# define RADEON_FP_DFP_SYNC_SEL (1 << 21) |
# define RADEON_FP_CRTC_LOCK_8DOT (1 << 22) |
# define RADEON_FP_CRT_SYNC_SEL (1 << 23) |
# define RADEON_FP_USE_SHADOW_EN (1 << 24) |
# define RADEON_FP_CRT_SYNC_ALT (1 << 26) |
#define RADEON_FP2_GEN_CNTL 0x0288 |
# define RADEON_FP2_BLANK_EN (1 << 1) |
# define RADEON_FP2_ON (1 << 2) |
# define RADEON_FP2_PANEL_FORMAT (1 << 3) |
# define RADEON_FP2_SOURCE_SEL_MASK (3 << 10) |
# define RADEON_FP2_SOURCE_SEL_CRTC2 (1 << 10) |
# define RADEON_FP2_SRC_SEL_MASK (3 << 13) |
# define RADEON_FP2_SRC_SEL_CRTC2 (1 << 13) |
# define RADEON_FP2_FP_POL (1 << 16) |
# define RADEON_FP2_LP_POL (1 << 17) |
# define RADEON_FP2_SCK_POL (1 << 18) |
# define RADEON_FP2_LCD_CNTL_MASK (7 << 19) |
# define RADEON_FP2_PAD_FLOP_EN (1 << 22) |
# define RADEON_FP2_CRC_EN (1 << 23) |
# define RADEON_FP2_CRC_READ_EN (1 << 24) |
# define RADEON_FP2_DV0_EN (1 << 25) |
# define RADEON_FP2_DV0_RATE_SEL_SDR (1 << 26) |
#define RADEON_FP_H_SYNC_STRT_WID 0x02c4 |
#define RADEON_FP_H2_SYNC_STRT_WID 0x03c4 |
#define RADEON_FP_HORZ_STRETCH 0x028c |
#define RADEON_FP_HORZ2_STRETCH 0x038c |
# define RADEON_HORZ_STRETCH_RATIO_MASK 0xffff |
# define RADEON_HORZ_STRETCH_RATIO_MAX 4096 |
# define RADEON_HORZ_PANEL_SIZE (0x1ff << 16) |
# define RADEON_HORZ_PANEL_SHIFT 16 |
# define RADEON_HORZ_STRETCH_PIXREP (0 << 25) |
# define RADEON_HORZ_STRETCH_BLEND (1 << 26) |
# define RADEON_HORZ_STRETCH_ENABLE (1 << 25) |
# define RADEON_HORZ_AUTO_RATIO (1 << 27) |
# define RADEON_HORZ_FP_LOOP_STRETCH (0x7 << 28) |
# define RADEON_HORZ_AUTO_RATIO_INC (1 << 31) |
#define RADEON_FP_V_SYNC_STRT_WID 0x02c8 |
#define RADEON_FP_VERT_STRETCH 0x0290 |
#define RADEON_FP_V2_SYNC_STRT_WID 0x03c8 |
#define RADEON_FP_VERT2_STRETCH 0x0390 |
# define RADEON_VERT_PANEL_SIZE (0xfff << 12) |
# define RADEON_VERT_PANEL_SHIFT 12 |
# define RADEON_VERT_STRETCH_RATIO_MASK 0xfff |
# define RADEON_VERT_STRETCH_RATIO_SHIFT 0 |
# define RADEON_VERT_STRETCH_RATIO_MAX 4096 |
# define RADEON_VERT_STRETCH_ENABLE (1 << 25) |
# define RADEON_VERT_STRETCH_LINEREP (0 << 26) |
# define RADEON_VERT_STRETCH_BLEND (1 << 26) |
# define RADEON_VERT_AUTO_RATIO_EN (1 << 27) |
# define RADEON_VERT_STRETCH_RESERVED 0xf1000000 |
#define RADEON_GEN_INT_CNTL 0x0040 |
#define RADEON_GEN_INT_STATUS 0x0044 |
# define RADEON_VSYNC_INT_AK (1 << 2) |
# define RADEON_VSYNC_INT (1 << 2) |
# define RADEON_VSYNC2_INT_AK (1 << 6) |
# define RADEON_VSYNC2_INT (1 << 6) |
#define RADEON_GENENB 0x03c3 /* VGA */ |
#define RADEON_GENFC_RD 0x03ca /* VGA */ |
#define RADEON_GENFC_WT 0x03da /* VGA, 0x03ba */ |
#define RADEON_GENMO_RD 0x03cc /* VGA */ |
#define RADEON_GENMO_WT 0x03c2 /* VGA */ |
#define RADEON_GENS0 0x03c2 /* VGA */ |
#define RADEON_GENS1 0x03da /* VGA, 0x03ba */ |
#define RADEON_GPIO_MONID 0x0068 /* DDC interface via I2C */ |
#define RADEON_GPIO_MONIDB 0x006c |
#define RADEON_GPIO_CRT2_DDC 0x006c |
#define RADEON_GPIO_DVI_DDC 0x0064 |
#define RADEON_GPIO_VGA_DDC 0x0060 |
# define RADEON_GPIO_A_0 (1 << 0) |
# define RADEON_GPIO_A_1 (1 << 1) |
# define RADEON_GPIO_Y_0 (1 << 8) |
# define RADEON_GPIO_Y_1 (1 << 9) |
# define RADEON_GPIO_Y_SHIFT_0 8 |
# define RADEON_GPIO_Y_SHIFT_1 9 |
# define RADEON_GPIO_EN_0 (1 << 16) |
# define RADEON_GPIO_EN_1 (1 << 17) |
# define RADEON_GPIO_MASK_0 (1 << 24) /*??*/ |
# define RADEON_GPIO_MASK_1 (1 << 25) /*??*/ |
#define RADEON_GRPH8_DATA 0x03cf /* VGA */ |
#define RADEON_GRPH8_IDX 0x03ce /* VGA */ |
#define RADEON_GUI_SCRATCH_REG0 0x15e0 |
#define RADEON_GUI_SCRATCH_REG1 0x15e4 |
#define RADEON_GUI_SCRATCH_REG2 0x15e8 |
#define RADEON_GUI_SCRATCH_REG3 0x15ec |
#define RADEON_GUI_SCRATCH_REG4 0x15f0 |
#define RADEON_GUI_SCRATCH_REG5 0x15f4 |
#define RADEON_HEADER 0x0f0e /* PCI */ |
#define RADEON_HOST_DATA0 0x17c0 |
#define RADEON_HOST_DATA1 0x17c4 |
#define RADEON_HOST_DATA2 0x17c8 |
#define RADEON_HOST_DATA3 0x17cc |
#define RADEON_HOST_DATA4 0x17d0 |
#define RADEON_HOST_DATA5 0x17d4 |
#define RADEON_HOST_DATA6 0x17d8 |
#define RADEON_HOST_DATA7 0x17dc |
#define RADEON_HOST_DATA_LAST 0x17e0 |
#define RADEON_HOST_PATH_CNTL 0x0130 |
# define RADEON_HDP_SOFT_RESET (1 << 26) |
#define RADEON_HTOTAL_CNTL 0x0009 /* PLL */ |
#define RADEON_HTOTAL2_CNTL 0x002e /* PLL */ |
#define RADEON_I2C_CNTL_1 0x0094 /* ? */ |
#define RADEON_DVI_I2C_CNTL_1 0x02e4 /* ? */ |
#define RADEON_INTERRUPT_LINE 0x0f3c /* PCI */ |
#define RADEON_INTERRUPT_PIN 0x0f3d /* PCI */ |
#define RADEON_IO_BASE 0x0f14 /* PCI */ |
#define RADEON_LATENCY 0x0f0d /* PCI */ |
#define RADEON_LEAD_BRES_DEC 0x1608 |
#define RADEON_LEAD_BRES_LNTH 0x161c |
#define RADEON_LEAD_BRES_LNTH_SUB 0x1624 |
#define RADEON_LVDS_GEN_CNTL 0x02d0 |
# define RADEON_LVDS_ON (1 << 0) |
# define RADEON_LVDS_DISPLAY_DIS (1 << 1) |
# define RADEON_LVDS_PANEL_TYPE (1 << 2) |
# define RADEON_LVDS_PANEL_FORMAT (1 << 3) |
# define RADEON_LVDS_EN (1 << 7) |
# define RADEON_LVDS_DIGON (1 << 18) |
# define RADEON_LVDS_BLON (1 << 19) |
# define RADEON_LVDS_SEL_CRTC2 (1 << 23) |
#define RADEON_LVDS_PLL_CNTL 0x02d4 |
# define RADEON_HSYNC_DELAY_SHIFT 28 |
# define RADEON_HSYNC_DELAY_MASK (0xf << 28) |
#define RADEON_MAX_LATENCY 0x0f3f /* PCI */ |
#define RADEON_MC_AGP_LOCATION 0x014c |
#define RADEON_MC_FB_LOCATION 0x0148 |
#define RADEON_DISPLAY_BASE_ADDR 0x23c |
#define RADEON_DISPLAY2_BASE_ADDR 0x33c |
#define RADEON_OV0_BASE_ADDR 0x43c |
#define RADEON_NB_TOM 0x15c |
#define RADEON_MCLK_CNTL 0x0012 /* PLL */ |
# define RADEON_FORCEON_MCLKA (1 << 16) |
# define RADEON_FORCEON_MCLKB (1 << 17) |
# define RADEON_FORCEON_YCLKA (1 << 18) |
# define RADEON_FORCEON_YCLKB (1 << 19) |
# define RADEON_FORCEON_MC (1 << 20) |
# define RADEON_FORCEON_AIC (1 << 21) |
#define RADEON_MDGPIO_A_REG 0x01ac |
#define RADEON_MDGPIO_EN_REG 0x01b0 |
#define RADEON_MDGPIO_MASK 0x0198 |
#define RADEON_MDGPIO_Y_REG 0x01b4 |
#define RADEON_MEM_ADDR_CONFIG 0x0148 |
#define RADEON_MEM_BASE 0x0f10 /* PCI */ |
#define RADEON_MEM_CNTL 0x0140 |
# define RADEON_MEM_NUM_CHANNELS_MASK 0x01 |
# define RADEON_MEM_USE_B_CH_ONLY (1<<1) |
# define RV100_HALF_MODE (1<<3) |
#define RADEON_MEM_TIMING_CNTL 0x0144 /* EXT_MEM_CNTL */ |
#define RADEON_MEM_INIT_LAT_TIMER 0x0154 |
#define RADEON_MEM_INTF_CNTL 0x014c |
#define RADEON_MEM_SDRAM_MODE_REG 0x0158 |
#define RADEON_MEM_STR_CNTL 0x0150 |
#define RADEON_MEM_VGA_RP_SEL 0x003c |
#define RADEON_MEM_VGA_WP_SEL 0x0038 |
#define RADEON_MIN_GRANT 0x0f3e /* PCI */ |
#define RADEON_MM_DATA 0x0004 |
#define RADEON_MM_INDEX 0x0000 |
#define RADEON_MPLL_CNTL 0x000e /* PLL */ |
#define RADEON_MPP_TB_CONFIG 0x01c0 /* ? */ |
#define RADEON_MPP_GP_CONFIG 0x01c8 /* ? */ |
#define RADEON_N_VIF_COUNT 0x0248 |
#define RADEON_OV0_AUTO_FLIP_CNTL 0x0470 |
#define RADEON_OV0_COLOUR_CNTL 0x04E0 |
#define RADEON_OV0_DEINTERLACE_PATTERN 0x0474 |
#define RADEON_OV0_EXCLUSIVE_HORZ 0x0408 |
# define RADEON_EXCL_HORZ_START_MASK 0x000000ff |
# define RADEON_EXCL_HORZ_END_MASK 0x0000ff00 |
# define RADEON_EXCL_HORZ_BACK_PORCH_MASK 0x00ff0000 |
# define RADEON_EXCL_HORZ_EXCLUSIVE_EN 0x80000000 |
#define RADEON_OV0_EXCLUSIVE_VERT 0x040C |
# define RADEON_EXCL_VERT_START_MASK 0x000003ff |
# define RADEON_EXCL_VERT_END_MASK 0x03ff0000 |
#define RADEON_OV0_FILTER_CNTL 0x04A0 |
#define RADEON_OV0_FOUR_TAP_COEF_0 0x04B0 |
#define RADEON_OV0_FOUR_TAP_COEF_1 0x04B4 |
#define RADEON_OV0_FOUR_TAP_COEF_2 0x04B8 |
#define RADEON_OV0_FOUR_TAP_COEF_3 0x04BC |
#define RADEON_OV0_FOUR_TAP_COEF_4 0x04C0 |
#define RADEON_OV0_GAMMA_000_00F 0x0d40 |
#define RADEON_OV0_GAMMA_010_01F 0x0d44 |
#define RADEON_OV0_GAMMA_020_03F 0x0d48 |
#define RADEON_OV0_GAMMA_040_07F 0x0d4c |
#define RADEON_OV0_GAMMA_080_0BF 0x0e00 |
#define RADEON_OV0_GAMMA_0C0_0FF 0x0e04 |
#define RADEON_OV0_GAMMA_100_13F 0x0e08 |
#define RADEON_OV0_GAMMA_140_17F 0x0e0c |
#define RADEON_OV0_GAMMA_180_1BF 0x0e10 |
#define RADEON_OV0_GAMMA_1C0_1FF 0x0e14 |
#define RADEON_OV0_GAMMA_200_23F 0x0e18 |
#define RADEON_OV0_GAMMA_240_27F 0x0e1c |
#define RADEON_OV0_GAMMA_280_2BF 0x0e20 |
#define RADEON_OV0_GAMMA_2C0_2FF 0x0e24 |
#define RADEON_OV0_GAMMA_300_33F 0x0e28 |
#define RADEON_OV0_GAMMA_340_37F 0x0e2c |
#define RADEON_OV0_GAMMA_380_3BF 0x0d50 |
#define RADEON_OV0_GAMMA_3C0_3FF 0x0d54 |
#define RADEON_OV0_GRAPHICS_KEY_CLR_LOW 0x04EC |
#define RADEON_OV0_GRAPHICS_KEY_CLR_HIGH 0x04F0 |
#define RADEON_OV0_H_INC 0x0480 |
#define RADEON_OV0_KEY_CNTL 0x04F4 |
# define RADEON_VIDEO_KEY_FN_MASK 0x00000003L |
# define RADEON_VIDEO_KEY_FN_FALSE 0x00000000L |
# define RADEON_VIDEO_KEY_FN_TRUE 0x00000001L |
# define RADEON_VIDEO_KEY_FN_EQ 0x00000002L |
# define RADEON_VIDEO_KEY_FN_NE 0x00000003L |
# define RADEON_GRAPHIC_KEY_FN_MASK 0x00000030L |
# define RADEON_GRAPHIC_KEY_FN_FALSE 0x00000000L |
# define RADEON_GRAPHIC_KEY_FN_TRUE 0x00000010L |
# define RADEON_GRAPHIC_KEY_FN_EQ 0x00000020L |
# define RADEON_GRAPHIC_KEY_FN_NE 0x00000030L |
# define RADEON_CMP_MIX_MASK 0x00000100L |
# define RADEON_CMP_MIX_OR 0x00000000L |
# define RADEON_CMP_MIX_AND 0x00000100L |
#define RADEON_OV0_LIN_TRANS_A 0x0d20 |
#define RADEON_OV0_LIN_TRANS_B 0x0d24 |
#define RADEON_OV0_LIN_TRANS_C 0x0d28 |
#define RADEON_OV0_LIN_TRANS_D 0x0d2c |
#define RADEON_OV0_LIN_TRANS_E 0x0d30 |
#define RADEON_OV0_LIN_TRANS_F 0x0d34 |
#define RADEON_OV0_P1_BLANK_LINES_AT_TOP 0x0430 |
# define RADEON_P1_BLNK_LN_AT_TOP_M1_MASK 0x00000fffL |
# define RADEON_P1_ACTIVE_LINES_M1 0x0fff0000L |
#define RADEON_OV0_P1_H_ACCUM_INIT 0x0488 |
#define RADEON_OV0_P1_V_ACCUM_INIT 0x0428 |
# define RADEON_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L |
# define RADEON_OV0_P1_V_ACCUM_INIT_MASK 0x01ff8000L |
#define RADEON_OV0_P1_X_START_END 0x0494 |
#define RADEON_OV0_P2_X_START_END 0x0498 |
#define RADEON_OV0_P23_BLANK_LINES_AT_TOP 0x0434 |
# define RADEON_P23_BLNK_LN_AT_TOP_M1_MASK 0x000007ffL |
# define RADEON_P23_ACTIVE_LINES_M1 0x07ff0000L |
#define RADEON_OV0_P23_H_ACCUM_INIT 0x048C |
#define RADEON_OV0_P23_V_ACCUM_INIT 0x042C |
#define RADEON_OV0_P3_X_START_END 0x049C |
#define RADEON_OV0_REG_LOAD_CNTL 0x0410 |
# define RADEON_REG_LD_CTL_LOCK 0x00000001L |
# define RADEON_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L |
# define RADEON_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L |
# define RADEON_REG_LD_CTL_LOCK_READBACK 0x00000008L |
#define RADEON_OV0_SCALE_CNTL 0x0420 |
# define RADEON_SCALER_HORZ_PICK_NEAREST 0x00000004L |
# define RADEON_SCALER_VERT_PICK_NEAREST 0x00000008L |
# define RADEON_SCALER_SIGNED_UV 0x00000010L |
# define RADEON_SCALER_GAMMA_SEL_MASK 0x00000060L |
# define RADEON_SCALER_GAMMA_SEL_BRIGHT 0x00000000L |
# define RADEON_SCALER_GAMMA_SEL_G22 0x00000020L |
# define RADEON_SCALER_GAMMA_SEL_G18 0x00000040L |
# define RADEON_SCALER_GAMMA_SEL_G14 0x00000060L |
# define RADEON_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L |
# define RADEON_SCALER_SURFAC_FORMAT 0x00000f00L |
# define RADEON_SCALER_SOURCE_15BPP 0x00000300L |
# define RADEON_SCALER_SOURCE_16BPP 0x00000400L |
# define RADEON_SCALER_SOURCE_32BPP 0x00000600L |
# define RADEON_SCALER_SOURCE_YUV9 0x00000900L |
# define RADEON_SCALER_SOURCE_YUV12 0x00000A00L |
# define RADEON_SCALER_SOURCE_VYUY422 0x00000B00L |
# define RADEON_SCALER_SOURCE_YVYU422 0x00000C00L |
# define RADEON_SCALER_ADAPTIVE_DEINT 0x00001000L |
# define RADEON_SCALER_TEMPORAL_DEINT 0x00002000L |
# define RADEON_SCALER_SMART_SWITCH 0x00008000L |
# define RADEON_SCALER_BURST_PER_PLANE 0x007F0000L |
# define RADEON_SCALER_DOUBLE_BUFFER 0x01000000L |
# define RADEON_SCALER_DIS_LIMIT 0x08000000L |
# define RADEON_SCALER_INT_EMU 0x20000000L |
# define RADEON_SCALER_ENABLE 0x40000000L |
# define RADEON_SCALER_SOFT_RESET 0x80000000L |
# define RADEON_SCALER_ADAPTIVE_DEINT 0x00001000L |
#define RADEON_OV0_STEP_BY 0x0484 |
#define RADEON_OV0_TEST 0x04F8 |
#define RADEON_OV0_V_INC 0x0424 |
#define RADEON_OV0_VID_BUF_PITCH0_VALUE 0x0460 |
#define RADEON_OV0_VID_BUF_PITCH1_VALUE 0x0464 |
#define RADEON_OV0_VID_BUF0_BASE_ADRS 0x0440 |
# define RADEON_VIF_BUF0_PITCH_SEL 0x00000001L |
# define RADEON_VIF_BUF0_TILE_ADRS 0x00000002L |
# define RADEON_VIF_BUF0_BASE_ADRS_MASK 0x03fffff0L |
# define RADEON_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L |
#define RADEON_OV0_VID_BUF1_BASE_ADRS 0x0444 |
# define RADEON_VIF_BUF1_PITCH_SEL 0x00000001L |
# define RADEON_VIF_BUF1_TILE_ADRS 0x00000002L |
# define RADEON_VIF_BUF1_BASE_ADRS_MASK 0x03fffff0L |
# define RADEON_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L |
#define RADEON_OV0_VID_BUF2_BASE_ADRS 0x0448 |
# define RADEON_VIF_BUF2_PITCH_SEL 0x00000001L |
# define RADEON_VIF_BUF2_TILE_ADRS 0x00000002L |
# define RADEON_VIF_BUF2_BASE_ADRS_MASK 0x03fffff0L |
# define RADEON_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L |
#define RADEON_OV0_VID_BUF3_BASE_ADRS 0x044C |
#define RADEON_OV0_VID_BUF4_BASE_ADRS 0x0450 |
#define RADEON_OV0_VID_BUF5_BASE_ADRS 0x0454 |
#define RADEON_OV0_VIDEO_KEY_CLR_HIGH 0x04E8 |
#define RADEON_OV0_VIDEO_KEY_CLR_LOW 0x04E4 |
#define RADEON_OV0_Y_X_START 0x0400 |
#define RADEON_OV0_Y_X_END 0x0404 |
#define RADEON_OV1_Y_X_START 0x0600 |
#define RADEON_OV1_Y_X_END 0x0604 |
#define RADEON_OVR_CLR 0x0230 |
#define RADEON_OVR_WID_LEFT_RIGHT 0x0234 |
#define RADEON_OVR_WID_TOP_BOTTOM 0x0238 |
#define RADEON_P2PLL_CNTL 0x002a /* P2PLL */ |
# define RADEON_P2PLL_RESET (1 << 0) |
# define RADEON_P2PLL_SLEEP (1 << 1) |
# define RADEON_P2PLL_ATOMIC_UPDATE_EN (1 << 16) |
# define RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN (1 << 17) |
# define RADEON_P2PLL_ATOMIC_UPDATE_VSYNC (1 << 18) |
#define RADEON_P2PLL_DIV_0 0x002c |
# define RADEON_P2PLL_FB0_DIV_MASK 0x07ff |
# define RADEON_P2PLL_POST0_DIV_MASK 0x00070000 |
#define RADEON_P2PLL_REF_DIV 0x002B /* PLL */ |
# define RADEON_P2PLL_REF_DIV_MASK 0x03ff |
# define RADEON_P2PLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */ |
# define RADEON_P2PLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */ |
#define RADEON_PALETTE_DATA 0x00b4 |
#define RADEON_PALETTE_30_DATA 0x00b8 |
#define RADEON_PALETTE_INDEX 0x00b0 |
#define RADEON_PCI_GART_PAGE 0x017c |
#define RADEON_PIXCLKS_CNTL 0x002d |
# define RADEON_PIX2CLK_SRC_SEL_MASK 0x03 |
# define RADEON_PIX2CLK_SRC_SEL_CPUCLK 0x00 |
# define RADEON_PIX2CLK_SRC_SEL_PSCANCLK 0x01 |
# define RADEON_PIX2CLK_SRC_SEL_BYTECLK 0x02 |
# define RADEON_PIX2CLK_SRC_SEL_P2PLLCLK 0x03 |
# define RADEON_PIX2CLK_ALWAYS_ONb (1<<6) |
# define RADEON_PIX2CLK_DAC_ALWAYS_ONb (1<<7) |
# define RADEON_PIXCLK_TV_SRC_SEL (1 << 8) |
# define RADEON_PIXCLK_LVDS_ALWAYS_ONb (1 << 14) |
# define RADEON_PIXCLK_TMDS_ALWAYS_ONb (1 << 15) |
#define RADEON_PLANE_3D_MASK_C 0x1d44 |
#define RADEON_PLL_TEST_CNTL 0x0013 /* PLL */ |
#define RADEON_PMI_CAP_ID 0x0f5c /* PCI */ |
#define RADEON_PMI_DATA 0x0f63 /* PCI */ |
#define RADEON_PMI_NXT_CAP_PTR 0x0f5d /* PCI */ |
#define RADEON_PMI_PMC_REG 0x0f5e /* PCI */ |
#define RADEON_PMI_PMCSR_REG 0x0f60 /* PCI */ |
#define RADEON_PMI_REGISTER 0x0f5c /* PCI */ |
#define RADEON_PPLL_CNTL 0x0002 /* PLL */ |
# define RADEON_PPLL_RESET (1 << 0) |
# define RADEON_PPLL_SLEEP (1 << 1) |
# define RADEON_PPLL_ATOMIC_UPDATE_EN (1 << 16) |
# define RADEON_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17) |
# define RADEON_PPLL_ATOMIC_UPDATE_VSYNC (1 << 18) |
#define RADEON_PPLL_DIV_0 0x0004 /* PLL */ |
#define RADEON_PPLL_DIV_1 0x0005 /* PLL */ |
#define RADEON_PPLL_DIV_2 0x0006 /* PLL */ |
#define RADEON_PPLL_DIV_3 0x0007 /* PLL */ |
# define RADEON_PPLL_FB3_DIV_MASK 0x07ff |
# define RADEON_PPLL_POST3_DIV_MASK 0x00070000 |
#define RADEON_PPLL_REF_DIV 0x0003 /* PLL */ |
# define RADEON_PPLL_REF_DIV_MASK 0x03ff |
# define RADEON_PPLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */ |
# define RADEON_PPLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */ |
#define RADEON_PWR_MNGMT_CNTL_STATUS 0x0f60 /* PCI */ |
#define RADEON_RBBM_GUICNTL 0x172c |
# define RADEON_HOST_DATA_SWAP_NONE (0 << 0) |
# define RADEON_HOST_DATA_SWAP_16BIT (1 << 0) |
# define RADEON_HOST_DATA_SWAP_32BIT (2 << 0) |
# define RADEON_HOST_DATA_SWAP_HDW (3 << 0) |
#define RADEON_RBBM_SOFT_RESET 0x00f0 |
# define RADEON_SOFT_RESET_CP (1 << 0) |
# define RADEON_SOFT_RESET_HI (1 << 1) |
# define RADEON_SOFT_RESET_SE (1 << 2) |
# define RADEON_SOFT_RESET_RE (1 << 3) |
# define RADEON_SOFT_RESET_PP (1 << 4) |
# define RADEON_SOFT_RESET_E2 (1 << 5) |
# define RADEON_SOFT_RESET_RB (1 << 6) |
# define RADEON_SOFT_RESET_HDP (1 << 7) |
#define RADEON_RBBM_STATUS 0x0e40 |
# define RADEON_RBBM_FIFOCNT_MASK 0x007f |
# define RADEON_RBBM_ACTIVE (1 << 31) |
#define RADEON_RB2D_DSTCACHE_CTLSTAT 0x342c |
# define RADEON_RB2D_DC_FLUSH (3 << 0) |
# define RADEON_RB2D_DC_FREE (3 << 2) |
# define RADEON_RB2D_DC_FLUSH_ALL 0xf |
# define RADEON_RB2D_DC_BUSY (1 << 31) |
#define RADEON_RB2D_DSTCACHE_MODE 0x3428 |
#define RADEON_REG_BASE 0x0f18 /* PCI */ |
#define RADEON_REGPROG_INF 0x0f09 /* PCI */ |
#define RADEON_REVISION_ID 0x0f08 /* PCI */ |
#define RADEON_SC_BOTTOM 0x164c |
#define RADEON_SC_BOTTOM_RIGHT 0x16f0 |
#define RADEON_SC_BOTTOM_RIGHT_C 0x1c8c |
#define RADEON_SC_LEFT 0x1640 |
#define RADEON_SC_RIGHT 0x1644 |
#define RADEON_SC_TOP 0x1648 |
#define RADEON_SC_TOP_LEFT 0x16ec |
#define RADEON_SC_TOP_LEFT_C 0x1c88 |
# define RADEON_SC_SIGN_MASK_LO 0x8000 |
# define RADEON_SC_SIGN_MASK_HI 0x80000000 |
#define RADEON_SCLK_CNTL 0x000d /* PLL */ |
# define RADEON_DYN_STOP_LAT_MASK 0x00007ff8 |
# define RADEON_CP_MAX_DYN_STOP_LAT 0x0008 |
# define RADEON_SCLK_FORCEON_MASK 0xffff8000 |
#define RADEON_SCLK_MORE_CNTL 0x0035 /* PLL */ |
# define RADEON_SCLK_MORE_FORCEON 0x0700 |
#define RADEON_SDRAM_MODE_REG 0x0158 |
#define RADEON_SEQ8_DATA 0x03c5 /* VGA */ |
#define RADEON_SEQ8_IDX 0x03c4 /* VGA */ |
#define RADEON_SNAPSHOT_F_COUNT 0x0244 |
#define RADEON_SNAPSHOT_VH_COUNTS 0x0240 |
#define RADEON_SNAPSHOT_VIF_COUNT 0x024c |
#define RADEON_SRC_OFFSET 0x15ac |
#define RADEON_SRC_PITCH 0x15b0 |
#define RADEON_SRC_PITCH_OFFSET 0x1428 |
#define RADEON_SRC_SC_BOTTOM 0x165c |
#define RADEON_SRC_SC_BOTTOM_RIGHT 0x16f4 |
#define RADEON_SRC_SC_RIGHT 0x1654 |
#define RADEON_SRC_X 0x1414 |
#define RADEON_SRC_X_Y 0x1590 |
#define RADEON_SRC_Y 0x1418 |
#define RADEON_SRC_Y_X 0x1434 |
#define RADEON_STATUS 0x0f06 /* PCI */ |
#define RADEON_SUBPIC_CNTL 0x0540 /* ? */ |
#define RADEON_SUB_CLASS 0x0f0a /* PCI */ |
#define RADEON_SURFACE_CNTL 0x0b00 |
# define RADEON_SURF_TRANSLATION_DIS (1 << 8) |
# define RADEON_NONSURF_AP0_SWP_16BPP (1 << 20) |
# define RADEON_NONSURF_AP0_SWP_32BPP (1 << 21) |
#define RADEON_SURFACE0_INFO 0x0b0c |
# define RADEON_SURF_TILE_COLOR_MACRO (0 << 16) |
# define RADEON_SURF_TILE_COLOR_BOTH (1 << 16) |
# define RADEON_SURF_TILE_DEPTH_32BPP (2 << 16) |
# define RADEON_SURF_TILE_DEPTH_16BPP (3 << 16) |
# define R200_SURF_TILE_NONE (0 << 16) |
# define R200_SURF_TILE_COLOR_MACRO (1 << 16) |
# define R200_SURF_TILE_COLOR_MICRO (2 << 16) |
# define R200_SURF_TILE_COLOR_BOTH (3 << 16) |
# define R200_SURF_TILE_DEPTH_32BPP (4 << 16) |
# define R200_SURF_TILE_DEPTH_16BPP (5 << 16) |
# define RADEON_SURF_AP0_SWP_16BPP (1 << 20) |
# define RADEON_SURF_AP0_SWP_32BPP (1 << 21) |
# define RADEON_SURF_AP1_SWP_16BPP (1 << 22) |
# define RADEON_SURF_AP1_SWP_32BPP (1 << 23) |
#define RADEON_SURFACE0_LOWER_BOUND 0x0b04 |
#define RADEON_SURFACE0_UPPER_BOUND 0x0b08 |
#define RADEON_SURFACE1_INFO 0x0b1c |
#define RADEON_SURFACE1_LOWER_BOUND 0x0b14 |
#define RADEON_SURFACE1_UPPER_BOUND 0x0b18 |
#define RADEON_SURFACE2_INFO 0x0b2c |
#define RADEON_SURFACE2_LOWER_BOUND 0x0b24 |
#define RADEON_SURFACE2_UPPER_BOUND 0x0b28 |
#define RADEON_SURFACE3_INFO 0x0b3c |
#define RADEON_SURFACE3_LOWER_BOUND 0x0b34 |
#define RADEON_SURFACE3_UPPER_BOUND 0x0b38 |
#define RADEON_SURFACE4_INFO 0x0b4c |
#define RADEON_SURFACE4_LOWER_BOUND 0x0b44 |
#define RADEON_SURFACE4_UPPER_BOUND 0x0b48 |
#define RADEON_SURFACE5_INFO 0x0b5c |
#define RADEON_SURFACE5_LOWER_BOUND 0x0b54 |
#define RADEON_SURFACE5_UPPER_BOUND 0x0b58 |
#define RADEON_SURFACE6_INFO 0x0b6c |
#define RADEON_SURFACE6_LOWER_BOUND 0x0b64 |
#define RADEON_SURFACE6_UPPER_BOUND 0x0b68 |
#define RADEON_SURFACE7_INFO 0x0b7c |
#define RADEON_SURFACE7_LOWER_BOUND 0x0b74 |
#define RADEON_SURFACE7_UPPER_BOUND 0x0b78 |
#define RADEON_SW_SEMAPHORE 0x013c |
#define RADEON_TEST_DEBUG_CNTL 0x0120 |
#define RADEON_TEST_DEBUG_MUX 0x0124 |
#define RADEON_TEST_DEBUG_OUT 0x012c |
#define RADEON_TMDS_PLL_CNTL 0x02a8 |
#define RADEON_TMDS_TRANSMITTER_CNTL 0x02a4 |
# define RADEON_TMDS_TRANSMITTER_PLLEN 1 |
# define RADEON_TMDS_TRANSMITTER_PLLRST 2 |
#define RADEON_TRAIL_BRES_DEC 0x1614 |
#define RADEON_TRAIL_BRES_ERR 0x160c |
#define RADEON_TRAIL_BRES_INC 0x1610 |
#define RADEON_TRAIL_X 0x1618 |
#define RADEON_TRAIL_X_SUB 0x1620 |
#define RADEON_VCLK_ECP_CNTL 0x0008 /* PLL */ |
# define RADEON_VCLK_SRC_SEL_MASK 0x03 |
# define RADEON_VCLK_SRC_SEL_CPUCLK 0x00 |
# define RADEON_VCLK_SRC_SEL_PSCANCLK 0x01 |
# define RADEON_VCLK_SRC_SEL_BYTECLK 0x02 |
# define RADEON_VCLK_SRC_SEL_PPLLCLK 0x03 |
# define RADEON_PIXCLK_ALWAYS_ONb (1<<6) |
# define RADEON_PIXCLK_DAC_ALWAYS_ONb (1<<7) |
#define RADEON_VENDOR_ID 0x0f00 /* PCI */ |
#define RADEON_VGA_DDA_CONFIG 0x02e8 |
#define RADEON_VGA_DDA_ON_OFF 0x02ec |
#define RADEON_VID_BUFFER_CONTROL 0x0900 |
#define RADEON_VIDEOMUX_CNTL 0x0190 |
#define RADEON_VIPH_CONTROL 0x0c40 /* ? */ |
#define RADEON_WAIT_UNTIL 0x1720 |
# define RADEON_WAIT_CRTC_PFLIP (1 << 0) |
# define RADEON_WAIT_2D_IDLECLEAN (1 << 16) |
# define RADEON_WAIT_3D_IDLECLEAN (1 << 17) |
# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) |
#define RADEON_X_MPLL_REF_FB_DIV 0x000a /* PLL */ |
#define RADEON_XCLK_CNTL 0x000d /* PLL */ |
#define RADEON_XDLL_CNTL 0x000c /* PLL */ |
#define RADEON_XPLL_CNTL 0x000b /* PLL */ |
/* Registers for 3D/TCL */ |
#define RADEON_PP_BORDER_COLOR_0 0x1d40 |
#define RADEON_PP_BORDER_COLOR_1 0x1d44 |
#define RADEON_PP_BORDER_COLOR_2 0x1d48 |
#define RADEON_PP_CNTL 0x1c38 |
# define RADEON_STIPPLE_ENABLE (1 << 0) |
# define RADEON_SCISSOR_ENABLE (1 << 1) |
# define RADEON_PATTERN_ENABLE (1 << 2) |
# define RADEON_SHADOW_ENABLE (1 << 3) |
# define RADEON_TEX_ENABLE_MASK (0xf << 4) |
# define RADEON_TEX_0_ENABLE (1 << 4) |
# define RADEON_TEX_1_ENABLE (1 << 5) |
# define RADEON_TEX_2_ENABLE (1 << 6) |
# define RADEON_TEX_3_ENABLE (1 << 7) |
# define RADEON_TEX_BLEND_ENABLE_MASK (0xf << 12) |
# define RADEON_TEX_BLEND_0_ENABLE (1 << 12) |
# define RADEON_TEX_BLEND_1_ENABLE (1 << 13) |
# define RADEON_TEX_BLEND_2_ENABLE (1 << 14) |
# define RADEON_TEX_BLEND_3_ENABLE (1 << 15) |
# define RADEON_PLANAR_YUV_ENABLE (1 << 20) |
# define RADEON_SPECULAR_ENABLE (1 << 21) |
# define RADEON_FOG_ENABLE (1 << 22) |
# define RADEON_ALPHA_TEST_ENABLE (1 << 23) |
# define RADEON_ANTI_ALIAS_NONE (0 << 24) |
# define RADEON_ANTI_ALIAS_LINE (1 << 24) |
# define RADEON_ANTI_ALIAS_POLY (2 << 24) |
# define RADEON_ANTI_ALIAS_LINE_POLY (3 << 24) |
# define RADEON_BUMP_MAP_ENABLE (1 << 26) |
# define RADEON_BUMPED_MAP_T0 (0 << 27) |
# define RADEON_BUMPED_MAP_T1 (1 << 27) |
# define RADEON_BUMPED_MAP_T2 (2 << 27) |
# define RADEON_TEX_3D_ENABLE_0 (1 << 29) |
# define RADEON_TEX_3D_ENABLE_1 (1 << 30) |
# define RADEON_MC_ENABLE (1 << 31) |
#define RADEON_PP_FOG_COLOR 0x1c18 |
# define RADEON_FOG_COLOR_MASK 0x00ffffff |
# define RADEON_FOG_VERTEX (0 << 24) |
# define RADEON_FOG_TABLE (1 << 24) |
# define RADEON_FOG_USE_DEPTH (0 << 25) |
# define RADEON_FOG_USE_DIFFUSE_ALPHA (2 << 25) |
# define RADEON_FOG_USE_SPEC_ALPHA (3 << 25) |
#define RADEON_PP_LUM_MATRIX 0x1d00 |
#define RADEON_PP_MISC 0x1c14 |
# define RADEON_REF_ALPHA_MASK 0x000000ff |
# define RADEON_ALPHA_TEST_FAIL (0 << 8) |
# define RADEON_ALPHA_TEST_LESS (1 << 8) |
# define RADEON_ALPHA_TEST_LEQUAL (2 << 8) |
# define RADEON_ALPHA_TEST_EQUAL (3 << 8) |
# define RADEON_ALPHA_TEST_GEQUAL (4 << 8) |
# define RADEON_ALPHA_TEST_GREATER (5 << 8) |
# define RADEON_ALPHA_TEST_NEQUAL (6 << 8) |
# define RADEON_ALPHA_TEST_PASS (7 << 8) |
# define RADEON_ALPHA_TEST_OP_MASK (7 << 8) |
# define RADEON_CHROMA_FUNC_FAIL (0 << 16) |
# define RADEON_CHROMA_FUNC_PASS (1 << 16) |
# define RADEON_CHROMA_FUNC_NEQUAL (2 << 16) |
# define RADEON_CHROMA_FUNC_EQUAL (3 << 16) |
# define RADEON_CHROMA_KEY_NEAREST (0 << 18) |
# define RADEON_CHROMA_KEY_ZERO (1 << 18) |
# define RADEON_SHADOW_ID_AUTO_INC (1 << 20) |
# define RADEON_SHADOW_FUNC_EQUAL (0 << 21) |
# define RADEON_SHADOW_FUNC_NEQUAL (1 << 21) |
# define RADEON_SHADOW_PASS_1 (0 << 22) |
# define RADEON_SHADOW_PASS_2 (1 << 22) |
# define RADEON_RIGHT_HAND_CUBE_D3D (0 << 24) |
# define RADEON_RIGHT_HAND_CUBE_OGL (1 << 24) |
#define RADEON_PP_ROT_MATRIX_0 0x1d58 |
#define RADEON_PP_ROT_MATRIX_1 0x1d5c |
#define RADEON_PP_TXFILTER_0 0x1c54 |
#define RADEON_PP_TXFILTER_1 0x1c6c |
#define RADEON_PP_TXFILTER_2 0x1c84 |
# define RADEON_MAG_FILTER_NEAREST (0 << 0) |
# define RADEON_MAG_FILTER_LINEAR (1 << 0) |
# define RADEON_MAG_FILTER_MASK (1 << 0) |
# define RADEON_MIN_FILTER_NEAREST (0 << 1) |
# define RADEON_MIN_FILTER_LINEAR (1 << 1) |
# define RADEON_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1) |
# define RADEON_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1) |
# define RADEON_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1) |
# define RADEON_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1) |
# define RADEON_MIN_FILTER_ANISO_NEAREST (8 << 1) |
# define RADEON_MIN_FILTER_ANISO_LINEAR (9 << 1) |
# define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1) |
# define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1) |
# define RADEON_MIN_FILTER_MASK (15 << 1) |
# define RADEON_MAX_ANISO_1_TO_1 (0 << 5) |
# define RADEON_MAX_ANISO_2_TO_1 (1 << 5) |
# define RADEON_MAX_ANISO_4_TO_1 (2 << 5) |
# define RADEON_MAX_ANISO_8_TO_1 (3 << 5) |
# define RADEON_MAX_ANISO_16_TO_1 (4 << 5) |
# define RADEON_MAX_ANISO_MASK (7 << 5) |
# define RADEON_LOD_BIAS_MASK (0xff << 8) |
# define RADEON_LOD_BIAS_SHIFT 8 |
# define RADEON_MAX_MIP_LEVEL_MASK (0x0f << 16) |
# define RADEON_MAX_MIP_LEVEL_SHIFT 16 |
# define RADEON_YUV_TO_RGB (1 << 20) |
# define RADEON_YUV_TEMPERATURE_COOL (0 << 21) |
# define RADEON_YUV_TEMPERATURE_HOT (1 << 21) |
# define RADEON_YUV_TEMPERATURE_MASK (1 << 21) |
# define RADEON_WRAPEN_S (1 << 22) |
# define RADEON_CLAMP_S_WRAP (0 << 23) |
# define RADEON_CLAMP_S_MIRROR (1 << 23) |
# define RADEON_CLAMP_S_CLAMP_LAST (2 << 23) |
# define RADEON_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) |
# define RADEON_CLAMP_S_CLAMP_BORDER (4 << 23) |
# define RADEON_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) |
# define RADEON_CLAMP_S_CLAMP_GL (6 << 23) |
# define RADEON_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) |
# define RADEON_CLAMP_S_MASK (7 << 23) |
# define RADEON_WRAPEN_T (1 << 26) |
# define RADEON_CLAMP_T_WRAP (0 << 27) |
# define RADEON_CLAMP_T_MIRROR (1 << 27) |
# define RADEON_CLAMP_T_CLAMP_LAST (2 << 27) |
# define RADEON_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) |
# define RADEON_CLAMP_T_CLAMP_BORDER (4 << 27) |
# define RADEON_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) |
# define RADEON_CLAMP_T_CLAMP_GL (6 << 27) |
# define RADEON_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) |
# define RADEON_CLAMP_T_MASK (7 << 27) |
# define RADEON_BORDER_MODE_OGL (0 << 31) |
# define RADEON_BORDER_MODE_D3D (1 << 31) |
#define RADEON_PP_TXFORMAT_0 0x1c58 |
#define RADEON_PP_TXFORMAT_1 0x1c70 |
#define RADEON_PP_TXFORMAT_2 0x1c88 |
# define RADEON_TXFORMAT_I8 (0 << 0) |
# define RADEON_TXFORMAT_AI88 (1 << 0) |
# define RADEON_TXFORMAT_RGB332 (2 << 0) |
# define RADEON_TXFORMAT_ARGB1555 (3 << 0) |
# define RADEON_TXFORMAT_RGB565 (4 << 0) |
# define RADEON_TXFORMAT_ARGB4444 (5 << 0) |
# define RADEON_TXFORMAT_ARGB8888 (6 << 0) |
# define RADEON_TXFORMAT_RGBA8888 (7 << 0) |
# define RADEON_TXFORMAT_Y8 (8 << 0) |
# define RADEON_TXFORMAT_VYUY422 (10 << 0) |
# define RADEON_TXFORMAT_YVYU422 (11 << 0) |
# define RADEON_TXFORMAT_DXT1 (12 << 0) |
# define RADEON_TXFORMAT_DXT23 (14 << 0) |
# define RADEON_TXFORMAT_DXT45 (15 << 0) |
# define RADEON_TXFORMAT_SHADOW16 (16 << 0) |
# define RADEON_TXFORMAT_SHADOW32 (17 << 0) |
# define RADEON_TXFORMAT_DUDV88 (18 << 0) |
# define RADEON_TXFORMAT_LDUDV655 (19 << 0) |
# define RADEON_TXFORMAT_LDUDUV8888 (20 << 0) |
# define RADEON_TXFORMAT_FORMAT_MASK (31 << 0) |
# define RADEON_TXFORMAT_FORMAT_SHIFT 0 |
# define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5) |
# define RADEON_TXFORMAT_ALPHA_IN_MAP (1 << 6) |
# define RADEON_TXFORMAT_NON_POWER2 (1 << 7) |
# define RADEON_TXFORMAT_WIDTH_MASK (15 << 8) |
# define RADEON_TXFORMAT_WIDTH_SHIFT 8 |
# define RADEON_TXFORMAT_HEIGHT_MASK (15 << 12) |
# define RADEON_TXFORMAT_HEIGHT_SHIFT 12 |
# define RADEON_TXFORMAT_F5_WIDTH_MASK (15 << 16) |
# define RADEON_TXFORMAT_F5_WIDTH_SHIFT 16 |
# define RADEON_TXFORMAT_F5_HEIGHT_MASK (15 << 20) |
# define RADEON_TXFORMAT_F5_HEIGHT_SHIFT 20 |
# define RADEON_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) |
# define RADEON_TXFORMAT_ST_ROUTE_MASK (3 << 24) |
# define RADEON_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) |
# define RADEON_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) |
# define RADEON_TXFORMAT_ENDIAN_NO_SWAP (0 << 26) |
# define RADEON_TXFORMAT_ENDIAN_16BPP_SWAP (1 << 26) |
# define RADEON_TXFORMAT_ENDIAN_32BPP_SWAP (2 << 26) |
# define RADEON_TXFORMAT_ENDIAN_HALFDW_SWAP (3 << 26) |
# define RADEON_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) |
# define RADEON_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) |
# define RADEON_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) |
# define RADEON_TXFORMAT_PERSPECTIVE_ENABLE (1 << 31) |
#define RADEON_PP_CUBIC_FACES_0 0x1d24 |
#define RADEON_PP_CUBIC_FACES_1 0x1d28 |
#define RADEON_PP_CUBIC_FACES_2 0x1d2c |
# define RADEON_FACE_WIDTH_1_SHIFT 0 |
# define RADEON_FACE_HEIGHT_1_SHIFT 4 |
# define RADEON_FACE_WIDTH_1_MASK (0xf << 0) |
# define RADEON_FACE_HEIGHT_1_MASK (0xf << 4) |
# define RADEON_FACE_WIDTH_2_SHIFT 8 |
# define RADEON_FACE_HEIGHT_2_SHIFT 12 |
# define RADEON_FACE_WIDTH_2_MASK (0xf << 8) |
# define RADEON_FACE_HEIGHT_2_MASK (0xf << 12) |
# define RADEON_FACE_WIDTH_3_SHIFT 16 |
# define RADEON_FACE_HEIGHT_3_SHIFT 20 |
# define RADEON_FACE_WIDTH_3_MASK (0xf << 16) |
# define RADEON_FACE_HEIGHT_3_MASK (0xf << 20) |
# define RADEON_FACE_WIDTH_4_SHIFT 24 |
# define RADEON_FACE_HEIGHT_4_SHIFT 28 |
# define RADEON_FACE_WIDTH_4_MASK (0xf << 24) |
# define RADEON_FACE_HEIGHT_4_MASK (0xf << 28) |
#define RADEON_PP_TXOFFSET_0 0x1c5c |
#define RADEON_PP_TXOFFSET_1 0x1c74 |
#define RADEON_PP_TXOFFSET_2 0x1c8c |
# define RADEON_TXO_ENDIAN_NO_SWAP (0 << 0) |
# define RADEON_TXO_ENDIAN_BYTE_SWAP (1 << 0) |
# define RADEON_TXO_ENDIAN_WORD_SWAP (2 << 0) |
# define RADEON_TXO_ENDIAN_HALFDW_SWAP (3 << 0) |
# define RADEON_TXO_MACRO_LINEAR (0 << 2) |
# define RADEON_TXO_MACRO_TILE (1 << 2) |
# define RADEON_TXO_MICRO_LINEAR (0 << 3) |
# define RADEON_TXO_MICRO_TILE_X2 (1 << 3) |
# define RADEON_TXO_MICRO_TILE_OPT (2 << 3) |
# define RADEON_TXO_OFFSET_MASK 0xffffffe0 |
# define RADEON_TXO_OFFSET_SHIFT 5 |
#define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */ |
#define RADEON_PP_CUBIC_OFFSET_T0_1 0x1dd4 |
#define RADEON_PP_CUBIC_OFFSET_T0_2 0x1dd8 |
#define RADEON_PP_CUBIC_OFFSET_T0_3 0x1ddc |
#define RADEON_PP_CUBIC_OFFSET_T0_4 0x1de0 |
#define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00 |
#define RADEON_PP_CUBIC_OFFSET_T1_1 0x1e04 |
#define RADEON_PP_CUBIC_OFFSET_T1_2 0x1e08 |
#define RADEON_PP_CUBIC_OFFSET_T1_3 0x1e0c |
#define RADEON_PP_CUBIC_OFFSET_T1_4 0x1e10 |
#define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14 |
#define RADEON_PP_CUBIC_OFFSET_T2_1 0x1e18 |
#define RADEON_PP_CUBIC_OFFSET_T2_2 0x1e1c |
#define RADEON_PP_CUBIC_OFFSET_T2_3 0x1e20 |
#define RADEON_PP_CUBIC_OFFSET_T2_4 0x1e24 |
#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */ |
#define RADEON_PP_TEX_SIZE_1 0x1d0c |
#define RADEON_PP_TEX_SIZE_2 0x1d14 |
# define RADEON_TEX_USIZE_MASK (0x7ff << 0) |
# define RADEON_TEX_USIZE_SHIFT 0 |
# define RADEON_TEX_VSIZE_MASK (0x7ff << 16) |
# define RADEON_TEX_VSIZE_SHIFT 16 |
# define RADEON_SIGNED_RGB_MASK (1 << 30) |
# define RADEON_SIGNED_RGB_SHIFT 30 |
# define RADEON_SIGNED_ALPHA_MASK (1 << 31) |
# define RADEON_SIGNED_ALPHA_SHIFT 31 |
#define RADEON_PP_TEX_PITCH_0 0x1d08 /* NPOT */ |
#define RADEON_PP_TEX_PITCH_1 0x1d10 /* NPOT */ |
#define RADEON_PP_TEX_PITCH_2 0x1d18 /* NPOT */ |
/* note: bits 13-5: 32 byte aligned stride of texture map */ |
#define RADEON_PP_TXCBLEND_0 0x1c60 |
#define RADEON_PP_TXCBLEND_1 0x1c78 |
#define RADEON_PP_TXCBLEND_2 0x1c90 |
# define RADEON_COLOR_ARG_A_SHIFT 0 |
# define RADEON_COLOR_ARG_A_MASK (0x1f << 0) |
# define RADEON_COLOR_ARG_A_ZERO (0 << 0) |
# define RADEON_COLOR_ARG_A_CURRENT_COLOR (2 << 0) |
# define RADEON_COLOR_ARG_A_CURRENT_ALPHA (3 << 0) |
# define RADEON_COLOR_ARG_A_DIFFUSE_COLOR (4 << 0) |
# define RADEON_COLOR_ARG_A_DIFFUSE_ALPHA (5 << 0) |
# define RADEON_COLOR_ARG_A_SPECULAR_COLOR (6 << 0) |
# define RADEON_COLOR_ARG_A_SPECULAR_ALPHA (7 << 0) |
# define RADEON_COLOR_ARG_A_TFACTOR_COLOR (8 << 0) |
# define RADEON_COLOR_ARG_A_TFACTOR_ALPHA (9 << 0) |
# define RADEON_COLOR_ARG_A_T0_COLOR (10 << 0) |
# define RADEON_COLOR_ARG_A_T0_ALPHA (11 << 0) |
# define RADEON_COLOR_ARG_A_T1_COLOR (12 << 0) |
# define RADEON_COLOR_ARG_A_T1_ALPHA (13 << 0) |
# define RADEON_COLOR_ARG_A_T2_COLOR (14 << 0) |
# define RADEON_COLOR_ARG_A_T2_ALPHA (15 << 0) |
# define RADEON_COLOR_ARG_A_T3_COLOR (16 << 0) |
# define RADEON_COLOR_ARG_A_T3_ALPHA (17 << 0) |
# define RADEON_COLOR_ARG_B_SHIFT 5 |
# define RADEON_COLOR_ARG_B_MASK (0x1f << 5) |
# define RADEON_COLOR_ARG_B_ZERO (0 << 5) |
# define RADEON_COLOR_ARG_B_CURRENT_COLOR (2 << 5) |
# define RADEON_COLOR_ARG_B_CURRENT_ALPHA (3 << 5) |
# define RADEON_COLOR_ARG_B_DIFFUSE_COLOR (4 << 5) |
# define RADEON_COLOR_ARG_B_DIFFUSE_ALPHA (5 << 5) |
# define RADEON_COLOR_ARG_B_SPECULAR_COLOR (6 << 5) |
# define RADEON_COLOR_ARG_B_SPECULAR_ALPHA (7 << 5) |
# define RADEON_COLOR_ARG_B_TFACTOR_COLOR (8 << 5) |
# define RADEON_COLOR_ARG_B_TFACTOR_ALPHA (9 << 5) |
# define RADEON_COLOR_ARG_B_T0_COLOR (10 << 5) |
# define RADEON_COLOR_ARG_B_T0_ALPHA (11 << 5) |
# define RADEON_COLOR_ARG_B_T1_COLOR (12 << 5) |
# define RADEON_COLOR_ARG_B_T1_ALPHA (13 << 5) |
# define RADEON_COLOR_ARG_B_T2_COLOR (14 << 5) |
# define RADEON_COLOR_ARG_B_T2_ALPHA (15 << 5) |
# define RADEON_COLOR_ARG_B_T3_COLOR (16 << 5) |
# define RADEON_COLOR_ARG_B_T3_ALPHA (17 << 5) |
# define RADEON_COLOR_ARG_C_SHIFT 10 |
# define RADEON_COLOR_ARG_C_MASK (0x1f << 10) |
# define RADEON_COLOR_ARG_C_ZERO (0 << 10) |
# define RADEON_COLOR_ARG_C_CURRENT_COLOR (2 << 10) |
# define RADEON_COLOR_ARG_C_CURRENT_ALPHA (3 << 10) |
# define RADEON_COLOR_ARG_C_DIFFUSE_COLOR (4 << 10) |
# define RADEON_COLOR_ARG_C_DIFFUSE_ALPHA (5 << 10) |
# define RADEON_COLOR_ARG_C_SPECULAR_COLOR (6 << 10) |
# define RADEON_COLOR_ARG_C_SPECULAR_ALPHA (7 << 10) |
# define RADEON_COLOR_ARG_C_TFACTOR_COLOR (8 << 10) |
# define RADEON_COLOR_ARG_C_TFACTOR_ALPHA (9 << 10) |
# define RADEON_COLOR_ARG_C_T0_COLOR (10 << 10) |
# define RADEON_COLOR_ARG_C_T0_ALPHA (11 << 10) |
# define RADEON_COLOR_ARG_C_T1_COLOR (12 << 10) |
# define RADEON_COLOR_ARG_C_T1_ALPHA (13 << 10) |
# define RADEON_COLOR_ARG_C_T2_COLOR (14 << 10) |
# define RADEON_COLOR_ARG_C_T2_ALPHA (15 << 10) |
# define RADEON_COLOR_ARG_C_T3_COLOR (16 << 10) |
# define RADEON_COLOR_ARG_C_T3_ALPHA (17 << 10) |
# define RADEON_COMP_ARG_A (1 << 15) |
# define RADEON_COMP_ARG_A_SHIFT 15 |
# define RADEON_COMP_ARG_B (1 << 16) |
# define RADEON_COMP_ARG_B_SHIFT 16 |
# define RADEON_COMP_ARG_C (1 << 17) |
# define RADEON_COMP_ARG_C_SHIFT 17 |
# define RADEON_BLEND_CTL_MASK (7 << 18) |
# define RADEON_BLEND_CTL_ADD (0 << 18) |
# define RADEON_BLEND_CTL_SUBTRACT (1 << 18) |
# define RADEON_BLEND_CTL_ADDSIGNED (2 << 18) |
# define RADEON_BLEND_CTL_BLEND (3 << 18) |
# define RADEON_BLEND_CTL_DOT3 (4 << 18) |
# define RADEON_SCALE_SHIFT 21 |
# define RADEON_SCALE_MASK (3 << 21) |
# define RADEON_SCALE_1X (0 << 21) |
# define RADEON_SCALE_2X (1 << 21) |
# define RADEON_SCALE_4X (2 << 21) |
# define RADEON_CLAMP_TX (1 << 23) |
# define RADEON_T0_EQ_TCUR (1 << 24) |
# define RADEON_T1_EQ_TCUR (1 << 25) |
# define RADEON_T2_EQ_TCUR (1 << 26) |
# define RADEON_T3_EQ_TCUR (1 << 27) |
# define RADEON_COLOR_ARG_MASK 0x1f |
# define RADEON_COMP_ARG_SHIFT 15 |
#define RADEON_PP_TXABLEND_0 0x1c64 |
#define RADEON_PP_TXABLEND_1 0x1c7c |
#define RADEON_PP_TXABLEND_2 0x1c94 |
# define RADEON_ALPHA_ARG_A_SHIFT 0 |
# define RADEON_ALPHA_ARG_A_MASK (0xf << 0) |
# define RADEON_ALPHA_ARG_A_ZERO (0 << 0) |
# define RADEON_ALPHA_ARG_A_CURRENT_ALPHA (1 << 0) |
# define RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA (2 << 0) |
# define RADEON_ALPHA_ARG_A_SPECULAR_ALPHA (3 << 0) |
# define RADEON_ALPHA_ARG_A_TFACTOR_ALPHA (4 << 0) |
# define RADEON_ALPHA_ARG_A_T0_ALPHA (5 << 0) |
# define RADEON_ALPHA_ARG_A_T1_ALPHA (6 << 0) |
# define RADEON_ALPHA_ARG_A_T2_ALPHA (7 << 0) |
# define RADEON_ALPHA_ARG_A_T3_ALPHA (8 << 0) |
# define RADEON_ALPHA_ARG_B_SHIFT 4 |
# define RADEON_ALPHA_ARG_B_MASK (0xf << 4) |
# define RADEON_ALPHA_ARG_B_ZERO (0 << 4) |
# define RADEON_ALPHA_ARG_B_CURRENT_ALPHA (1 << 4) |
# define RADEON_ALPHA_ARG_B_DIFFUSE_ALPHA (2 << 4) |
# define RADEON_ALPHA_ARG_B_SPECULAR_ALPHA (3 << 4) |
# define RADEON_ALPHA_ARG_B_TFACTOR_ALPHA (4 << 4) |
# define RADEON_ALPHA_ARG_B_T0_ALPHA (5 << 4) |
# define RADEON_ALPHA_ARG_B_T1_ALPHA (6 << 4) |
# define RADEON_ALPHA_ARG_B_T2_ALPHA (7 << 4) |
# define RADEON_ALPHA_ARG_B_T3_ALPHA (8 << 4) |
# define RADEON_ALPHA_ARG_C_SHIFT 8 |
# define RADEON_ALPHA_ARG_C_MASK (0xf << 8) |
# define RADEON_ALPHA_ARG_C_ZERO (0 << 8) |
# define RADEON_ALPHA_ARG_C_CURRENT_ALPHA (1 << 8) |
# define RADEON_ALPHA_ARG_C_DIFFUSE_ALPHA (2 << 8) |
# define RADEON_ALPHA_ARG_C_SPECULAR_ALPHA (3 << 8) |
# define RADEON_ALPHA_ARG_C_TFACTOR_ALPHA (4 << 8) |
# define RADEON_ALPHA_ARG_C_T0_ALPHA (5 << 8) |
# define RADEON_ALPHA_ARG_C_T1_ALPHA (6 << 8) |
# define RADEON_ALPHA_ARG_C_T2_ALPHA (7 << 8) |
# define RADEON_ALPHA_ARG_C_T3_ALPHA (8 << 8) |
# define RADEON_DOT_ALPHA_DONT_REPLICATE (1 << 12) |
# define RADEON_ALPHA_ARG_MASK 0xf |
#define RADEON_PP_TFACTOR_0 0x1c68 |
#define RADEON_PP_TFACTOR_1 0x1c80 |
#define RADEON_PP_TFACTOR_2 0x1c98 |
#define RADEON_RB3D_BLENDCNTL 0x1c20 |
# define RADEON_COMB_FCN_MASK (3 << 12) |
# define RADEON_COMB_FCN_ADD_CLAMP (0 << 12) |
# define RADEON_COMB_FCN_ADD_NOCLAMP (1 << 12) |
# define RADEON_COMB_FCN_SUB_CLAMP (2 << 12) |
# define RADEON_COMB_FCN_SUB_NOCLAMP (3 << 12) |
# define RADEON_SRC_BLEND_GL_ZERO (32 << 16) |
# define RADEON_SRC_BLEND_GL_ONE (33 << 16) |
# define RADEON_SRC_BLEND_GL_SRC_COLOR (34 << 16) |
# define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16) |
# define RADEON_SRC_BLEND_GL_DST_COLOR (36 << 16) |
# define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16) |
# define RADEON_SRC_BLEND_GL_SRC_ALPHA (38 << 16) |
# define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16) |
# define RADEON_SRC_BLEND_GL_DST_ALPHA (40 << 16) |
# define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16) |
# define RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16) |
# define RADEON_SRC_BLEND_MASK (63 << 16) |
# define RADEON_DST_BLEND_GL_ZERO (32 << 24) |
# define RADEON_DST_BLEND_GL_ONE (33 << 24) |
# define RADEON_DST_BLEND_GL_SRC_COLOR (34 << 24) |
# define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24) |
# define RADEON_DST_BLEND_GL_DST_COLOR (36 << 24) |
# define RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24) |
# define RADEON_DST_BLEND_GL_SRC_ALPHA (38 << 24) |
# define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24) |
# define RADEON_DST_BLEND_GL_DST_ALPHA (40 << 24) |
# define RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24) |
# define RADEON_DST_BLEND_MASK (63 << 24) |
#define RADEON_RB3D_CNTL 0x1c3c |
# define RADEON_ALPHA_BLEND_ENABLE (1 << 0) |
# define RADEON_PLANE_MASK_ENABLE (1 << 1) |
# define RADEON_DITHER_ENABLE (1 << 2) |
# define RADEON_ROUND_ENABLE (1 << 3) |
# define RADEON_SCALE_DITHER_ENABLE (1 << 4) |
# define RADEON_DITHER_INIT (1 << 5) |
# define RADEON_ROP_ENABLE (1 << 6) |
# define RADEON_STENCIL_ENABLE (1 << 7) |
# define RADEON_Z_ENABLE (1 << 8) |
# define RADEON_DEPTH_XZ_OFFEST_ENABLE (1 << 9) |
# define RADEON_COLOR_FORMAT_ARGB1555 (3 << 10) |
# define RADEON_COLOR_FORMAT_RGB565 (4 << 10) |
# define RADEON_COLOR_FORMAT_ARGB8888 (6 << 10) |
# define RADEON_COLOR_FORMAT_RGB332 (7 << 10) |
# define RADEON_COLOR_FORMAT_Y8 (8 << 10) |
# define RADEON_COLOR_FORMAT_RGB8 (9 << 10) |
# define RADEON_COLOR_FORMAT_YUV422_VYUY (11 << 10) |
# define RADEON_COLOR_FORMAT_YUV422_YVYU (12 << 10) |
# define RADEON_COLOR_FORMAT_aYUV444 (14 << 10) |
# define RADEON_COLOR_FORMAT_ARGB4444 (15 << 10) |
# define RADEON_CLRCMP_FLIP_ENABLE (1 << 14) |
# define RADEON_ZBLOCK16 (1 << 15) |
#define RADEON_RB3D_COLOROFFSET 0x1c40 |
# define RADEON_COLOROFFSET_MASK 0xfffffff0 |
#define RADEON_RB3D_COLORPITCH 0x1c48 |
# define RADEON_COLORPITCH_MASK 0x000001ff8 |
# define RADEON_COLOR_TILE_ENABLE (1 << 16) |
# define RADEON_COLOR_MICROTILE_ENABLE (1 << 17) |
# define RADEON_COLOR_ENDIAN_NO_SWAP (0 << 18) |
# define RADEON_COLOR_ENDIAN_WORD_SWAP (1 << 18) |
# define RADEON_COLOR_ENDIAN_DWORD_SWAP (2 << 18) |
#define RADEON_RB3D_DEPTHOFFSET 0x1c24 |
#define RADEON_RB3D_DEPTHPITCH 0x1c28 |
# define RADEON_DEPTHPITCH_MASK 0x00001ff8 |
# define RADEON_DEPTH_HYPERZ (3 << 16) |
# define RADEON_DEPTH_ENDIAN_NO_SWAP (0 << 18) |
# define RADEON_DEPTH_ENDIAN_WORD_SWAP (1 << 18) |
# define RADEON_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) |
#define RADEON_RB3D_PLANEMASK 0x1d84 |
#define RADEON_RB3D_ROPCNTL 0x1d80 |
# define RADEON_ROP_MASK (15 << 8) |
# define RADEON_ROP_CLEAR (0 << 8) |
# define RADEON_ROP_NOR (1 << 8) |
# define RADEON_ROP_AND_INVERTED (2 << 8) |
# define RADEON_ROP_COPY_INVERTED (3 << 8) |
# define RADEON_ROP_AND_REVERSE (4 << 8) |
# define RADEON_ROP_INVERT (5 << 8) |
# define RADEON_ROP_XOR (6 << 8) |
# define RADEON_ROP_NAND (7 << 8) |
# define RADEON_ROP_AND (8 << 8) |
# define RADEON_ROP_EQUIV (9 << 8) |
# define RADEON_ROP_NOOP (10 << 8) |
# define RADEON_ROP_OR_INVERTED (11 << 8) |
# define RADEON_ROP_COPY (12 << 8) |
# define RADEON_ROP_OR_REVERSE (13 << 8) |
# define RADEON_ROP_OR (14 << 8) |
# define RADEON_ROP_SET (15 << 8) |
#define RADEON_RB3D_STENCILREFMASK 0x1d7c |
# define RADEON_STENCIL_REF_SHIFT 0 |
# define RADEON_STENCIL_REF_MASK (0xff << 0) |
# define RADEON_STENCIL_MASK_SHIFT 16 |
# define RADEON_STENCIL_VALUE_MASK (0xff << 16) |
# define RADEON_STENCIL_WRITEMASK_SHIFT 24 |
# define RADEON_STENCIL_WRITE_MASK (0xff << 24) |
#define RADEON_RB3D_ZPASS_DATA 0x3290 |
#define RADEON_RB3D_ZPASS_ADDR 0x3294 |
#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c |
# define RADEON_DEPTH_FORMAT_MASK (0xf << 0) |
# define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0) |
# define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0) |
# define RADEON_DEPTH_FORMAT_24BIT_FLOAT_Z (3 << 0) |
# define RADEON_DEPTH_FORMAT_32BIT_INT_Z (4 << 0) |
# define RADEON_DEPTH_FORMAT_32BIT_FLOAT_Z (5 << 0) |
# define RADEON_DEPTH_FORMAT_16BIT_FLOAT_W (7 << 0) |
# define RADEON_DEPTH_FORMAT_24BIT_FLOAT_W (9 << 0) |
# define RADEON_DEPTH_FORMAT_32BIT_FLOAT_W (11 << 0) |
# define RADEON_Z_TEST_NEVER (0 << 4) |
# define RADEON_Z_TEST_LESS (1 << 4) |
# define RADEON_Z_TEST_LEQUAL (2 << 4) |
# define RADEON_Z_TEST_EQUAL (3 << 4) |
# define RADEON_Z_TEST_GEQUAL (4 << 4) |
# define RADEON_Z_TEST_GREATER (5 << 4) |
# define RADEON_Z_TEST_NEQUAL (6 << 4) |
# define RADEON_Z_TEST_ALWAYS (7 << 4) |
# define RADEON_Z_TEST_MASK (7 << 4) |
# define RADEON_Z_HIERARCHY_ENABLE (1 << 8) |
# define RADEON_STENCIL_TEST_NEVER (0 << 12) |
# define RADEON_STENCIL_TEST_LESS (1 << 12) |
# define RADEON_STENCIL_TEST_LEQUAL (2 << 12) |
# define RADEON_STENCIL_TEST_EQUAL (3 << 12) |
# define RADEON_STENCIL_TEST_GEQUAL (4 << 12) |
# define RADEON_STENCIL_TEST_GREATER (5 << 12) |
# define RADEON_STENCIL_TEST_NEQUAL (6 << 12) |
# define RADEON_STENCIL_TEST_ALWAYS (7 << 12) |
# define RADEON_STENCIL_TEST_MASK (0x7 << 12) |
# define RADEON_STENCIL_FAIL_KEEP (0 << 16) |
# define RADEON_STENCIL_FAIL_ZERO (1 << 16) |
# define RADEON_STENCIL_FAIL_REPLACE (2 << 16) |
# define RADEON_STENCIL_FAIL_INC (3 << 16) |
# define RADEON_STENCIL_FAIL_DEC (4 << 16) |
# define RADEON_STENCIL_FAIL_INVERT (5 << 16) |
# define RADEON_STENCIL_FAIL_INC_WRAP (6 << 16) |
# define RADEON_STENCIL_FAIL_DEC_WRAP (7 << 16) |
# define RADEON_STENCIL_FAIL_MASK (0x7 << 16) |
# define RADEON_STENCIL_ZPASS_KEEP (0 << 20) |
# define RADEON_STENCIL_ZPASS_ZERO (1 << 20) |
# define RADEON_STENCIL_ZPASS_REPLACE (2 << 20) |
# define RADEON_STENCIL_ZPASS_INC (3 << 20) |
# define RADEON_STENCIL_ZPASS_DEC (4 << 20) |
# define RADEON_STENCIL_ZPASS_INVERT (5 << 20) |
# define RADEON_STENCIL_ZPASS_INC_WRAP (6 << 20) |
# define RADEON_STENCIL_ZPASS_DEC_WRAP (7 << 20) |
# define RADEON_STENCIL_ZPASS_MASK (0x7 << 20) |
# define RADEON_STENCIL_ZFAIL_KEEP (0 << 24) |
# define RADEON_STENCIL_ZFAIL_ZERO (1 << 24) |
# define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24) |
# define RADEON_STENCIL_ZFAIL_INC (3 << 24) |
# define RADEON_STENCIL_ZFAIL_DEC (4 << 24) |
# define RADEON_STENCIL_ZFAIL_INVERT (5 << 24) |
# define RADEON_STENCIL_ZFAIL_INC_WRAP (6 << 24) |
# define RADEON_STENCIL_ZFAIL_DEC_WRAP (7 << 24) |
# define RADEON_STENCIL_ZFAIL_MASK (0x7 << 24) |
# define RADEON_Z_COMPRESSION_ENABLE (1 << 28) |
# define RADEON_FORCE_Z_DIRTY (1 << 29) |
# define RADEON_Z_WRITE_ENABLE (1 << 30) |
# define RADEON_Z_DECOMPRESSION_ENABLE (1 << 31) |
#define RADEON_RE_STIPPLE_ADDR 0x1cc8 |
#define RADEON_RE_STIPPLE_DATA 0x1ccc |
#define RADEON_RE_LINE_PATTERN 0x1cd0 |
# define RADEON_LINE_PATTERN_MASK 0x0000ffff |
# define RADEON_LINE_REPEAT_COUNT_SHIFT 16 |
# define RADEON_LINE_PATTERN_START_SHIFT 24 |
# define RADEON_LINE_PATTERN_LITTLE_BIT_ORDER (0 << 28) |
# define RADEON_LINE_PATTERN_BIG_BIT_ORDER (1 << 28) |
# define RADEON_LINE_PATTERN_AUTO_RESET (1 << 29) |
#define RADEON_RE_LINE_STATE 0x1cd4 |
# define RADEON_LINE_CURRENT_PTR_SHIFT 0 |
# define RADEON_LINE_CURRENT_COUNT_SHIFT 8 |
#define RADEON_RE_MISC 0x26c4 |
# define RADEON_STIPPLE_COORD_MASK 0x1f |
# define RADEON_STIPPLE_X_OFFSET_SHIFT 0 |
# define RADEON_STIPPLE_X_OFFSET_MASK (0x1f << 0) |
# define RADEON_STIPPLE_Y_OFFSET_SHIFT 8 |
# define RADEON_STIPPLE_Y_OFFSET_MASK (0x1f << 8) |
# define RADEON_STIPPLE_LITTLE_BIT_ORDER (0 << 16) |
# define RADEON_STIPPLE_BIG_BIT_ORDER (1 << 16) |
#define RADEON_RE_SOLID_COLOR 0x1c1c |
#define RADEON_RE_TOP_LEFT 0x26c0 |
# define RADEON_RE_LEFT_SHIFT 0 |
# define RADEON_RE_TOP_SHIFT 16 |
#define RADEON_RE_WIDTH_HEIGHT 0x1c44 |
# define RADEON_RE_WIDTH_SHIFT 0 |
# define RADEON_RE_HEIGHT_SHIFT 16 |
#define RADEON_SE_CNTL 0x1c4c |
# define RADEON_FFACE_CULL_CW (0 << 0) |
# define RADEON_FFACE_CULL_CCW (1 << 0) |
# define RADEON_FFACE_CULL_DIR_MASK (1 << 0) |
# define RADEON_BFACE_CULL (0 << 1) |
# define RADEON_BFACE_SOLID (3 << 1) |
# define RADEON_FFACE_CULL (0 << 3) |
# define RADEON_FFACE_SOLID (3 << 3) |
# define RADEON_FFACE_CULL_MASK (3 << 3) |
# define RADEON_BADVTX_CULL_DISABLE (1 << 5) |
# define RADEON_FLAT_SHADE_VTX_0 (0 << 6) |
# define RADEON_FLAT_SHADE_VTX_1 (1 << 6) |
# define RADEON_FLAT_SHADE_VTX_2 (2 << 6) |
# define RADEON_FLAT_SHADE_VTX_LAST (3 << 6) |
# define RADEON_DIFFUSE_SHADE_SOLID (0 << 8) |
# define RADEON_DIFFUSE_SHADE_FLAT (1 << 8) |
# define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8) |
# define RADEON_DIFFUSE_SHADE_MASK (3 << 8) |
# define RADEON_ALPHA_SHADE_SOLID (0 << 10) |
# define RADEON_ALPHA_SHADE_FLAT (1 << 10) |
# define RADEON_ALPHA_SHADE_GOURAUD (2 << 10) |
# define RADEON_ALPHA_SHADE_MASK (3 << 10) |
# define RADEON_SPECULAR_SHADE_SOLID (0 << 12) |
# define RADEON_SPECULAR_SHADE_FLAT (1 << 12) |
# define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12) |
# define RADEON_SPECULAR_SHADE_MASK (3 << 12) |
# define RADEON_FOG_SHADE_SOLID (0 << 14) |
# define RADEON_FOG_SHADE_FLAT (1 << 14) |
# define RADEON_FOG_SHADE_GOURAUD (2 << 14) |
# define RADEON_FOG_SHADE_MASK (3 << 14) |
# define RADEON_ZBIAS_ENABLE_POINT (1 << 16) |
# define RADEON_ZBIAS_ENABLE_LINE (1 << 17) |
# define RADEON_ZBIAS_ENABLE_TRI (1 << 18) |
# define RADEON_WIDELINE_ENABLE (1 << 20) |
# define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24) |
# define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25) |
# define RADEON_VTX_PIX_CENTER_D3D (0 << 27) |
# define RADEON_VTX_PIX_CENTER_OGL (1 << 27) |
# define RADEON_ROUND_MODE_TRUNC (0 << 28) |
# define RADEON_ROUND_MODE_ROUND (1 << 28) |
# define RADEON_ROUND_MODE_ROUND_EVEN (2 << 28) |
# define RADEON_ROUND_MODE_ROUND_ODD (3 << 28) |
# define RADEON_ROUND_PREC_16TH_PIX (0 << 30) |
# define RADEON_ROUND_PREC_8TH_PIX (1 << 30) |
# define RADEON_ROUND_PREC_4TH_PIX (2 << 30) |
# define RADEON_ROUND_PREC_HALF_PIX (3 << 30) |
#define RADEON_SE_CNTL_STATUS 0x2140 |
# define RADEON_VC_NO_SWAP (0 << 0) |
# define RADEON_VC_16BIT_SWAP (1 << 0) |
# define RADEON_VC_32BIT_SWAP (2 << 0) |
# define RADEON_VC_HALF_DWORD_SWAP (3 << 0) |
# define RADEON_TCL_BYPASS (1 << 8) |
#define RADEON_SE_COORD_FMT 0x1c50 |
# define RADEON_VTX_XY_PRE_MULT_1_OVER_W0 (1 << 0) |
# define RADEON_VTX_Z_PRE_MULT_1_OVER_W0 (1 << 1) |
# define RADEON_VTX_ST0_NONPARAMETRIC (1 << 8) |
# define RADEON_VTX_ST1_NONPARAMETRIC (1 << 9) |
# define RADEON_VTX_ST2_NONPARAMETRIC (1 << 10) |
# define RADEON_VTX_ST3_NONPARAMETRIC (1 << 11) |
# define RADEON_VTX_W0_NORMALIZE (1 << 12) |
# define RADEON_VTX_W0_IS_NOT_1_OVER_W0 (1 << 16) |
# define RADEON_VTX_ST0_PRE_MULT_1_OVER_W0 (1 << 17) |
# define RADEON_VTX_ST1_PRE_MULT_1_OVER_W0 (1 << 19) |
# define RADEON_VTX_ST2_PRE_MULT_1_OVER_W0 (1 << 21) |
# define RADEON_VTX_ST3_PRE_MULT_1_OVER_W0 (1 << 23) |
# define RADEON_TEX1_W_ROUTING_USE_W0 (0 << 26) |
# define RADEON_TEX1_W_ROUTING_USE_Q1 (1 << 26) |
#define RADEON_SE_LINE_WIDTH 0x1db8 |
#define RADEON_SE_TCL_LIGHT_MODEL_CTL 0x226c |
# define RADEON_LIGHTING_ENABLE (1 << 0) |
# define RADEON_LIGHT_IN_MODELSPACE (1 << 1) |
# define RADEON_LOCAL_VIEWER (1 << 2) |
# define RADEON_NORMALIZE_NORMALS (1 << 3) |
# define RADEON_RESCALE_NORMALS (1 << 4) |
# define RADEON_SPECULAR_LIGHTS (1 << 5) |
# define RADEON_DIFFUSE_SPECULAR_COMBINE (1 << 6) |
# define RADEON_LIGHT_ALPHA (1 << 7) |
# define RADEON_LOCAL_LIGHT_VEC_GL (1 << 8) |
# define RADEON_LIGHT_NO_NORMAL_AMBIENT_ONLY (1 << 9) |
# define RADEON_LM_SOURCE_STATE_PREMULT 0 |
# define RADEON_LM_SOURCE_STATE_MULT 1 |
# define RADEON_LM_SOURCE_VERTEX_DIFFUSE 2 |
# define RADEON_LM_SOURCE_VERTEX_SPECULAR 3 |
# define RADEON_EMISSIVE_SOURCE_SHIFT 16 |
# define RADEON_AMBIENT_SOURCE_SHIFT 18 |
# define RADEON_DIFFUSE_SOURCE_SHIFT 20 |
# define RADEON_SPECULAR_SOURCE_SHIFT 22 |
#define RADEON_SE_TCL_MATERIAL_AMBIENT_RED 0x2220 |
#define RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN 0x2224 |
#define RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE 0x2228 |
#define RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA 0x222c |
#define RADEON_SE_TCL_MATERIAL_DIFFUSE_RED 0x2230 |
#define RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN 0x2234 |
#define RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE 0x2238 |
#define RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA 0x223c |
#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210 |
#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN 0x2214 |
#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE 0x2218 |
#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA 0x221c |
#define RADEON_SE_TCL_MATERIAL_SPECULAR_RED 0x2240 |
#define RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN 0x2244 |
#define RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE 0x2248 |
#define RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA 0x224c |
#define RADEON_SE_TCL_MATRIX_SELECT_0 0x225c |
# define RADEON_MODELVIEW_0_SHIFT 0 |
# define RADEON_MODELVIEW_1_SHIFT 4 |
# define RADEON_MODELVIEW_2_SHIFT 8 |
# define RADEON_MODELVIEW_3_SHIFT 12 |
# define RADEON_IT_MODELVIEW_0_SHIFT 16 |
# define RADEON_IT_MODELVIEW_1_SHIFT 20 |
# define RADEON_IT_MODELVIEW_2_SHIFT 24 |
# define RADEON_IT_MODELVIEW_3_SHIFT 28 |
#define RADEON_SE_TCL_MATRIX_SELECT_1 0x2260 |
# define RADEON_MODELPROJECT_0_SHIFT 0 |
# define RADEON_MODELPROJECT_1_SHIFT 4 |
# define RADEON_MODELPROJECT_2_SHIFT 8 |
# define RADEON_MODELPROJECT_3_SHIFT 12 |
# define RADEON_TEXMAT_0_SHIFT 16 |
# define RADEON_TEXMAT_1_SHIFT 20 |
# define RADEON_TEXMAT_2_SHIFT 24 |
# define RADEON_TEXMAT_3_SHIFT 28 |
#define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254 |
# define RADEON_TCL_VTX_W0 (1 << 0) |
# define RADEON_TCL_VTX_FP_DIFFUSE (1 << 1) |
# define RADEON_TCL_VTX_FP_ALPHA (1 << 2) |
# define RADEON_TCL_VTX_PK_DIFFUSE (1 << 3) |
# define RADEON_TCL_VTX_FP_SPEC (1 << 4) |
# define RADEON_TCL_VTX_FP_FOG (1 << 5) |
# define RADEON_TCL_VTX_PK_SPEC (1 << 6) |
# define RADEON_TCL_VTX_ST0 (1 << 7) |
# define RADEON_TCL_VTX_ST1 (1 << 8) |
# define RADEON_TCL_VTX_Q1 (1 << 9) |
# define RADEON_TCL_VTX_ST2 (1 << 10) |
# define RADEON_TCL_VTX_Q2 (1 << 11) |
# define RADEON_TCL_VTX_ST3 (1 << 12) |
# define RADEON_TCL_VTX_Q3 (1 << 13) |
# define RADEON_TCL_VTX_Q0 (1 << 14) |
# define RADEON_TCL_VTX_WEIGHT_COUNT_SHIFT 15 |
# define RADEON_TCL_VTX_NORM0 (1 << 18) |
# define RADEON_TCL_VTX_XY1 (1 << 27) |
# define RADEON_TCL_VTX_Z1 (1 << 28) |
# define RADEON_TCL_VTX_W1 (1 << 29) |
# define RADEON_TCL_VTX_NORM1 (1 << 30) |
# define RADEON_TCL_VTX_Z0 (1 << 31) |
#define RADEON_SE_TCL_OUTPUT_VTX_SEL 0x2258 |
# define RADEON_TCL_COMPUTE_XYZW (1 << 0) |
# define RADEON_TCL_COMPUTE_DIFFUSE (1 << 1) |
# define RADEON_TCL_COMPUTE_SPECULAR (1 << 2) |
# define RADEON_TCL_FORCE_NAN_IF_COLOR_NAN (1 << 3) |
# define RADEON_TCL_FORCE_INORDER_PROC (1 << 4) |
# define RADEON_TCL_TEX_INPUT_TEX_0 0 |
# define RADEON_TCL_TEX_INPUT_TEX_1 1 |
# define RADEON_TCL_TEX_INPUT_TEX_2 2 |
# define RADEON_TCL_TEX_INPUT_TEX_3 3 |
# define RADEON_TCL_TEX_COMPUTED_TEX_0 8 |
# define RADEON_TCL_TEX_COMPUTED_TEX_1 9 |
# define RADEON_TCL_TEX_COMPUTED_TEX_2 10 |
# define RADEON_TCL_TEX_COMPUTED_TEX_3 11 |
# define RADEON_TCL_TEX_0_OUTPUT_SHIFT 16 |
# define RADEON_TCL_TEX_1_OUTPUT_SHIFT 20 |
# define RADEON_TCL_TEX_2_OUTPUT_SHIFT 24 |
# define RADEON_TCL_TEX_3_OUTPUT_SHIFT 28 |
#define RADEON_SE_TCL_PER_LIGHT_CTL_0 0x2270 |
# define RADEON_LIGHT_0_ENABLE (1 << 0) |
# define RADEON_LIGHT_0_ENABLE_AMBIENT (1 << 1) |
# define RADEON_LIGHT_0_ENABLE_SPECULAR (1 << 2) |
# define RADEON_LIGHT_0_IS_LOCAL (1 << 3) |
# define RADEON_LIGHT_0_IS_SPOT (1 << 4) |
# define RADEON_LIGHT_0_DUAL_CONE (1 << 5) |
# define RADEON_LIGHT_0_ENABLE_RANGE_ATTEN (1 << 6) |
# define RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN (1 << 7) |
# define RADEON_LIGHT_0_SHIFT 0 |
# define RADEON_LIGHT_1_ENABLE (1 << 16) |
# define RADEON_LIGHT_1_ENABLE_AMBIENT (1 << 17) |
# define RADEON_LIGHT_1_ENABLE_SPECULAR (1 << 18) |
# define RADEON_LIGHT_1_IS_LOCAL (1 << 19) |
# define RADEON_LIGHT_1_IS_SPOT (1 << 20) |
# define RADEON_LIGHT_1_DUAL_CONE (1 << 21) |
# define RADEON_LIGHT_1_ENABLE_RANGE_ATTEN (1 << 22) |
# define RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN (1 << 23) |
# define RADEON_LIGHT_1_SHIFT 16 |
#define RADEON_SE_TCL_PER_LIGHT_CTL_1 0x2274 |
# define RADEON_LIGHT_2_SHIFT 0 |
# define RADEON_LIGHT_3_SHIFT 16 |
#define RADEON_SE_TCL_PER_LIGHT_CTL_2 0x2278 |
# define RADEON_LIGHT_4_SHIFT 0 |
# define RADEON_LIGHT_5_SHIFT 16 |
#define RADEON_SE_TCL_PER_LIGHT_CTL_3 0x227c |
# define RADEON_LIGHT_6_SHIFT 0 |
# define RADEON_LIGHT_7_SHIFT 16 |
#define RADEON_SE_TCL_STATE_FLUSH 0x2284 |
#define RADEON_SE_TCL_SHININESS 0x2250 |
#define RADEON_SE_TCL_TEXTURE_PROC_CTL 0x2268 |
# define RADEON_TEXGEN_TEXMAT_0_ENABLE (1 << 0) |
# define RADEON_TEXGEN_TEXMAT_1_ENABLE (1 << 1) |
# define RADEON_TEXGEN_TEXMAT_2_ENABLE (1 << 2) |
# define RADEON_TEXGEN_TEXMAT_3_ENABLE (1 << 3) |
# define RADEON_TEXMAT_0_ENABLE (1 << 4) |
# define RADEON_TEXMAT_1_ENABLE (1 << 5) |
# define RADEON_TEXMAT_2_ENABLE (1 << 6) |
# define RADEON_TEXMAT_3_ENABLE (1 << 7) |
# define RADEON_TEXGEN_INPUT_MASK 0xf |
# define RADEON_TEXGEN_INPUT_TEXCOORD_0 0 |
# define RADEON_TEXGEN_INPUT_TEXCOORD_1 1 |
# define RADEON_TEXGEN_INPUT_TEXCOORD_2 2 |
# define RADEON_TEXGEN_INPUT_TEXCOORD_3 3 |
# define RADEON_TEXGEN_INPUT_OBJ 4 |
# define RADEON_TEXGEN_INPUT_EYE 5 |
# define RADEON_TEXGEN_INPUT_EYE_NORMAL 6 |
# define RADEON_TEXGEN_INPUT_EYE_REFLECT 7 |
# define RADEON_TEXGEN_INPUT_EYE_NORMALIZED 8 |
# define RADEON_TEXGEN_0_INPUT_SHIFT 16 |
# define RADEON_TEXGEN_1_INPUT_SHIFT 20 |
# define RADEON_TEXGEN_2_INPUT_SHIFT 24 |
# define RADEON_TEXGEN_3_INPUT_SHIFT 28 |
#define RADEON_SE_TCL_UCP_VERT_BLEND_CTL 0x2264 |
# define RADEON_UCP_IN_CLIP_SPACE (1 << 0) |
# define RADEON_UCP_IN_MODEL_SPACE (1 << 1) |
# define RADEON_UCP_ENABLE_0 (1 << 2) |
# define RADEON_UCP_ENABLE_1 (1 << 3) |
# define RADEON_UCP_ENABLE_2 (1 << 4) |
# define RADEON_UCP_ENABLE_3 (1 << 5) |
# define RADEON_UCP_ENABLE_4 (1 << 6) |
# define RADEON_UCP_ENABLE_5 (1 << 7) |
# define RADEON_TCL_FOG_MASK (3 << 8) |
# define RADEON_TCL_FOG_DISABLE (0 << 8) |
# define RADEON_TCL_FOG_EXP (1 << 8) |
# define RADEON_TCL_FOG_EXP2 (2 << 8) |
# define RADEON_TCL_FOG_LINEAR (3 << 8) |
# define RADEON_RNG_BASED_FOG (1 << 10) |
# define RADEON_LIGHT_TWOSIDE (1 << 11) |
# define RADEON_BLEND_OP_COUNT_MASK (7 << 12) |
# define RADEON_BLEND_OP_COUNT_SHIFT 12 |
# define RADEON_POSITION_BLEND_OP_ENABLE (1 << 16) |
# define RADEON_NORMAL_BLEND_OP_ENABLE (1 << 17) |
# define RADEON_VERTEX_BLEND_SRC_0_PRIMARY (0 << 18) |
# define RADEON_VERTEX_BLEND_SRC_0_SECONDARY (1 << 18) |
# define RADEON_VERTEX_BLEND_SRC_1_PRIMARY (0 << 19) |
# define RADEON_VERTEX_BLEND_SRC_1_SECONDARY (1 << 19) |
# define RADEON_VERTEX_BLEND_SRC_2_PRIMARY (0 << 20) |
# define RADEON_VERTEX_BLEND_SRC_2_SECONDARY (1 << 20) |
# define RADEON_VERTEX_BLEND_SRC_3_PRIMARY (0 << 21) |
# define RADEON_VERTEX_BLEND_SRC_3_SECONDARY (1 << 21) |
# define RADEON_VERTEX_BLEND_WGT_MINUS_ONE (1 << 22) |
# define RADEON_CULL_FRONT_IS_CW (0 << 28) |
# define RADEON_CULL_FRONT_IS_CCW (1 << 28) |
# define RADEON_CULL_FRONT (1 << 29) |
# define RADEON_CULL_BACK (1 << 30) |
# define RADEON_FORCE_W_TO_ONE (1 << 31) |
#define RADEON_SE_VPORT_XSCALE 0x1d98 |
#define RADEON_SE_VPORT_XOFFSET 0x1d9c |
#define RADEON_SE_VPORT_YSCALE 0x1da0 |
#define RADEON_SE_VPORT_YOFFSET 0x1da4 |
#define RADEON_SE_VPORT_ZSCALE 0x1da8 |
#define RADEON_SE_VPORT_ZOFFSET 0x1dac |
#define RADEON_SE_ZBIAS_FACTOR 0x1db0 |
#define RADEON_SE_ZBIAS_CONSTANT 0x1db4 |
#define RADEON_SE_VTX_FMT 0x2080 |
# define RADEON_SE_VTX_FMT_XY 0x00000000 |
# define RADEON_SE_VTX_FMT_W0 0x00000001 |
# define RADEON_SE_VTX_FMT_FPCOLOR 0x00000002 |
# define RADEON_SE_VTX_FMT_FPALPHA 0x00000004 |
# define RADEON_SE_VTX_FMT_PKCOLOR 0x00000008 |
# define RADEON_SE_VTX_FMT_FPSPEC 0x00000010 |
# define RADEON_SE_VTX_FMT_FPFOG 0x00000020 |
# define RADEON_SE_VTX_FMT_PKSPEC 0x00000040 |
# define RADEON_SE_VTX_FMT_ST0 0x00000080 |
# define RADEON_SE_VTX_FMT_ST1 0x00000100 |
# define RADEON_SE_VTX_FMT_Q1 0x00000200 |
# define RADEON_SE_VTX_FMT_ST2 0x00000400 |
# define RADEON_SE_VTX_FMT_Q2 0x00000800 |
# define RADEON_SE_VTX_FMT_ST3 0x00001000 |
# define RADEON_SE_VTX_FMT_Q3 0x00002000 |
# define RADEON_SE_VTX_FMT_Q0 0x00004000 |
# define RADEON_SE_VTX_FMT_BLND_WEIGHT_CNT_MASK 0x00038000 |
# define RADEON_SE_VTX_FMT_N0 0x00040000 |
# define RADEON_SE_VTX_FMT_XY1 0x08000000 |
# define RADEON_SE_VTX_FMT_Z1 0x10000000 |
# define RADEON_SE_VTX_FMT_W1 0x20000000 |
# define RADEON_SE_VTX_FMT_N1 0x40000000 |
# define RADEON_SE_VTX_FMT_Z 0x80000000 |
/* Registers for CP and Microcode Engine */ |
#define RADEON_CP_ME_RAM_ADDR 0x07d4 |
#define RADEON_CP_ME_RAM_RADDR 0x07d8 |
#define RADEON_CP_ME_RAM_DATAH 0x07dc |
#define RADEON_CP_ME_RAM_DATAL 0x07e0 |
#define RADEON_CP_RB_BASE 0x0700 |
#define RADEON_CP_RB_CNTL 0x0704 |
#define RADEON_CP_RB_RPTR_ADDR 0x070c |
#define RADEON_CP_RB_RPTR 0x0710 |
#define RADEON_CP_RB_WPTR 0x0714 |
#define RADEON_CP_IB_BASE 0x0738 |
#define RADEON_CP_IB_BUFSZ 0x073c |
#define RADEON_CP_CSQ_CNTL 0x0740 |
# define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0) |
# define RADEON_CSQ_PRIDIS_INDDIS (0 << 28) |
# define RADEON_CSQ_PRIPIO_INDDIS (1 << 28) |
# define RADEON_CSQ_PRIBM_INDDIS (2 << 28) |
# define RADEON_CSQ_PRIPIO_INDBM (3 << 28) |
# define RADEON_CSQ_PRIBM_INDBM (4 << 28) |
# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) |
#define RADEON_CP_CSQ_STAT 0x07f8 |
# define RADEON_CSQ_RPTR_PRIMARY_MASK (0xff << 0) |
# define RADEON_CSQ_WPTR_PRIMARY_MASK (0xff << 8) |
# define RADEON_CSQ_RPTR_INDIRECT_MASK (0xff << 16) |
# define RADEON_CSQ_WPTR_INDIRECT_MASK (0xff << 24) |
#define RADEON_CP_CSQ_ADDR 0x07f0 |
#define RADEON_CP_CSQ_DATA 0x07f4 |
#define RADEON_CP_CSQ_APER_PRIMARY 0x1000 |
#define RADEON_CP_CSQ_APER_INDIRECT 0x1300 |
#define RADEON_CP_RB_WPTR_DELAY 0x0718 |
# define RADEON_PRE_WRITE_TIMER_SHIFT 0 |
# define RADEON_PRE_WRITE_LIMIT_SHIFT 23 |
#define RADEON_AIC_CNTL 0x01d0 |
# define RADEON_PCIGART_TRANSLATE_EN (1 << 0) |
#define RADEON_AIC_LO_ADDR 0x01dc |
/* Constants */ |
#define RADEON_LAST_FRAME_REG RADEON_GUI_SCRATCH_REG0 |
#define RADEON_LAST_CLEAR_REG RADEON_GUI_SCRATCH_REG2 |
/* CP packet types */ |
#define RADEON_CP_PACKET0 0x00000000 |
#define RADEON_CP_PACKET1 0x40000000 |
#define RADEON_CP_PACKET2 0x80000000 |
#define RADEON_CP_PACKET3 0xC0000000 |
# define RADEON_CP_PACKET_MASK 0xC0000000 |
# define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000 |
# define RADEON_CP_PACKET_MAX_DWORDS (1 << 12) |
# define RADEON_CP_PACKET0_REG_MASK 0x000007ff |
# define RADEON_CP_PACKET1_REG0_MASK 0x000007ff |
# define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 |
#define RADEON_CP_PACKET0_ONE_REG_WR 0x00008000 |
#define RADEON_CP_PACKET3_NOP 0xC0001000 |
#define RADEON_CP_PACKET3_NEXT_CHAR 0xC0001900 |
#define RADEON_CP_PACKET3_PLY_NEXTSCAN 0xC0001D00 |
#define RADEON_CP_PACKET3_SET_SCISSORS 0xC0001E00 |
#define RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300 |
#define RADEON_CP_PACKET3_LOAD_MICROCODE 0xC0002400 |
#define RADEON_CP_PACKET3_WAIT_FOR_IDLE 0xC0002600 |
#define RADEON_CP_PACKET3_3D_DRAW_VBUF 0xC0002800 |
#define RADEON_CP_PACKET3_3D_DRAW_IMMD 0xC0002900 |
#define RADEON_CP_PACKET3_3D_DRAW_INDX 0xC0002A00 |
#define RADEON_CP_PACKET3_LOAD_PALETTE 0xC0002C00 |
#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00 |
#define R200_CP_CMD_3D_DRAW_VBUF_2 0xC0003400 |
#define R200_CP_CMD_3D_DRAW_IMMD_2 0xC0003500 |
#define R200_CP_CMD_3D_DRAW_INDX_2 0xC0003600 |
#define RADEON_CP_PACKET3_CNTL_PAINT 0xC0009100 |
#define RADEON_CP_PACKET3_CNTL_BITBLT 0xC0009200 |
#define RADEON_CP_PACKET3_CNTL_SMALLTEXT 0xC0009300 |
#define RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400 |
#define RADEON_CP_PACKET3_CNTL_POLYLINE 0xC0009500 |
#define RADEON_CP_PACKET3_CNTL_POLYSCANLINES 0xC0009800 |
#define RADEON_CP_PACKET3_CNTL_PAINT_MULTI 0xC0009A00 |
#define RADEON_CP_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00 |
#define RADEON_CP_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00 |
#define RADEON_CP_VC_FRMT_XY 0x00000000 |
#define RADEON_CP_VC_FRMT_W0 0x00000001 |
#define RADEON_CP_VC_FRMT_FPCOLOR 0x00000002 |
#define RADEON_CP_VC_FRMT_FPALPHA 0x00000004 |
#define RADEON_CP_VC_FRMT_PKCOLOR 0x00000008 |
#define RADEON_CP_VC_FRMT_FPSPEC 0x00000010 |
#define RADEON_CP_VC_FRMT_FPFOG 0x00000020 |
#define RADEON_CP_VC_FRMT_PKSPEC 0x00000040 |
#define RADEON_CP_VC_FRMT_ST0 0x00000080 |
#define RADEON_CP_VC_FRMT_ST1 0x00000100 |
#define RADEON_CP_VC_FRMT_Q1 0x00000200 |
#define RADEON_CP_VC_FRMT_ST2 0x00000400 |
#define RADEON_CP_VC_FRMT_Q2 0x00000800 |
#define RADEON_CP_VC_FRMT_ST3 0x00001000 |
#define RADEON_CP_VC_FRMT_Q3 0x00002000 |
#define RADEON_CP_VC_FRMT_Q0 0x00004000 |
#define RADEON_CP_VC_FRMT_BLND_WEIGHT_CNT_MASK 0x00038000 |
#define RADEON_CP_VC_FRMT_N0 0x00040000 |
#define RADEON_CP_VC_FRMT_XY1 0x08000000 |
#define RADEON_CP_VC_FRMT_Z1 0x10000000 |
#define RADEON_CP_VC_FRMT_W1 0x20000000 |
#define RADEON_CP_VC_FRMT_N1 0x40000000 |
#define RADEON_CP_VC_FRMT_Z 0x80000000 |
#define RADEON_CP_VC_CNTL_PRIM_TYPE_NONE 0x00000000 |
#define RADEON_CP_VC_CNTL_PRIM_TYPE_POINT 0x00000001 |
#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE 0x00000002 |
#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP 0x00000003 |
#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004 |
#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005 |
#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006 |
#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_TYPE_2 0x00000007 |
#define RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST 0x00000008 |
#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST 0x00000009 |
#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST 0x0000000a |
#define RADEON_CP_VC_CNTL_PRIM_WALK_IND 0x00000010 |
#define RADEON_CP_VC_CNTL_PRIM_WALK_LIST 0x00000020 |
#define RADEON_CP_VC_CNTL_PRIM_WALK_RING 0x00000030 |
#define RADEON_CP_VC_CNTL_COLOR_ORDER_BGRA 0x00000000 |
#define RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA 0x00000040 |
#define RADEON_CP_VC_CNTL_MAOS_ENABLE 0x00000080 |
#define RADEON_CP_VC_CNTL_VTX_FMT_NON_RADEON_MODE 0x00000000 |
#define RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE 0x00000100 |
#define RADEON_CP_VC_CNTL_TCL_DISABLE 0x00000000 |
#define RADEON_CP_VC_CNTL_TCL_ENABLE 0x00000200 |
#define RADEON_CP_VC_CNTL_NUM_SHIFT 16 |
#define RADEON_VS_MATRIX_0_ADDR 0 |
#define RADEON_VS_MATRIX_1_ADDR 4 |
#define RADEON_VS_MATRIX_2_ADDR 8 |
#define RADEON_VS_MATRIX_3_ADDR 12 |
#define RADEON_VS_MATRIX_4_ADDR 16 |
#define RADEON_VS_MATRIX_5_ADDR 20 |
#define RADEON_VS_MATRIX_6_ADDR 24 |
#define RADEON_VS_MATRIX_7_ADDR 28 |
#define RADEON_VS_MATRIX_8_ADDR 32 |
#define RADEON_VS_MATRIX_9_ADDR 36 |
#define RADEON_VS_MATRIX_10_ADDR 40 |
#define RADEON_VS_MATRIX_11_ADDR 44 |
#define RADEON_VS_MATRIX_12_ADDR 48 |
#define RADEON_VS_MATRIX_13_ADDR 52 |
#define RADEON_VS_MATRIX_14_ADDR 56 |
#define RADEON_VS_MATRIX_15_ADDR 60 |
#define RADEON_VS_LIGHT_AMBIENT_ADDR 64 |
#define RADEON_VS_LIGHT_DIFFUSE_ADDR 72 |
#define RADEON_VS_LIGHT_SPECULAR_ADDR 80 |
#define RADEON_VS_LIGHT_DIRPOS_ADDR 88 |
#define RADEON_VS_LIGHT_HWVSPOT_ADDR 96 |
#define RADEON_VS_LIGHT_ATTENUATION_ADDR 104 |
#define RADEON_VS_MATRIX_EYE2CLIP_ADDR 112 |
#define RADEON_VS_UCP_ADDR 116 |
#define RADEON_VS_GLOBAL_AMBIENT_ADDR 122 |
#define RADEON_VS_FOG_PARAM_ADDR 123 |
#define RADEON_VS_EYE_VECTOR_ADDR 124 |
#define RADEON_SS_LIGHT_DCD_ADDR 0 |
#define RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR 8 |
#define RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR 16 |
#define RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR 24 |
#define RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR 32 |
#define RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR 48 |
#define RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR 49 |
#define RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR 50 |
#define RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR 51 |
#define RADEON_SS_SHININESS 60 |
#define RADEON_TV_MASTER_CNTL 0x0800 |
# define RADEON_TVCLK_ALWAYS_ONb (1 << 30) |
#define RADEON_TV_DAC_CNTL 0x088c |
# define RADEON_TV_DAC_CMPOUT (1 << 5) |
#define RADEON_TV_PRE_DAC_MUX_CNTL 0x0888 |
# define RADEON_Y_RED_EN (1 << 0) |
# define RADEON_C_GRN_EN (1 << 1) |
# define RADEON_CMP_BLU_EN (1 << 2) |
# define RADEON_RED_MX_FORCE_DAC_DATA (6 << 4) |
# define RADEON_GRN_MX_FORCE_DAC_DATA (6 << 8) |
# define RADEON_BLU_MX_FORCE_DAC_DATA (6 << 12) |
# define RADEON_TV_FORCE_DAC_DATA_SHIFT 16 |
#endif |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/swrast/Makefile.am |
---|
0,0 → 1,53 |
# Copyright © 2012 Matt Turner <mattst88@gmail.com> |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
# copy of this software and associated documentation files (the "Software"), |
# to deal in the Software without restriction, including without limitation |
# the rights to use, copy, modify, merge, publish, distribute, sublicense, |
# and/or sell copies of the Software, and to permit persons to whom the |
# Software is furnished to do so, subject to the following conditions: |
# |
# The above copyright notice and this permission notice (including the next |
# paragraph) shall be included in all copies or substantial portions of the |
# Software. |
# |
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
# IN THE SOFTWARE. |
include Makefile.sources |
AM_CFLAGS = \ |
-D__NOT_HAVE_DRM_H \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
-I$(top_srcdir)/src/mesa/drivers/dri/common \ |
$(DEFINES) \ |
$(VISIBILITY_CFLAGS) |
dridir = $(DRI_DRIVER_INSTALL_DIR) |
if HAVE_SWRAST_DRI |
dri_LTLIBRARIES = swrast_dri.la |
endif |
swrast_dri_la_SOURCES = \ |
$(SWRAST_C_FILES) |
swrast_dri_la_LDFLAGS = -module -avoid-version -shared |
swrast_dri_la_LIBADD = \ |
$(DRI_LIB_DEPS) |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
all-local: swrast_dri.la |
$(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
ln -f .libs/swrast_dri.so $(top_builddir)/$(LIB_DIR)/swrast_dri.so; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/swrast/Makefile.in |
---|
0,0 → 1,879 |
# 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 Matt Turner <mattst88@gmail.com> |
# |
# Permission is hereby granted, free of charge, to any person obtaining a |
# copy of this software and associated documentation files (the "Software"), |
# to deal in the Software without restriction, including without limitation |
# the rights to use, copy, modify, merge, publish, distribute, 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 = $(srcdir)/Makefile.sources $(srcdir)/Makefile.in \ |
$(srcdir)/Makefile.am $(top_srcdir)/bin/depcomp |
subdir = src/mesa/drivers/dri/swrast |
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 = |
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; |
am__vpath_adj = case $$p in \ |
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ |
*) f=$$p;; \ |
esac; |
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; |
am__install_max = 40 |
am__nobase_strip_setup = \ |
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` |
am__nobase_strip = \ |
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" |
am__nobase_list = $(am__nobase_strip_setup); \ |
for p in $$list; do echo "$$p $$p"; done | \ |
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ |
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ |
if (++n[$$2] == $(am__install_max)) \ |
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ |
END { for (dir in files) print dir, files[dir] }' |
am__base_list = \ |
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ |
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' |
am__uninstall_files_from_dir = { \ |
test -z "$$files" \ |
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ |
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \ |
$(am__cd) "$$dir" && rm -f $$files; }; \ |
} |
am__installdirs = "$(DESTDIR)$(dridir)" |
LTLIBRARIES = $(dri_LTLIBRARIES) |
am__DEPENDENCIES_1 = |
swrast_dri_la_DEPENDENCIES = $(am__DEPENDENCIES_1) |
am__objects_1 = utils.lo drisw_util.lo |
am__objects_2 = swrast.lo |
am__objects_3 = $(am__objects_1) $(am__objects_2) |
am_swrast_dri_la_OBJECTS = $(am__objects_3) |
swrast_dri_la_OBJECTS = $(am_swrast_dri_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 = |
swrast_dri_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ |
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ |
$(swrast_dri_la_LDFLAGS) $(LDFLAGS) -o $@ |
@HAVE_SWRAST_DRI_TRUE@am_swrast_dri_la_rpath = -rpath $(dridir) |
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 = $(swrast_dri_la_SOURCES) |
DIST_SOURCES = $(swrast_dri_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@ |
SWRAST_DRIVER_FILES = \ |
swrast.c |
SWRAST_COMMON_FILES = \ |
../common/utils.c \ |
../common/drisw_util.c |
SWRAST_C_FILES = \ |
$(SWRAST_COMMON_FILES) \ |
$(SWRAST_DRIVER_FILES) |
AM_CFLAGS = \ |
-D__NOT_HAVE_DRM_H \ |
-I$(top_srcdir)/include \ |
-I$(top_srcdir)/src/ \ |
-I$(top_srcdir)/src/mapi \ |
-I$(top_srcdir)/src/mesa/ \ |
-I$(top_srcdir)/src/mesa/drivers/dri/common \ |
$(DEFINES) \ |
$(VISIBILITY_CFLAGS) |
dridir = $(DRI_DRIVER_INSTALL_DIR) |
@HAVE_SWRAST_DRI_TRUE@dri_LTLIBRARIES = swrast_dri.la |
swrast_dri_la_SOURCES = \ |
$(SWRAST_C_FILES) |
swrast_dri_la_LDFLAGS = -module -avoid-version -shared |
swrast_dri_la_LIBADD = \ |
$(DRI_LIB_DEPS) |
all: all-am |
.SUFFIXES: |
.SUFFIXES: .c .lo .o .obj |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/Makefile.sources $(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/mesa/drivers/dri/swrast/Makefile'; \ |
$(am__cd) $(top_srcdir) && \ |
$(AUTOMAKE) --foreign src/mesa/drivers/dri/swrast/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; |
$(srcdir)/Makefile.sources: |
$(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): |
install-driLTLIBRARIES: $(dri_LTLIBRARIES) |
@$(NORMAL_INSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
list2=; for p in $$list; do \ |
if test -f $$p; then \ |
list2="$$list2 $$p"; \ |
else :; fi; \ |
done; \ |
test -z "$$list2" || { \ |
echo " $(MKDIR_P) '$(DESTDIR)$(dridir)'"; \ |
$(MKDIR_P) "$(DESTDIR)$(dridir)" || exit 1; \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(dridir)'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(dridir)"; \ |
} |
uninstall-driLTLIBRARIES: |
@$(NORMAL_UNINSTALL) |
@list='$(dri_LTLIBRARIES)'; test -n "$(dridir)" || list=; \ |
for p in $$list; do \ |
$(am__strip_dir) \ |
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(dridir)/$$f'"; \ |
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(dridir)/$$f"; \ |
done |
clean-driLTLIBRARIES: |
-test -z "$(dri_LTLIBRARIES)" || rm -f $(dri_LTLIBRARIES) |
@list='$(dri_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}; \ |
} |
swrast_dri.la: $(swrast_dri_la_OBJECTS) $(swrast_dri_la_DEPENDENCIES) $(EXTRA_swrast_dri_la_DEPENDENCIES) |
$(AM_V_CCLD)$(swrast_dri_la_LINK) $(am_swrast_dri_la_rpath) $(swrast_dri_la_OBJECTS) $(swrast_dri_la_LIBADD) $(LIBS) |
mostlyclean-compile: |
-rm -f *.$(OBJEXT) |
distclean-compile: |
-rm -f *.tab.c |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drisw_util.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swrast.Plo@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.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 $@ $< |
utils.lo: ../common/utils.c |
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utils.lo -MD -MP -MF $(DEPDIR)/utils.Tpo -c -o utils.lo `test -f '../common/utils.c' || echo '$(srcdir)/'`../common/utils.c |
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/utils.Tpo $(DEPDIR)/utils.Plo |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../common/utils.c' object='utils.lo' libtool=yes @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utils.lo `test -f '../common/utils.c' || echo '$(srcdir)/'`../common/utils.c |
drisw_util.lo: ../common/drisw_util.c |
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT drisw_util.lo -MD -MP -MF $(DEPDIR)/drisw_util.Tpo -c -o drisw_util.lo `test -f '../common/drisw_util.c' || echo '$(srcdir)/'`../common/drisw_util.c |
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/drisw_util.Tpo $(DEPDIR)/drisw_util.Plo |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../common/drisw_util.c' object='drisw_util.lo' libtool=yes @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o drisw_util.lo `test -f '../common/drisw_util.c' || echo '$(srcdir)/'`../common/drisw_util.c |
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) all-local |
installdirs: |
for dir in "$(DESTDIR)$(dridir)"; do \ |
test -z "$$dir" || $(MKDIR_P) "$$dir"; \ |
done |
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-driLTLIBRARIES clean-generic clean-libtool \ |
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-driLTLIBRARIES |
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: uninstall-driLTLIBRARIES |
.MAKE: install-am install-strip |
.PHONY: CTAGS GTAGS TAGS all all-am all-local check check-am clean \ |
clean-driLTLIBRARIES clean-generic clean-libtool 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-driLTLIBRARIES 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 \ |
uninstall-driLTLIBRARIES |
# Provide compatibility with scripts for the old Mesa build system for |
# a while by putting a link to the driver into /lib of the build tree. |
all-local: swrast_dri.la |
$(MKDIR_P) $(top_builddir)/$(LIB_DIR); |
ln -f .libs/swrast_dri.so $(top_builddir)/$(LIB_DIR)/swrast_dri.so; |
# 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/src/mesa/drivers/dri/swrast/Makefile.sources |
---|
0,0 → 1,10 |
SWRAST_DRIVER_FILES = \ |
swrast.c |
SWRAST_COMMON_FILES = \ |
../common/utils.c \ |
../common/drisw_util.c |
SWRAST_C_FILES = \ |
$(SWRAST_COMMON_FILES) \ |
$(SWRAST_DRIVER_FILES) |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/swrast/swrast.c |
---|
0,0 → 1,851 |
/* |
* Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com> |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, 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. |
*/ |
/* |
* DRI software rasterizer |
* |
* This is the mesa swrast module packaged into a DRI driver structure. |
* |
* The front-buffer is allocated by the loader. The loader provides read/write |
* callbacks for access to the front-buffer. The driver uses a scratch row for |
* front-buffer rendering to avoid repeated calls to the loader. |
* |
* The back-buffer is allocated by the driver and is private. |
*/ |
#include "main/api_exec.h" |
#include "main/context.h" |
#include "main/extensions.h" |
#include "main/formats.h" |
#include "main/framebuffer.h" |
#include "main/imports.h" |
#include "main/renderbuffer.h" |
#include "main/version.h" |
#include "main/vtxfmt.h" |
#include "swrast/swrast.h" |
#include "swrast/s_renderbuffer.h" |
#include "swrast_setup/swrast_setup.h" |
#include "tnl/tnl.h" |
#include "tnl/t_context.h" |
#include "tnl/t_pipeline.h" |
#include "vbo/vbo.h" |
#include "drivers/common/driverfuncs.h" |
#include "drivers/common/meta.h" |
#include "utils.h" |
#include "main/teximage.h" |
#include "main/texformat.h" |
#include "main/texstate.h" |
#include "swrast_priv.h" |
#include "swrast/s_context.h" |
/** |
* Screen and config-related functions |
*/ |
static void swrastSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, |
GLint texture_format, __DRIdrawable *dPriv) |
{ |
struct dri_context *dri_ctx; |
int x, y, w, h; |
__DRIscreen *sPriv = dPriv->driScreenPriv; |
struct gl_texture_unit *texUnit; |
struct gl_texture_object *texObj; |
struct gl_texture_image *texImage; |
struct swrast_texture_image *swImage; |
uint32_t internalFormat; |
gl_format texFormat; |
dri_ctx = pDRICtx->driverPrivate; |
internalFormat = (texture_format == __DRI_TEXTURE_FORMAT_RGB ? 3 : 4); |
texUnit = _mesa_get_current_tex_unit(&dri_ctx->Base); |
texObj = _mesa_select_tex_object(&dri_ctx->Base, texUnit, target); |
texImage = _mesa_get_tex_image(&dri_ctx->Base, texObj, target, 0); |
swImage = swrast_texture_image(texImage); |
_mesa_lock_texture(&dri_ctx->Base, texObj); |
sPriv->swrast_loader->getDrawableInfo(dPriv, &x, &y, &w, &h, dPriv->loaderPrivate); |
if (texture_format == __DRI_TEXTURE_FORMAT_RGB) |
texFormat = MESA_FORMAT_XRGB8888; |
else |
texFormat = MESA_FORMAT_ARGB8888; |
_mesa_init_teximage_fields(&dri_ctx->Base, texImage, |
w, h, 1, 0, internalFormat, texFormat); |
sPriv->swrast_loader->getImage(dPriv, x, y, w, h, (char *)swImage->Buffer, |
dPriv->loaderPrivate); |
_mesa_unlock_texture(&dri_ctx->Base, texObj); |
} |
static void swrastSetTexBuffer(__DRIcontext *pDRICtx, GLint target, |
__DRIdrawable *dPriv) |
{ |
swrastSetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); |
} |
static const __DRItexBufferExtension swrastTexBufferExtension = { |
{ __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, |
swrastSetTexBuffer, |
swrastSetTexBuffer2, |
}; |
static const __DRIextension *dri_screen_extensions[] = { |
&swrastTexBufferExtension.base, |
NULL |
}; |
static __DRIconfig ** |
swrastFillInModes(__DRIscreen *psp, |
unsigned pixel_bits, unsigned depth_bits, |
unsigned stencil_bits, GLboolean have_back_buffer) |
{ |
__DRIconfig **configs; |
unsigned depth_buffer_factor; |
unsigned back_buffer_factor; |
gl_format format; |
/* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't |
* support pageflipping at all. |
*/ |
static const GLenum back_buffer_modes[] = { |
GLX_NONE, GLX_SWAP_UNDEFINED_OML |
}; |
uint8_t depth_bits_array[4]; |
uint8_t stencil_bits_array[4]; |
uint8_t msaa_samples_array[1]; |
(void) psp; |
(void) have_back_buffer; |
depth_bits_array[0] = 0; |
depth_bits_array[1] = 0; |
depth_bits_array[2] = depth_bits; |
depth_bits_array[3] = depth_bits; |
/* Just like with the accumulation buffer, always provide some modes |
* with a stencil buffer. |
*/ |
stencil_bits_array[0] = 0; |
stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; |
stencil_bits_array[2] = 0; |
stencil_bits_array[3] = (stencil_bits == 0) ? 8 : stencil_bits; |
msaa_samples_array[0] = 0; |
depth_buffer_factor = 4; |
back_buffer_factor = 2; |
switch (pixel_bits) { |
case 16: |
format = MESA_FORMAT_RGB565; |
break; |
case 24: |
format = MESA_FORMAT_XRGB8888; |
break; |
case 32: |
format = MESA_FORMAT_ARGB8888; |
break; |
default: |
fprintf(stderr, "[%s:%u] bad depth %d\n", __func__, __LINE__, |
pixel_bits); |
return NULL; |
} |
configs = driCreateConfigs(format, |
depth_bits_array, stencil_bits_array, |
depth_buffer_factor, back_buffer_modes, |
back_buffer_factor, msaa_samples_array, 1, |
GL_TRUE); |
if (configs == NULL) { |
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__, |
__LINE__); |
return NULL; |
} |
return configs; |
} |
static const __DRIconfig ** |
dri_init_screen(__DRIscreen * psp) |
{ |
__DRIconfig **configs16, **configs24, **configs32; |
TRACE; |
psp->extensions = dri_screen_extensions; |
configs16 = swrastFillInModes(psp, 16, 16, 0, 1); |
configs24 = swrastFillInModes(psp, 24, 24, 8, 1); |
configs32 = swrastFillInModes(psp, 32, 24, 8, 1); |
configs24 = driConcatConfigs(configs16, configs24); |
configs32 = driConcatConfigs(configs24, configs32); |
return (const __DRIconfig **)configs32; |
} |
static void |
dri_destroy_screen(__DRIscreen * sPriv) |
{ |
TRACE; |
(void) sPriv; |
} |
/** |
* Framebuffer and renderbuffer-related functions. |
*/ |
static GLuint |
choose_pixel_format(const struct gl_config *v) |
{ |
int depth = v->rgbBits; |
if (depth == 32 |
&& v->redMask == 0xff0000 |
&& v->greenMask == 0x00ff00 |
&& v->blueMask == 0x0000ff) |
return PF_A8R8G8B8; |
else if (depth == 24 |
&& v->redMask == 0xff0000 |
&& v->greenMask == 0x00ff00 |
&& v->blueMask == 0x0000ff) |
return PF_X8R8G8B8; |
else if (depth == 16 |
&& v->redMask == 0xf800 |
&& v->greenMask == 0x07e0 |
&& v->blueMask == 0x001f) |
return PF_R5G6B5; |
else if (depth == 8 |
&& v->redMask == 0x07 |
&& v->greenMask == 0x38 |
&& v->blueMask == 0xc0) |
return PF_R3G3B2; |
_mesa_problem( NULL, "unexpected format in %s", __FUNCTION__ ); |
return 0; |
} |
static void |
swrast_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) |
{ |
struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); |
TRACE; |
free(xrb->Base.Buffer); |
_mesa_delete_renderbuffer(ctx, rb); |
} |
/* see bytes_per_line in libGL */ |
static INLINE int |
bytes_per_line(unsigned pitch_bits, unsigned mul) |
{ |
unsigned mask = mul - 1; |
return ((pitch_bits + mask) & ~mask) / 8; |
} |
static GLboolean |
swrast_alloc_front_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, GLuint width, GLuint height) |
{ |
struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); |
TRACE; |
(void) ctx; |
(void) internalFormat; |
xrb->Base.Buffer = NULL; |
rb->Width = width; |
rb->Height = height; |
xrb->pitch = bytes_per_line(width * xrb->bpp, 32); |
return GL_TRUE; |
} |
static GLboolean |
swrast_alloc_back_storage(struct gl_context *ctx, struct gl_renderbuffer *rb, |
GLenum internalFormat, GLuint width, GLuint height) |
{ |
struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); |
TRACE; |
free(xrb->Base.Buffer); |
swrast_alloc_front_storage(ctx, rb, internalFormat, width, height); |
xrb->Base.Buffer = malloc(height * xrb->pitch); |
return GL_TRUE; |
} |
static struct dri_swrast_renderbuffer * |
swrast_new_renderbuffer(const struct gl_config *visual, __DRIdrawable *dPriv, |
GLboolean front) |
{ |
struct dri_swrast_renderbuffer *xrb = calloc(1, sizeof *xrb); |
struct gl_renderbuffer *rb; |
GLuint pixel_format; |
TRACE; |
if (!xrb) |
return NULL; |
rb = &xrb->Base.Base; |
_mesa_init_renderbuffer(rb, 0); |
pixel_format = choose_pixel_format(visual); |
xrb->dPriv = dPriv; |
xrb->Base.Base.Delete = swrast_delete_renderbuffer; |
if (front) { |
rb->AllocStorage = swrast_alloc_front_storage; |
} |
else { |
rb->AllocStorage = swrast_alloc_back_storage; |
} |
switch (pixel_format) { |
case PF_A8R8G8B8: |
rb->Format = MESA_FORMAT_ARGB8888; |
rb->InternalFormat = GL_RGBA; |
rb->_BaseFormat = GL_RGBA; |
xrb->bpp = 32; |
break; |
case PF_X8R8G8B8: |
rb->Format = MESA_FORMAT_ARGB8888; /* XXX */ |
rb->InternalFormat = GL_RGB; |
rb->_BaseFormat = GL_RGB; |
xrb->bpp = 32; |
break; |
case PF_R5G6B5: |
rb->Format = MESA_FORMAT_RGB565; |
rb->InternalFormat = GL_RGB; |
rb->_BaseFormat = GL_RGB; |
xrb->bpp = 16; |
break; |
case PF_R3G3B2: |
rb->Format = MESA_FORMAT_RGB332; |
rb->InternalFormat = GL_RGB; |
rb->_BaseFormat = GL_RGB; |
xrb->bpp = 8; |
break; |
default: |
free(xrb); |
return NULL; |
} |
return xrb; |
} |
static void |
swrast_map_renderbuffer(struct gl_context *ctx, |
struct gl_renderbuffer *rb, |
GLuint x, GLuint y, GLuint w, GLuint h, |
GLbitfield mode, |
GLubyte **out_map, |
GLint *out_stride) |
{ |
struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); |
GLubyte *map = xrb->Base.Buffer; |
int cpp = _mesa_get_format_bytes(rb->Format); |
int stride = rb->Width * cpp; |
if (rb->AllocStorage == swrast_alloc_front_storage) { |
__DRIdrawable *dPriv = xrb->dPriv; |
__DRIscreen *sPriv = dPriv->driScreenPriv; |
xrb->map_mode = mode; |
xrb->map_x = x; |
xrb->map_y = y; |
xrb->map_w = w; |
xrb->map_h = h; |
stride = w * cpp; |
xrb->Base.Buffer = malloc(h * stride); |
sPriv->swrast_loader->getImage(dPriv, x, y, w, h, |
(char *) xrb->Base.Buffer, |
dPriv->loaderPrivate); |
*out_map = xrb->Base.Buffer; |
*out_stride = stride; |
return; |
} |
ASSERT(xrb->Base.Buffer); |
if (rb->AllocStorage == swrast_alloc_back_storage) { |
map += (rb->Height - 1) * stride; |
stride = -stride; |
} |
map += (GLsizei)y * stride; |
map += (GLsizei)x * cpp; |
*out_map = map; |
*out_stride = stride; |
} |
static void |
swrast_unmap_renderbuffer(struct gl_context *ctx, |
struct gl_renderbuffer *rb) |
{ |
struct dri_swrast_renderbuffer *xrb = dri_swrast_renderbuffer(rb); |
if (rb->AllocStorage == swrast_alloc_front_storage) { |
__DRIdrawable *dPriv = xrb->dPriv; |
__DRIscreen *sPriv = dPriv->driScreenPriv; |
if (xrb->map_mode & GL_MAP_WRITE_BIT) { |
sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_DRAW, |
xrb->map_x, xrb->map_y, |
xrb->map_w, xrb->map_h, |
(char *) xrb->Base.Buffer, |
dPriv->loaderPrivate); |
} |
free(xrb->Base.Buffer); |
xrb->Base.Buffer = NULL; |
} |
} |
static GLboolean |
dri_create_buffer(__DRIscreen * sPriv, |
__DRIdrawable * dPriv, |
const struct gl_config * visual, GLboolean isPixmap) |
{ |
struct dri_drawable *drawable = NULL; |
struct gl_framebuffer *fb; |
struct dri_swrast_renderbuffer *frontrb, *backrb; |
TRACE; |
(void) sPriv; |
(void) isPixmap; |
drawable = CALLOC_STRUCT(dri_drawable); |
if (drawable == NULL) |
goto drawable_fail; |
dPriv->driverPrivate = drawable; |
drawable->dPriv = dPriv; |
drawable->row = malloc(SWRAST_MAX_WIDTH * 4); |
if (drawable->row == NULL) |
goto drawable_fail; |
fb = &drawable->Base; |
/* basic framebuffer setup */ |
_mesa_initialize_window_framebuffer(fb, visual); |
/* add front renderbuffer */ |
frontrb = swrast_new_renderbuffer(visual, dPriv, GL_TRUE); |
_mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontrb->Base.Base); |
/* add back renderbuffer */ |
if (visual->doubleBufferMode) { |
backrb = swrast_new_renderbuffer(visual, dPriv, GL_FALSE); |
_mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backrb->Base.Base); |
} |
/* add software renderbuffers */ |
_swrast_add_soft_renderbuffers(fb, |
GL_FALSE, /* color */ |
visual->haveDepthBuffer, |
visual->haveStencilBuffer, |
visual->haveAccumBuffer, |
GL_FALSE, /* alpha */ |
GL_FALSE /* aux bufs */); |
return GL_TRUE; |
drawable_fail: |
if (drawable) |
free(drawable->row); |
free(drawable); |
return GL_FALSE; |
} |
static void |
dri_destroy_buffer(__DRIdrawable * dPriv) |
{ |
TRACE; |
if (dPriv) { |
struct dri_drawable *drawable = dri_drawable(dPriv); |
struct gl_framebuffer *fb; |
free(drawable->row); |
fb = &drawable->Base; |
fb->DeletePending = GL_TRUE; |
_mesa_reference_framebuffer(&fb, NULL); |
} |
} |
static void |
dri_swap_buffers(__DRIdrawable * dPriv) |
{ |
__DRIscreen *sPriv = dPriv->driScreenPriv; |
GET_CURRENT_CONTEXT(ctx); |
struct dri_drawable *drawable = dri_drawable(dPriv); |
struct gl_framebuffer *fb; |
struct dri_swrast_renderbuffer *frontrb, *backrb; |
TRACE; |
fb = &drawable->Base; |
frontrb = |
dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); |
backrb = |
dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer); |
/* check for signle-buffered */ |
if (backrb == NULL) |
return; |
/* check if swapping currently bound buffer */ |
if (ctx && ctx->DrawBuffer == fb) { |
/* flush pending rendering */ |
_mesa_notifySwapBuffers(ctx); |
} |
sPriv->swrast_loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, |
0, 0, |
frontrb->Base.Base.Width, |
frontrb->Base.Base.Height, |
(char *) backrb->Base.Buffer, |
dPriv->loaderPrivate); |
} |
/** |
* General device driver functions. |
*/ |
static void |
get_window_size( struct gl_framebuffer *fb, GLsizei *w, GLsizei *h ) |
{ |
__DRIdrawable *dPriv = swrast_drawable(fb)->dPriv; |
__DRIscreen *sPriv = dPriv->driScreenPriv; |
int x, y; |
sPriv->swrast_loader->getDrawableInfo(dPriv, |
&x, &y, w, h, |
dPriv->loaderPrivate); |
} |
static void |
swrast_check_and_update_window_size( struct gl_context *ctx, struct gl_framebuffer *fb ) |
{ |
GLsizei width, height; |
get_window_size(fb, &width, &height); |
if (fb->Width != width || fb->Height != height) { |
_mesa_resize_framebuffer(ctx, fb, width, height); |
} |
} |
static const GLubyte * |
get_string(struct gl_context *ctx, GLenum pname) |
{ |
(void) ctx; |
switch (pname) { |
case GL_VENDOR: |
return (const GLubyte *) "Mesa Project"; |
case GL_RENDERER: |
return (const GLubyte *) "Software Rasterizer"; |
default: |
return NULL; |
} |
} |
static void |
update_state( struct gl_context *ctx, GLuint new_state ) |
{ |
/* not much to do here - pass it on */ |
_swrast_InvalidateState( ctx, new_state ); |
_swsetup_InvalidateState( ctx, new_state ); |
_vbo_InvalidateState( ctx, new_state ); |
_tnl_InvalidateState( ctx, new_state ); |
} |
static void |
viewport(struct gl_context *ctx, GLint x, GLint y, GLsizei w, GLsizei h) |
{ |
struct gl_framebuffer *draw = ctx->WinSysDrawBuffer; |
struct gl_framebuffer *read = ctx->WinSysReadBuffer; |
(void) x; |
(void) y; |
(void) w; |
(void) h; |
swrast_check_and_update_window_size(ctx, draw); |
swrast_check_and_update_window_size(ctx, read); |
} |
static gl_format swrastChooseTextureFormat(struct gl_context * ctx, |
GLenum target, |
GLint internalFormat, |
GLenum format, |
GLenum type) |
{ |
if (internalFormat == GL_RGB) |
return MESA_FORMAT_XRGB8888; |
return _mesa_choose_tex_format(ctx, target, internalFormat, format, type); |
} |
static void |
swrast_init_driver_functions(struct dd_function_table *driver) |
{ |
driver->GetString = get_string; |
driver->UpdateState = update_state; |
driver->Viewport = viewport; |
driver->ChooseTextureFormat = swrastChooseTextureFormat; |
driver->MapRenderbuffer = swrast_map_renderbuffer; |
driver->UnmapRenderbuffer = swrast_unmap_renderbuffer; |
} |
/** |
* Context-related functions. |
*/ |
static GLboolean |
dri_create_context(gl_api api, |
const struct gl_config * visual, |
__DRIcontext * cPriv, |
unsigned major_version, |
unsigned minor_version, |
uint32_t flags, |
unsigned *error, |
void *sharedContextPrivate) |
{ |
struct dri_context *ctx = NULL; |
struct dri_context *share = (struct dri_context *)sharedContextPrivate; |
struct gl_context *mesaCtx = NULL; |
struct gl_context *sharedCtx = NULL; |
struct dd_function_table functions; |
TRACE; |
/* Flag filtering is handled in dri2CreateContextAttribs. |
*/ |
(void) flags; |
switch (api) { |
case API_OPENGL_COMPAT: |
if (major_version > 2 |
|| (major_version == 2 && minor_version > 1)) { |
*error = __DRI_CTX_ERROR_BAD_VERSION; |
return GL_FALSE; |
} |
break; |
case API_OPENGLES: |
case API_OPENGLES2: |
break; |
case API_OPENGL_CORE: |
*error = __DRI_CTX_ERROR_BAD_API; |
return GL_FALSE; |
} |
ctx = CALLOC_STRUCT(dri_context); |
if (ctx == NULL) { |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
goto context_fail; |
} |
cPriv->driverPrivate = ctx; |
ctx->cPriv = cPriv; |
/* build table of device driver functions */ |
_mesa_init_driver_functions(&functions); |
swrast_init_driver_functions(&functions); |
if (share) { |
sharedCtx = &share->Base; |
} |
mesaCtx = &ctx->Base; |
/* basic context setup */ |
if (!_mesa_initialize_context(mesaCtx, api, visual, sharedCtx, &functions)) { |
*error = __DRI_CTX_ERROR_NO_MEMORY; |
goto context_fail; |
} |
/* do bounds checking to prevent segfaults and server crashes! */ |
mesaCtx->Const.CheckArrayBounds = GL_TRUE; |
/* create module contexts */ |
_swrast_CreateContext( mesaCtx ); |
_vbo_CreateContext( mesaCtx ); |
_tnl_CreateContext( mesaCtx ); |
_swsetup_CreateContext( mesaCtx ); |
_swsetup_Wakeup( mesaCtx ); |
/* use default TCL pipeline */ |
{ |
TNLcontext *tnl = TNL_CONTEXT(mesaCtx); |
tnl->Driver.RunPipeline = _tnl_run_pipeline; |
} |
_mesa_meta_init(mesaCtx); |
_mesa_enable_sw_extensions(mesaCtx); |
_mesa_compute_version(mesaCtx); |
_mesa_initialize_dispatch_tables(mesaCtx); |
_mesa_initialize_vbo_vtxfmt(mesaCtx); |
*error = __DRI_CTX_ERROR_SUCCESS; |
return GL_TRUE; |
context_fail: |
free(ctx); |
return GL_FALSE; |
} |
static void |
dri_destroy_context(__DRIcontext * cPriv) |
{ |
TRACE; |
if (cPriv) { |
struct dri_context *ctx = dri_context(cPriv); |
struct gl_context *mesaCtx; |
mesaCtx = &ctx->Base; |
_mesa_meta_free(mesaCtx); |
_swsetup_DestroyContext( mesaCtx ); |
_swrast_DestroyContext( mesaCtx ); |
_tnl_DestroyContext( mesaCtx ); |
_vbo_DestroyContext( mesaCtx ); |
_mesa_destroy_context( mesaCtx ); |
} |
} |
static GLboolean |
dri_make_current(__DRIcontext * cPriv, |
__DRIdrawable * driDrawPriv, |
__DRIdrawable * driReadPriv) |
{ |
struct gl_context *mesaCtx; |
struct gl_framebuffer *mesaDraw; |
struct gl_framebuffer *mesaRead; |
TRACE; |
if (cPriv) { |
struct dri_context *ctx = dri_context(cPriv); |
struct dri_drawable *draw; |
struct dri_drawable *read; |
if (!driDrawPriv || !driReadPriv) |
return GL_FALSE; |
draw = dri_drawable(driDrawPriv); |
read = dri_drawable(driReadPriv); |
mesaCtx = &ctx->Base; |
mesaDraw = &draw->Base; |
mesaRead = &read->Base; |
/* check for same context and buffer */ |
if (mesaCtx == _mesa_get_current_context() |
&& mesaCtx->DrawBuffer == mesaDraw |
&& mesaCtx->ReadBuffer == mesaRead) { |
return GL_TRUE; |
} |
_glapi_check_multithread(); |
swrast_check_and_update_window_size(mesaCtx, mesaDraw); |
if (mesaRead != mesaDraw) |
swrast_check_and_update_window_size(mesaCtx, mesaRead); |
_mesa_make_current( mesaCtx, |
mesaDraw, |
mesaRead ); |
} |
else { |
/* unbind */ |
_mesa_make_current( NULL, NULL, NULL ); |
} |
return GL_TRUE; |
} |
static GLboolean |
dri_unbind_context(__DRIcontext * cPriv) |
{ |
TRACE; |
(void) cPriv; |
/* Unset current context and dispath table */ |
_mesa_make_current(NULL, NULL, NULL); |
return GL_TRUE; |
} |
const struct __DriverAPIRec driDriverAPI = { |
.InitScreen = dri_init_screen, |
.DestroyScreen = dri_destroy_screen, |
.CreateContext = dri_create_context, |
.DestroyContext = dri_destroy_context, |
.CreateBuffer = dri_create_buffer, |
.DestroyBuffer = dri_destroy_buffer, |
.SwapBuffers = dri_swap_buffers, |
.MakeCurrent = dri_make_current, |
.UnbindContext = dri_unbind_context, |
}; |
/* This is the table of extensions that the loader will dlsym() for. */ |
PUBLIC const __DRIextension *__driDriverExtensions[] = { |
&driCoreExtension.base, |
&driSWRastExtension.base, |
NULL |
}; |
/contrib/sdk/sources/Mesa/src/mesa/drivers/dri/swrast/swrast_priv.h |
---|
0,0 → 1,134 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved. |
* Copyright 2008, 2010 George Sapountzis <gsapountzis@gmail.com> |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, 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. |
*/ |
#ifndef _SWRAST_PRIV_H |
#define _SWRAST_PRIV_H |
#include <GL/gl.h> |
#include <GL/internal/dri_interface.h> |
#include "main/mtypes.h" |
#include "dri_util.h" |
#include "swrast/s_context.h" |
/** |
* Debugging |
*/ |
#define DEBUG_CORE 0 |
#define DEBUG_SPAN 0 |
#if DEBUG_CORE |
#define TRACE printf("--> %s\n", __FUNCTION__) |
#else |
#define TRACE |
#endif |
#if DEBUG_SPAN |
#define TRACE_SPAN printf("--> %s\n", __FUNCTION__) |
#else |
#define TRACE_SPAN |
#endif |
/** |
* Data types |
*/ |
struct dri_context |
{ |
/* mesa, base class, must be first */ |
struct gl_context Base; |
/* dri */ |
__DRIcontext *cPriv; |
}; |
static INLINE struct dri_context * |
dri_context(__DRIcontext * driContextPriv) |
{ |
return (struct dri_context *)driContextPriv->driverPrivate; |
} |
static INLINE struct dri_context * |
swrast_context(struct gl_context *ctx) |
{ |
return (struct dri_context *) ctx; |
} |
struct dri_drawable |
{ |
/* mesa, base class, must be first */ |
struct gl_framebuffer Base; |
/* dri */ |
__DRIdrawable *dPriv; |
/* scratch row for optimized front-buffer rendering */ |
char *row; |
}; |
static INLINE struct dri_drawable * |
dri_drawable(__DRIdrawable * driDrawPriv) |
{ |
return (struct dri_drawable *)driDrawPriv->driverPrivate; |
} |
static INLINE struct dri_drawable * |
swrast_drawable(struct gl_framebuffer *fb) |
{ |
return (struct dri_drawable *) fb; |
} |
struct dri_swrast_renderbuffer { |
struct swrast_renderbuffer Base; |
__DRIdrawable *dPriv; |
/* GL_MAP_*_BIT, used for mapping of front buffer. */ |
GLbitfield map_mode; |
int map_x, map_y, map_w, map_h; |
/* renderbuffer pitch (in bytes) */ |
GLuint pitch; |
/* bits per pixel of storage */ |
GLuint bpp; |
}; |
static INLINE struct dri_swrast_renderbuffer * |
dri_swrast_renderbuffer(struct gl_renderbuffer *rb) |
{ |
return (struct dri_swrast_renderbuffer *) rb; |
} |
/** |
* Pixel formats we support |
*/ |
#define PF_A8R8G8B8 1 /**< 32bpp TrueColor: 8-A, 8-R, 8-G, 8-B bits */ |
#define PF_R5G6B5 2 /**< 16bpp TrueColor: 5-R, 6-G, 5-B bits */ |
#define PF_R3G3B2 3 /**< 8bpp TrueColor: 3-R, 3-G, 2-B bits */ |
#define PF_X8R8G8B8 4 /**< 32bpp TrueColor: 8-R, 8-G, 8-B bits */ |
#endif /* _SWRAST_PRIV_H_ */ |