mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 17:58:26 +02:00
Merge remote branch 'origin/master' into nv50-compiler
Conflicts: src/gallium/drivers/nv50/nv50_program.c
This commit is contained in:
commit
222d2f2ac2
1069 changed files with 116927 additions and 48446 deletions
15
Makefile
15
Makefile
|
|
@ -187,8 +187,6 @@ GLUT_NAME = MesaGLUT-$(VERSION)
|
|||
|
||||
# This is part of MAIN_FILES
|
||||
MAIN_ES_FILES = \
|
||||
$(DIRECTORY)/src/mesa/es/Makefile \
|
||||
$(DIRECTORY)/src/mesa/es/sources.mak \
|
||||
$(DIRECTORY)/src/mesa/main/*.xml \
|
||||
$(DIRECTORY)/src/mesa/main/*.py \
|
||||
$(DIRECTORY)/src/mesa/main/*.dtd
|
||||
|
|
@ -229,8 +227,10 @@ MAIN_FILES = \
|
|||
$(DIRECTORY)/src/glsl/Makefile \
|
||||
$(DIRECTORY)/src/glsl/Makefile.template \
|
||||
$(DIRECTORY)/src/glsl/SConscript \
|
||||
$(DIRECTORY)/src/glsl/*/Makefile \
|
||||
$(DIRECTORY)/src/glsl/*/*.[ch] \
|
||||
$(DIRECTORY)/src/glsl/*.[ch] \
|
||||
$(DIRECTORY)/src/glsl/*.[cly]pp \
|
||||
$(DIRECTORY)/src/glsl/README \
|
||||
$(DIRECTORY)/src/glsl/glcpp/README \
|
||||
$(DIRECTORY)/src/Makefile \
|
||||
$(DIRECTORY)/src/mesa/Makefile* \
|
||||
$(DIRECTORY)/src/mesa/sources.mak \
|
||||
|
|
@ -246,10 +246,6 @@ MAIN_FILES = \
|
|||
$(DIRECTORY)/src/mesa/program/*.[chly] \
|
||||
$(DIRECTORY)/src/mesa/program/Makefile \
|
||||
$(DIRECTORY)/src/mesa/program/descrip.mms \
|
||||
$(DIRECTORY)/src/mesa/slang/*.[ch] \
|
||||
$(DIRECTORY)/src/mesa/slang/descrip.mms \
|
||||
$(DIRECTORY)/src/mesa/slang/library/*.gc \
|
||||
$(DIRECTORY)/src/mesa/slang/library/Makefile \
|
||||
$(DIRECTORY)/src/mesa/swrast/*.[ch] \
|
||||
$(DIRECTORY)/src/mesa/swrast/descrip.mms \
|
||||
$(DIRECTORY)/src/mesa/swrast_setup/*.[ch] \
|
||||
|
|
@ -278,8 +274,6 @@ MAIN_FILES = \
|
|||
$(DIRECTORY)/src/mesa/drivers/x11/Makefile \
|
||||
$(DIRECTORY)/src/mesa/drivers/x11/descrip.mms \
|
||||
$(DIRECTORY)/src/mesa/drivers/x11/*.[ch] \
|
||||
$(DIRECTORY)/src/mesa/drivers/glslcompiler/Makefile \
|
||||
$(DIRECTORY)/src/mesa/drivers/glslcompiler/glslcompiler.c \
|
||||
$(DIRECTORY)/src/mesa/ppc/*.[ch] \
|
||||
$(DIRECTORY)/src/mesa/sparc/*.[chS] \
|
||||
$(DIRECTORY)/src/mesa/x86/Makefile \
|
||||
|
|
@ -331,7 +325,6 @@ GALLIUM_FILES = \
|
|||
$(DIRECTORY)/src/gallium/Makefile.template \
|
||||
$(DIRECTORY)/src/gallium/SConscript \
|
||||
$(DIRECTORY)/src/gallium/targets/Makefile.dri \
|
||||
$(DIRECTORY)/src/gallium/targets/Makefile.egl \
|
||||
$(DIRECTORY)/src/gallium/*/Makefile \
|
||||
$(DIRECTORY)/src/gallium/*/SConscript \
|
||||
$(DIRECTORY)/src/gallium/*/*/Makefile \
|
||||
|
|
|
|||
22
SConstruct
22
SConstruct
|
|
@ -206,28 +206,6 @@ Export('env')
|
|||
# TODO: Build several variants at the same time?
|
||||
# http://www.scons.org/wiki/SimultaneousVariantBuilds
|
||||
|
||||
if env['platform'] != common.default_platform:
|
||||
# GLSL code has to be built twice -- one for the host OS, another for the target OS...
|
||||
|
||||
host_env = Environment(
|
||||
# options are ignored
|
||||
# default tool is used
|
||||
tools = ['default', 'custom'],
|
||||
toolpath = ['#scons'],
|
||||
ENV = os.environ,
|
||||
)
|
||||
|
||||
host_env['platform'] = common.default_platform
|
||||
host_env['machine'] = common.default_machine
|
||||
host_env['debug'] = env['debug']
|
||||
|
||||
SConscript(
|
||||
'src/glsl/SConscript',
|
||||
variant_dir = os.path.join(env['build'], 'host'),
|
||||
duplicate = 0, # http://www.scons.org/doc/0.97/HTML/scons-user/x2261.html
|
||||
exports={'env':host_env},
|
||||
)
|
||||
|
||||
SConscript(
|
||||
'src/SConscript',
|
||||
variant_dir = env['build'],
|
||||
|
|
|
|||
21
bin/minstall
21
bin/minstall
|
|
@ -31,7 +31,7 @@ if [ $# -ge 2 ] ; then
|
|||
|
||||
# Last cmd line arg is the dest dir
|
||||
for FILE in $@ ; do
|
||||
DEST="$FILE"
|
||||
DESTDIR="$FILE"
|
||||
done
|
||||
|
||||
# Loop over args, moving them to DEST directory
|
||||
|
|
@ -42,6 +42,25 @@ if [ $# -ge 2 ] ; then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
DEST=$DESTDIR
|
||||
|
||||
# On CYGWIN, because DLLs are loaded by the native Win32 loader,
|
||||
# they are installed in the executable path. Stub libraries used
|
||||
# only for linking are installed in the library path
|
||||
case `uname` in
|
||||
CYGWIN*)
|
||||
case $FILE in
|
||||
*.dll)
|
||||
DEST="$DEST/../bin"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
PWDSAVE=`pwd`
|
||||
|
||||
# determine file's type
|
||||
|
|
|
|||
34
bin/mklib
34
bin/mklib
|
|
@ -930,6 +930,16 @@ case $ARCH in
|
|||
|
||||
CYGWIN*)
|
||||
# GCC-based environment
|
||||
|
||||
if [ "x$LINK" = "x" ] ; then
|
||||
# -linker was not specified so set default link command now
|
||||
if [ $CPLUSPLUS = 1 ] ; then
|
||||
LINK=g++
|
||||
else
|
||||
LINK=gcc
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $NOPREFIX = 1 ] ; then
|
||||
# No "lib" or ".so" part
|
||||
echo "mklib: Making CYGWIN shared library: " ${LIBNAME}
|
||||
|
|
@ -938,7 +948,7 @@ case $ARCH in
|
|||
OPTS=${ALTOPTS}
|
||||
fi
|
||||
rm -f ${LIBNAME}
|
||||
${LINK} ${OPTS} ${LDFLAGS} -o ${LIBNAME} ${OBJECTS} ${DEPS}
|
||||
${LINK} ${OPTS} ${LDFLAGS} -o ${LIBNAME} ${OBJECTS} ${DEPS} || exit $?
|
||||
FINAL_LIBS=${LIBNAME}
|
||||
else
|
||||
CYGNAME="cyg${LIBNAME}" # prefix with "cyg"
|
||||
|
|
@ -946,7 +956,7 @@ case $ARCH in
|
|||
|
||||
if [ $STATIC = 1 ] ; then
|
||||
LIBNAME=${LIBNAME}.a
|
||||
echo "mklib: Making" $ARCH "static library: " ${LIBNAME}
|
||||
echo "mklib: Making CYGWIN static library: " ${LIBNAME}
|
||||
OPTS="-ru"
|
||||
if [ "${ALTOPTS}" ] ; then
|
||||
OPTS=${ALTOPTS}
|
||||
|
|
@ -964,13 +974,7 @@ case $ARCH in
|
|||
if [ "${ALTOPTS}" ] ; then
|
||||
OPTS=${ALTOPTS}
|
||||
fi
|
||||
echo "mklib: Making" $ARCH "shared library: " ${CYGNAME}-${MAJOR}.dll
|
||||
|
||||
if [ $CPLUSPLUS = 1 ] ; then
|
||||
LINK="g++"
|
||||
else
|
||||
LINK="gcc"
|
||||
fi
|
||||
echo "mklib: Making CYGWIN shared library: " ${CYGNAME}-${MAJOR}.dll
|
||||
|
||||
# rm any old libs
|
||||
rm -f ${CYGNAME}-${MAJOR}.dll
|
||||
|
|
@ -979,12 +983,7 @@ case $ARCH in
|
|||
rm -f ${LIBNAME}.a
|
||||
|
||||
# make lib
|
||||
${LINK} ${OPTS} ${LDFLAGS} -o ${CYGNAME}-${MAJOR}.dll ${OBJECTS} ${DEPS}
|
||||
# make build fail if link failed
|
||||
es=$?
|
||||
if [ "$es" -ne "0" ]; then
|
||||
exit $es
|
||||
fi
|
||||
${LINK} ${OPTS} ${LDFLAGS} -o ${CYGNAME}-${MAJOR}.dll ${OBJECTS} ${DEPS} || exit $?
|
||||
# make usual symlinks
|
||||
ln -s ${LIBNAME}-${MAJOR}.dll.a ${LIBNAME}.dll.a
|
||||
# finish up
|
||||
|
|
@ -1024,4 +1023,9 @@ if [ ${INSTALLDIR} != "." ] ; then
|
|||
echo "mklib: Installing" ${FINAL_LIBS} "in" ${INSTALLDIR}
|
||||
test -d ${INSTALLDIR} || mkdir -p ${INSTALLDIR}
|
||||
mv ${FINAL_LIBS} ${INSTALLDIR}/
|
||||
|
||||
if [ "x${FINAL_BINS}" != "x" ] ; then
|
||||
echo "mklib: Installing" ${FINAL_BINS} "in" ${INSTALLDIR}
|
||||
mv ${FINAL_BINS} ${INSTALLDIR}/
|
||||
fi
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ LLVM_LIBS = @LLVM_LIBS@
|
|||
GLW_CFLAGS = @GLW_CFLAGS@
|
||||
GLUT_CFLAGS = @GLUT_CFLAGS@
|
||||
|
||||
TALLOC_LIBS = @TALLOC_LIBS@
|
||||
TALLOC_CFLAGS = @TALLOC_CFLAGS@
|
||||
|
||||
# dlopen
|
||||
DLOPEN_LIBS = @DLOPEN_LIBS@
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ GLESv1_CM_LIB_GLOB = $(GLESv1_CM_LIB_NAME)*
|
|||
GLESv2_LIB_GLOB = $(GLESv2_LIB_NAME)*
|
||||
VG_LIB_GLOB = $(VG_LIB_NAME)*
|
||||
|
||||
TALLOC_LIBS = `pkg-config --libs talloc`
|
||||
TALLOC_CFLAGS = `pkg-config --cflags talloc`
|
||||
|
||||
# Optional assembly language optimization files for libGL
|
||||
MESA_ASM_SOURCES =
|
||||
|
||||
|
|
@ -116,7 +119,7 @@ EGL_CLIENT_APIS = $(GL_LIB)
|
|||
|
||||
# Library dependencies
|
||||
#EXTRA_LIB_PATH ?=
|
||||
GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread
|
||||
GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread $(TALLOC_LIBS)
|
||||
EGL_LIB_DEPS = $(EXTRA_LIB_PATH) -ldl -lpthread
|
||||
OSMESA_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB)
|
||||
GLU_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) -lm
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ EXTRA_LIB_PATH=-L/usr/X11R6/lib
|
|||
|
||||
LIBDRM_CFLAGS = $(shell pkg-config --cflags libdrm)
|
||||
LIBDRM_LIB = $(shell pkg-config --libs libdrm)
|
||||
DRI_LIB_DEPS = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
|
||||
DRI_LIB_DEPS = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl -ltalloc $(LIBDRM_LIB)
|
||||
GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
|
||||
-lm -lpthread -ldl $(LIBDRM_LIB)
|
||||
|
||||
|
|
|
|||
|
|
@ -41,4 +41,4 @@ else
|
|||
endif
|
||||
|
||||
LD = g++
|
||||
GL_LIB_DEPS = $(LLVM_LDFLAGS) $(LLVM_LIBS) $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -lstdc++ -ludis86
|
||||
GL_LIB_DEPS = $(LLVM_LDFLAGS) $(LLVM_LIBS) $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -ltalloc -lstdc++ -ludis86
|
||||
|
|
|
|||
63
configure.ac
63
configure.ac
|
|
@ -48,9 +48,23 @@ solaris*)
|
|||
;;
|
||||
esac
|
||||
|
||||
dnl clang is mostly GCC-compatible, but its version is much lower,
|
||||
dnl so we have to check for it.
|
||||
AC_MSG_CHECKING([if compiling with clang])
|
||||
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([], [[
|
||||
#ifndef __clang__
|
||||
not clang
|
||||
#endif
|
||||
]])],
|
||||
[CLANG=yes], [CLANG=no])
|
||||
|
||||
AC_MSG_RESULT([$CLANG])
|
||||
|
||||
dnl If we're using GCC, make sure that it is at least version 3.3.0. Older
|
||||
dnl versions are explictly not supported.
|
||||
if test "x$GCC" = xyes; then
|
||||
if test "x$GCC" = xyes -a "x$CLANG" = xno; then
|
||||
AC_MSG_CHECKING([whether gcc version is sufficient])
|
||||
major=0
|
||||
minor=0
|
||||
|
|
@ -123,7 +137,10 @@ esac
|
|||
|
||||
dnl Add flags for gcc and g++
|
||||
if test "x$GCC" = xyes; then
|
||||
CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -std=c99 -ffast-math"
|
||||
CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -std=c99"
|
||||
if test "x$CLANG" = "xno"; then
|
||||
CFLAGS="$CFLAGS -ffast-math"
|
||||
fi
|
||||
|
||||
# Enable -fvisibility=hidden if using a gcc that supports it
|
||||
save_CFLAGS="$CFLAGS"
|
||||
|
|
@ -258,6 +275,8 @@ fi
|
|||
dnl
|
||||
dnl library names
|
||||
dnl
|
||||
LIB_PREFIX_GLOB='lib'
|
||||
LIB_VERSION_SEPARATOR='.'
|
||||
if test "$enable_static" = yes; then
|
||||
LIB_EXTENSION='a'
|
||||
else
|
||||
|
|
@ -265,7 +284,10 @@ else
|
|||
darwin* )
|
||||
LIB_EXTENSION='dylib' ;;
|
||||
cygwin* )
|
||||
LIB_EXTENSION='dll.a' ;;
|
||||
dnl prefix can be 'cyg' or 'lib'
|
||||
LIB_PREFIX_GLOB='???'
|
||||
LIB_VERSION_SEPARATOR='-'
|
||||
LIB_EXTENSION='dll' ;;
|
||||
aix* )
|
||||
LIB_EXTENSION='a' ;;
|
||||
* )
|
||||
|
|
@ -283,15 +305,16 @@ GLESv1_CM_LIB_NAME='lib$(GLESv1_CM_LIB).'${LIB_EXTENSION}
|
|||
GLESv2_LIB_NAME='lib$(GLESv2_LIB).'${LIB_EXTENSION}
|
||||
VG_LIB_NAME='lib$(VG_LIB).'${LIB_EXTENSION}
|
||||
|
||||
GL_LIB_GLOB='lib$(GL_LIB).*'${LIB_EXTENSION}'*'
|
||||
GLU_LIB_GLOB='lib$(GLU_LIB).*'${LIB_EXTENSION}'*'
|
||||
GLUT_LIB_GLOB='lib$(GLUT_LIB).*'${LIB_EXTENSION}'*'
|
||||
GLW_LIB_GLOB='lib$(GLW_LIB).*'${LIB_EXTENSION}'*'
|
||||
OSMESA_LIB_GLOB='lib$(OSMESA_LIB).*'${LIB_EXTENSION}'*'
|
||||
EGL_LIB_GLOB='lib$(EGL_LIB).*'${LIB_EXTENSION}'*'
|
||||
GLESv1_CM_LIB_GLOB='lib$(GLESv1_CM_LIB).*'${LIB_EXTENSION}'*'
|
||||
GLESv2_LIB_GLOB='lib$(GLESv2_LIB).*'${LIB_EXTENSION}'*'
|
||||
VG_LIB_GLOB='lib$(VG_LIB).*'${LIB_EXTENSION}'*'
|
||||
GL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
|
||||
GLU_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLU_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
|
||||
GLUT_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLUT_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
|
||||
GLW_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLW_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
|
||||
OSMESA_LIB_GLOB=${LIB_PREFIX_GLOB}'$(OSMESA_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
|
||||
EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
|
||||
EGL_LIB_GLOB=${LIB_PREFIX_GLOB}'$(EGL_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
|
||||
GLESv1_CM_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv1_CM_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
|
||||
GLESv2_LIB_GLOB=${LIB_PREFIX_GLOB}'$(GLESv2_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
|
||||
VG_LIB_GLOB=${LIB_PREFIX_GLOB}'$(VG_LIB)'${LIB_VERSION_SEPARATOR}'*'${LIB_EXTENSION}'*'
|
||||
|
||||
AC_SUBST([GL_LIB_NAME])
|
||||
AC_SUBST([GLU_LIB_NAME])
|
||||
|
|
@ -463,6 +486,10 @@ xxlib|xdri|xosmesa)
|
|||
;;
|
||||
esac
|
||||
|
||||
PKG_CHECK_MODULES([TALLOC], [talloc])
|
||||
AC_SUBST([TALLOC_LIBS])
|
||||
AC_SUBST([TALLOC_CFLAGS])
|
||||
|
||||
dnl
|
||||
dnl Driver specific build directories
|
||||
dnl
|
||||
|
|
@ -574,8 +601,8 @@ xlib)
|
|||
GL_PC_LIB_PRIV="$GL_LIB_DEPS"
|
||||
GL_PC_CFLAGS="$X11_INCLUDES"
|
||||
fi
|
||||
GL_LIB_DEPS="$GL_LIB_DEPS $SELINUX_LIBS -lm -lpthread"
|
||||
GL_PC_LIB_PRIV="$GL_PC_LIB_PRIV $SELINUX_LIBS -lm -lpthread"
|
||||
GL_LIB_DEPS="$GL_LIB_DEPS $SELINUX_LIBS -lm -lpthread $TALLOC_LIBS"
|
||||
GL_PC_LIB_PRIV="$GL_PC_LIB_PRIV $SELINUX_LIBS -lm -lpthread $TALLOC_LIBS"
|
||||
|
||||
# if static, move the external libraries to the programs
|
||||
# and empty the libraries for libGL
|
||||
|
|
@ -853,7 +880,7 @@ if test "$mesa_driver" = dri; then
|
|||
[AC_MSG_ERROR([Expat required for DRI.])])
|
||||
|
||||
# put all the necessary libs together
|
||||
DRI_LIB_DEPS="$SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm -lpthread $DLOPEN_LIBS"
|
||||
DRI_LIB_DEPS="$SELINUX_LIBS $LIBDRM_LIBS $EXPAT_LIB -lm -lpthread $DLOPEN_LIBS $TALLOC_LIBS"
|
||||
fi
|
||||
AC_SUBST([DRI_DIRS])
|
||||
AC_SUBST([EXPAT_INCLUDES])
|
||||
|
|
@ -931,12 +958,12 @@ case "$DRIVER_DIRS" in
|
|||
*osmesa*)
|
||||
# only link libraries with osmesa if shared
|
||||
if test "$enable_static" = no; then
|
||||
OSMESA_LIB_DEPS="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS"
|
||||
OSMESA_LIB_DEPS="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS $TALLOC_LIBS"
|
||||
else
|
||||
OSMESA_LIB_DEPS=""
|
||||
fi
|
||||
OSMESA_MESA_DEPS=""
|
||||
OSMESA_PC_LIB_PRIV="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS"
|
||||
OSMESA_PC_LIB_PRIV="-lm -lpthread $SELINUX_LIBS $DLOPEN_LIBS $TALLOC_LIBS"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST([OSMESA_LIB_DEPS])
|
||||
|
|
@ -1484,7 +1511,7 @@ AC_ARG_ENABLE([gallium-radeon],
|
|||
[enable_gallium_radeon=auto])
|
||||
if test "x$enable_gallium_radeon" = xyes; then
|
||||
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300"
|
||||
gallium_check_st "radeon/drm" "dri-radeong" "xorg-radeon"
|
||||
gallium_check_st "radeon/drm" "dri-r300" "xorg-radeon"
|
||||
elif test "x$enable_gallium_radeon" = xauto; then
|
||||
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300"
|
||||
fi
|
||||
|
|
|
|||
149
docs/MESA_drm_image.spec
Normal file
149
docs/MESA_drm_image.spec
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
Name
|
||||
|
||||
MESA_drm_image
|
||||
|
||||
Name Strings
|
||||
|
||||
EGL_MESA_drm_image
|
||||
|
||||
Contact
|
||||
|
||||
Kristian Høgsberg <krh@bitplanet.net>
|
||||
|
||||
Status
|
||||
|
||||
Proposal
|
||||
|
||||
Version
|
||||
|
||||
Version 2, August 25, 2010
|
||||
|
||||
Number
|
||||
|
||||
EGL Extension #not assigned
|
||||
|
||||
Dependencies
|
||||
|
||||
Reguires EGL 1.4 or later. This extension is written against the
|
||||
wording of the EGL 1.4 specification.
|
||||
|
||||
EGL_KHR_base_image is required.
|
||||
|
||||
Overview
|
||||
|
||||
This extension provides entry points for integrating EGLImage with the
|
||||
Linux DRM mode setting and memory management drivers. The extension
|
||||
lets applications create EGLImages without a client API resource and
|
||||
lets the application get the DRM buffer handles.
|
||||
|
||||
IP Status
|
||||
|
||||
Open-source; freely implementable.
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
EGLImageKHR eglCreateDRMImageMESA(EGLDisplay dpy,
|
||||
const EGLint *attrib_list);
|
||||
|
||||
EGLBoolean eglExportDRMImageMESA(EGLDisplay dpy,
|
||||
EGLImageKHR image,
|
||||
EGLint *name,
|
||||
EGLint *handle,
|
||||
EGLint *stride);
|
||||
|
||||
New Tokens
|
||||
|
||||
Accepted in the <attrib_list> parameter of eglCreateDRMImageMESA:
|
||||
|
||||
EGL_DRM_BUFFER_FORMAT_MESA 0x31D0
|
||||
EGL_DRM_BUFFER_USE_MESA 0x31D1
|
||||
|
||||
Accepted as values for the EGL_IMAGE_FORMAT_MESA attribute:
|
||||
|
||||
EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
|
||||
|
||||
Bits accepted in EGL_DRM_BUFFER_USE_MESA:
|
||||
|
||||
EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x0001
|
||||
EGL_DRM_BUFFER_USE_SHARE_MESA 0x0002
|
||||
|
||||
Accepted in the <target> parameter of eglCreateImageKHR:
|
||||
|
||||
EGL_DRM_BUFFER_MESA 0x31D3
|
||||
|
||||
Use when importing drm buffer:
|
||||
|
||||
EGL_DRM_BUFFER_STRIDE_MESA 0x31D4
|
||||
EGL_DRM_BUFFER_FORMAT_MESA 0x31D0
|
||||
|
||||
Additions to the EGL 1.4 Specification:
|
||||
|
||||
To create a DRM EGLImage, call
|
||||
|
||||
EGLImageKHR eglCreateDRMImageMESA(EGLDisplay dpy,
|
||||
const EGLint *attrib_list);
|
||||
|
||||
In the attribute list, pass EGL_WIDTH, EGL_EIGHT and format and
|
||||
use in the attrib list using EGL_DRM_BUFFER_FORMAT_MESA and
|
||||
EGL_DRM_BUFFER_USE_MESA. The only format specified by this
|
||||
extension is EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, where each pixel
|
||||
is a CPU-endian, 32-bit quantity, with alpha in the upper 8 bits,
|
||||
then red, then green, then blue. The bit values accepted by
|
||||
EGL_DRM_BUFFER_USE_MESA are EGL_DRM_BUFFER_USE_SCANOUT_MESA and
|
||||
EGL_DRM_BUFFER_USE_SHARE_MESA. EGL_DRM_BUFFER_USE_SCANOUT_MESA
|
||||
requests that the created EGLImage should be usable as a scanout
|
||||
buffer with the DRM kernel modesetting API. The
|
||||
EGL_DRM_BUFFER_USE_SHARE_MESA bit requests that the EGLImage can
|
||||
be shared with other processes by passing the underlying DRM
|
||||
buffer name.
|
||||
|
||||
To create a process local handle or a global DRM name for a
|
||||
buffer, call
|
||||
|
||||
EGLBoolean eglExportDRMImageMESA(EGLDisplay dpy,
|
||||
EGLImageKHR image,
|
||||
EGLint *name,
|
||||
EGLint *handle,
|
||||
EGLint *stride);
|
||||
|
||||
If <name> is non-NULL, a global name is assigned to the image and
|
||||
written to <name>, the handle (local to the DRM file descriptor,
|
||||
for use with DRM kernel modesetting API) is written to <handle> if
|
||||
non-NULL and the stride (in bytes) is written to <stride>, if
|
||||
non-NULL.
|
||||
|
||||
Import a shared buffer by calling eglCreateImageKHR with
|
||||
EGL_DRM_BUFFER_MESA as the target, using EGL_WIDTH, EGL_HEIGHT,
|
||||
EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_STRIDE_MESA
|
||||
in the attrib list.
|
||||
|
||||
Issues
|
||||
|
||||
1. Why don't we use eglCreateImageKHR with a target that
|
||||
indicates that we want to create an EGLImage from scratch?
|
||||
|
||||
RESOLVED: The eglCreateImageKHR entry point is reserved for
|
||||
creating an EGLImage from an already existing client API
|
||||
resource. This is fine when we're creating the EGLImage from
|
||||
an existing DRM buffer name, it doesn't seem right to overload
|
||||
the function to also allocate the underlying resource.
|
||||
|
||||
2. Why don't we use an eglQueryImageMESA type functions for
|
||||
querying the DRM EGLImage attributes (name, handle, and stride)?
|
||||
|
||||
RESOLVED: The eglQueryImage function has been proposed often,
|
||||
but it goes against the EGLImage design. EGLImages are opaque
|
||||
handles to a 2D array of pixels, which can be passed between
|
||||
client APIs. By referenceing an EGLImage in a client API, the
|
||||
EGLImage target (a texture, a renderbuffer or such) can be
|
||||
used to query the attributes of the EGLImage. We don't have a
|
||||
full client API for creating and querying DRM buffers, though,
|
||||
so we use a new EGL extension entry point instead.
|
||||
|
||||
Revision History
|
||||
|
||||
Version 1, June 3, 2010
|
||||
Initial draft (Kristian Høgsberg)
|
||||
Version 2, August 25, 2010
|
||||
Flesh out the extension a bit, add final EGL tokens, capture
|
||||
some of the original discussion in the issues section.
|
||||
|
|
@ -69,7 +69,6 @@ a:visited {
|
|||
<li><a href="http://sourceforge.net/projects/mesa3d" target="_parent">SourceForge homepage</a>
|
||||
<li><a href="repository.html" target="MainFrame">Source Code Repository</a>
|
||||
<li><a href="sourcetree.html" target="MainFrame">Source Code Tree</a>
|
||||
<li><a href="memory.html" target="MainFrame">DRI Memory Management</a>
|
||||
<li><a href="glu.html" target="MainFrame">SGI's GLU</a>
|
||||
<li><a href="utilities.html" target="MainFrame">Utilities</a>
|
||||
<li><a href="helpwanted.html" target="MainFrame">Help Wanted</a>
|
||||
|
|
|
|||
|
|
@ -12,12 +12,14 @@
|
|||
Both professional and volunteer developers contribute to Mesa.
|
||||
</p>
|
||||
<p>
|
||||
<a href="http://www.tungstengraphics.com/" target="_parent">Tungsten Graphics</a>
|
||||
<a href="http://www.vmware.com/" target="_parent">VMware</a>
|
||||
employs several of the main Mesa developers including Brian Paul
|
||||
and Keith Whitwell.
|
||||
Much of the on-going work in Mesa is done through Tungsten Graphics engineering
|
||||
contracts.
|
||||
Prominent examples of this work includes:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In the past, Tungsten Graphics contracts implemented many Mesa features
|
||||
including:
|
||||
</p>
|
||||
<ul>
|
||||
<li>DRI drivers for Intel i965, i945, i915 and other chips
|
||||
|
|
@ -29,7 +31,13 @@ Prominent examples of this work includes:
|
|||
<p>
|
||||
Other companies including
|
||||
<a href="http://www.intellinuxgraphics.org/index.html" target="_parent">Intel</a>
|
||||
and IBM also actively contribute to the project.
|
||||
and RedHat also actively contribute to the project.
|
||||
Intel has recently contributed the new GLSL compiler in Mesa 7.9.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="http://www.lunarg.com/" target="_parent">LunarG</a> can be contacted
|
||||
for custom Mesa / 3D graphics development.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -37,15 +45,5 @@ Volunteers have made significant contributions to all parts of Mesa, including
|
|||
complete device drivers.
|
||||
</p>
|
||||
|
||||
|
||||
<H1>Custom Development</H1>
|
||||
<p>
|
||||
Contact <a href="http://www.tungstengraphics.com/" target="_parent">
|
||||
Tungsten Graphics</a>
|
||||
for information about custom development in Mesa, OpenGL, X and other
|
||||
graphics technologies.
|
||||
</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -111,11 +111,9 @@ It implements the OpenGL 1.3 specification.
|
|||
|
||||
|
||||
<p>
|
||||
November 2001: I cofound <a href="http://www.tungstengraphics.com" target="_parent">
|
||||
Tungsten Graphics, Inc.</a> with Keith Whitwell, Jens Owen, David Dawes and
|
||||
Frank LaMonica.
|
||||
I continue to develop Mesa as part of my resposibilities with Tungsten
|
||||
Graphics and as a spare-time project.
|
||||
November 2001: I cofounded Tungsten Graphics, Inc. with Keith Whitwell,
|
||||
Jens Owen, David Dawes and Frank LaMonica.
|
||||
Tungsten Graphics was acquired by VMware in December 2008.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,14 @@
|
|||
<H1>News</H1>
|
||||
|
||||
|
||||
<h2>June 16, 2010</h2>
|
||||
|
||||
<p>
|
||||
<a href="relnotes-7.8.2.html">Mesa 7.8.2</a> is released. This is a bug-fix
|
||||
release collecting fixes since the 7.8.1 release.
|
||||
</p>
|
||||
|
||||
|
||||
<h2>April 5, 2010</h2>
|
||||
|
||||
<p>
|
||||
|
|
@ -157,9 +165,6 @@ Added a new page describing the <a href="cell.html">Mesa Cell driver</a>.
|
|||
<p>
|
||||
Gallium3D is the codename for the new Mesa device driver architecture
|
||||
which is currently under development.
|
||||
A <a href="http://wiki.freedesktop.org/wiki/Software/gallium"
|
||||
target="_parent"> summary</a> of the architecture can be found on the
|
||||
Tungsten Graphics website.
|
||||
</p>
|
||||
<p>
|
||||
Gallium3D development is taking place on the <em>gallium-0.1</em> branch
|
||||
|
|
@ -210,11 +215,8 @@ shading language and built-in functions.
|
|||
|
||||
<h2>April 2007</h2>
|
||||
<p>
|
||||
Thomas Hellström of
|
||||
<a href="http://www.tungstengraphics.com" target="_parent">
|
||||
Tungsten Graphics</a> has written a whitepaper describing the new
|
||||
<a href="http://www.tungstengraphics.com/mm.pdf">DRI memory management
|
||||
system</a>.
|
||||
Thomas Hellström of Tungsten Graphics has written a whitepaper
|
||||
describing the new DRI memory management system</a>.
|
||||
</p>
|
||||
|
||||
<h2>December 5, 2006</h2>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,11 @@ tbd
|
|||
|
||||
<h2>New features</h2>
|
||||
<ul>
|
||||
<li>New, improved GLSL compiler written by Intel.
|
||||
See the <a href="shading.html"> Shading Language</a> page for
|
||||
more information.
|
||||
<li>GL_EXT_timer_query extension (i965 driver only)
|
||||
<li>GL_EXT_framebuffer_multisample extension (intel drivers, MAX_SAMPLES = 1)
|
||||
<li>GL_ARB_texture_swizzle extension (alias of GL_EXT_texture_swizzle)
|
||||
<li>GL_ARB_draw_elements_base_vertex, GL_ARB_fragment_program_shadow
|
||||
and GL_EXT_draw_buffers2 in Gallium drivers
|
||||
|
|
|
|||
|
|
@ -39,19 +39,19 @@ list of keywords to control some aspects of the GLSL compiler and shader
|
|||
execution. These are generally used for debugging.
|
||||
</p>
|
||||
<ul>
|
||||
<li>dump - print GLSL shader code to stdout at link time
|
||||
<li>log - log all GLSL shaders to files.
|
||||
<li><b>dump</b> - print GLSL shader code to stdout at link time
|
||||
<li><b>log</b> - log all GLSL shaders to files.
|
||||
The filenames will be "shader_X.vert" or "shader_X.frag" where X
|
||||
the shader ID.
|
||||
<li>nopt - disable compiler optimizations
|
||||
<li>opt - force compiler optimizations
|
||||
<li>uniform - print message to stdout when glUniform is called
|
||||
<li>nopvert - force vertex shaders to be a simple shader that just transforms
|
||||
<li><b>nopt</b> - disable compiler optimizations
|
||||
<li><b>opt</b> - force compiler optimizations
|
||||
<li><b>uniform</b> - print message to stdout when glUniform is called
|
||||
<li><b>nopvert</b> - force vertex shaders to be a simple shader that just transforms
|
||||
the vertex position with ftransform() and passes through the color and
|
||||
texcoord[0] attributes.
|
||||
<li>nopfrag - force fragment shader to be a simple shader that passes
|
||||
<li><b>nopfrag</b> - force fragment shader to be a simple shader that passes
|
||||
through the color attribute.
|
||||
<li>useprog - log glUseProgram calls to stderr
|
||||
<li><b>useprog</b> - log glUseProgram calls to stderr
|
||||
</ul>
|
||||
<p>
|
||||
Example: export MESA_GLSL=dump,nopt
|
||||
|
|
@ -59,30 +59,28 @@ Example: export MESA_GLSL=dump,nopt
|
|||
|
||||
|
||||
<a name="120">
|
||||
<h2>GLSL 1.20 support</h2>
|
||||
<h2>GLSL Version</h2>
|
||||
|
||||
<p>
|
||||
GLSL version 1.20 is supported in Mesa 7.3 and later.
|
||||
Among the features/differences of GLSL 1.20 are:
|
||||
<ul>
|
||||
<li><code>mat2x3, mat2x4</code>, etc. types and functions
|
||||
<li><code>transpose(), outerProduct(), matrixCompMult()</code> functions
|
||||
(but untested)
|
||||
<li>precision qualifiers (lowp, mediump, highp)
|
||||
<li><code>invariant</code> qualifier
|
||||
<li><code>array.length()</code> method
|
||||
<li><code>float[5] a;</code> array syntax
|
||||
<li><code>centroid</code> qualifier
|
||||
<li>unsized array constructors
|
||||
<li>initializers for uniforms
|
||||
<li>const initializers calling built-in functions
|
||||
</ul>
|
||||
The GLSL compiler currently supports version 1.20 of the shading language.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Several GLSL extensions are also supported:
|
||||
</p>
|
||||
<ul>
|
||||
<li>GL_ARB_draw_buffers
|
||||
<li>GL_ARB_texture_rectangle
|
||||
<li>GL_ARB_fragment_coord_conventions
|
||||
<li>GL_EXT_texture_array
|
||||
</ul>
|
||||
|
||||
|
||||
<a name="unsup">
|
||||
<h2>Unsupported Features</h2>
|
||||
|
||||
<p>XXX update this section</p>
|
||||
|
||||
<p>
|
||||
The following features of the shading language are not yet fully supported
|
||||
in Mesa:
|
||||
|
|
@ -130,39 +128,6 @@ These issues will be addressed/resolved in the future.
|
|||
<h2>Programming Hints</h2>
|
||||
|
||||
<ul>
|
||||
<li>Declare <em>in</em> function parameters as <em>const</em> whenever possible.
|
||||
This improves the efficiency of function inlining.
|
||||
</li>
|
||||
<br>
|
||||
<li>To reduce register usage, declare variables within smaller scopes.
|
||||
For example, the following code:
|
||||
<pre>
|
||||
void main()
|
||||
{
|
||||
vec4 a1, a2, b1, b2;
|
||||
gl_Position = expression using a1, a2.
|
||||
gl_Color = expression using b1, b2;
|
||||
}
|
||||
</pre>
|
||||
Can be rewritten as follows to use half as many registers:
|
||||
<pre>
|
||||
void main()
|
||||
{
|
||||
{
|
||||
vec4 a1, a2;
|
||||
gl_Position = expression using a1, a2.
|
||||
}
|
||||
{
|
||||
vec4 b1, b2;
|
||||
gl_Color = expression using b1, b2;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
Alternately, rather than using several float variables, use
|
||||
a vec4 instead. Use swizzling and writemasks to access the
|
||||
components of the vec4 as floats.
|
||||
</li>
|
||||
<br>
|
||||
<li>Use the built-in library functions whenever possible.
|
||||
For example, instead of writing this:
|
||||
<pre>
|
||||
|
|
@ -172,8 +137,6 @@ These issues will be addressed/resolved in the future.
|
|||
<pre>
|
||||
float x = inversesqrt(y);
|
||||
</pre>
|
||||
<li>
|
||||
Use ++i when possible as it's more efficient than i++
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
|
@ -182,13 +145,8 @@ These issues will be addressed/resolved in the future.
|
|||
<h2>Stand-alone GLSL Compiler</h2>
|
||||
|
||||
<p>
|
||||
A unique stand-alone GLSL compiler driver has been added to Mesa.
|
||||
<p>
|
||||
|
||||
<p>
|
||||
The stand-alone compiler (like a conventional command-line compiler)
|
||||
is a tool that accepts Shading Language programs and emits low-level
|
||||
GPU programs.
|
||||
The stand-alone GLSL compiler program can be used to compile GLSL shaders
|
||||
into low-level GPU code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -201,59 +159,25 @@ This tool is useful for:
|
|||
</ul>
|
||||
|
||||
<p>
|
||||
After building Mesa, the glslcompiler can be built by manually running:
|
||||
After building Mesa, the compiler can be found at src/glsl/glsl_compiler
|
||||
</p>
|
||||
<pre>
|
||||
make realclean
|
||||
make linux
|
||||
cd src/mesa/drivers/glslcompiler
|
||||
make
|
||||
</pre>
|
||||
|
||||
|
||||
<p>
|
||||
Here's an example of using the compiler to compile a vertex shader and
|
||||
emit GL_ARB_vertex_program-style instructions:
|
||||
</p>
|
||||
<pre>
|
||||
bin/glslcompiler --debug --numbers --fs progs/glsl/CH06-brick.frag.txt
|
||||
</pre>
|
||||
<p>
|
||||
results in:
|
||||
</p>
|
||||
<pre>
|
||||
# Fragment Program/Shader
|
||||
0: RCP TEMP[4].x, UNIFORM[2].xxxx;
|
||||
1: RCP TEMP[4].y, UNIFORM[2].yyyy;
|
||||
2: MUL TEMP[3].xy, VARYING[0], TEMP[4];
|
||||
3: MOV TEMP[1], TEMP[3];
|
||||
4: MUL TEMP[0].w, TEMP[1].yyyy, CONST[4].xxxx;
|
||||
5: FRC TEMP[1].z, TEMP[0].wwww;
|
||||
6: SGT.C TEMP[0].w, TEMP[1].zzzz, CONST[4].xxxx;
|
||||
7: IF (NE.wwww); # (if false, goto 9);
|
||||
8: ADD TEMP[1].x, TEMP[1].xxxx, CONST[4].xxxx;
|
||||
9: ENDIF;
|
||||
10: FRC TEMP[1].xy, TEMP[1];
|
||||
11: SGT TEMP[2].xy, UNIFORM[3], TEMP[1];
|
||||
12: MUL TEMP[1].z, TEMP[2].xxxx, TEMP[2].yyyy;
|
||||
13: LRP TEMP[0], TEMP[1].zzzz, UNIFORM[0], UNIFORM[1];
|
||||
14: MUL TEMP[0].xyz, TEMP[0], VARYING[1].xxxx;
|
||||
15: MOV OUTPUT[0].xyz, TEMP[0];
|
||||
16: MOV OUTPUT[0].w, CONST[4].yyyy;
|
||||
17: END
|
||||
src/glsl/glslcompiler --dump-ast myshader.vert
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Note that some shading language constructs (such as uniform and varying
|
||||
variables) aren't expressible in ARB or NV-style programs.
|
||||
Therefore, the resulting output is not always legal by definition of
|
||||
those program languages.
|
||||
</p>
|
||||
<p>
|
||||
Also note that this compiler driver is still under development.
|
||||
Over time, the correctness of the GPU programs, with respect to the ARB
|
||||
and NV languagues, should improve.
|
||||
</p>
|
||||
Options include
|
||||
<ul>
|
||||
<li><b>--dump-ast</b> - dump GPU code
|
||||
<li><b>--dump-hir</b> - dump high-level IR code
|
||||
<li><b>--dump-lir</b> - dump low-level IR code
|
||||
<li><b>--link</b> - ???
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -262,38 +186,12 @@ and NV languagues, should improve.
|
|||
|
||||
<p>
|
||||
The source code for Mesa's shading language compiler is in the
|
||||
<code>src/mesa/shader/slang/</code> directory.
|
||||
<code>src/glsl/</code> directory.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The compiler follows a fairly standard design and basically works as follows:
|
||||
XXX provide some info about the compiler....
|
||||
</p>
|
||||
<ul>
|
||||
<li>The input string is tokenized (see grammar.c) and parsed
|
||||
(see slang_compiler_*.c) to produce an Abstract Syntax Tree (AST).
|
||||
The nodes in this tree are slang_operation structures
|
||||
(see slang_compile_operation.h).
|
||||
The nodes are decorated with symbol table, scoping and datatype information.
|
||||
<li>The AST is converted into an Intermediate representation (IR) tree
|
||||
(see the slang_codegen.c file).
|
||||
The IR nodes represent basic GPU instructions, like add, dot product,
|
||||
move, etc.
|
||||
The IR tree is mostly a binary tree, but a few nodes have three or four
|
||||
children.
|
||||
In principle, the IR tree could be executed by doing an in-order traversal.
|
||||
<li>The IR tree is traversed in-order to emit code (see slang_emit.c).
|
||||
This is also when registers are allocated to store variables and temps.
|
||||
<li>In the future, a pattern-matching code generator-generator may be
|
||||
used for code generation.
|
||||
Programs such as L-BURG (Bottom-Up Rewrite Generator) and Twig look for
|
||||
patterns in IR trees, compute weights for subtrees and use the weights
|
||||
to select the best instructions to represent the sub-tree.
|
||||
<li>The emitted GPU instructions (see prog_instruction.h) are stored in a
|
||||
gl_program object (see mtypes.h).
|
||||
<li>When a fragment shader and vertex shader are linked (see slang_link.c)
|
||||
the varying vars are matched up, uniforms are merged, and vertex
|
||||
attributes are resolved (rewriting instructions as needed).
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The final vertex and fragment programs may be interpreted in software
|
||||
|
|
@ -351,20 +249,20 @@ Extra NOP instructions will also be inserted.
|
|||
<h2>Compiler Validation</h2>
|
||||
|
||||
<p>
|
||||
A <a href="http://glean.sf.net" target="_parent">Glean</a> test has
|
||||
been create to exercise the GLSL compiler.
|
||||
</p>
|
||||
<p>
|
||||
The <em>glsl1</em> test runs over 170 sub-tests to check that the language
|
||||
features and built-in functions work properly.
|
||||
This test should be run frequently while working on the compiler to catch
|
||||
Developers working on the GLSL compiler should test frequently to avoid
|
||||
regressions.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The test coverage is reasonably broad and complete but additional tests
|
||||
should be added.
|
||||
The <a href="http://people.freedesktop.org/~nh/piglit/">Piglit</a> project
|
||||
has many GLSL tests and the
|
||||
<a href="http://glean.sf.net" target="_parent">Glean</a> glsl1 test
|
||||
tests GLSL features.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The Mesa demos repository also has some good GLSL tests.
|
||||
</p>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@
|
|||
</h3>
|
||||
</center>
|
||||
</h2>
|
||||
<p> Copyright © 2002-2003 by <a
|
||||
href="http://www.tungstengraphics.com/">Tungsten Graphics, Inc.</a>,
|
||||
<p> Copyright © 2002-2003 by Tungsten Graphics, Inc.,
|
||||
Cedar Park, Texas. All Rights Reserved. <br>
|
||||
<br>
|
||||
Permission is granted to make and distribute verbatim copies of this
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/*
|
||||
** Copyright (c) 2007-2009 The Khronos Group Inc.
|
||||
** Copyright (c) 2007-2010 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
|
|
@ -34,8 +34,8 @@ extern "C" {
|
|||
|
||||
/* Header file version number */
|
||||
/* Current version at http://www.khronos.org/registry/egl/ */
|
||||
/* $Revision: 10185 $ on $Date: 2010-01-22 11:38:01 -0800 (Fri, 22 Jan 2010) $ */
|
||||
#define EGL_EGLEXT_VERSION 5
|
||||
/* $Revision: 12124 $ on $Date: 2010-07-27 20:12:35 -0700 (Tue, 27 Jul 2010) $ */
|
||||
#define EGL_EGLEXT_VERSION 7
|
||||
|
||||
#ifndef EGL_KHR_config_attribs
|
||||
#define EGL_KHR_config_attribs 1
|
||||
|
|
@ -120,6 +120,30 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGL
|
|||
#define EGL_GL_RENDERBUFFER_KHR 0x30B9 /* eglCreateImageKHR target */
|
||||
#endif
|
||||
|
||||
#ifndef EGL_MESA_drm_image
|
||||
#define EGL_MESA_drm_image 1
|
||||
#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0 /* eglCreateImageKHR attribute */
|
||||
#define EGL_DRM_BUFFER_USE_MESA 0x31D1
|
||||
|
||||
/* EGL_DRM_BUFFER_FORMAT_MESA tokens */
|
||||
#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
|
||||
|
||||
/* EGL_DRM_BUFFER_USE_MESA bits */
|
||||
#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x0001
|
||||
#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x0002
|
||||
|
||||
#define EGL_DRM_BUFFER_MESA 0x31D3 /* eglCreateImageKHR target */
|
||||
#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4 /* eglCreateImageKHR attribute */
|
||||
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attrib_list);
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA(EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
|
||||
#endif
|
||||
typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESA) (EGLDisplay dpy, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESA) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64 /* EGLTimeKHR requires 64-bit uint support */
|
||||
#ifndef EGL_KHR_reusable_sync
|
||||
#define EGL_KHR_reusable_sync 1
|
||||
|
||||
|
|
@ -149,6 +173,7 @@ typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSy
|
|||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* EGL_MESA_screen extension >>> PRELIMINARY <<< */
|
||||
#ifndef EGL_MESA_screen_surface
|
||||
|
|
@ -238,6 +263,101 @@ typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETDRMDISPLAYMESA) (int fd);
|
|||
#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
|
||||
#endif
|
||||
|
||||
#ifndef EGL_KHR_lock_surface2
|
||||
#define EGL_KHR_lock_surface2 1
|
||||
#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110
|
||||
#endif
|
||||
|
||||
#ifndef EGL_NV_coverage_sample
|
||||
#define EGL_NV_coverage_sample 1
|
||||
#define EGL_COVERAGE_BUFFERS_NV 0x30E0
|
||||
#define EGL_COVERAGE_SAMPLES_NV 0x30E1
|
||||
#endif
|
||||
|
||||
#ifndef EGL_NV_depth_nonlinear
|
||||
#define EGL_NV_depth_nonlinear 1
|
||||
#define EGL_DEPTH_ENCODING_NV 0x30E2
|
||||
#define EGL_DEPTH_ENCODING_NONE_NV 0
|
||||
#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64 /* EGLTimeNV requires 64-bit uint support */
|
||||
#ifndef EGL_NV_sync
|
||||
#define EGL_NV_sync 1
|
||||
#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
|
||||
#define EGL_SYNC_STATUS_NV 0x30E7
|
||||
#define EGL_SIGNALED_NV 0x30E8
|
||||
#define EGL_UNSIGNALED_NV 0x30E9
|
||||
#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001
|
||||
#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull
|
||||
#define EGL_ALREADY_SIGNALED_NV 0x30EA
|
||||
#define EGL_TIMEOUT_EXPIRED_NV 0x30EB
|
||||
#define EGL_CONDITION_SATISFIED_NV 0x30EC
|
||||
#define EGL_SYNC_TYPE_NV 0x30ED
|
||||
#define EGL_SYNC_CONDITION_NV 0x30EE
|
||||
#define EGL_SYNC_FENCE_NV 0x30EF
|
||||
#define EGL_NO_SYNC_NV ((EGLSyncNV)0)
|
||||
typedef void* EGLSyncNV;
|
||||
typedef khronos_utime_nanoseconds_t EGLTimeNV;
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLSyncNV eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
|
||||
EGLBoolean eglDestroySyncNV (EGLSyncNV sync);
|
||||
EGLBoolean eglFenceNV (EGLSyncNV sync);
|
||||
EGLint eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
|
||||
EGLBoolean eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
|
||||
EGLBoolean eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
|
||||
typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64 /* Dependent on EGL_KHR_reusable_sync which requires 64-bit uint support */
|
||||
#ifndef EGL_KHR_fence_sync
|
||||
#define EGL_KHR_fence_sync 1
|
||||
/* Reuses most tokens and entry points from EGL_KHR_reusable_sync */
|
||||
#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
|
||||
#define EGL_SYNC_CONDITION_KHR 0x30F8
|
||||
#define EGL_SYNC_FENCE_KHR 0x30F9
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef EGL_HI_clientpixmap
|
||||
#define EGL_HI_clientpixmap 1
|
||||
|
||||
/* Surface Attribute */
|
||||
#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74
|
||||
/*
|
||||
* Structure representing a client pixmap
|
||||
* (pixmap's data is in client-space memory).
|
||||
*/
|
||||
struct EGLClientPixmapHI
|
||||
{
|
||||
void* pData;
|
||||
EGLint iWidth;
|
||||
EGLint iHeight;
|
||||
EGLint iStride;
|
||||
};
|
||||
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI(EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
|
||||
#endif /* EGL_EGLEXT_PROTOTYPES */
|
||||
typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap);
|
||||
#endif /* EGL_HI_clientpixmap */
|
||||
|
||||
#ifndef EGL_HI_colorformats
|
||||
#define EGL_HI_colorformats 1
|
||||
/* Config Attribute */
|
||||
#define EGL_COLOR_FORMAT_HI 0x8F70
|
||||
/* Color Formats */
|
||||
#define EGL_COLOR_RGB_HI 0x8F71
|
||||
#define EGL_COLOR_RGBA_HI 0x8F72
|
||||
#define EGL_COLOR_ARGB_HI 0x8F73
|
||||
#endif /* EGL_HI_colorformats */
|
||||
|
||||
#ifndef EGL_NOK_swap_region
|
||||
#define EGL_NOK_swap_region 1
|
||||
|
|
|
|||
|
|
@ -789,6 +789,17 @@ struct __DRIdri2ExtensionRec {
|
|||
#define __DRI_IMAGE_FORMAT_XRGB8888 0x1002
|
||||
#define __DRI_IMAGE_FORMAT_ARGB8888 0x1003
|
||||
|
||||
#define __DRI_IMAGE_USE_SHARE 0x0001
|
||||
#define __DRI_IMAGE_USE_SCANOUT 0x0002
|
||||
|
||||
/**
|
||||
* queryImage attributes
|
||||
*/
|
||||
|
||||
#define __DRI_IMAGE_ATTRIB_STRIDE 0x2000
|
||||
#define __DRI_IMAGE_ATTRIB_HANDLE 0x2001
|
||||
#define __DRI_IMAGE_ATTRIB_NAME 0x2002
|
||||
|
||||
typedef struct __DRIimageRec __DRIimage;
|
||||
typedef struct __DRIimageExtensionRec __DRIimageExtension;
|
||||
struct __DRIimageExtensionRec {
|
||||
|
|
@ -804,8 +815,16 @@ struct __DRIimageExtensionRec {
|
|||
void *loaderPrivate);
|
||||
|
||||
void (*destroyImage)(__DRIimage *image);
|
||||
|
||||
__DRIimage *(*createImage)(__DRIscreen *screen,
|
||||
int width, int height, int format,
|
||||
unsigned int use,
|
||||
void *loaderPrivate);
|
||||
|
||||
GLboolean (*queryImage)(__DRIimage *image, int attrib, int *value);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This extension must be implemented by the loader and passed to the
|
||||
* driver at screen creation time. The EGLImage entry points in the
|
||||
|
|
|
|||
305
include/c99/inttypes.h
Normal file
305
include/c99/inttypes.h
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
// ISO C9x compliant inttypes.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_INTTYPES_H_ // [
|
||||
#define _MSC_INTTYPES_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
// 7.8 Format conversion of integer types
|
||||
|
||||
typedef struct {
|
||||
intmax_t quot;
|
||||
intmax_t rem;
|
||||
} imaxdiv_t;
|
||||
|
||||
// 7.8.1 Macros for format specifiers
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
|
||||
|
||||
// The fprintf macros for signed integers are:
|
||||
#define PRId8 "d"
|
||||
#define PRIi8 "i"
|
||||
#define PRIdLEAST8 "d"
|
||||
#define PRIiLEAST8 "i"
|
||||
#define PRIdFAST8 "d"
|
||||
#define PRIiFAST8 "i"
|
||||
|
||||
#define PRId16 "hd"
|
||||
#define PRIi16 "hi"
|
||||
#define PRIdLEAST16 "hd"
|
||||
#define PRIiLEAST16 "hi"
|
||||
#define PRIdFAST16 "hd"
|
||||
#define PRIiFAST16 "hi"
|
||||
|
||||
#define PRId32 "I32d"
|
||||
#define PRIi32 "I32i"
|
||||
#define PRIdLEAST32 "I32d"
|
||||
#define PRIiLEAST32 "I32i"
|
||||
#define PRIdFAST32 "I32d"
|
||||
#define PRIiFAST32 "I32i"
|
||||
|
||||
#define PRId64 "I64d"
|
||||
#define PRIi64 "I64i"
|
||||
#define PRIdLEAST64 "I64d"
|
||||
#define PRIiLEAST64 "I64i"
|
||||
#define PRIdFAST64 "I64d"
|
||||
#define PRIiFAST64 "I64i"
|
||||
|
||||
#define PRIdMAX "I64d"
|
||||
#define PRIiMAX "I64i"
|
||||
|
||||
#define PRIdPTR "Id"
|
||||
#define PRIiPTR "Ii"
|
||||
|
||||
// The fprintf macros for unsigned integers are:
|
||||
#define PRIo8 "o"
|
||||
#define PRIu8 "u"
|
||||
#define PRIx8 "x"
|
||||
#define PRIX8 "X"
|
||||
#define PRIoLEAST8 "o"
|
||||
#define PRIuLEAST8 "u"
|
||||
#define PRIxLEAST8 "x"
|
||||
#define PRIXLEAST8 "X"
|
||||
#define PRIoFAST8 "o"
|
||||
#define PRIuFAST8 "u"
|
||||
#define PRIxFAST8 "x"
|
||||
#define PRIXFAST8 "X"
|
||||
|
||||
#define PRIo16 "ho"
|
||||
#define PRIu16 "hu"
|
||||
#define PRIx16 "hx"
|
||||
#define PRIX16 "hX"
|
||||
#define PRIoLEAST16 "ho"
|
||||
#define PRIuLEAST16 "hu"
|
||||
#define PRIxLEAST16 "hx"
|
||||
#define PRIXLEAST16 "hX"
|
||||
#define PRIoFAST16 "ho"
|
||||
#define PRIuFAST16 "hu"
|
||||
#define PRIxFAST16 "hx"
|
||||
#define PRIXFAST16 "hX"
|
||||
|
||||
#define PRIo32 "I32o"
|
||||
#define PRIu32 "I32u"
|
||||
#define PRIx32 "I32x"
|
||||
#define PRIX32 "I32X"
|
||||
#define PRIoLEAST32 "I32o"
|
||||
#define PRIuLEAST32 "I32u"
|
||||
#define PRIxLEAST32 "I32x"
|
||||
#define PRIXLEAST32 "I32X"
|
||||
#define PRIoFAST32 "I32o"
|
||||
#define PRIuFAST32 "I32u"
|
||||
#define PRIxFAST32 "I32x"
|
||||
#define PRIXFAST32 "I32X"
|
||||
|
||||
#define PRIo64 "I64o"
|
||||
#define PRIu64 "I64u"
|
||||
#define PRIx64 "I64x"
|
||||
#define PRIX64 "I64X"
|
||||
#define PRIoLEAST64 "I64o"
|
||||
#define PRIuLEAST64 "I64u"
|
||||
#define PRIxLEAST64 "I64x"
|
||||
#define PRIXLEAST64 "I64X"
|
||||
#define PRIoFAST64 "I64o"
|
||||
#define PRIuFAST64 "I64u"
|
||||
#define PRIxFAST64 "I64x"
|
||||
#define PRIXFAST64 "I64X"
|
||||
|
||||
#define PRIoMAX "I64o"
|
||||
#define PRIuMAX "I64u"
|
||||
#define PRIxMAX "I64x"
|
||||
#define PRIXMAX "I64X"
|
||||
|
||||
#define PRIoPTR "Io"
|
||||
#define PRIuPTR "Iu"
|
||||
#define PRIxPTR "Ix"
|
||||
#define PRIXPTR "IX"
|
||||
|
||||
// The fscanf macros for signed integers are:
|
||||
#define SCNd8 "d"
|
||||
#define SCNi8 "i"
|
||||
#define SCNdLEAST8 "d"
|
||||
#define SCNiLEAST8 "i"
|
||||
#define SCNdFAST8 "d"
|
||||
#define SCNiFAST8 "i"
|
||||
|
||||
#define SCNd16 "hd"
|
||||
#define SCNi16 "hi"
|
||||
#define SCNdLEAST16 "hd"
|
||||
#define SCNiLEAST16 "hi"
|
||||
#define SCNdFAST16 "hd"
|
||||
#define SCNiFAST16 "hi"
|
||||
|
||||
#define SCNd32 "ld"
|
||||
#define SCNi32 "li"
|
||||
#define SCNdLEAST32 "ld"
|
||||
#define SCNiLEAST32 "li"
|
||||
#define SCNdFAST32 "ld"
|
||||
#define SCNiFAST32 "li"
|
||||
|
||||
#define SCNd64 "I64d"
|
||||
#define SCNi64 "I64i"
|
||||
#define SCNdLEAST64 "I64d"
|
||||
#define SCNiLEAST64 "I64i"
|
||||
#define SCNdFAST64 "I64d"
|
||||
#define SCNiFAST64 "I64i"
|
||||
|
||||
#define SCNdMAX "I64d"
|
||||
#define SCNiMAX "I64i"
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define SCNdPTR "I64d"
|
||||
# define SCNiPTR "I64i"
|
||||
#else // _WIN64 ][
|
||||
# define SCNdPTR "ld"
|
||||
# define SCNiPTR "li"
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// The fscanf macros for unsigned integers are:
|
||||
#define SCNo8 "o"
|
||||
#define SCNu8 "u"
|
||||
#define SCNx8 "x"
|
||||
#define SCNX8 "X"
|
||||
#define SCNoLEAST8 "o"
|
||||
#define SCNuLEAST8 "u"
|
||||
#define SCNxLEAST8 "x"
|
||||
#define SCNXLEAST8 "X"
|
||||
#define SCNoFAST8 "o"
|
||||
#define SCNuFAST8 "u"
|
||||
#define SCNxFAST8 "x"
|
||||
#define SCNXFAST8 "X"
|
||||
|
||||
#define SCNo16 "ho"
|
||||
#define SCNu16 "hu"
|
||||
#define SCNx16 "hx"
|
||||
#define SCNX16 "hX"
|
||||
#define SCNoLEAST16 "ho"
|
||||
#define SCNuLEAST16 "hu"
|
||||
#define SCNxLEAST16 "hx"
|
||||
#define SCNXLEAST16 "hX"
|
||||
#define SCNoFAST16 "ho"
|
||||
#define SCNuFAST16 "hu"
|
||||
#define SCNxFAST16 "hx"
|
||||
#define SCNXFAST16 "hX"
|
||||
|
||||
#define SCNo32 "lo"
|
||||
#define SCNu32 "lu"
|
||||
#define SCNx32 "lx"
|
||||
#define SCNX32 "lX"
|
||||
#define SCNoLEAST32 "lo"
|
||||
#define SCNuLEAST32 "lu"
|
||||
#define SCNxLEAST32 "lx"
|
||||
#define SCNXLEAST32 "lX"
|
||||
#define SCNoFAST32 "lo"
|
||||
#define SCNuFAST32 "lu"
|
||||
#define SCNxFAST32 "lx"
|
||||
#define SCNXFAST32 "lX"
|
||||
|
||||
#define SCNo64 "I64o"
|
||||
#define SCNu64 "I64u"
|
||||
#define SCNx64 "I64x"
|
||||
#define SCNX64 "I64X"
|
||||
#define SCNoLEAST64 "I64o"
|
||||
#define SCNuLEAST64 "I64u"
|
||||
#define SCNxLEAST64 "I64x"
|
||||
#define SCNXLEAST64 "I64X"
|
||||
#define SCNoFAST64 "I64o"
|
||||
#define SCNuFAST64 "I64u"
|
||||
#define SCNxFAST64 "I64x"
|
||||
#define SCNXFAST64 "I64X"
|
||||
|
||||
#define SCNoMAX "I64o"
|
||||
#define SCNuMAX "I64u"
|
||||
#define SCNxMAX "I64x"
|
||||
#define SCNXMAX "I64X"
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define SCNoPTR "I64o"
|
||||
# define SCNuPTR "I64u"
|
||||
# define SCNxPTR "I64x"
|
||||
# define SCNXPTR "I64X"
|
||||
#else // _WIN64 ][
|
||||
# define SCNoPTR "lo"
|
||||
# define SCNuPTR "lu"
|
||||
# define SCNxPTR "lx"
|
||||
# define SCNXPTR "lX"
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#endif // __STDC_FORMAT_MACROS ]
|
||||
|
||||
// 7.8.2 Functions for greatest-width integer types
|
||||
|
||||
// 7.8.2.1 The imaxabs function
|
||||
#define imaxabs _abs64
|
||||
|
||||
// 7.8.2.2 The imaxdiv function
|
||||
|
||||
// This is modified version of div() function from Microsoft's div.c found
|
||||
// in %MSVC.NET%\crt\src\div.c
|
||||
#ifdef STATIC_IMAXDIV // [
|
||||
static
|
||||
#else // STATIC_IMAXDIV ][
|
||||
_inline
|
||||
#endif // STATIC_IMAXDIV ]
|
||||
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
|
||||
{
|
||||
imaxdiv_t result;
|
||||
|
||||
result.quot = numer / denom;
|
||||
result.rem = numer % denom;
|
||||
|
||||
if (numer < 0 && result.rem > 0) {
|
||||
// did division wrong; must fix up
|
||||
++result.quot;
|
||||
result.rem -= denom;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// 7.8.2.3 The strtoimax and strtoumax functions
|
||||
#define strtoimax _strtoi64
|
||||
#define strtoumax _strtoui64
|
||||
|
||||
// 7.8.2.4 The wcstoimax and wcstoumax functions
|
||||
#define wcstoimax _wcstoi64
|
||||
#define wcstoumax _wcstoui64
|
||||
|
||||
|
||||
#endif // _MSC_INTTYPES_H_ ]
|
||||
|
|
@ -1,117 +1,247 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007-2010 VMware, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* stdint.h --
|
||||
*
|
||||
* Portable subset of C99's stdint.h.
|
||||
*
|
||||
* At the moment it only supports MSVC, given all other mainstream compilers
|
||||
* already support C99. If this is necessary for other compilers then it
|
||||
* might be worth to replace this with
|
||||
* http://www.azillionmonkeys.com/qed/pstdint.h.
|
||||
*/
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _STDINT_H_
|
||||
#define _STDINT_H_
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
|
||||
#ifndef INT8_MAX
|
||||
#define INT8_MAX 127
|
||||
#endif
|
||||
#ifndef INT8_MIN
|
||||
#define INT8_MIN -128
|
||||
#endif
|
||||
#ifndef UINT8_MAX
|
||||
#define UINT8_MAX 255
|
||||
#endif
|
||||
#ifndef INT16_MAX
|
||||
#define INT16_MAX 32767
|
||||
#endif
|
||||
#ifndef INT16_MIN
|
||||
#define INT16_MIN -32768
|
||||
#endif
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX 65535
|
||||
#endif
|
||||
#ifndef INT32_MAX
|
||||
#define INT32_MAX 2147483647
|
||||
#endif
|
||||
#ifndef INT32_MIN
|
||||
#define INT32_MIN -2147483648
|
||||
#endif
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX 4294967295U
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef INT8_C
|
||||
#define INT8_C(__val) __val
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifndef UINT8_C
|
||||
#define UINT8_C(__val) __val
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#ifndef INT16_C
|
||||
#define INT16_C(__val) __val
|
||||
#endif
|
||||
#ifndef UINT16_C
|
||||
#define UINT16_C(__val) __val
|
||||
#endif
|
||||
#ifndef INT32_C
|
||||
#define INT32_C(__val) __val
|
||||
#endif
|
||||
#ifndef UINT32_C
|
||||
#define UINT32_C(__val) __val##U
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// 7.18.1 Integer types
|
||||
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
#if defined(_WIN64)
|
||||
typedef __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef __int32 intptr_t;
|
||||
typedef unsigned __int32 uintptr_t;
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#define INT64_C(__val) __val##i64
|
||||
#define UINT64_C(__val) __val##ui64
|
||||
|
||||
#else
|
||||
#error "Unsupported compiler"
|
||||
#endif
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
#endif /* _STDINT_H_ */
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
|
|
|
|||
|
|
@ -291,6 +291,8 @@ def generate(env):
|
|||
]
|
||||
if env['machine'] == 'x86_64':
|
||||
ccflags += ['-m64']
|
||||
if platform == 'darwin':
|
||||
ccflags += ['-fno-common']
|
||||
# See also:
|
||||
# - http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
|
||||
ccflags += [
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ if 'egl' in env['statetrackers']:
|
|||
SConscript('egl/main/SConscript')
|
||||
|
||||
if 'mesa' in env['statetrackers']:
|
||||
if platform == 'windows':
|
||||
SConscript('talloc/SConscript')
|
||||
|
||||
SConscript('glsl/SConscript')
|
||||
SConscript('mapi/glapi/SConscript')
|
||||
SConscript('mesa/SConscript')
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ Contact
|
|||
|
||||
Status
|
||||
|
||||
Preliminary - totally subject to change.
|
||||
Obsolete.
|
||||
|
||||
Version
|
||||
|
||||
|
|
|
|||
|
|
@ -836,6 +836,7 @@ dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp,
|
|||
goto cleanup_configs;
|
||||
}
|
||||
|
||||
disp->Extensions.MESA_drm_image = EGL_TRUE;
|
||||
disp->Extensions.KHR_image_base = EGL_TRUE;
|
||||
disp->Extensions.KHR_image_pixmap = EGL_TRUE;
|
||||
disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
|
||||
|
|
@ -994,6 +995,7 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp,
|
|||
for (i = 0; dri2_dpy->driver_configs[i]; i++)
|
||||
dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0);
|
||||
|
||||
disp->Extensions.MESA_drm_image = EGL_TRUE;
|
||||
disp->Extensions.KHR_image_base = EGL_TRUE;
|
||||
disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
|
||||
disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
|
||||
|
|
@ -1620,6 +1622,96 @@ dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
|
|||
return &dri2_img->base;
|
||||
}
|
||||
|
||||
static _EGLImage *
|
||||
dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
|
||||
EGLClientBuffer buffer, const EGLint *attr_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
|
||||
struct dri2_egl_image *dri2_img;
|
||||
EGLint width, height, format, name, stride, pitch, i, err;
|
||||
|
||||
name = (EGLint) buffer;
|
||||
|
||||
err = EGL_SUCCESS;
|
||||
width = 0;
|
||||
height = 0;
|
||||
format = 0;
|
||||
stride = 0;
|
||||
|
||||
for (i = 0; attr_list[i] != EGL_NONE; i++) {
|
||||
EGLint attr = attr_list[i++];
|
||||
EGLint val = attr_list[i];
|
||||
|
||||
switch (attr) {
|
||||
case EGL_WIDTH:
|
||||
width = val;
|
||||
break;
|
||||
case EGL_HEIGHT:
|
||||
height = val;
|
||||
break;
|
||||
case EGL_DRM_BUFFER_FORMAT_MESA:
|
||||
format = val;
|
||||
break;
|
||||
case EGL_DRM_BUFFER_STRIDE_MESA:
|
||||
stride = val;
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err != EGL_SUCCESS) {
|
||||
_eglLog(_EGL_WARNING, "bad image attribute 0x%04x", attr);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (width <= 0 || height <= 0 || stride <= 0) {
|
||||
_eglError(EGL_BAD_PARAMETER,
|
||||
"bad width, height or stride");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
|
||||
format = __DRI_IMAGE_FORMAT_ARGB8888;
|
||||
pitch = stride;
|
||||
break;
|
||||
default:
|
||||
_eglError(EGL_BAD_PARAMETER,
|
||||
"dri2_create_image_khr: unsupported pixmap depth");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dri2_img = malloc(sizeof *dri2_img);
|
||||
if (!dri2_img) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
|
||||
free(dri2_img);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dri2_img->dri_image =
|
||||
dri2_dpy->image->createImageFromName(dri2_ctx->dri_context,
|
||||
width,
|
||||
height,
|
||||
format,
|
||||
name,
|
||||
pitch,
|
||||
dri2_img);
|
||||
if (dri2_img->dri_image == NULL) {
|
||||
free(dri2_img);
|
||||
_eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &dri2_img->base;
|
||||
}
|
||||
|
||||
static _EGLImage *
|
||||
dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
|
||||
_EGLContext *ctx, EGLenum target,
|
||||
|
|
@ -1630,6 +1722,8 @@ dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
|
|||
return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
|
||||
case EGL_GL_RENDERBUFFER_KHR:
|
||||
return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
|
||||
case EGL_DRM_BUFFER_MESA:
|
||||
return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
|
||||
default:
|
||||
_eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
|
|
@ -1648,6 +1742,133 @@ dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
|
|||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
static _EGLImage *
|
||||
dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
|
||||
const EGLint *attr_list)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_image *dri2_img;
|
||||
int width, height, format, i;
|
||||
unsigned int use, dri_use, valid_mask;
|
||||
EGLint err = EGL_SUCCESS;
|
||||
|
||||
dri2_img = malloc(sizeof *dri2_img);
|
||||
if (!dri2_img) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
if (!attr_list) {
|
||||
err = EGL_BAD_PARAMETER;
|
||||
goto cleanup_img;
|
||||
}
|
||||
|
||||
if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
|
||||
err = EGL_BAD_PARAMETER;
|
||||
goto cleanup_img;
|
||||
}
|
||||
|
||||
width = 0;
|
||||
height = 0;
|
||||
format = 0;
|
||||
use = 0;
|
||||
for (i = 0; attr_list[i] != EGL_NONE; i++) {
|
||||
EGLint attr = attr_list[i++];
|
||||
EGLint val = attr_list[i];
|
||||
|
||||
switch (attr) {
|
||||
case EGL_WIDTH:
|
||||
width = val;
|
||||
break;
|
||||
case EGL_HEIGHT:
|
||||
height = val;
|
||||
break;
|
||||
case EGL_DRM_BUFFER_FORMAT_MESA:
|
||||
format = val;
|
||||
break;
|
||||
case EGL_DRM_BUFFER_USE_MESA:
|
||||
use = val;
|
||||
break;
|
||||
default:
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err != EGL_SUCCESS) {
|
||||
_eglLog(_EGL_WARNING, "bad image attribute 0x%04x", attr);
|
||||
goto cleanup_img;
|
||||
}
|
||||
}
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
_eglLog(_EGL_WARNING, "bad width or height (%dx%d)", width, height);
|
||||
goto cleanup_img;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
|
||||
format = __DRI_IMAGE_FORMAT_ARGB8888;
|
||||
break;
|
||||
default:
|
||||
_eglLog(_EGL_WARNING, "bad image format value 0x%04x", format);
|
||||
goto cleanup_img;
|
||||
}
|
||||
|
||||
valid_mask =
|
||||
EGL_DRM_BUFFER_USE_SCANOUT_MESA |
|
||||
EGL_DRM_BUFFER_USE_SHARE_MESA;
|
||||
if (use & ~valid_mask) {
|
||||
_eglLog(_EGL_WARNING, "bad image use bit 0x%04x", use & ~valid_mask);
|
||||
goto cleanup_img;
|
||||
}
|
||||
|
||||
dri_use = 0;
|
||||
if (use & EGL_DRM_BUFFER_USE_SHARE_MESA)
|
||||
dri_use |= __DRI_IMAGE_USE_SHARE;
|
||||
if (use & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
|
||||
dri_use |= __DRI_IMAGE_USE_SCANOUT;
|
||||
|
||||
dri2_img->dri_image =
|
||||
dri2_dpy->image->createImage(dri2_dpy->dri_screen,
|
||||
width, height, format, dri_use, dri2_img);
|
||||
if (dri2_img->dri_image == NULL) {
|
||||
err = EGL_BAD_ALLOC;
|
||||
goto cleanup_img;
|
||||
}
|
||||
|
||||
return &dri2_img->base;
|
||||
|
||||
cleanup_img:
|
||||
free(dri2_img);
|
||||
_eglError(err, "dri2_create_drm_image_mesa");
|
||||
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
static EGLBoolean
|
||||
dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
|
||||
EGLint *name, EGLint *handle, EGLint *stride)
|
||||
{
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
||||
struct dri2_egl_image *dri2_img = dri2_egl_image(img);
|
||||
|
||||
if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
|
||||
__DRI_IMAGE_ATTRIB_NAME, name)) {
|
||||
_eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
if (handle)
|
||||
dri2_dpy->image->queryImage(dri2_img->dri_image,
|
||||
__DRI_IMAGE_ATTRIB_HANDLE, handle);
|
||||
|
||||
if (stride)
|
||||
dri2_dpy->image->queryImage(dri2_img->dri_image,
|
||||
__DRI_IMAGE_ATTRIB_STRIDE, stride);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main entrypoint into the driver, called by libEGL.
|
||||
* Create a new _EGLDriver object and init its dispatch table.
|
||||
|
|
@ -1681,6 +1902,8 @@ _eglMain(const char *args)
|
|||
dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr;
|
||||
dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
|
||||
dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
|
||||
dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
|
||||
dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
|
||||
|
||||
dri2_drv->base.Name = "DRI2";
|
||||
dri2_drv->base.Unload = dri2_unload;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ HEADERS = \
|
|||
eglmutex.h \
|
||||
eglscreen.h \
|
||||
eglstring.h \
|
||||
eglsurface.h
|
||||
eglsurface.h \
|
||||
eglsync.h
|
||||
|
||||
SOURCES = \
|
||||
eglapi.c \
|
||||
|
|
@ -44,7 +45,8 @@ SOURCES = \
|
|||
eglmode.c \
|
||||
eglscreen.c \
|
||||
eglstring.c \
|
||||
eglsurface.c
|
||||
eglsurface.c \
|
||||
eglsync.c
|
||||
|
||||
OBJECTS = $(SOURCES:.c=.o)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ if env['platform'] != 'winddk':
|
|||
'_EGL_NATIVE_PLATFORM=_EGL_PLATFORM_WINDOWS',
|
||||
'_EGL_DRIVER_SEARCH_DIR=\\"\\"',
|
||||
'_EGL_OS_WINDOWS',
|
||||
'_EGL_GET_CORE_ADDRESSES',
|
||||
'KHRONOS_DLL_EXPORTS',
|
||||
])
|
||||
|
||||
|
|
@ -36,11 +37,12 @@ if env['platform'] != 'winddk':
|
|||
'eglscreen.c',
|
||||
'eglstring.c',
|
||||
'eglsurface.c',
|
||||
'eglsync.c',
|
||||
]
|
||||
|
||||
egl = env.SharedLibrary(
|
||||
target = 'libEGL',
|
||||
source = egl_sources,
|
||||
source = egl_sources + ['egl.def'],
|
||||
)
|
||||
|
||||
env.InstallSharedLibrary(egl, version=(1, 4, 0))
|
||||
|
|
|
|||
35
src/egl/main/egl.def
Normal file
35
src/egl/main/egl.def
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
EXPORTS
|
||||
eglBindAPI
|
||||
eglBindTexImage
|
||||
eglChooseConfig
|
||||
eglCopyBuffers
|
||||
eglCreateContext
|
||||
eglCreatePbufferFromClientBuffer
|
||||
eglCreatePbufferSurface
|
||||
eglCreatePixmapSurface
|
||||
eglCreateWindowSurface
|
||||
eglDestroyContext
|
||||
eglDestroySurface
|
||||
eglGetConfigAttrib
|
||||
eglGetConfigs
|
||||
eglGetCurrentContext
|
||||
eglGetCurrentDisplay
|
||||
eglGetCurrentSurface
|
||||
eglGetDisplay
|
||||
eglGetError
|
||||
eglGetProcAddress
|
||||
eglInitialize
|
||||
eglMakeCurrent
|
||||
eglQueryAPI
|
||||
eglQueryContext
|
||||
eglQueryString
|
||||
eglQuerySurface
|
||||
eglReleaseTexImage
|
||||
eglReleaseThread
|
||||
eglSurfaceAttrib
|
||||
eglSwapBuffers
|
||||
eglSwapInterval
|
||||
eglTerminate
|
||||
eglWaitClient
|
||||
eglWaitGL
|
||||
eglWaitNative
|
||||
|
|
@ -68,6 +68,7 @@
|
|||
#include "eglscreen.h"
|
||||
#include "eglmode.h"
|
||||
#include "eglimage.h"
|
||||
#include "eglsync.h"
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -126,6 +127,8 @@
|
|||
#define _EGL_CHECK_MODE(disp, m, ret, drv) \
|
||||
_EGL_CHECK_OBJECT(disp, Mode, m, ret, drv)
|
||||
|
||||
#define _EGL_CHECK_SYNC(disp, s, ret, drv) \
|
||||
_EGL_CHECK_OBJECT(disp, Sync, s, ret, drv)
|
||||
|
||||
|
||||
static INLINE _EGLDriver *
|
||||
|
|
@ -185,6 +188,26 @@ _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
|
|||
}
|
||||
|
||||
|
||||
#ifdef EGL_KHR_reusable_sync
|
||||
|
||||
|
||||
static INLINE _EGLDriver *
|
||||
_eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
|
||||
{
|
||||
_EGLDriver *drv = _eglCheckDisplay(disp, msg);
|
||||
if (!drv)
|
||||
return NULL;
|
||||
if (!s) {
|
||||
_eglError(EGL_BAD_PARAMETER, msg);
|
||||
return NULL;
|
||||
}
|
||||
return drv;
|
||||
}
|
||||
|
||||
|
||||
#endif /* EGL_KHR_reusable_sync */
|
||||
|
||||
|
||||
#ifdef EGL_MESA_screen_surface
|
||||
|
||||
|
||||
|
|
@ -809,7 +832,44 @@ eglGetProcAddress(const char *procname)
|
|||
const char *name;
|
||||
_EGLProc function;
|
||||
} egl_functions[] = {
|
||||
/* extensions only */
|
||||
/* core functions should not be queryable, but, well... */
|
||||
#ifdef _EGL_GET_CORE_ADDRESSES
|
||||
/* alphabetical order */
|
||||
{ "eglBindAPI", (_EGLProc) eglBindAPI },
|
||||
{ "eglBindTexImage", (_EGLProc) eglBindTexImage },
|
||||
{ "eglChooseConfig", (_EGLProc) eglChooseConfig },
|
||||
{ "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
|
||||
{ "eglCreateContext", (_EGLProc) eglCreateContext },
|
||||
{ "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
|
||||
{ "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
|
||||
{ "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
|
||||
{ "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
|
||||
{ "eglDestroyContext", (_EGLProc) eglDestroyContext },
|
||||
{ "eglDestroySurface", (_EGLProc) eglDestroySurface },
|
||||
{ "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
|
||||
{ "eglGetConfigs", (_EGLProc) eglGetConfigs },
|
||||
{ "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
|
||||
{ "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
|
||||
{ "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
|
||||
{ "eglGetDisplay", (_EGLProc) eglGetDisplay },
|
||||
{ "eglGetError", (_EGLProc) eglGetError },
|
||||
{ "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
|
||||
{ "eglInitialize", (_EGLProc) eglInitialize },
|
||||
{ "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
|
||||
{ "eglQueryAPI", (_EGLProc) eglQueryAPI },
|
||||
{ "eglQueryContext", (_EGLProc) eglQueryContext },
|
||||
{ "eglQueryString", (_EGLProc) eglQueryString },
|
||||
{ "eglQuerySurface", (_EGLProc) eglQuerySurface },
|
||||
{ "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
|
||||
{ "eglReleaseThread", (_EGLProc) eglReleaseThread },
|
||||
{ "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
|
||||
{ "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
|
||||
{ "eglSwapInterval", (_EGLProc) eglSwapInterval },
|
||||
{ "eglTerminate", (_EGLProc) eglTerminate },
|
||||
{ "eglWaitClient", (_EGLProc) eglWaitClient },
|
||||
{ "eglWaitGL", (_EGLProc) eglWaitGL },
|
||||
{ "eglWaitNative", (_EGLProc) eglWaitNative },
|
||||
#endif /* _EGL_GET_CORE_ADDRESSES */
|
||||
#ifdef EGL_MESA_screen_surface
|
||||
{ "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
|
||||
{ "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
|
||||
|
|
@ -833,6 +893,10 @@ eglGetProcAddress(const char *procname)
|
|||
#endif /* EGL_KHR_image_base */
|
||||
#ifdef EGL_NOK_swap_region
|
||||
{ "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
|
||||
#endif
|
||||
#ifdef EGL_MESA_drm_image
|
||||
{ "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
|
||||
{ "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
|
||||
#endif
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
@ -1245,6 +1309,90 @@ eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
|
|||
#endif /* EGL_KHR_image_base */
|
||||
|
||||
|
||||
#ifdef EGL_KHR_reusable_sync
|
||||
|
||||
|
||||
EGLSyncKHR EGLAPIENTRY
|
||||
eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLockDisplay(dpy);
|
||||
_EGLDriver *drv;
|
||||
_EGLSync *sync;
|
||||
EGLSyncKHR ret;
|
||||
|
||||
_EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
|
||||
|
||||
sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
|
||||
ret = (sync) ? _eglLinkSync(sync, disp) : EGL_NO_SYNC_KHR;
|
||||
|
||||
RETURN_EGL_EVAL(disp, ret);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean EGLAPIENTRY
|
||||
eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLockDisplay(dpy);
|
||||
_EGLSync *s = _eglLookupSync(sync, disp);
|
||||
_EGLDriver *drv;
|
||||
EGLBoolean ret;
|
||||
|
||||
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
|
||||
_eglUnlinkSync(s);
|
||||
ret = drv->API.DestroySyncKHR(drv, disp, s);
|
||||
|
||||
RETURN_EGL_EVAL(disp, ret);
|
||||
}
|
||||
|
||||
|
||||
EGLint EGLAPIENTRY
|
||||
eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLockDisplay(dpy);
|
||||
_EGLSync *s = _eglLookupSync(sync, disp);
|
||||
_EGLDriver *drv;
|
||||
EGLint ret;
|
||||
|
||||
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
|
||||
ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
|
||||
|
||||
RETURN_EGL_EVAL(disp, ret);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean EGLAPIENTRY
|
||||
eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLockDisplay(dpy);
|
||||
_EGLSync *s = _eglLookupSync(sync, disp);
|
||||
_EGLDriver *drv;
|
||||
EGLBoolean ret;
|
||||
|
||||
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
|
||||
ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
|
||||
|
||||
RETURN_EGL_EVAL(disp, ret);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean EGLAPIENTRY
|
||||
eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLockDisplay(dpy);
|
||||
_EGLSync *s = _eglLookupSync(sync, disp);
|
||||
_EGLDriver *drv;
|
||||
EGLBoolean ret;
|
||||
|
||||
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
|
||||
ret = drv->API.GetSyncAttribKHR(drv, disp, s, attribute, value);
|
||||
|
||||
RETURN_EGL_EVAL(disp, ret);
|
||||
}
|
||||
|
||||
|
||||
#endif /* EGL_KHR_reusable_sync */
|
||||
|
||||
|
||||
#ifdef EGL_NOK_swap_region
|
||||
|
||||
EGLBoolean EGLAPIENTRY
|
||||
|
|
@ -1272,3 +1420,42 @@ eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
|
|||
}
|
||||
|
||||
#endif /* EGL_NOK_swap_region */
|
||||
|
||||
|
||||
#ifdef EGL_MESA_drm_image
|
||||
|
||||
EGLImageKHR EGLAPIENTRY
|
||||
eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLockDisplay(dpy);
|
||||
_EGLDriver *drv;
|
||||
_EGLImage *img;
|
||||
EGLImageKHR ret;
|
||||
|
||||
_EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
|
||||
|
||||
img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
|
||||
ret = (img) ? _eglLinkImage(img, disp) : EGL_NO_IMAGE_KHR;
|
||||
|
||||
RETURN_EGL_EVAL(disp, ret);
|
||||
}
|
||||
|
||||
EGLBoolean EGLAPIENTRY
|
||||
eglExportDRMImageMESA(EGLDisplay dpy, EGLImageKHR image,
|
||||
EGLint *name, EGLint *handle, EGLint *stride)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLockDisplay(dpy);
|
||||
_EGLImage *img = _eglLookupImage(image, disp);
|
||||
_EGLDriver *drv;
|
||||
EGLBoolean ret;
|
||||
|
||||
_EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
|
||||
if (!img)
|
||||
RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
|
||||
|
||||
ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
|
||||
|
||||
RETURN_EGL_EVAL(disp, ret);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -76,10 +76,25 @@ typedef _EGLImage *(*CreateImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLCo
|
|||
typedef EGLBoolean (*DestroyImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
|
||||
#endif /* EGL_KHR_image_base */
|
||||
|
||||
|
||||
#ifdef EGL_KHR_reusable_sync
|
||||
typedef _EGLSync *(*CreateSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum type, const EGLint *attrib_list);
|
||||
typedef EGLBoolean (*DestroySyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync);
|
||||
typedef EGLint (*ClientWaitSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, EGLint flags, EGLTimeKHR timeout);
|
||||
typedef EGLBoolean (*SignalSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, EGLenum mode);
|
||||
typedef EGLBoolean (*GetSyncAttribKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, EGLint attribute, EGLint *value);
|
||||
#endif /* EGL_KHR_reusable_sync */
|
||||
|
||||
|
||||
#ifdef EGL_NOK_swap_region
|
||||
typedef EGLBoolean (*SwapBuffersRegionNOK_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, EGLint numRects, const EGLint *rects);
|
||||
#endif
|
||||
|
||||
#ifdef EGL_MESA_drm_image
|
||||
typedef _EGLImage *(*CreateDRMImageMESA_t)(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attr_list);
|
||||
typedef EGLBoolean (*ExportDRMImageMESA_t)(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, EGLint *name, EGLint *handle, EGLint *stride);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The API dispatcher jumps through these functions
|
||||
*/
|
||||
|
|
@ -138,9 +153,22 @@ struct _egl_api
|
|||
DestroyImageKHR_t DestroyImageKHR;
|
||||
#endif /* EGL_KHR_image_base */
|
||||
|
||||
#ifdef EGL_KHR_reusable_sync
|
||||
CreateSyncKHR_t CreateSyncKHR;
|
||||
DestroySyncKHR_t DestroySyncKHR;
|
||||
ClientWaitSyncKHR_t ClientWaitSyncKHR;
|
||||
SignalSyncKHR_t SignalSyncKHR;
|
||||
GetSyncAttribKHR_t GetSyncAttribKHR;
|
||||
#endif /* EGL_KHR_reusable_sync */
|
||||
|
||||
#ifdef EGL_NOK_swap_region
|
||||
SwapBuffersRegionNOK_t SwapBuffersRegionNOK;
|
||||
#endif
|
||||
|
||||
#ifdef EGL_MESA_drm_image
|
||||
CreateDRMImageMESA_t CreateDRMImageMESA;
|
||||
ExportDRMImageMESA_t ExportDRMImageMESA;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* EGLAPI_INCLUDED */
|
||||
|
|
|
|||
|
|
@ -460,11 +460,14 @@ _eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
|
|||
}
|
||||
|
||||
if (!matched) {
|
||||
#ifdef DEBUG
|
||||
#ifndef DEBUG
|
||||
/* only print the common errors when DEBUG is not defined */
|
||||
if (attr != EGL_RENDERABLE_TYPE)
|
||||
break;
|
||||
#endif
|
||||
_eglLog(_EGL_DEBUG,
|
||||
"the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)",
|
||||
val, attr, cmp);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,15 +83,6 @@ _eglParseContextAttribList(_EGLContext *ctx, const EGLint *attrib_list)
|
|||
}
|
||||
}
|
||||
|
||||
if (err == EGL_SUCCESS && ctx->Config) {
|
||||
EGLint renderable_type, api_bit;
|
||||
|
||||
renderable_type = GET_CONFIG_ATTRIB(ctx->Config, EGL_RENDERABLE_TYPE);
|
||||
api_bit = _eglGetContextAPIBit(ctx);
|
||||
if (!(renderable_type & api_bit))
|
||||
err = EGL_BAD_CONFIG;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -121,6 +112,17 @@ _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
|
|||
ctx->ClientVersion = 1; /* the default, per EGL spec */
|
||||
|
||||
err = _eglParseContextAttribList(ctx, attrib_list);
|
||||
if (err == EGL_SUCCESS && ctx->Config) {
|
||||
EGLint renderable_type, api_bit;
|
||||
|
||||
renderable_type = GET_CONFIG_ATTRIB(ctx->Config, EGL_RENDERABLE_TYPE);
|
||||
api_bit = _eglGetContextAPIBit(ctx);
|
||||
if (!(renderable_type & api_bit)) {
|
||||
_eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
|
||||
api_bit, renderable_type);
|
||||
err = EGL_BAD_CONFIG;
|
||||
}
|
||||
}
|
||||
if (err != EGL_SUCCESS)
|
||||
return _eglError(err, "eglCreateContext");
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ enum _egl_resource_type {
|
|||
_EGL_RESOURCE_CONTEXT,
|
||||
_EGL_RESOURCE_SURFACE,
|
||||
_EGL_RESOURCE_IMAGE,
|
||||
_EGL_RESOURCE_SYNC,
|
||||
|
||||
_EGL_NUM_RESOURCES
|
||||
};
|
||||
|
|
@ -53,6 +54,8 @@ struct _egl_extensions
|
|||
EGLBoolean MESA_screen_surface;
|
||||
EGLBoolean MESA_copy_context;
|
||||
EGLBoolean MESA_drm_display;
|
||||
EGLBoolean MESA_drm_image;
|
||||
|
||||
EGLBoolean KHR_image_base;
|
||||
EGLBoolean KHR_image_pixmap;
|
||||
EGLBoolean KHR_vg_parent_image;
|
||||
|
|
@ -60,9 +63,14 @@ struct _egl_extensions
|
|||
EGLBoolean KHR_gl_texture_cubemap_image;
|
||||
EGLBoolean KHR_gl_texture_3D_image;
|
||||
EGLBoolean KHR_gl_renderbuffer_image;
|
||||
|
||||
EGLBoolean KHR_reusable_sync;
|
||||
EGLBoolean KHR_fence_sync;
|
||||
|
||||
EGLBoolean KHR_surfaceless_gles1;
|
||||
EGLBoolean KHR_surfaceless_gles2;
|
||||
EGLBoolean KHR_surfaceless_opengl;
|
||||
|
||||
EGLBoolean NOK_swap_region;
|
||||
EGLBoolean NOK_texture_from_pixmap;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "eglstring.h"
|
||||
#include "eglsurface.h"
|
||||
#include "eglimage.h"
|
||||
#include "eglsync.h"
|
||||
#include "eglmutex.h"
|
||||
|
||||
#if defined(_EGL_OS_UNIX)
|
||||
|
|
@ -722,6 +723,14 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
|
|||
drv->API.CreateImageKHR = _eglCreateImageKHR;
|
||||
drv->API.DestroyImageKHR = _eglDestroyImageKHR;
|
||||
#endif /* EGL_KHR_image_base */
|
||||
|
||||
#ifdef EGL_KHR_reusable_sync
|
||||
drv->API.CreateSyncKHR = _eglCreateSyncKHR;
|
||||
drv->API.DestroySyncKHR = _eglDestroySyncKHR;
|
||||
drv->API.ClientWaitSyncKHR = _eglClientWaitSyncKHR;
|
||||
drv->API.SignalSyncKHR = _eglSignalSyncKHR;
|
||||
drv->API.GetSyncAttribKHR = _eglGetSyncAttribKHR;
|
||||
#endif /* EGL_KHR_reusable_sync */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
|
|||
_EGL_CHECK_EXTENSION(MESA_screen_surface);
|
||||
_EGL_CHECK_EXTENSION(MESA_copy_context);
|
||||
_EGL_CHECK_EXTENSION(MESA_drm_display);
|
||||
_EGL_CHECK_EXTENSION(MESA_drm_image);
|
||||
|
||||
_EGL_CHECK_EXTENSION(KHR_image_base);
|
||||
_EGL_CHECK_EXTENSION(KHR_image_pixmap);
|
||||
|
|
@ -97,6 +98,9 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
|
|||
_EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
|
||||
_EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
|
||||
|
||||
_EGL_CHECK_EXTENSION(KHR_reusable_sync);
|
||||
_EGL_CHECK_EXTENSION(KHR_fence_sync);
|
||||
|
||||
_EGL_CHECK_EXTENSION(KHR_surfaceless_gles1);
|
||||
_EGL_CHECK_EXTENSION(KHR_surfaceless_gles2);
|
||||
_EGL_CHECK_EXTENSION(KHR_surfaceless_opengl);
|
||||
|
|
|
|||
128
src/egl/main/eglsync.c
Normal file
128
src/egl/main/eglsync.c
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "eglsync.h"
|
||||
#include "eglcurrent.h"
|
||||
#include "egllog.h"
|
||||
|
||||
|
||||
#ifdef EGL_KHR_reusable_sync
|
||||
|
||||
|
||||
/**
|
||||
* Parse the list of sync attributes and return the proper error code.
|
||||
*/
|
||||
static EGLint
|
||||
_eglParseSyncAttribList(_EGLSync *sync, const EGLint *attrib_list)
|
||||
{
|
||||
EGLint i, err = EGL_SUCCESS;
|
||||
|
||||
if (!attrib_list)
|
||||
return EGL_SUCCESS;
|
||||
|
||||
for (i = 0; attrib_list[i] != EGL_NONE; i++) {
|
||||
EGLint attr = attrib_list[i++];
|
||||
EGLint val = attrib_list[i];
|
||||
|
||||
switch (attr) {
|
||||
default:
|
||||
(void) val;
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err != EGL_SUCCESS) {
|
||||
_eglLog(_EGL_DEBUG, "bad sync attribute 0x%04x", attr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
|
||||
const EGLint *attrib_list)
|
||||
{
|
||||
EGLint err;
|
||||
|
||||
if (!(type == EGL_SYNC_REUSABLE_KHR && dpy->Extensions.KHR_reusable_sync) &&
|
||||
!(type == EGL_SYNC_FENCE_KHR && dpy->Extensions.KHR_fence_sync))
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
|
||||
|
||||
memset(sync, 0, sizeof(*sync));
|
||||
|
||||
sync->Resource.Display = dpy;
|
||||
|
||||
sync->Type = type;
|
||||
sync->SyncStatus = EGL_UNSIGNALED_KHR;
|
||||
sync->SyncCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
|
||||
|
||||
err = _eglParseSyncAttribList(sync, attrib_list);
|
||||
if (err != EGL_SUCCESS)
|
||||
return _eglError(err, "eglCreateSyncKHR");
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
_EGLSync *
|
||||
_eglCreateSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||
EGLenum type, const EGLint *attrib_list)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglDestroySyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync)
|
||||
{
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
EGLint
|
||||
_eglClientWaitSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
|
||||
EGLint flags, EGLTimeKHR timeout)
|
||||
{
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglSignalSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
|
||||
EGLenum mode)
|
||||
{
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglGetSyncAttribKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
|
||||
EGLint attribute, EGLint *value)
|
||||
{
|
||||
if (!value)
|
||||
return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs");
|
||||
|
||||
switch (attribute) {
|
||||
case EGL_SYNC_TYPE_KHR:
|
||||
*value = sync->Type;
|
||||
break;
|
||||
case EGL_SYNC_STATUS_KHR:
|
||||
*value = sync->SyncStatus;
|
||||
break;
|
||||
case EGL_SYNC_CONDITION_KHR:
|
||||
if (sync->Type != EGL_SYNC_FENCE_KHR)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglGetSyncAttribKHR");
|
||||
*value = sync->SyncCondition;
|
||||
break;
|
||||
default:
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglGetSyncAttribKHR");
|
||||
break;
|
||||
}
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
#endif /* EGL_KHR_reusable_sync */
|
||||
120
src/egl/main/eglsync.h
Normal file
120
src/egl/main/eglsync.h
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
#ifndef EGLSYNC_INCLUDED
|
||||
#define EGLSYNC_INCLUDED
|
||||
|
||||
|
||||
#include "egltypedefs.h"
|
||||
#include "egldisplay.h"
|
||||
|
||||
|
||||
#ifdef EGL_KHR_reusable_sync
|
||||
|
||||
|
||||
/**
|
||||
* "Base" class for device driver syncs.
|
||||
*/
|
||||
struct _egl_sync
|
||||
{
|
||||
/* A sync is a display resource */
|
||||
_EGLResource Resource;
|
||||
|
||||
EGLenum Type;
|
||||
EGLenum SyncStatus;
|
||||
EGLenum SyncCondition;
|
||||
};
|
||||
|
||||
|
||||
PUBLIC EGLBoolean
|
||||
_eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
|
||||
const EGLint *attrib_list);
|
||||
|
||||
|
||||
extern _EGLSync *
|
||||
_eglCreateSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||
EGLenum type, const EGLint *attrib_list);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglDestroySyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync);
|
||||
|
||||
|
||||
extern EGLint
|
||||
_eglClientWaitSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
|
||||
EGLint flags, EGLTimeKHR timeout);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglSignalSyncKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
|
||||
EGLenum mode);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglGetSyncAttribKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
|
||||
EGLint attribute, EGLint *value);
|
||||
|
||||
|
||||
/**
|
||||
* Link a sync to a display and return the handle of the link.
|
||||
* The handle can be passed to client directly.
|
||||
*/
|
||||
static INLINE EGLSyncKHR
|
||||
_eglLinkSync(_EGLSync *sync, _EGLDisplay *dpy)
|
||||
{
|
||||
_eglLinkResource(&sync->Resource, _EGL_RESOURCE_SYNC, dpy);
|
||||
return (EGLSyncKHR) sync;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unlink a linked sync from its display.
|
||||
*/
|
||||
static INLINE void
|
||||
_eglUnlinkSync(_EGLSync *sync)
|
||||
{
|
||||
_eglUnlinkResource(&sync->Resource, _EGL_RESOURCE_SYNC);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lookup a handle to find the linked sync.
|
||||
* Return NULL if the handle has no corresponding linked sync.
|
||||
*/
|
||||
static INLINE _EGLSync *
|
||||
_eglLookupSync(EGLSyncKHR handle, _EGLDisplay *dpy)
|
||||
{
|
||||
_EGLSync *sync = (_EGLSync *) handle;
|
||||
if (!dpy || !_eglCheckResource((void *) sync, _EGL_RESOURCE_SYNC, dpy))
|
||||
sync = NULL;
|
||||
return sync;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the handle of a linked sync, or EGL_NO_SYNC_KHR.
|
||||
*/
|
||||
static INLINE EGLSyncKHR
|
||||
_eglGetSyncHandle(_EGLSync *sync)
|
||||
{
|
||||
_EGLResource *res = (_EGLResource *) sync;
|
||||
return (res && _eglIsResourceLinked(res)) ?
|
||||
(EGLSyncKHR) sync : EGL_NO_SYNC_KHR;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if the sync is linked to a display.
|
||||
*
|
||||
* The link is considered a reference to the sync (the display is owning the
|
||||
* sync). Drivers should not destroy a sync when it is linked.
|
||||
*/
|
||||
static INLINE EGLBoolean
|
||||
_eglIsSyncLinked(_EGLSync *sync)
|
||||
{
|
||||
_EGLResource *res = (_EGLResource *) sync;
|
||||
return (res && _eglIsResourceLinked(res));
|
||||
}
|
||||
|
||||
|
||||
#endif /* EGL_KHR_reusable_sync */
|
||||
|
||||
|
||||
#endif /* EGLSYNC_INCLUDED */
|
||||
|
|
@ -32,6 +32,8 @@ typedef struct _egl_screen _EGLScreen;
|
|||
|
||||
typedef struct _egl_surface _EGLSurface;
|
||||
|
||||
typedef struct _egl_sync _EGLSync;
|
||||
|
||||
typedef struct _egl_thread_info _EGLThreadInfo;
|
||||
|
||||
#endif /* EGLTYPEDEFS_INCLUDED */
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ include $(TOP)/configs/current
|
|||
LIBNAME = gallium
|
||||
|
||||
C_SOURCES = \
|
||||
cso_cache/cso_context.c \
|
||||
cso_cache/cso_cache.c \
|
||||
cso_cache/cso_context.c \
|
||||
cso_cache/cso_hash.c \
|
||||
draw/draw_context.c \
|
||||
draw/draw_gs.c \
|
||||
|
|
@ -26,7 +26,6 @@ C_SOURCES = \
|
|||
draw/draw_pipe_wide_line.c \
|
||||
draw/draw_pipe_wide_point.c \
|
||||
draw/draw_pt.c \
|
||||
draw/draw_pt_elts.c \
|
||||
draw/draw_pt_emit.c \
|
||||
draw/draw_pt_fetch.c \
|
||||
draw/draw_pt_fetch_emit.c \
|
||||
|
|
@ -35,24 +34,24 @@ C_SOURCES = \
|
|||
draw/draw_pt_post_vs.c \
|
||||
draw/draw_pt_so_emit.c \
|
||||
draw/draw_pt_util.c \
|
||||
draw/draw_pt_varray.c \
|
||||
draw/draw_pt_vcache.c \
|
||||
draw/draw_pt_vsplit.c \
|
||||
draw/draw_vertex.c \
|
||||
draw/draw_vs.c \
|
||||
draw/draw_vs_varient.c \
|
||||
draw/draw_vs_aos.c \
|
||||
draw/draw_vs_aos_io.c \
|
||||
draw/draw_vs_aos_machine.c \
|
||||
draw/draw_vs_exec.c \
|
||||
draw/draw_vs_ppc.c \
|
||||
draw/draw_vs_sse.c \
|
||||
draw/draw_vs_varient.c \
|
||||
indices/u_indices_gen.c \
|
||||
indices/u_unfilled_gen.c \
|
||||
os/os_misc.c \
|
||||
os/os_stream.c \
|
||||
os/os_stream_log.c \
|
||||
os/os_stream_null.c \
|
||||
os/os_stream_stdc.c \
|
||||
os/os_stream_str.c \
|
||||
os/os_stream_null.c \
|
||||
os/os_time.c \
|
||||
pipebuffer/pb_buffer_fenced.c \
|
||||
pipebuffer/pb_buffer_malloc.c \
|
||||
|
|
@ -65,17 +64,16 @@ C_SOURCES = \
|
|||
pipebuffer/pb_bufmgr_slab.c \
|
||||
pipebuffer/pb_validate.c \
|
||||
rbug/rbug_connection.c \
|
||||
rbug/rbug_core.c \
|
||||
rbug/rbug_texture.c \
|
||||
rbug/rbug_context.c \
|
||||
rbug/rbug_shader.c \
|
||||
rbug/rbug_core.c \
|
||||
rbug/rbug_demarshal.c \
|
||||
rbug/rbug_texture.c \
|
||||
rbug/rbug_shader.c \
|
||||
rtasm/rtasm_cpu.c \
|
||||
rtasm/rtasm_execmem.c \
|
||||
rtasm/rtasm_x86sse.c \
|
||||
rtasm/rtasm_ppc.c \
|
||||
rtasm/rtasm_ppc_spe.c \
|
||||
tgsi/tgsi_sanity.c \
|
||||
rtasm/rtasm_x86sse.c \
|
||||
tgsi/tgsi_build.c \
|
||||
tgsi/tgsi_dump.c \
|
||||
tgsi/tgsi_exec.c \
|
||||
|
|
@ -83,19 +81,22 @@ C_SOURCES = \
|
|||
tgsi/tgsi_iterate.c \
|
||||
tgsi/tgsi_parse.c \
|
||||
tgsi/tgsi_ppc.c \
|
||||
tgsi/tgsi_sanity.c \
|
||||
tgsi/tgsi_scan.c \
|
||||
tgsi/tgsi_sse2.c \
|
||||
tgsi/tgsi_text.c \
|
||||
tgsi/tgsi_transform.c \
|
||||
tgsi/tgsi_ureg.c \
|
||||
tgsi/tgsi_util.c \
|
||||
translate/translate_generic.c \
|
||||
translate/translate_sse.c \
|
||||
translate/translate.c \
|
||||
translate/translate_cache.c \
|
||||
translate/translate_generic.c \
|
||||
translate/translate_sse.c \
|
||||
util/u_debug.c \
|
||||
util/u_debug_symbol.c \
|
||||
util/u_debug_describe.c \
|
||||
util/u_debug_refcnt.c \
|
||||
util/u_debug_stack.c \
|
||||
util/u_debug_symbol.c \
|
||||
util/u_dump_defines.c \
|
||||
util/u_dump_state.c \
|
||||
util/u_bitmask.c \
|
||||
|
|
@ -118,10 +119,11 @@ C_SOURCES = \
|
|||
util/u_gen_mipmap.c \
|
||||
util/u_half.c \
|
||||
util/u_handle_table.c \
|
||||
util/u_hash_table.c \
|
||||
util/u_hash.c \
|
||||
util/u_hash_table.c \
|
||||
util/u_keymap.c \
|
||||
util/u_linear.c \
|
||||
util/u_linkage.c \
|
||||
util/u_network.c \
|
||||
util/u_math.c \
|
||||
util/u_mempool.c \
|
||||
|
|
@ -172,10 +174,10 @@ GALLIVM_SOURCES = \
|
|||
gallivm/lp_bld_tgsi_soa.c \
|
||||
gallivm/lp_bld_type.c \
|
||||
draw/draw_llvm.c \
|
||||
draw/draw_vs_llvm.c \
|
||||
draw/draw_pt_fetch_shade_pipeline_llvm.c \
|
||||
draw/draw_llvm_sample.c \
|
||||
draw/draw_llvm_translate.c \
|
||||
draw/draw_llvm_sample.c
|
||||
draw/draw_vs_llvm.c \
|
||||
draw/draw_pt_fetch_shade_pipeline_llvm.c
|
||||
|
||||
GALLIVM_CPP_SOURCES = \
|
||||
gallivm/lp_bld_misc.cpp
|
||||
|
|
|
|||
|
|
@ -50,10 +50,11 @@ env.Depends('util/u_format_table.c', [
|
|||
])
|
||||
|
||||
source = [
|
||||
'cso_cache/cso_context.c',
|
||||
'cso_cache/cso_cache.c',
|
||||
'cso_cache/cso_context.c',
|
||||
'cso_cache/cso_hash.c',
|
||||
'draw/draw_context.c',
|
||||
'draw/draw_gs.c',
|
||||
'draw/draw_pipe.c',
|
||||
'draw/draw_pipe_aaline.c',
|
||||
'draw/draw_pipe_aapoint.c',
|
||||
|
|
@ -71,7 +72,6 @@ source = [
|
|||
'draw/draw_pipe_wide_line.c',
|
||||
'draw/draw_pipe_wide_point.c',
|
||||
'draw/draw_pt.c',
|
||||
'draw/draw_pt_elts.c',
|
||||
'draw/draw_pt_emit.c',
|
||||
'draw/draw_pt_fetch.c',
|
||||
'draw/draw_pt_fetch_emit.c',
|
||||
|
|
@ -80,8 +80,7 @@ source = [
|
|||
'draw/draw_pt_post_vs.c',
|
||||
'draw/draw_pt_so_emit.c',
|
||||
'draw/draw_pt_util.c',
|
||||
'draw/draw_pt_varray.c',
|
||||
'draw/draw_pt_vcache.c',
|
||||
'draw/draw_pt_vsplit.c',
|
||||
'draw/draw_vertex.c',
|
||||
'draw/draw_vs.c',
|
||||
'draw/draw_vs_aos.c',
|
||||
|
|
@ -91,16 +90,16 @@ source = [
|
|||
'draw/draw_vs_ppc.c',
|
||||
'draw/draw_vs_sse.c',
|
||||
'draw/draw_vs_varient.c',
|
||||
'draw/draw_gs.c',
|
||||
#'indices/u_indices.c',
|
||||
#'indices/u_unfilled_indices.c',
|
||||
'indices/u_indices_gen.c',
|
||||
'indices/u_unfilled_gen.c',
|
||||
'os/os_misc.c',
|
||||
'os/os_stream.c',
|
||||
'os/os_stream_log.c',
|
||||
'os/os_stream_null.c',
|
||||
'os/os_stream_stdc.c',
|
||||
'os/os_stream_str.c',
|
||||
'os/os_stream_null.c',
|
||||
'os/os_time.c',
|
||||
'pipebuffer/pb_buffer_fenced.c',
|
||||
'pipebuffer/pb_buffer_malloc.c',
|
||||
|
|
@ -112,35 +111,35 @@ source = [
|
|||
'pipebuffer/pb_bufmgr_pool.c',
|
||||
'pipebuffer/pb_bufmgr_slab.c',
|
||||
'pipebuffer/pb_validate.c',
|
||||
'rbug/rbug_core.c',
|
||||
'rbug/rbug_shader.c',
|
||||
'rbug/rbug_context.c',
|
||||
'rbug/rbug_texture.c',
|
||||
'rbug/rbug_demarshal.c',
|
||||
'rbug/rbug_connection.c',
|
||||
'rbug/rbug_context.c',
|
||||
'rbug/rbug_core.c',
|
||||
'rbug/rbug_demarshal.c',
|
||||
'rbug/rbug_shader.c',
|
||||
'rbug/rbug_texture.c',
|
||||
'rtasm/rtasm_cpu.c',
|
||||
'rtasm/rtasm_execmem.c',
|
||||
'rtasm/rtasm_x86sse.c',
|
||||
'rtasm/rtasm_ppc.c',
|
||||
'rtasm/rtasm_ppc_spe.c',
|
||||
'rtasm/rtasm_x86sse.c',
|
||||
'tgsi/tgsi_build.c',
|
||||
'tgsi/tgsi_dump.c',
|
||||
'tgsi/tgsi_exec.c',
|
||||
'tgsi/tgsi_info.c',
|
||||
'tgsi/tgsi_iterate.c',
|
||||
'tgsi/tgsi_parse.c',
|
||||
'tgsi/tgsi_ppc.c',
|
||||
'tgsi/tgsi_sanity.c',
|
||||
'tgsi/tgsi_scan.c',
|
||||
'tgsi/tgsi_ppc.c',
|
||||
'tgsi/tgsi_sse2.c',
|
||||
'tgsi/tgsi_text.c',
|
||||
'tgsi/tgsi_transform.c',
|
||||
'tgsi/tgsi_ureg.c',
|
||||
'tgsi/tgsi_util.c',
|
||||
'translate/translate_generic.c',
|
||||
'translate/translate_sse.c',
|
||||
'translate/translate.c',
|
||||
'translate/translate_cache.c',
|
||||
'translate/translate_generic.c',
|
||||
'translate/translate_sse.c',
|
||||
'util/u_bitmask.c',
|
||||
'util/u_blit.c',
|
||||
'util/u_blitter.c',
|
||||
|
|
@ -148,7 +147,9 @@ source = [
|
|||
'util/u_caps.c',
|
||||
'util/u_cpu_detect.c',
|
||||
'util/u_debug.c',
|
||||
'util/u_debug_describe.c',
|
||||
'util/u_debug_memory.c',
|
||||
'util/u_debug_refcnt.c',
|
||||
'util/u_debug_stack.c',
|
||||
'util/u_debug_symbol.c',
|
||||
'util/u_dump_defines.c',
|
||||
|
|
@ -170,6 +171,8 @@ source = [
|
|||
'util/u_hash.c',
|
||||
'util/u_hash_table.c',
|
||||
'util/u_keymap.c',
|
||||
'util/u_linear.c',
|
||||
'util/u_linkage.c',
|
||||
'util/u_network.c',
|
||||
'util/u_math.c',
|
||||
'util/u_mempool.c',
|
||||
|
|
@ -208,9 +211,9 @@ if env['llvm']:
|
|||
'gallivm/lp_bld_format_soa.c',
|
||||
'gallivm/lp_bld_format_yuv.c',
|
||||
'gallivm/lp_bld_gather.c',
|
||||
'gallivm/lp_bld_init.c',
|
||||
'gallivm/lp_bld_intr.c',
|
||||
'gallivm/lp_bld_logic.c',
|
||||
'gallivm/lp_bld_init.c',
|
||||
'gallivm/lp_bld_misc.cpp',
|
||||
'gallivm/lp_bld_pack.c',
|
||||
'gallivm/lp_bld_printf.c',
|
||||
|
|
@ -222,10 +225,10 @@ if env['llvm']:
|
|||
'gallivm/lp_bld_tgsi_soa.c',
|
||||
'gallivm/lp_bld_type.c',
|
||||
'draw/draw_llvm.c',
|
||||
'draw/draw_pt_fetch_shade_pipeline_llvm.c',
|
||||
'draw/draw_llvm_sample.c',
|
||||
'draw/draw_llvm_translate.c',
|
||||
'draw/draw_vs_llvm.c',
|
||||
'draw/draw_llvm_sample.c'
|
||||
'draw/draw_pt_fetch_shade_pipeline_llvm.c',
|
||||
'draw/draw_vs_llvm.c'
|
||||
]
|
||||
|
||||
gallium = env.ConvenienceLibrary(
|
||||
|
|
|
|||
114
src/gallium/auxiliary/draw/draw_cliptest_tmp.h
Normal file
114
src/gallium/auxiliary/draw/draw_cliptest_tmp.h
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2010, VMware, inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
|
||||
struct draw_vertex_info *info )
|
||||
{
|
||||
struct vertex_header *out = info->verts;
|
||||
const float *scale = pvs->draw->viewport.scale;
|
||||
const float *trans = pvs->draw->viewport.translate;
|
||||
/* const */ float (*plane)[4] = pvs->draw->plane;
|
||||
const unsigned pos = draw_current_shader_position_output(pvs->draw);
|
||||
const unsigned ef = pvs->draw->vs.edgeflag_output;
|
||||
const unsigned nr = pvs->draw->nr_planes;
|
||||
const unsigned flags = (FLAGS);
|
||||
unsigned need_pipeline = 0;
|
||||
unsigned j;
|
||||
|
||||
for (j = 0; j < info->count; j++) {
|
||||
float *position = out->data[pos];
|
||||
unsigned mask = 0x0;
|
||||
|
||||
initialize_vertex_header(out);
|
||||
|
||||
if (flags & (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_HALF_Z | DO_CLIP_USER)) {
|
||||
out->clip[0] = position[0];
|
||||
out->clip[1] = position[1];
|
||||
out->clip[2] = position[2];
|
||||
out->clip[3] = position[3];
|
||||
|
||||
/* Do the hardwired planes first:
|
||||
*/
|
||||
if (flags & DO_CLIP_XY) {
|
||||
if (-position[0] + position[3] < 0) mask |= (1<<0);
|
||||
if ( position[0] + position[3] < 0) mask |= (1<<1);
|
||||
if (-position[1] + position[3] < 0) mask |= (1<<2);
|
||||
if ( position[1] + position[3] < 0) mask |= (1<<3);
|
||||
}
|
||||
|
||||
/* Clip Z planes according to full cube, half cube or none.
|
||||
*/
|
||||
if (flags & DO_CLIP_FULL_Z) {
|
||||
if ( position[2] + position[3] < 0) mask |= (1<<4);
|
||||
if (-position[2] + position[3] < 0) mask |= (1<<5);
|
||||
}
|
||||
else if (flags & DO_CLIP_HALF_Z) {
|
||||
if ( position[2] < 0) mask |= (1<<4);
|
||||
if (-position[2] + position[3] < 0) mask |= (1<<5);
|
||||
}
|
||||
|
||||
if (flags & DO_CLIP_USER) {
|
||||
unsigned i;
|
||||
for (i = 6; i < nr; i++) {
|
||||
if (dot4(position, plane[i]) < 0)
|
||||
mask |= (1<<i);
|
||||
}
|
||||
}
|
||||
|
||||
out->clipmask = mask;
|
||||
need_pipeline |= out->clipmask;
|
||||
}
|
||||
|
||||
if ((flags & DO_VIEWPORT) && mask == 0)
|
||||
{
|
||||
/* divide by w */
|
||||
float w = 1.0f / position[3];
|
||||
|
||||
/* Viewport mapping */
|
||||
position[0] = position[0] * w * scale[0] + trans[0];
|
||||
position[1] = position[1] * w * scale[1] + trans[1];
|
||||
position[2] = position[2] * w * scale[2] + trans[2];
|
||||
position[3] = w;
|
||||
}
|
||||
|
||||
if ((flags & DO_EDGEFLAG) && ef) {
|
||||
const float *edgeflag = out->data[ef];
|
||||
out->edgeflag = !(edgeflag[0] != 1.0f);
|
||||
need_pipeline |= !out->edgeflag;
|
||||
}
|
||||
|
||||
out = (struct vertex_header *)( (char *)out + info->stride );
|
||||
}
|
||||
|
||||
return need_pipeline != 0;
|
||||
}
|
||||
|
||||
|
||||
#undef FLAGS
|
||||
#undef TAG
|
||||
|
|
@ -34,6 +34,7 @@
|
|||
#include "pipe/p_context.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_cpu_detect.h"
|
||||
#include "draw_context.h"
|
||||
#include "draw_vs.h"
|
||||
#include "draw_gs.h"
|
||||
|
|
@ -41,6 +42,25 @@
|
|||
#if HAVE_LLVM
|
||||
#include "gallivm/lp_bld_init.h"
|
||||
#include "draw_llvm.h"
|
||||
|
||||
static boolean
|
||||
draw_get_option_use_llvm(void)
|
||||
{
|
||||
static boolean first = TRUE;
|
||||
static boolean value;
|
||||
if (first) {
|
||||
first = FALSE;
|
||||
value = debug_get_bool_option("DRAW_USE_LLVM", TRUE);
|
||||
|
||||
#ifdef PIPE_ARCH_X86
|
||||
util_cpu_detect();
|
||||
/* require SSE2 due to LLVM PR6960. */
|
||||
if (!util_cpu_caps.has_sse2)
|
||||
value = FALSE;
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct draw_context *draw_create( struct pipe_context *pipe )
|
||||
|
|
@ -50,10 +70,13 @@ struct draw_context *draw_create( struct pipe_context *pipe )
|
|||
goto fail;
|
||||
|
||||
#if HAVE_LLVM
|
||||
lp_build_init();
|
||||
assert(lp_build_engine);
|
||||
draw->engine = lp_build_engine;
|
||||
draw->llvm = draw_llvm_create(draw);
|
||||
if(draw_get_option_use_llvm())
|
||||
{
|
||||
lp_build_init();
|
||||
assert(lp_build_engine);
|
||||
draw->engine = lp_build_engine;
|
||||
draw->llvm = draw_llvm_create(draw);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!draw_init(draw))
|
||||
|
|
@ -83,6 +106,8 @@ boolean draw_init(struct draw_context *draw)
|
|||
ASSIGN_4V( draw->plane[4], 0, 0, 1, 1 ); /* yes these are correct */
|
||||
ASSIGN_4V( draw->plane[5], 0, 0, -1, 1 ); /* mesa's a bit wonky */
|
||||
draw->nr_planes = 6;
|
||||
draw->clip_xy = 1;
|
||||
draw->clip_z = 1;
|
||||
|
||||
|
||||
draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */
|
||||
|
|
@ -135,7 +160,8 @@ void draw_destroy( struct draw_context *draw )
|
|||
draw_vs_destroy( draw );
|
||||
draw_gs_destroy( draw );
|
||||
#ifdef HAVE_LLVM
|
||||
draw_llvm_destroy( draw->llvm );
|
||||
if(draw->llvm)
|
||||
draw_llvm_destroy( draw->llvm );
|
||||
#endif
|
||||
|
||||
FREE( draw );
|
||||
|
|
@ -162,6 +188,14 @@ void draw_set_mrd(struct draw_context *draw, double mrd)
|
|||
}
|
||||
|
||||
|
||||
static void update_clip_flags( struct draw_context *draw )
|
||||
{
|
||||
draw->clip_xy = !draw->driver.bypass_clip_xy;
|
||||
draw->clip_z = (!draw->driver.bypass_clip_z &&
|
||||
!draw->depth_clamp);
|
||||
draw->clip_user = (draw->nr_planes > 6);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new primitive rasterization/rendering state.
|
||||
* This causes the drawing pipeline to be rebuilt.
|
||||
|
|
@ -176,18 +210,25 @@ void draw_set_rasterizer_state( struct draw_context *draw,
|
|||
draw->rasterizer = raster;
|
||||
draw->rast_handle = rast_handle;
|
||||
|
||||
draw->bypass_clipping = draw->driver.bypass_clipping;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* With a little more work, llvmpipe will be able to turn this off and
|
||||
* do its own x/y clipping.
|
||||
*
|
||||
* Some hardware can turn off clipping altogether - in particular any
|
||||
* hardware with a TNL unit can do its own clipping, even if it is
|
||||
* relying on the draw module for some other reason.
|
||||
*/
|
||||
void draw_set_driver_clipping( struct draw_context *draw,
|
||||
boolean bypass_clipping )
|
||||
boolean bypass_clip_xy,
|
||||
boolean bypass_clip_z )
|
||||
{
|
||||
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
|
||||
|
||||
draw->driver.bypass_clipping = bypass_clipping;
|
||||
draw->bypass_clipping = draw->driver.bypass_clipping;
|
||||
draw->driver.bypass_clip_xy = bypass_clip_xy;
|
||||
draw->driver.bypass_clip_z = bypass_clip_z;
|
||||
update_clip_flags(draw);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -217,6 +258,8 @@ void draw_set_clip_state( struct draw_context *draw,
|
|||
memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0]));
|
||||
draw->nr_planes = 6 + clip->nr;
|
||||
draw->depth_clamp = clip->depth_clamp;
|
||||
|
||||
update_clip_flags(draw);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -472,47 +515,28 @@ void draw_set_render( struct draw_context *draw,
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
draw_set_index_buffer(struct draw_context *draw,
|
||||
const struct pipe_index_buffer *ib)
|
||||
{
|
||||
if (ib)
|
||||
memcpy(&draw->pt.index_buffer, ib, sizeof(draw->pt.index_buffer));
|
||||
else
|
||||
memset(&draw->pt.index_buffer, 0, sizeof(draw->pt.index_buffer));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tell the drawing context about the index/element buffer to use
|
||||
* (ala glDrawElements)
|
||||
* If no element buffer is to be used (i.e. glDrawArrays) then this
|
||||
* should be called with eltSize=0 and elements=NULL.
|
||||
*
|
||||
* \param draw the drawing context
|
||||
* \param eltSize size of each element (1, 2 or 4 bytes)
|
||||
* \param elements the element buffer ptr
|
||||
* Tell drawing context where to find mapped index/element buffer.
|
||||
*/
|
||||
void
|
||||
draw_set_mapped_element_buffer_range( struct draw_context *draw,
|
||||
unsigned eltSize,
|
||||
int eltBias,
|
||||
unsigned min_index,
|
||||
unsigned max_index,
|
||||
const void *elements )
|
||||
draw_set_mapped_index_buffer(struct draw_context *draw,
|
||||
const void *elements)
|
||||
{
|
||||
draw->pt.user.elts = elements;
|
||||
draw->pt.user.eltSize = eltSize;
|
||||
draw->pt.user.eltBias = eltBias;
|
||||
draw->pt.user.min_index = min_index;
|
||||
draw->pt.user.max_index = max_index;
|
||||
draw->pt.user.elts = elements;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
draw_set_mapped_element_buffer( struct draw_context *draw,
|
||||
unsigned eltSize,
|
||||
int eltBias,
|
||||
const void *elements )
|
||||
{
|
||||
draw->pt.user.elts = elements;
|
||||
draw->pt.user.eltSize = eltSize;
|
||||
draw->pt.user.eltBias = eltBias;
|
||||
draw->pt.user.min_index = 0;
|
||||
draw->pt.user.max_index = 0xffffffff;
|
||||
}
|
||||
|
||||
|
||||
/* Revamp me please:
|
||||
*/
|
||||
void draw_do_flush( struct draw_context *draw, unsigned flags )
|
||||
|
|
@ -659,7 +683,8 @@ draw_set_mapped_texture(struct draw_context *draw,
|
|||
const void *data[DRAW_MAX_TEXTURE_LEVELS])
|
||||
{
|
||||
#ifdef HAVE_LLVM
|
||||
draw_llvm_set_mapped_texture(draw,
|
||||
if(draw->llvm)
|
||||
draw_llvm_set_mapped_texture(draw,
|
||||
sampler_idx,
|
||||
width, height, depth, last_level,
|
||||
row_stride, img_stride, data);
|
||||
|
|
|
|||
|
|
@ -160,18 +160,11 @@ void draw_set_vertex_elements(struct draw_context *draw,
|
|||
unsigned count,
|
||||
const struct pipe_vertex_element *elements);
|
||||
|
||||
void
|
||||
draw_set_mapped_element_buffer_range( struct draw_context *draw,
|
||||
unsigned eltSize,
|
||||
int eltBias,
|
||||
unsigned min_index,
|
||||
unsigned max_index,
|
||||
const void *elements );
|
||||
void draw_set_index_buffer(struct draw_context *draw,
|
||||
const struct pipe_index_buffer *ib);
|
||||
|
||||
void draw_set_mapped_element_buffer( struct draw_context *draw,
|
||||
unsigned eltSize,
|
||||
int eltBias,
|
||||
const void *elements );
|
||||
void draw_set_mapped_index_buffer(struct draw_context *draw,
|
||||
const void *elements);
|
||||
|
||||
void draw_set_mapped_vertex_buffer(struct draw_context *draw,
|
||||
unsigned attr, const void *buffer);
|
||||
|
|
@ -196,6 +189,9 @@ draw_set_so_state(struct draw_context *draw,
|
|||
* draw_pt.c
|
||||
*/
|
||||
|
||||
void draw_vbo(struct draw_context *draw,
|
||||
const struct pipe_draw_info *info);
|
||||
|
||||
void draw_arrays(struct draw_context *draw, unsigned prim,
|
||||
unsigned start, unsigned count);
|
||||
|
||||
|
|
@ -216,7 +212,8 @@ void draw_set_render( struct draw_context *draw,
|
|||
struct vbuf_render *render );
|
||||
|
||||
void draw_set_driver_clipping( struct draw_context *draw,
|
||||
boolean bypass_clipping );
|
||||
boolean bypass_clip_xy,
|
||||
boolean bypass_clip_z );
|
||||
|
||||
void draw_set_force_passthrough( struct draw_context *draw,
|
||||
boolean enable );
|
||||
|
|
|
|||
|
|
@ -54,10 +54,10 @@ FUNC(FUNC_VARS)
|
|||
|
||||
FUNC_ENTER;
|
||||
|
||||
/* prim, count, and last_vertex_last should have been defined */
|
||||
/* prim, prim_flags, count, and last_vertex_last should have been defined */
|
||||
if (0) {
|
||||
debug_printf("%s: prim 0x%x, count %d, last_vertex_last %d\n",
|
||||
__FUNCTION__, prim, count, last_vertex_last);
|
||||
debug_printf("%s: prim 0x%x, prim_flags 0x%x, count %d, last_vertex_last %d\n",
|
||||
__FUNCTION__, prim, prim_flags, count, last_vertex_last);
|
||||
}
|
||||
|
||||
switch (prim) {
|
||||
|
|
@ -80,7 +80,7 @@ FUNC(FUNC_VARS)
|
|||
case PIPE_PRIM_LINE_LOOP:
|
||||
case PIPE_PRIM_LINE_STRIP:
|
||||
if (count >= 2) {
|
||||
flags = DRAW_PIPE_RESET_STIPPLE;
|
||||
flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
|
||||
idx[1] = GET_ELT(0);
|
||||
idx[2] = idx[1];
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ FUNC(FUNC_VARS)
|
|||
LINE(flags, idx[0], idx[1]);
|
||||
}
|
||||
/* close the loop */
|
||||
if (prim == PIPE_PRIM_LINE_LOOP)
|
||||
if (prim == PIPE_PRIM_LINE_LOOP && !prim_flags)
|
||||
LINE(flags, idx[1], idx[2]);
|
||||
}
|
||||
break;
|
||||
|
|
@ -255,17 +255,23 @@ FUNC(FUNC_VARS)
|
|||
|
||||
if (last_vertex_last) {
|
||||
flags = (DRAW_PIPE_RESET_STIPPLE |
|
||||
DRAW_PIPE_EDGE_FLAG_2 |
|
||||
DRAW_PIPE_EDGE_FLAG_0);
|
||||
if (!(prim_flags & DRAW_SPLIT_BEFORE))
|
||||
flags |= DRAW_PIPE_EDGE_FLAG_2;
|
||||
|
||||
edge_next = DRAW_PIPE_EDGE_FLAG_0;
|
||||
edge_finish = DRAW_PIPE_EDGE_FLAG_1;
|
||||
edge_finish =
|
||||
(prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_1;
|
||||
}
|
||||
else {
|
||||
flags = (DRAW_PIPE_RESET_STIPPLE |
|
||||
DRAW_PIPE_EDGE_FLAG_0 |
|
||||
DRAW_PIPE_EDGE_FLAG_1);
|
||||
if (!(prim_flags & DRAW_SPLIT_BEFORE))
|
||||
flags |= DRAW_PIPE_EDGE_FLAG_0;
|
||||
|
||||
edge_next = DRAW_PIPE_EDGE_FLAG_1;
|
||||
edge_finish = DRAW_PIPE_EDGE_FLAG_2;
|
||||
edge_finish =
|
||||
(prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_2;
|
||||
}
|
||||
|
||||
idx[0] = GET_ELT(0);
|
||||
|
|
@ -300,7 +306,7 @@ FUNC(FUNC_VARS)
|
|||
|
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
|
||||
if (count >= 4) {
|
||||
flags = DRAW_PIPE_RESET_STIPPLE;
|
||||
flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
|
||||
idx[1] = GET_ELT(0);
|
||||
idx[2] = GET_ELT(1);
|
||||
idx[3] = GET_ELT(2);
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ static void gs_tri_adj(struct draw_geometry_shader *shader,
|
|||
|
||||
#define FUNC gs_run_elts
|
||||
#define LOCAL_VARS const ushort *elts = input_prims->elts;
|
||||
#define GET_ELT(idx) (elts[idx] & ~DRAW_PIPE_FLAG_MASK)
|
||||
#define GET_ELT(idx) (elts[idx])
|
||||
#include "draw_gs_tmp.h"
|
||||
|
||||
|
||||
|
|
@ -457,6 +457,7 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
|
|||
output_prims->start = 0;
|
||||
output_prims->count = shader->emitted_vertices;
|
||||
output_prims->prim = shader->output_primitive;
|
||||
output_prims->flags = 0x0;
|
||||
output_prims->primitive_lengths = shader->primitive_lengths;
|
||||
output_prims->primitive_count = shader->emitted_primitives;
|
||||
output_verts->count = shader->emitted_vertices;
|
||||
|
|
|
|||
|
|
@ -6,12 +6,10 @@
|
|||
|
||||
#define FUNC_ENTER \
|
||||
/* declare more local vars */ \
|
||||
struct draw_context *draw = gs->draw; \
|
||||
const unsigned prim = input_prims->prim; \
|
||||
const unsigned prim_flags = input_prims->flags; \
|
||||
const unsigned count = input_prims->count; \
|
||||
const boolean last_vertex_last = \
|
||||
!(draw->rasterizer->flatshade && \
|
||||
draw->rasterizer->flatshade_first); \
|
||||
const boolean last_vertex_last = TRUE; \
|
||||
do { \
|
||||
debug_assert(input_prims->primitive_count == 1); \
|
||||
switch (prim) { \
|
||||
|
|
|
|||
|
|
@ -210,13 +210,6 @@ draw_llvm_create(struct draw_context *draw)
|
|||
{
|
||||
struct draw_llvm *llvm;
|
||||
|
||||
#ifdef PIPE_ARCH_X86
|
||||
util_cpu_detect();
|
||||
/* require SSE2 due to LLVM PR6960. */
|
||||
if (!util_cpu_caps.has_sse2)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
llvm = CALLOC_STRUCT( draw_llvm );
|
||||
if (!llvm)
|
||||
return NULL;
|
||||
|
|
@ -292,15 +285,23 @@ draw_llvm_destroy(struct draw_llvm *llvm)
|
|||
}
|
||||
|
||||
struct draw_llvm_variant *
|
||||
draw_llvm_create_variant(struct draw_llvm *llvm, int num_inputs)
|
||||
draw_llvm_create_variant(struct draw_llvm *llvm,
|
||||
unsigned num_inputs,
|
||||
const struct draw_llvm_variant_key *key)
|
||||
{
|
||||
struct draw_llvm_variant *variant = MALLOC(sizeof(struct draw_llvm_variant));
|
||||
struct draw_llvm_variant *variant;
|
||||
struct llvm_vertex_shader *shader =
|
||||
llvm_vertex_shader(llvm->draw->vs.vertex_shader);
|
||||
|
||||
variant = MALLOC(sizeof *variant +
|
||||
shader->variant_key_size -
|
||||
sizeof variant->key);
|
||||
if (variant == NULL)
|
||||
return NULL;
|
||||
|
||||
variant->llvm = llvm;
|
||||
|
||||
draw_llvm_make_variant_key(llvm, &variant->key);
|
||||
memcpy(&variant->key, key, shader->variant_key_size);
|
||||
|
||||
llvm->vertex_header_ptr_type = create_vertex_header(llvm, num_inputs);
|
||||
|
||||
|
|
@ -738,8 +739,9 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
|
|||
step = LLVMConstInt(LLVMInt32Type(), max_vertices, 0);
|
||||
|
||||
/* code generated texture sampling */
|
||||
sampler = draw_llvm_sampler_soa_create(variant->key.sampler,
|
||||
context_ptr);
|
||||
sampler = draw_llvm_sampler_soa_create(
|
||||
draw_llvm_variant_key_samplers(&variant->key),
|
||||
context_ptr);
|
||||
|
||||
#if DEBUG_STORE
|
||||
lp_build_printf(builder, "start = %d, end = %d, step = %d\n",
|
||||
|
|
@ -901,8 +903,9 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
|
|||
step = LLVMConstInt(LLVMInt32Type(), max_vertices, 0);
|
||||
|
||||
/* code generated texture sampling */
|
||||
sampler = draw_llvm_sampler_soa_create(variant->key.sampler,
|
||||
context_ptr);
|
||||
sampler = draw_llvm_sampler_soa_create(
|
||||
draw_llvm_variant_key_samplers(&variant->key),
|
||||
context_ptr);
|
||||
|
||||
fetch_max = LLVMBuildSub(builder, fetch_count,
|
||||
LLVMConstInt(LLVMInt32Type(), 1, 0),
|
||||
|
|
@ -1002,35 +1005,42 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
|
|||
lp_func_delete_body(variant->function_elts);
|
||||
}
|
||||
|
||||
void
|
||||
draw_llvm_make_variant_key(struct draw_llvm *llvm,
|
||||
struct draw_llvm_variant_key *key)
|
||||
|
||||
struct draw_llvm_variant_key *
|
||||
draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
|
||||
{
|
||||
unsigned i;
|
||||
struct draw_llvm_variant_key *key;
|
||||
struct lp_sampler_static_state *sampler;
|
||||
|
||||
memset(key, 0, sizeof(struct draw_llvm_variant_key));
|
||||
key = (struct draw_llvm_variant_key *)store;
|
||||
|
||||
/* Presumably all variants of the shader should have the same
|
||||
* number of vertex elements - ie the number of shader inputs.
|
||||
*/
|
||||
key->nr_vertex_elements = llvm->draw->pt.nr_vertex_elements;
|
||||
|
||||
/* All variants of this shader will have the same value for
|
||||
* nr_samplers. Not yet trying to compact away holes in the
|
||||
* sampler array.
|
||||
*/
|
||||
key->nr_samplers = llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_SAMPLER] + 1;
|
||||
|
||||
sampler = draw_llvm_variant_key_samplers(key);
|
||||
|
||||
memcpy(key->vertex_element,
|
||||
llvm->draw->pt.vertex_element,
|
||||
sizeof(struct pipe_vertex_element) * key->nr_vertex_elements);
|
||||
|
||||
memset(sampler, 0, key->nr_samplers * sizeof *sampler);
|
||||
|
||||
memcpy(&key->vs,
|
||||
&llvm->draw->vs.vertex_shader->state,
|
||||
sizeof(struct pipe_shader_state));
|
||||
|
||||
/* if the driver implemented the sampling hooks then
|
||||
* setup our sampling state */
|
||||
if (llvm->draw->num_sampler_views && llvm->draw->num_samplers) {
|
||||
for(i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) {
|
||||
struct draw_vertex_shader *shader = llvm->draw->vs.vertex_shader;
|
||||
if(shader->info.file_mask[TGSI_FILE_SAMPLER] & (1 << i))
|
||||
lp_sampler_static_state(&key->sampler[i],
|
||||
llvm->draw->sampler_views[i],
|
||||
llvm->draw->samplers[i]);
|
||||
}
|
||||
for (i = 0 ; i < key->nr_samplers; i++) {
|
||||
lp_sampler_static_state(&sampler[i],
|
||||
llvm->draw->sampler_views[i],
|
||||
llvm->draw->samplers[i]);
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -151,12 +151,43 @@ typedef void
|
|||
|
||||
struct draw_llvm_variant_key
|
||||
{
|
||||
struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
|
||||
unsigned nr_vertex_elements;
|
||||
struct pipe_shader_state vs;
|
||||
struct lp_sampler_static_state sampler[PIPE_MAX_VERTEX_SAMPLERS];
|
||||
unsigned nr_vertex_elements:16;
|
||||
unsigned nr_samplers:16;
|
||||
|
||||
/* Variable number of vertex elements:
|
||||
*/
|
||||
struct pipe_vertex_element vertex_element[1];
|
||||
|
||||
/* Followed by variable number of samplers:
|
||||
*/
|
||||
/* struct lp_sampler_static_state sampler; */
|
||||
};
|
||||
|
||||
#define DRAW_LLVM_MAX_VARIANT_KEY_SIZE \
|
||||
(sizeof(struct draw_llvm_variant_key) + \
|
||||
PIPE_MAX_VERTEX_SAMPLERS * sizeof(struct lp_sampler_static_state) + \
|
||||
(PIPE_MAX_ATTRIBS-1) * sizeof(struct pipe_vertex_element))
|
||||
|
||||
|
||||
static INLINE size_t
|
||||
draw_llvm_variant_key_size(unsigned nr_vertex_elements,
|
||||
unsigned nr_samplers)
|
||||
{
|
||||
return (sizeof(struct draw_llvm_variant_key) +
|
||||
nr_samplers * sizeof(struct lp_sampler_static_state) +
|
||||
(nr_vertex_elements - 1) * sizeof(struct pipe_vertex_element));
|
||||
}
|
||||
|
||||
|
||||
static INLINE struct lp_sampler_static_state *
|
||||
draw_llvm_variant_key_samplers(struct draw_llvm_variant_key *key)
|
||||
{
|
||||
return (struct lp_sampler_static_state *)
|
||||
&key->vertex_element[key->nr_vertex_elements];
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct draw_llvm_variant_list_item
|
||||
{
|
||||
struct draw_llvm_variant *base;
|
||||
|
|
@ -165,7 +196,6 @@ struct draw_llvm_variant_list_item
|
|||
|
||||
struct draw_llvm_variant
|
||||
{
|
||||
struct draw_llvm_variant_key key;
|
||||
LLVMValueRef function;
|
||||
LLVMValueRef function_elts;
|
||||
draw_jit_vert_func jit_func;
|
||||
|
|
@ -176,11 +206,16 @@ struct draw_llvm_variant
|
|||
struct draw_llvm *llvm;
|
||||
struct draw_llvm_variant_list_item list_item_global;
|
||||
struct draw_llvm_variant_list_item list_item_local;
|
||||
|
||||
/* key is variable-sized, must be last */
|
||||
struct draw_llvm_variant_key key;
|
||||
/* key is variable-sized, must be last */
|
||||
};
|
||||
|
||||
struct llvm_vertex_shader {
|
||||
struct draw_vertex_shader base;
|
||||
|
||||
unsigned variant_key_size;
|
||||
struct draw_llvm_variant_list_item variants;
|
||||
unsigned variants_created;
|
||||
unsigned variants_cached;
|
||||
|
|
@ -220,14 +255,15 @@ void
|
|||
draw_llvm_destroy(struct draw_llvm *llvm);
|
||||
|
||||
struct draw_llvm_variant *
|
||||
draw_llvm_create_variant(struct draw_llvm *llvm, int num_inputs);
|
||||
draw_llvm_create_variant(struct draw_llvm *llvm,
|
||||
unsigned num_vertex_header_attribs,
|
||||
const struct draw_llvm_variant_key *key);
|
||||
|
||||
void
|
||||
draw_llvm_destroy_variant(struct draw_llvm_variant *variant);
|
||||
|
||||
void
|
||||
draw_llvm_make_variant_key(struct draw_llvm *llvm,
|
||||
struct draw_llvm_variant_key *key);
|
||||
struct draw_llvm_variant_key *
|
||||
draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store);
|
||||
|
||||
LLVMValueRef
|
||||
draw_llvm_translate_from(LLVMBuilderRef builder,
|
||||
|
|
|
|||
|
|
@ -169,35 +169,27 @@ static void do_triangle( struct draw_context *draw,
|
|||
/*
|
||||
* Set up macros for draw_pt_decompose.h template code.
|
||||
* This code uses vertex indexes / elements.
|
||||
*
|
||||
* Flags are needed by the stipple and unfilled stages. When the two stages
|
||||
* are active, vcache_run_extras is called and the flags are stored in the
|
||||
* higher bits of i0. Otherwise, flags do not matter.
|
||||
*/
|
||||
|
||||
#define TRIANGLE(flags,i0,i1,i2) \
|
||||
do { \
|
||||
assert(!((i1) & DRAW_PIPE_FLAG_MASK)); \
|
||||
assert(!((i2) & DRAW_PIPE_FLAG_MASK)); \
|
||||
do_triangle( draw, \
|
||||
i0, /* flags */ \
|
||||
verts + stride * (i0 & ~DRAW_PIPE_FLAG_MASK), \
|
||||
flags, \
|
||||
verts + stride * (i0), \
|
||||
verts + stride * (i1), \
|
||||
verts + stride * (i2) ); \
|
||||
} while (0)
|
||||
|
||||
#define LINE(flags,i0,i1) \
|
||||
do { \
|
||||
assert(!((i1) & DRAW_PIPE_FLAG_MASK)); \
|
||||
do_line( draw, \
|
||||
i0, /* flags */ \
|
||||
verts + stride * (i0 & ~DRAW_PIPE_FLAG_MASK), \
|
||||
flags, \
|
||||
verts + stride * (i0), \
|
||||
verts + stride * (i1) ); \
|
||||
} while (0)
|
||||
|
||||
#define POINT(i0) \
|
||||
do { \
|
||||
assert(!((i0) & DRAW_PIPE_FLAG_MASK)); \
|
||||
do_point( draw, verts + stride * (i0) ); \
|
||||
} while (0)
|
||||
|
||||
|
|
@ -207,6 +199,7 @@ static void do_triangle( struct draw_context *draw,
|
|||
#define FUNC_VARS \
|
||||
struct draw_context *draw, \
|
||||
unsigned prim, \
|
||||
unsigned prim_flags, \
|
||||
struct vertex_header *vertices, \
|
||||
unsigned stride, \
|
||||
const ushort *elts, \
|
||||
|
|
@ -245,22 +238,27 @@ void draw_pipeline_run( struct draw_context *draw,
|
|||
const unsigned count = prim_info->primitive_lengths[i];
|
||||
|
||||
#if DEBUG
|
||||
/* make sure none of the element indexes go outside the vertex buffer */
|
||||
/* Warn if one of the element indexes go outside the vertex buffer */
|
||||
{
|
||||
unsigned max_index = 0x0, i;
|
||||
/* find the largest element index */
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int index = (prim_info->elts[start + i]
|
||||
& ~DRAW_PIPE_FLAG_MASK);
|
||||
unsigned int index = prim_info->elts[start + i];
|
||||
if (index > max_index)
|
||||
max_index = index;
|
||||
}
|
||||
assert(max_index <= vert_info->count);
|
||||
if (max_index >= vert_info->count) {
|
||||
debug_printf("%s: max_index (%u) outside vertex buffer (%u)\n",
|
||||
__FUNCTION__,
|
||||
max_index,
|
||||
vert_info->count);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
pipe_run_elts(draw,
|
||||
prim_info->prim,
|
||||
prim_info->flags,
|
||||
vert_info->verts,
|
||||
vert_info->stride,
|
||||
prim_info->elts + start,
|
||||
|
|
@ -298,6 +296,7 @@ void draw_pipeline_run( struct draw_context *draw,
|
|||
#define FUNC_VARS \
|
||||
struct draw_context *draw, \
|
||||
unsigned prim, \
|
||||
unsigned prim_flags, \
|
||||
struct vertex_header *vertices, \
|
||||
unsigned stride, \
|
||||
unsigned count
|
||||
|
|
@ -330,6 +329,7 @@ void draw_pipeline_run_linear( struct draw_context *draw,
|
|||
|
||||
pipe_run_linear(draw,
|
||||
prim_info->prim,
|
||||
prim_info->flags,
|
||||
(struct vertex_header*)verts,
|
||||
vert_info->stride,
|
||||
count);
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage )
|
|||
|
||||
/* Clip stage
|
||||
*/
|
||||
if (!draw->bypass_clipping)
|
||||
if (draw->clip_xy || draw->clip_z || draw->clip_user)
|
||||
{
|
||||
draw->pipeline.clip->next = next;
|
||||
next = draw->pipeline.clip;
|
||||
|
|
|
|||
|
|
@ -353,9 +353,6 @@ vbuf_alloc_vertices( struct vbuf_stage *vbuf )
|
|||
/* Allocate a new vertex buffer */
|
||||
vbuf->max_vertices = vbuf->render->max_vertex_buffer_bytes / vbuf->vertex_size;
|
||||
|
||||
/* even number */
|
||||
vbuf->max_vertices = vbuf->max_vertices & ~1;
|
||||
|
||||
if(vbuf->max_vertices >= UNDEFINED_VERTEX_ID)
|
||||
vbuf->max_vertices = UNDEFINED_VERTEX_ID - 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -140,8 +140,7 @@ struct draw_context
|
|||
} middle;
|
||||
|
||||
struct {
|
||||
struct draw_pt_front_end *vcache;
|
||||
struct draw_pt_front_end *varray;
|
||||
struct draw_pt_front_end *vsplit;
|
||||
} front;
|
||||
|
||||
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
|
||||
|
|
@ -150,6 +149,8 @@ struct draw_context
|
|||
struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
|
||||
unsigned nr_vertex_elements;
|
||||
|
||||
struct pipe_index_buffer index_buffer;
|
||||
|
||||
/* user-space vertex data, buffers */
|
||||
struct {
|
||||
/** vertex element/index buffer (ex: glDrawElements) */
|
||||
|
|
@ -175,13 +176,19 @@ struct draw_context
|
|||
} pt;
|
||||
|
||||
struct {
|
||||
boolean bypass_clipping;
|
||||
boolean bypass_vs;
|
||||
boolean bypass_clip_xy;
|
||||
boolean bypass_clip_z;
|
||||
} driver;
|
||||
|
||||
boolean flushing; /**< debugging/sanity */
|
||||
boolean suspend_flushing; /**< internally set */
|
||||
boolean bypass_clipping; /**< set if either api or driver bypass_clipping true */
|
||||
|
||||
/* Flags set if API requires clipping in these planes and the
|
||||
* driver doesn't indicate that it can do it for us.
|
||||
*/
|
||||
boolean clip_xy;
|
||||
boolean clip_z;
|
||||
boolean clip_user;
|
||||
|
||||
boolean force_passthrough; /**< never clip or shade */
|
||||
|
||||
|
|
@ -296,6 +303,10 @@ struct draw_vertex_info {
|
|||
unsigned count;
|
||||
};
|
||||
|
||||
/* these flags are set if the primitive is a segment of a larger one */
|
||||
#define DRAW_SPLIT_BEFORE 0x1
|
||||
#define DRAW_SPLIT_AFTER 0x2
|
||||
|
||||
struct draw_prim_info {
|
||||
boolean linear;
|
||||
unsigned start;
|
||||
|
|
@ -304,6 +315,7 @@ struct draw_prim_info {
|
|||
unsigned count;
|
||||
|
||||
unsigned prim;
|
||||
unsigned flags;
|
||||
unsigned *primitive_lengths;
|
||||
unsigned primitive_count;
|
||||
};
|
||||
|
|
@ -369,21 +381,15 @@ void draw_pipeline_destroy( struct draw_context *draw );
|
|||
|
||||
|
||||
|
||||
/* We use the top few bits in the elts[] parameter to convey a little
|
||||
* API information. This limits the number of vertices we can address
|
||||
* to only 4096 -- if that becomes a problem, we can switch to 32-bit
|
||||
* draw indices.
|
||||
*
|
||||
* These flags expected at first vertex of lines & triangles when
|
||||
* unfilled and/or line stipple modes are operational.
|
||||
/*
|
||||
* These flags are used by the pipeline when unfilled and/or line stipple modes
|
||||
* are operational.
|
||||
*/
|
||||
#define DRAW_PIPE_MAX_VERTICES (0x1<<12)
|
||||
#define DRAW_PIPE_EDGE_FLAG_0 (0x1<<12)
|
||||
#define DRAW_PIPE_EDGE_FLAG_1 (0x2<<12)
|
||||
#define DRAW_PIPE_EDGE_FLAG_2 (0x4<<12)
|
||||
#define DRAW_PIPE_EDGE_FLAG_ALL (0x7<<12)
|
||||
#define DRAW_PIPE_RESET_STIPPLE (0x8<<12)
|
||||
#define DRAW_PIPE_FLAG_MASK (0xf<<12)
|
||||
#define DRAW_PIPE_EDGE_FLAG_0 0x1
|
||||
#define DRAW_PIPE_EDGE_FLAG_1 0x2
|
||||
#define DRAW_PIPE_EDGE_FLAG_2 0x4
|
||||
#define DRAW_PIPE_EDGE_FLAG_ALL 0x7
|
||||
#define DRAW_PIPE_RESET_STIPPLE 0x8
|
||||
|
||||
void draw_pipeline_run( struct draw_context *draw,
|
||||
const struct draw_vertex_info *vert,
|
||||
|
|
|
|||
|
|
@ -39,25 +39,14 @@
|
|||
#include "util/u_math.h"
|
||||
#include "util/u_prim.h"
|
||||
#include "util/u_format.h"
|
||||
#include "util/u_draw.h"
|
||||
|
||||
|
||||
DEBUG_GET_ONCE_BOOL_OPTION(draw_fse, "DRAW_FSE", FALSE)
|
||||
DEBUG_GET_ONCE_BOOL_OPTION(draw_no_fse, "DRAW_NO_FSE", FALSE)
|
||||
#ifdef HAVE_LLVM
|
||||
DEBUG_GET_ONCE_BOOL_OPTION(draw_use_llvm, "DRAW_USE_LLVM", TRUE)
|
||||
#endif
|
||||
|
||||
static unsigned trim( unsigned count, unsigned first, unsigned incr )
|
||||
{
|
||||
if (count < first)
|
||||
return 0;
|
||||
return count - (count - first) % incr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Overall we split things into:
|
||||
* - frontend -- prepare fetch_elts, draw_elts - eg vcache
|
||||
* - frontend -- prepare fetch_elts, draw_elts - eg vsplit
|
||||
* - middle -- fetch, shade, cliptest, viewport
|
||||
* - pipeline -- the prim pipeline: clipping, wide lines, etc
|
||||
* - backend -- the vbuf_render provided by the driver.
|
||||
|
|
@ -77,7 +66,7 @@ draw_pt_arrays(struct draw_context *draw,
|
|||
{
|
||||
unsigned first, incr;
|
||||
draw_pt_split_prim(prim, &first, &incr);
|
||||
count = trim(count, first, incr);
|
||||
count = draw_pt_trim_count(count, first, incr);
|
||||
if (count < first)
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -97,7 +86,9 @@ draw_pt_arrays(struct draw_context *draw,
|
|||
opt |= PT_PIPELINE;
|
||||
}
|
||||
|
||||
if (!draw->bypass_clipping && !draw->pt.test_fse) {
|
||||
if ((draw->clip_xy ||
|
||||
draw->clip_z ||
|
||||
draw->clip_user) && !draw->pt.test_fse) {
|
||||
opt |= PT_CLIPTEST;
|
||||
}
|
||||
|
||||
|
|
@ -115,22 +106,11 @@ draw_pt_arrays(struct draw_context *draw,
|
|||
middle = draw->pt.middle.general;
|
||||
}
|
||||
|
||||
|
||||
/* Pick the right frontend
|
||||
*/
|
||||
if (draw->pt.user.elts || (opt & PT_PIPELINE)) {
|
||||
frontend = draw->pt.front.vcache;
|
||||
} else {
|
||||
frontend = draw->pt.front.varray;
|
||||
}
|
||||
frontend = draw->pt.front.vsplit;
|
||||
|
||||
frontend->prepare( frontend, prim, middle, opt );
|
||||
|
||||
frontend->run(frontend,
|
||||
draw_pt_elt_func(draw),
|
||||
draw_pt_elt_ptr(draw, start),
|
||||
draw->pt.user.eltBias,
|
||||
count);
|
||||
frontend->run(frontend, start, count);
|
||||
|
||||
frontend->finish( frontend );
|
||||
|
||||
|
|
@ -143,12 +123,8 @@ boolean draw_pt_init( struct draw_context *draw )
|
|||
draw->pt.test_fse = debug_get_option_draw_fse();
|
||||
draw->pt.no_fse = debug_get_option_draw_no_fse();
|
||||
|
||||
draw->pt.front.vcache = draw_pt_vcache( draw );
|
||||
if (!draw->pt.front.vcache)
|
||||
return FALSE;
|
||||
|
||||
draw->pt.front.varray = draw_pt_varray(draw);
|
||||
if (!draw->pt.front.varray)
|
||||
draw->pt.front.vsplit = draw_pt_vsplit(draw);
|
||||
if (!draw->pt.front.vsplit)
|
||||
return FALSE;
|
||||
|
||||
draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw );
|
||||
|
|
@ -164,7 +140,7 @@ boolean draw_pt_init( struct draw_context *draw )
|
|||
return FALSE;
|
||||
|
||||
#if HAVE_LLVM
|
||||
if (debug_get_option_draw_use_llvm())
|
||||
if (draw->llvm)
|
||||
draw->pt.middle.llvm = draw_pt_fetch_pipeline_or_emit_llvm( draw );
|
||||
#endif
|
||||
|
||||
|
|
@ -194,14 +170,9 @@ void draw_pt_destroy( struct draw_context *draw )
|
|||
draw->pt.middle.fetch_shade_emit = NULL;
|
||||
}
|
||||
|
||||
if (draw->pt.front.vcache) {
|
||||
draw->pt.front.vcache->destroy( draw->pt.front.vcache );
|
||||
draw->pt.front.vcache = NULL;
|
||||
}
|
||||
|
||||
if (draw->pt.front.varray) {
|
||||
draw->pt.front.varray->destroy( draw->pt.front.varray );
|
||||
draw->pt.front.varray = NULL;
|
||||
if (draw->pt.front.vsplit) {
|
||||
draw->pt.front.vsplit->destroy( draw->pt.front.vsplit );
|
||||
draw->pt.front.vsplit = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -221,24 +192,29 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
|
|||
uint ii = 0;
|
||||
uint j;
|
||||
|
||||
if (draw->pt.user.elts) {
|
||||
if (draw->pt.user.eltSize) {
|
||||
const char *elts;
|
||||
|
||||
/* indexed arrays */
|
||||
elts = (const char *) draw->pt.user.elts;
|
||||
elts += draw->pt.index_buffer.offset;
|
||||
|
||||
switch (draw->pt.user.eltSize) {
|
||||
case 1:
|
||||
{
|
||||
const ubyte *elem = (const ubyte *) draw->pt.user.elts;
|
||||
const ubyte *elem = (const ubyte *) elts;
|
||||
ii = elem[start + i];
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
const ushort *elem = (const ushort *) draw->pt.user.elts;
|
||||
const ushort *elem = (const ushort *) elts;
|
||||
ii = elem[start + i];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
const uint *elem = (const uint *) draw->pt.user.elts;
|
||||
const uint *elem = (const uint *) elts;
|
||||
ii = elem[start + i];
|
||||
}
|
||||
break;
|
||||
|
|
@ -324,17 +300,8 @@ draw_arrays(struct draw_context *draw, unsigned prim,
|
|||
|
||||
|
||||
/**
|
||||
* Draw vertex arrays.
|
||||
* This is the main entrypoint into the drawing module.
|
||||
* If drawing an indexed primitive, the draw_set_mapped_element_buffer_range()
|
||||
* function should have already been called to specify the element/index buffer
|
||||
* information.
|
||||
*
|
||||
* \param prim one of PIPE_PRIM_x
|
||||
* \param start index of first vertex to draw
|
||||
* \param count number of vertices to draw
|
||||
* \param startInstance number for the first primitive instance (usually 0).
|
||||
* \param instanceCount number of instances to draw (1=non-instanced)
|
||||
* Instanced drawing.
|
||||
* \sa draw_vbo
|
||||
*/
|
||||
void
|
||||
draw_arrays_instanced(struct draw_context *draw,
|
||||
|
|
@ -344,10 +311,50 @@ draw_arrays_instanced(struct draw_context *draw,
|
|||
unsigned startInstance,
|
||||
unsigned instanceCount)
|
||||
{
|
||||
unsigned reduced_prim = u_reduced_prim(mode);
|
||||
struct pipe_draw_info info;
|
||||
|
||||
util_draw_init_info(&info);
|
||||
|
||||
info.mode = mode;
|
||||
info.start = start;
|
||||
info.count = count;
|
||||
info.start_instance = startInstance;
|
||||
info.instance_count = instanceCount;
|
||||
|
||||
info.indexed = (draw->pt.user.elts != NULL);
|
||||
if (!info.indexed) {
|
||||
info.min_index = start;
|
||||
info.max_index = start + count - 1;
|
||||
}
|
||||
|
||||
draw_vbo(draw, &info);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw vertex arrays.
|
||||
* This is the main entrypoint into the drawing module. If drawing an indexed
|
||||
* primitive, the draw_set_index_buffer() and draw_set_mapped_index_buffer()
|
||||
* functions should have already been called to specify the element/index
|
||||
* buffer information.
|
||||
*/
|
||||
void
|
||||
draw_vbo(struct draw_context *draw,
|
||||
const struct pipe_draw_info *info)
|
||||
{
|
||||
unsigned reduced_prim = u_reduced_prim(info->mode);
|
||||
unsigned instance;
|
||||
|
||||
assert(instanceCount > 0);
|
||||
assert(info->instance_count > 0);
|
||||
if (info->indexed)
|
||||
assert(draw->pt.user.elts);
|
||||
|
||||
draw->pt.user.eltSize =
|
||||
(info->indexed) ? draw->pt.index_buffer.index_size : 0;
|
||||
|
||||
draw->pt.user.eltBias = info->index_bias;
|
||||
draw->pt.user.min_index = info->min_index;
|
||||
draw->pt.user.max_index = info->max_index;
|
||||
|
||||
if (reduced_prim != draw->reduced_prim) {
|
||||
draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);
|
||||
|
|
@ -355,8 +362,8 @@ draw_arrays_instanced(struct draw_context *draw,
|
|||
}
|
||||
|
||||
if (0)
|
||||
debug_printf("draw_arrays(mode=%u start=%u count=%u):\n",
|
||||
mode, start, count);
|
||||
debug_printf("draw_vbo(mode=%u start=%u count=%u):\n",
|
||||
info->mode, info->start, info->count);
|
||||
|
||||
if (0)
|
||||
tgsi_dump(draw->vs.vertex_shader->state.tokens, 0);
|
||||
|
|
@ -384,10 +391,10 @@ draw_arrays_instanced(struct draw_context *draw,
|
|||
}
|
||||
|
||||
if (0)
|
||||
draw_print_arrays(draw, mode, start, MIN2(count, 20));
|
||||
draw_print_arrays(draw, info->mode, info->start, MIN2(info->count, 20));
|
||||
|
||||
for (instance = 0; instance < instanceCount; instance++) {
|
||||
draw->instance_id = instance + startInstance;
|
||||
draw_pt_arrays(draw, mode, start, count);
|
||||
for (instance = 0; instance < info->instance_count; instance++) {
|
||||
draw->instance_id = instance + info->start_instance;
|
||||
draw_pt_arrays(draw, info->mode, info->start, info->count);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@
|
|||
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
typedef unsigned (*pt_elt_func)( const void *elts, unsigned idx );
|
||||
|
||||
struct draw_pt_middle_end;
|
||||
struct draw_context;
|
||||
struct draw_prim_info;
|
||||
|
|
@ -52,13 +50,18 @@ struct draw_vertex_info;
|
|||
/* The "front end" - prepare sets of fetch, draw elements for the
|
||||
* middle end.
|
||||
*
|
||||
* Currenly one version of this:
|
||||
* - vcache - catchall implementation, decomposes to TRI/LINE/POINT prims
|
||||
* Later:
|
||||
* - varray, varray_split
|
||||
* - velement, velement_split
|
||||
* The fetch elements are indices to the vertices. The draw elements are
|
||||
* indices to the fetched vertices. When both arrays of elements are both
|
||||
* linear, middle->run_linear is called; When only the fetch elements are
|
||||
* linear, middle->run_linear_elts is called; Otherwise, middle->run is
|
||||
* called.
|
||||
*
|
||||
* Currenly only using the vcache version.
|
||||
* When the number of the draw elements exceeds max_vertex of the middle end,
|
||||
* the draw elements (as well as the fetch elements) are splitted and the
|
||||
* middle end is called multiple times.
|
||||
*
|
||||
* Currenly there is:
|
||||
* - vsplit - catchall implementation, splits big prims
|
||||
*/
|
||||
struct draw_pt_front_end {
|
||||
void (*prepare)( struct draw_pt_front_end *,
|
||||
|
|
@ -67,9 +70,7 @@ struct draw_pt_front_end {
|
|||
unsigned opt );
|
||||
|
||||
void (*run)( struct draw_pt_front_end *,
|
||||
pt_elt_func elt_func,
|
||||
const void *elt_ptr,
|
||||
int elt_bias,
|
||||
unsigned start,
|
||||
unsigned count );
|
||||
|
||||
void (*finish)( struct draw_pt_front_end * );
|
||||
|
|
@ -80,6 +81,8 @@ struct draw_pt_front_end {
|
|||
/* The "middle end" - prepares actual hardware vertices for the
|
||||
* hardware backend.
|
||||
*
|
||||
* prim_flags is as defined by pipe_draw_info::flags.
|
||||
*
|
||||
* Currently two versions of this:
|
||||
* - fetch, vertex shade, cliptest, prim-pipeline
|
||||
* - fetch, emit (ie passthrough)
|
||||
|
|
@ -94,11 +97,13 @@ struct draw_pt_middle_end {
|
|||
const unsigned *fetch_elts,
|
||||
unsigned fetch_count,
|
||||
const ushort *draw_elts,
|
||||
unsigned draw_count );
|
||||
unsigned draw_count,
|
||||
unsigned prim_flags );
|
||||
|
||||
void (*run_linear)(struct draw_pt_middle_end *,
|
||||
unsigned start,
|
||||
unsigned count);
|
||||
unsigned count,
|
||||
unsigned prim_flags );
|
||||
|
||||
/* Transform all vertices in a linear range and then draw them with
|
||||
* the supplied element list. May fail and return FALSE.
|
||||
|
|
@ -107,7 +112,8 @@ struct draw_pt_middle_end {
|
|||
unsigned fetch_start,
|
||||
unsigned fetch_count,
|
||||
const ushort *draw_elts,
|
||||
unsigned draw_count );
|
||||
unsigned draw_count,
|
||||
unsigned prim_flags );
|
||||
|
||||
int (*get_max_vertex_count)( struct draw_pt_middle_end * );
|
||||
|
||||
|
|
@ -122,19 +128,11 @@ struct vbuf_render;
|
|||
struct vertex_header;
|
||||
|
||||
|
||||
/* Helper functions.
|
||||
*/
|
||||
pt_elt_func draw_pt_elt_func( struct draw_context *draw );
|
||||
const void *draw_pt_elt_ptr( struct draw_context *draw,
|
||||
unsigned start );
|
||||
|
||||
/* Frontends:
|
||||
*
|
||||
* Currently only the general-purpose vcache implementation, could add
|
||||
* a special case for tiny vertex buffers.
|
||||
* Currently only the general-purpose vsplit implementation.
|
||||
*/
|
||||
struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw );
|
||||
struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw);
|
||||
struct draw_pt_front_end *draw_pt_vsplit(struct draw_context *draw);
|
||||
|
||||
|
||||
/* Middle-ends:
|
||||
|
|
@ -223,7 +221,9 @@ boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
|
|||
struct draw_vertex_info *info );
|
||||
|
||||
void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
|
||||
boolean bypass_clipping,
|
||||
boolean clip_xy,
|
||||
boolean clip_z,
|
||||
boolean clip_user,
|
||||
boolean bypass_viewport,
|
||||
boolean opengl,
|
||||
boolean need_edgeflags );
|
||||
|
|
@ -237,6 +237,7 @@ void draw_pt_post_vs_destroy( struct pt_post_vs *pvs );
|
|||
* Utils:
|
||||
*/
|
||||
void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr);
|
||||
unsigned draw_pt_trim_count(unsigned count, unsigned first, unsigned incr);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,89 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "draw/draw_pt.h"
|
||||
#include "draw/draw_private.h"
|
||||
|
||||
/* Neat get_elt func that also works for varrays drawing by encoding
|
||||
* the start value into a pointer.
|
||||
*/
|
||||
|
||||
static unsigned elt_uint( const void *elts, unsigned idx )
|
||||
{
|
||||
return *(((const uint *)elts) + idx);
|
||||
}
|
||||
|
||||
static unsigned elt_ushort( const void *elts, unsigned idx )
|
||||
{
|
||||
return *(((const ushort *)elts) + idx);
|
||||
}
|
||||
|
||||
static unsigned elt_ubyte( const void *elts, unsigned idx )
|
||||
{
|
||||
return *(((const ubyte *)elts) + idx);
|
||||
}
|
||||
|
||||
static unsigned elt_vert( const void *elts, unsigned idx )
|
||||
{
|
||||
/* unsigned index is packed in the pointer */
|
||||
return (unsigned)(uintptr_t)elts + idx;
|
||||
}
|
||||
|
||||
pt_elt_func draw_pt_elt_func( struct draw_context *draw )
|
||||
{
|
||||
switch (draw->pt.user.eltSize) {
|
||||
case 0: return &elt_vert;
|
||||
case 1: return &elt_ubyte;
|
||||
case 2: return &elt_ushort;
|
||||
case 4: return &elt_uint;
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const void *draw_pt_elt_ptr( struct draw_context *draw,
|
||||
unsigned start )
|
||||
{
|
||||
const char *elts = draw->pt.user.elts;
|
||||
|
||||
switch (draw->pt.user.eltSize) {
|
||||
case 0:
|
||||
return (const void *)(((const ubyte *)NULL) + start);
|
||||
case 1:
|
||||
return (const void *)(((const ubyte *)elts) + start);
|
||||
case 2:
|
||||
return (const void *)(((const ushort *)elts) + start);
|
||||
case 4:
|
||||
return (const void *)(((const uint *)elts) + start);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -120,9 +120,6 @@ void draw_pt_emit_prepare( struct pt_emit *emit,
|
|||
|
||||
*max_vertices = (draw->render->max_vertex_buffer_bytes /
|
||||
(vinfo->size * 4));
|
||||
|
||||
/* even number */
|
||||
*max_vertices = *max_vertices & ~1;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -147,11 +144,6 @@ void draw_pt_emit( struct pt_emit *emit,
|
|||
if (vertex_count == 0)
|
||||
return;
|
||||
|
||||
if (vertex_count >= UNDEFINED_VERTEX_ID) {
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX: and work out some way to coordinate the render primitive
|
||||
* between vbuf.c and here...
|
||||
*/
|
||||
|
|
@ -226,9 +218,6 @@ void draw_pt_emit_linear(struct pt_emit *emit,
|
|||
*/
|
||||
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
|
||||
|
||||
if (count >= UNDEFINED_VERTEX_ID)
|
||||
goto fail;
|
||||
|
||||
/* XXX: and work out some way to coordinate the render primitive
|
||||
* between vbuf.c and here...
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -191,15 +191,6 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
|
|||
|
||||
*max_vertices = (draw->render->max_vertex_buffer_bytes /
|
||||
(vinfo->size * 4));
|
||||
|
||||
/* Return an even number of verts.
|
||||
* This prevents "parity" errors when splitting long triangle strips which
|
||||
* can lead to front/back culling mix-ups.
|
||||
* Every other triangle in a strip has an alternate front/back orientation
|
||||
* so splitting at an odd position can cause the orientation of subsequent
|
||||
* triangles to get reversed.
|
||||
*/
|
||||
*max_vertices = *max_vertices & ~1;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -210,7 +201,8 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
|
|||
const unsigned *fetch_elts,
|
||||
unsigned fetch_count,
|
||||
const ushort *draw_elts,
|
||||
unsigned draw_count )
|
||||
unsigned draw_count,
|
||||
unsigned prim_flags )
|
||||
{
|
||||
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
|
||||
struct draw_context *draw = feme->draw;
|
||||
|
|
@ -220,11 +212,6 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
|
|||
*/
|
||||
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
|
||||
|
||||
if (fetch_count >= UNDEFINED_VERTEX_ID) {
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
draw->render->allocate_vertices( draw->render,
|
||||
(ushort)feme->translate->key.output_stride,
|
||||
(ushort)fetch_count );
|
||||
|
|
@ -273,7 +260,8 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle,
|
|||
|
||||
static void fetch_emit_run_linear( struct draw_pt_middle_end *middle,
|
||||
unsigned start,
|
||||
unsigned count )
|
||||
unsigned count,
|
||||
unsigned prim_flags )
|
||||
{
|
||||
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
|
||||
struct draw_context *draw = feme->draw;
|
||||
|
|
@ -283,9 +271,6 @@ static void fetch_emit_run_linear( struct draw_pt_middle_end *middle,
|
|||
*/
|
||||
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
|
||||
|
||||
if (count >= UNDEFINED_VERTEX_ID)
|
||||
goto fail;
|
||||
|
||||
if (!draw->render->allocate_vertices( draw->render,
|
||||
(ushort)feme->translate->key.output_stride,
|
||||
(ushort)count ))
|
||||
|
|
@ -334,7 +319,8 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle,
|
|||
unsigned start,
|
||||
unsigned count,
|
||||
const ushort *draw_elts,
|
||||
unsigned draw_count )
|
||||
unsigned draw_count,
|
||||
unsigned prim_flags )
|
||||
{
|
||||
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
|
||||
struct draw_context *draw = feme->draw;
|
||||
|
|
@ -344,9 +330,6 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle,
|
|||
*/
|
||||
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
|
||||
|
||||
if (count >= UNDEFINED_VERTEX_ID)
|
||||
return FALSE;
|
||||
|
||||
if (!draw->render->allocate_vertices( draw->render,
|
||||
(ushort)feme->translate->key.output_stride,
|
||||
(ushort)count ))
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
|
|||
fse->key.nr_inputs); /* inputs - fetch from api format */
|
||||
|
||||
fse->key.viewport = !draw->identity_viewport;
|
||||
fse->key.clip = !draw->bypass_clipping;
|
||||
fse->key.clip = draw->clip_xy || draw->clip_z || draw->clip_user;
|
||||
fse->key.const_vbuffers = 0;
|
||||
|
||||
memset(fse->key.element, 0,
|
||||
|
|
@ -175,15 +175,6 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
|
|||
*max_vertices = (draw->render->max_vertex_buffer_bytes /
|
||||
(vinfo->size * 4));
|
||||
|
||||
/* Return an even number of verts.
|
||||
* This prevents "parity" errors when splitting long triangle strips which
|
||||
* can lead to front/back culling mix-ups.
|
||||
* Every other triangle in a strip has an alternate front/back orientation
|
||||
* so splitting at an odd position can cause the orientation of subsequent
|
||||
* triangles to get reversed.
|
||||
*/
|
||||
*max_vertices = *max_vertices & ~1;
|
||||
|
||||
/* Probably need to do this somewhere (or fix exec shader not to
|
||||
* need it):
|
||||
*/
|
||||
|
|
@ -197,7 +188,8 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
|
|||
|
||||
static void fse_run_linear( struct draw_pt_middle_end *middle,
|
||||
unsigned start,
|
||||
unsigned count )
|
||||
unsigned count,
|
||||
unsigned prim_flags )
|
||||
{
|
||||
struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
|
||||
struct draw_context *draw = fse->draw;
|
||||
|
|
@ -207,9 +199,6 @@ static void fse_run_linear( struct draw_pt_middle_end *middle,
|
|||
*/
|
||||
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
|
||||
|
||||
if (count >= UNDEFINED_VERTEX_ID)
|
||||
goto fail;
|
||||
|
||||
if (!draw->render->allocate_vertices( draw->render,
|
||||
(ushort)fse->key.output_stride,
|
||||
(ushort)count ))
|
||||
|
|
@ -265,7 +254,8 @@ fse_run(struct draw_pt_middle_end *middle,
|
|||
const unsigned *fetch_elts,
|
||||
unsigned fetch_count,
|
||||
const ushort *draw_elts,
|
||||
unsigned draw_count )
|
||||
unsigned draw_count,
|
||||
unsigned prim_flags )
|
||||
{
|
||||
struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
|
||||
struct draw_context *draw = fse->draw;
|
||||
|
|
@ -275,9 +265,6 @@ fse_run(struct draw_pt_middle_end *middle,
|
|||
*/
|
||||
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
|
||||
|
||||
if (fetch_count >= UNDEFINED_VERTEX_ID)
|
||||
goto fail;
|
||||
|
||||
if (!draw->render->allocate_vertices( draw->render,
|
||||
(ushort)fse->key.output_stride,
|
||||
(ushort)fetch_count ))
|
||||
|
|
@ -327,7 +314,8 @@ static boolean fse_run_linear_elts( struct draw_pt_middle_end *middle,
|
|||
unsigned start,
|
||||
unsigned count,
|
||||
const ushort *draw_elts,
|
||||
unsigned draw_count )
|
||||
unsigned draw_count,
|
||||
unsigned prim_flags )
|
||||
{
|
||||
struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
|
||||
struct draw_context *draw = fse->draw;
|
||||
|
|
@ -337,9 +325,6 @@ static boolean fse_run_linear_elts( struct draw_pt_middle_end *middle,
|
|||
*/
|
||||
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
|
||||
|
||||
if (count >= UNDEFINED_VERTEX_ID)
|
||||
return FALSE;
|
||||
|
||||
if (!draw->render->allocate_vertices( draw->render,
|
||||
(ushort)fse->key.output_stride,
|
||||
(ushort)count ))
|
||||
|
|
|
|||
|
|
@ -100,8 +100,10 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
|
|||
* but gl vs dx9 clip spaces.
|
||||
*/
|
||||
draw_pt_post_vs_prepare( fpme->post_vs,
|
||||
(boolean)draw->bypass_clipping,
|
||||
(boolean)draw->identity_viewport,
|
||||
draw->clip_xy,
|
||||
draw->clip_z,
|
||||
draw->clip_user,
|
||||
draw->identity_viewport,
|
||||
(boolean)draw->rasterizer->gl_rasterization_rules,
|
||||
(draw->vs.edgeflag_output ? TRUE : FALSE) );
|
||||
|
||||
|
|
@ -112,16 +114,13 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
|
|||
gs_out_prim,
|
||||
max_vertices );
|
||||
|
||||
*max_vertices = MAX2( *max_vertices,
|
||||
DRAW_PIPE_MAX_VERTICES );
|
||||
*max_vertices = MAX2( *max_vertices, 4096 );
|
||||
}
|
||||
else {
|
||||
*max_vertices = DRAW_PIPE_MAX_VERTICES;
|
||||
/* limit max fetches by limiting max_vertices */
|
||||
*max_vertices = 4096;
|
||||
}
|
||||
|
||||
/* return even number */
|
||||
*max_vertices = *max_vertices & ~1;
|
||||
|
||||
/* No need to prepare the shader.
|
||||
*/
|
||||
vs->prepare(vs, draw);
|
||||
|
|
@ -295,7 +294,8 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
|
|||
const unsigned *fetch_elts,
|
||||
unsigned fetch_count,
|
||||
const ushort *draw_elts,
|
||||
unsigned draw_count )
|
||||
unsigned draw_count,
|
||||
unsigned prim_flags )
|
||||
{
|
||||
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
|
||||
struct draw_fetch_info fetch_info;
|
||||
|
|
@ -311,6 +311,7 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
|
|||
prim_info.count = draw_count;
|
||||
prim_info.elts = draw_elts;
|
||||
prim_info.prim = fpme->input_prim;
|
||||
prim_info.flags = prim_flags;
|
||||
prim_info.primitive_count = 1;
|
||||
prim_info.primitive_lengths = &draw_count;
|
||||
|
||||
|
|
@ -320,7 +321,8 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
|
|||
|
||||
static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
|
||||
unsigned start,
|
||||
unsigned count)
|
||||
unsigned count,
|
||||
unsigned prim_flags)
|
||||
{
|
||||
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
|
||||
struct draw_fetch_info fetch_info;
|
||||
|
|
@ -336,6 +338,7 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
|
|||
prim_info.count = count;
|
||||
prim_info.elts = NULL;
|
||||
prim_info.prim = fpme->input_prim;
|
||||
prim_info.flags = prim_flags;
|
||||
prim_info.primitive_count = 1;
|
||||
prim_info.primitive_lengths = &count;
|
||||
|
||||
|
|
@ -348,7 +351,8 @@ static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle
|
|||
unsigned start,
|
||||
unsigned count,
|
||||
const ushort *draw_elts,
|
||||
unsigned draw_count )
|
||||
unsigned draw_count,
|
||||
unsigned prim_flags )
|
||||
{
|
||||
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
|
||||
struct draw_fetch_info fetch_info;
|
||||
|
|
@ -364,6 +368,7 @@ static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle
|
|||
prim_info.count = draw_count;
|
||||
prim_info.elts = draw_elts;
|
||||
prim_info.prim = fpme->input_prim;
|
||||
prim_info.flags = prim_flags;
|
||||
prim_info.primitive_count = 1;
|
||||
prim_info.primitive_lengths = &draw_count;
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
|
|||
struct draw_context *draw = fpme->draw;
|
||||
struct llvm_vertex_shader *shader =
|
||||
llvm_vertex_shader(draw->vs.vertex_shader);
|
||||
struct draw_llvm_variant_key key;
|
||||
char store[DRAW_LLVM_MAX_VARIANT_KEY_SIZE];
|
||||
struct draw_llvm_variant_key *key;
|
||||
struct draw_llvm_variant *variant = NULL;
|
||||
struct draw_llvm_variant_list_item *li;
|
||||
unsigned i;
|
||||
|
|
@ -106,8 +107,10 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
|
|||
* but gl vs dx9 clip spaces.
|
||||
*/
|
||||
draw_pt_post_vs_prepare( fpme->post_vs,
|
||||
(boolean)draw->bypass_clipping,
|
||||
(boolean)(draw->identity_viewport),
|
||||
draw->clip_xy,
|
||||
draw->clip_z,
|
||||
draw->clip_user,
|
||||
draw->identity_viewport,
|
||||
(boolean)draw->rasterizer->gl_rasterization_rules,
|
||||
(draw->vs.edgeflag_output ? TRUE : FALSE) );
|
||||
|
||||
|
|
@ -118,21 +121,21 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
|
|||
out_prim,
|
||||
max_vertices );
|
||||
|
||||
*max_vertices = MAX2( *max_vertices,
|
||||
DRAW_PIPE_MAX_VERTICES );
|
||||
*max_vertices = MAX2( *max_vertices, 4096 );
|
||||
}
|
||||
else {
|
||||
*max_vertices = DRAW_PIPE_MAX_VERTICES;
|
||||
/* limit max fetches by limiting max_vertices */
|
||||
*max_vertices = 4096;
|
||||
}
|
||||
|
||||
/* return even number */
|
||||
*max_vertices = *max_vertices & ~1;
|
||||
|
||||
draw_llvm_make_variant_key(fpme->llvm, &key);
|
||||
|
||||
key = draw_llvm_make_variant_key(fpme->llvm, store);
|
||||
|
||||
li = first_elem(&shader->variants);
|
||||
while(!at_end(&shader->variants, li)) {
|
||||
if(memcmp(&li->base->key, &key, sizeof key) == 0) {
|
||||
if(memcmp(&li->base->key, key, shader->variant_key_size) == 0) {
|
||||
variant = li->base;
|
||||
break;
|
||||
}
|
||||
|
|
@ -155,7 +158,7 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
|
|||
}
|
||||
}
|
||||
|
||||
variant = draw_llvm_create_variant(fpme->llvm, nr);
|
||||
variant = draw_llvm_create_variant(fpme->llvm, nr, key);
|
||||
|
||||
if (variant) {
|
||||
insert_at_head(&shader->variants, &variant->list_item_local);
|
||||
|
|
@ -294,7 +297,8 @@ static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
|
|||
const unsigned *fetch_elts,
|
||||
unsigned fetch_count,
|
||||
const ushort *draw_elts,
|
||||
unsigned draw_count )
|
||||
unsigned draw_count,
|
||||
unsigned prim_flags )
|
||||
{
|
||||
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
|
||||
struct draw_fetch_info fetch_info;
|
||||
|
|
@ -310,6 +314,7 @@ static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
|
|||
prim_info.count = draw_count;
|
||||
prim_info.elts = draw_elts;
|
||||
prim_info.prim = fpme->input_prim;
|
||||
prim_info.flags = prim_flags;
|
||||
prim_info.primitive_count = 1;
|
||||
prim_info.primitive_lengths = &draw_count;
|
||||
|
||||
|
|
@ -319,7 +324,8 @@ static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
|
|||
|
||||
static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle,
|
||||
unsigned start,
|
||||
unsigned count)
|
||||
unsigned count,
|
||||
unsigned prim_flags)
|
||||
{
|
||||
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
|
||||
struct draw_fetch_info fetch_info;
|
||||
|
|
@ -335,6 +341,7 @@ static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle,
|
|||
prim_info.count = count;
|
||||
prim_info.elts = NULL;
|
||||
prim_info.prim = fpme->input_prim;
|
||||
prim_info.flags = prim_flags;
|
||||
prim_info.primitive_count = 1;
|
||||
prim_info.primitive_lengths = &count;
|
||||
|
||||
|
|
@ -348,7 +355,8 @@ llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle,
|
|||
unsigned start,
|
||||
unsigned count,
|
||||
const ushort *draw_elts,
|
||||
unsigned draw_count )
|
||||
unsigned draw_count,
|
||||
unsigned prim_flags )
|
||||
{
|
||||
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
|
||||
struct draw_fetch_info fetch_info;
|
||||
|
|
@ -364,6 +372,7 @@ llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle,
|
|||
prim_info.count = draw_count;
|
||||
prim_info.elts = draw_elts;
|
||||
prim_info.prim = fpme->input_prim;
|
||||
prim_info.flags = prim_flags;
|
||||
prim_info.primitive_count = 1;
|
||||
prim_info.primitive_lengths = &draw_count;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,14 +26,26 @@
|
|||
**************************************************************************/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_math.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "draw/draw_context.h"
|
||||
#include "draw/draw_private.h"
|
||||
#include "draw/draw_pt.h"
|
||||
|
||||
|
||||
#define DO_CLIP_XY 0x1
|
||||
#define DO_CLIP_FULL_Z 0x2
|
||||
#define DO_CLIP_HALF_Z 0x4
|
||||
#define DO_CLIP_USER 0x8
|
||||
#define DO_VIEWPORT 0x10
|
||||
#define DO_EDGEFLAG 0x20
|
||||
|
||||
|
||||
struct pt_post_vs {
|
||||
struct draw_context *draw;
|
||||
|
||||
unsigned flags;
|
||||
|
||||
boolean (*run)( struct pt_post_vs *pvs,
|
||||
struct draw_vertex_info *info );
|
||||
};
|
||||
|
|
@ -56,186 +68,47 @@ dot4(const float *a, const float *b)
|
|||
a[3]*b[3]);
|
||||
}
|
||||
|
||||
static INLINE unsigned
|
||||
compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr,
|
||||
boolean clip_depth)
|
||||
{
|
||||
unsigned mask = 0x0;
|
||||
unsigned i;
|
||||
#define FLAGS (0)
|
||||
#define TAG(x) x##_none
|
||||
#include "draw_cliptest_tmp.h"
|
||||
|
||||
#if 0
|
||||
debug_printf("compute clipmask %f %f %f %f\n",
|
||||
clip[0], clip[1], clip[2], clip[3]);
|
||||
assert(clip[3] != 0.0);
|
||||
#endif
|
||||
#define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_VIEWPORT)
|
||||
#define TAG(x) x##_xy_fullz_viewport
|
||||
#include "draw_cliptest_tmp.h"
|
||||
|
||||
/* Do the hardwired planes first:
|
||||
*/
|
||||
if (-clip[0] + clip[3] < 0) mask |= (1<<0);
|
||||
if ( clip[0] + clip[3] < 0) mask |= (1<<1);
|
||||
if (-clip[1] + clip[3] < 0) mask |= (1<<2);
|
||||
if ( clip[1] + clip[3] < 0) mask |= (1<<3);
|
||||
if (clip_depth) {
|
||||
if ( clip[2] + clip[3] < 0) mask |= (1<<4); /* match mesa clipplane numbering - for now */
|
||||
if (-clip[2] + clip[3] < 0) mask |= (1<<5); /* match mesa clipplane numbering - for now */
|
||||
}
|
||||
#define FLAGS (DO_CLIP_XY | DO_CLIP_HALF_Z | DO_VIEWPORT)
|
||||
#define TAG(x) x##_xy_halfz_viewport
|
||||
#include "draw_cliptest_tmp.h"
|
||||
|
||||
/* Followed by any remaining ones:
|
||||
*/
|
||||
for (i = 6; i < nr; i++) {
|
||||
if (dot4(clip, plane[i]) < 0)
|
||||
mask |= (1<<i);
|
||||
}
|
||||
#define FLAGS (DO_CLIP_FULL_Z | DO_VIEWPORT)
|
||||
#define TAG(x) x##_fullz_viewport
|
||||
#include "draw_cliptest_tmp.h"
|
||||
|
||||
return mask;
|
||||
}
|
||||
#define FLAGS (DO_CLIP_HALF_Z | DO_VIEWPORT)
|
||||
#define TAG(x) x##_halfz_viewport
|
||||
#include "draw_cliptest_tmp.h"
|
||||
|
||||
#define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT)
|
||||
#define TAG(x) x##_xy_fullz_user_viewport
|
||||
#include "draw_cliptest_tmp.h"
|
||||
|
||||
#define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT | DO_EDGEFLAG)
|
||||
#define TAG(x) x##_xy_fullz_user_viewport_edgeflag
|
||||
#include "draw_cliptest_tmp.h"
|
||||
|
||||
|
||||
/* The normal case - cliptest, rhw divide, viewport transform.
|
||||
*
|
||||
* Also handle identity viewport here at the expense of a few wasted
|
||||
* instructions
|
||||
|
||||
/* Don't want to create 64 versions of this function, so catch the
|
||||
* less common ones here. This is looking like something which should
|
||||
* be code-generated, perhaps appended to the end of the vertex
|
||||
* shader.
|
||||
*/
|
||||
static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
|
||||
struct draw_vertex_info *info )
|
||||
{
|
||||
struct vertex_header *out = info->verts;
|
||||
const float *scale = pvs->draw->viewport.scale;
|
||||
const float *trans = pvs->draw->viewport.translate;
|
||||
const unsigned pos = draw_current_shader_position_output(pvs->draw);
|
||||
unsigned clipped = 0;
|
||||
unsigned j;
|
||||
|
||||
if (0) debug_printf("%s count, %d\n", __FUNCTION__, info->count);
|
||||
|
||||
for (j = 0; j < info->count; j++) {
|
||||
float *position = out->data[pos];
|
||||
|
||||
initialize_vertex_header(out);
|
||||
#if 0
|
||||
debug_printf("%d) io = %p, data = %p = [%f, %f, %f, %f]\n",
|
||||
j, out, position, position[0], position[1], position[2], position[3]);
|
||||
#endif
|
||||
|
||||
out->clip[0] = position[0];
|
||||
out->clip[1] = position[1];
|
||||
out->clip[2] = position[2];
|
||||
out->clip[3] = position[3];
|
||||
|
||||
out->vertex_id = 0xffff;
|
||||
/* Disable depth clipping if depth clamping is enabled. */
|
||||
out->clipmask = compute_clipmask_gl(out->clip,
|
||||
pvs->draw->plane,
|
||||
pvs->draw->nr_planes,
|
||||
!pvs->draw->depth_clamp);
|
||||
clipped += out->clipmask;
|
||||
|
||||
if (out->clipmask == 0)
|
||||
{
|
||||
/* divide by w */
|
||||
float w = 1.0f / position[3];
|
||||
|
||||
/* Viewport mapping */
|
||||
position[0] = position[0] * w * scale[0] + trans[0];
|
||||
position[1] = position[1] * w * scale[1] + trans[1];
|
||||
position[2] = position[2] * w * scale[2] + trans[2];
|
||||
position[3] = w;
|
||||
#if 0
|
||||
debug_printf("post viewport: %f %f %f %f\n",
|
||||
position[0],
|
||||
position[1],
|
||||
position[2],
|
||||
position[3]);
|
||||
#endif
|
||||
}
|
||||
|
||||
out = (struct vertex_header *)( (char *)out + info->stride );
|
||||
}
|
||||
|
||||
return clipped != 0;
|
||||
}
|
||||
#define FLAGS (pvs->flags)
|
||||
#define TAG(x) x##_generic
|
||||
#include "draw_cliptest_tmp.h"
|
||||
|
||||
|
||||
|
||||
/* As above plus edgeflags
|
||||
*/
|
||||
static boolean
|
||||
post_vs_cliptest_viewport_gl_edgeflag(struct pt_post_vs *pvs,
|
||||
struct draw_vertex_info *info)
|
||||
{
|
||||
unsigned j;
|
||||
boolean needpipe;
|
||||
|
||||
needpipe = post_vs_cliptest_viewport_gl(pvs, info);
|
||||
|
||||
/* If present, copy edgeflag VS output into vertex header.
|
||||
* Otherwise, leave header as is.
|
||||
*/
|
||||
if (pvs->draw->vs.edgeflag_output) {
|
||||
struct vertex_header *out = info->verts;
|
||||
int ef = pvs->draw->vs.edgeflag_output;
|
||||
|
||||
for (j = 0; j < info->count; j++) {
|
||||
const float *edgeflag = out->data[ef];
|
||||
out->edgeflag = !(edgeflag[0] != 1.0f);
|
||||
needpipe |= !out->edgeflag;
|
||||
out = (struct vertex_header *)( (char *)out + info->stride );
|
||||
}
|
||||
}
|
||||
return needpipe;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* If bypass_clipping is set, skip cliptest and rhw divide.
|
||||
*/
|
||||
static boolean post_vs_viewport( struct pt_post_vs *pvs,
|
||||
struct draw_vertex_info *info )
|
||||
{
|
||||
struct vertex_header *out = info->verts;
|
||||
const float *scale = pvs->draw->viewport.scale;
|
||||
const float *trans = pvs->draw->viewport.translate;
|
||||
const unsigned pos = draw_current_shader_position_output(pvs->draw);
|
||||
unsigned j;
|
||||
|
||||
if (0) debug_printf("%s\n", __FUNCTION__);
|
||||
for (j = 0; j < info->count; j++) {
|
||||
float *position = out->data[pos];
|
||||
|
||||
initialize_vertex_header(out);
|
||||
/* Viewport mapping only, no cliptest/rhw divide
|
||||
*/
|
||||
position[0] = position[0] * scale[0] + trans[0];
|
||||
position[1] = position[1] * scale[1] + trans[1];
|
||||
position[2] = position[2] * scale[2] + trans[2];
|
||||
|
||||
out = (struct vertex_header *)((char *)out + info->stride);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* If bypass_clipping is set and we have an identity viewport, nothing
|
||||
* to do.
|
||||
*/
|
||||
static boolean post_vs_none( struct pt_post_vs *pvs,
|
||||
struct draw_vertex_info *info )
|
||||
{
|
||||
struct vertex_header *out = info->verts;
|
||||
unsigned j;
|
||||
|
||||
if (0) debug_printf("%s\n", __FUNCTION__);
|
||||
/* just initialize the vertex_id in all headers */
|
||||
for (j = 0; j < info->count; j++) {
|
||||
initialize_vertex_header(out);
|
||||
|
||||
out = (struct vertex_header *)((char *)out + info->stride);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
|
||||
struct draw_vertex_info *info )
|
||||
{
|
||||
|
|
@ -244,31 +117,72 @@ boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
|
|||
|
||||
|
||||
void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
|
||||
boolean bypass_clipping,
|
||||
boolean clip_xy,
|
||||
boolean clip_z,
|
||||
boolean clip_user,
|
||||
boolean bypass_viewport,
|
||||
boolean opengl,
|
||||
boolean need_edgeflags )
|
||||
{
|
||||
if (!need_edgeflags) {
|
||||
if (bypass_clipping) {
|
||||
if (bypass_viewport)
|
||||
pvs->run = post_vs_none;
|
||||
else
|
||||
pvs->run = post_vs_viewport;
|
||||
}
|
||||
else {
|
||||
/* if (opengl) */
|
||||
pvs->run = post_vs_cliptest_viewport_gl;
|
||||
}
|
||||
pvs->flags = 0;
|
||||
|
||||
if (clip_xy)
|
||||
pvs->flags |= DO_CLIP_XY;
|
||||
|
||||
if (clip_z && opengl) {
|
||||
pvs->flags |= DO_CLIP_FULL_Z;
|
||||
ASSIGN_4V( pvs->draw->plane[4], 0, 0, 1, 1 );
|
||||
}
|
||||
else {
|
||||
/* If we need to copy edgeflags to the vertex header, it should
|
||||
* mean we're running the primitive pipeline. Hence the bypass
|
||||
* flags should be false.
|
||||
*/
|
||||
assert(!bypass_clipping);
|
||||
assert(!bypass_viewport);
|
||||
pvs->run = post_vs_cliptest_viewport_gl_edgeflag;
|
||||
|
||||
if (clip_z && !opengl) {
|
||||
pvs->flags |= DO_CLIP_HALF_Z;
|
||||
ASSIGN_4V( pvs->draw->plane[4], 0, 0, 1, 0 );
|
||||
}
|
||||
|
||||
if (clip_user)
|
||||
pvs->flags |= DO_CLIP_USER;
|
||||
|
||||
if (!bypass_viewport)
|
||||
pvs->flags |= DO_VIEWPORT;
|
||||
|
||||
if (need_edgeflags)
|
||||
pvs->flags |= DO_EDGEFLAG;
|
||||
|
||||
/* Now select the relevant function:
|
||||
*/
|
||||
switch (pvs->flags) {
|
||||
case 0:
|
||||
pvs->run = do_cliptest_none;
|
||||
break;
|
||||
|
||||
case DO_CLIP_XY | DO_CLIP_FULL_Z | DO_VIEWPORT:
|
||||
pvs->run = do_cliptest_xy_fullz_viewport;
|
||||
break;
|
||||
|
||||
case DO_CLIP_XY | DO_CLIP_HALF_Z | DO_VIEWPORT:
|
||||
pvs->run = do_cliptest_xy_halfz_viewport;
|
||||
break;
|
||||
|
||||
case DO_CLIP_FULL_Z | DO_VIEWPORT:
|
||||
pvs->run = do_cliptest_fullz_viewport;
|
||||
break;
|
||||
|
||||
case DO_CLIP_HALF_Z | DO_VIEWPORT:
|
||||
pvs->run = do_cliptest_halfz_viewport;
|
||||
break;
|
||||
|
||||
case DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT:
|
||||
pvs->run = do_cliptest_xy_fullz_user_viewport;
|
||||
break;
|
||||
|
||||
case (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER |
|
||||
DO_VIEWPORT | DO_EDGEFLAG):
|
||||
pvs->run = do_cliptest_xy_fullz_user_viewport_edgeflag;
|
||||
break;
|
||||
|
||||
default:
|
||||
pvs->run = do_cliptest_generic;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ static void so_tri(struct pt_so_emit *so, int i0, int i1, int i2)
|
|||
|
||||
#define FUNC so_run_elts
|
||||
#define LOCAL_VARS const ushort *elts = input_prims->elts;
|
||||
#define GET_ELT(idx) (elts[start + (idx)] & ~DRAW_PIPE_FLAG_MASK)
|
||||
#define GET_ELT(idx) (elts[start + (idx)])
|
||||
#include "draw_so_emit_tmp.h"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -92,3 +92,10 @@ void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned draw_pt_trim_count(unsigned count, unsigned first, unsigned incr)
|
||||
{
|
||||
if (count < first)
|
||||
return 0;
|
||||
return count - (count - first) % incr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,200 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "draw/draw_context.h"
|
||||
#include "draw/draw_private.h"
|
||||
#include "draw/draw_pt.h"
|
||||
|
||||
#define FETCH_MAX 256
|
||||
#define DRAW_MAX (FETCH_MAX+8)
|
||||
|
||||
struct varray_frontend {
|
||||
struct draw_pt_front_end base;
|
||||
struct draw_context *draw;
|
||||
|
||||
ushort draw_elts[DRAW_MAX];
|
||||
unsigned fetch_elts[FETCH_MAX];
|
||||
|
||||
unsigned driver_fetch_max;
|
||||
unsigned fetch_max;
|
||||
|
||||
struct draw_pt_middle_end *middle;
|
||||
|
||||
unsigned input_prim;
|
||||
unsigned output_prim;
|
||||
};
|
||||
|
||||
|
||||
static void varray_flush_linear(struct varray_frontend *varray,
|
||||
unsigned start, unsigned count)
|
||||
{
|
||||
if (count) {
|
||||
assert(varray->middle->run_linear);
|
||||
varray->middle->run_linear(varray->middle, start, count);
|
||||
}
|
||||
}
|
||||
|
||||
static void varray_line_loop_segment(struct varray_frontend *varray,
|
||||
unsigned start,
|
||||
unsigned segment_start,
|
||||
unsigned segment_count,
|
||||
boolean end )
|
||||
{
|
||||
assert(segment_count < varray->fetch_max);
|
||||
if (segment_count >= 1) {
|
||||
unsigned nr = 0, i;
|
||||
|
||||
for (i = 0; i < segment_count; i++)
|
||||
varray->fetch_elts[nr++] = start + segment_start + i;
|
||||
|
||||
if (end)
|
||||
varray->fetch_elts[nr++] = start;
|
||||
|
||||
assert(nr <= FETCH_MAX);
|
||||
|
||||
varray->middle->run(varray->middle,
|
||||
varray->fetch_elts,
|
||||
nr,
|
||||
varray->draw_elts, /* ie. linear */
|
||||
nr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void varray_fan_segment(struct varray_frontend *varray,
|
||||
unsigned start,
|
||||
unsigned segment_start,
|
||||
unsigned segment_count )
|
||||
{
|
||||
assert(segment_count < varray->fetch_max);
|
||||
if (segment_count >= 2) {
|
||||
unsigned nr = 0, i;
|
||||
|
||||
if (segment_start != 0)
|
||||
varray->fetch_elts[nr++] = start;
|
||||
|
||||
for (i = 0 ; i < segment_count; i++)
|
||||
varray->fetch_elts[nr++] = start + segment_start + i;
|
||||
|
||||
assert(nr <= FETCH_MAX);
|
||||
|
||||
varray->middle->run(varray->middle,
|
||||
varray->fetch_elts,
|
||||
nr,
|
||||
varray->draw_elts, /* ie. linear */
|
||||
nr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define FUNC varray_run
|
||||
#include "draw_pt_varray_tmp_linear.h"
|
||||
|
||||
static unsigned decompose_prim[PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY + 1] = {
|
||||
PIPE_PRIM_POINTS,
|
||||
PIPE_PRIM_LINES,
|
||||
PIPE_PRIM_LINE_STRIP, /* decomposed LINELOOP */
|
||||
PIPE_PRIM_LINE_STRIP,
|
||||
PIPE_PRIM_TRIANGLES,
|
||||
PIPE_PRIM_TRIANGLE_STRIP,
|
||||
PIPE_PRIM_TRIANGLE_FAN,
|
||||
PIPE_PRIM_QUADS,
|
||||
PIPE_PRIM_QUAD_STRIP,
|
||||
PIPE_PRIM_POLYGON,
|
||||
PIPE_PRIM_LINES_ADJACENCY,
|
||||
PIPE_PRIM_LINE_STRIP_ADJACENCY,
|
||||
PIPE_PRIM_TRIANGLES_ADJACENCY,
|
||||
PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void varray_prepare(struct draw_pt_front_end *frontend,
|
||||
unsigned in_prim,
|
||||
struct draw_pt_middle_end *middle,
|
||||
unsigned opt)
|
||||
{
|
||||
struct varray_frontend *varray = (struct varray_frontend *)frontend;
|
||||
|
||||
varray->base.run = varray_run;
|
||||
|
||||
varray->input_prim = in_prim;
|
||||
assert(in_prim < Elements(decompose_prim));
|
||||
varray->output_prim = decompose_prim[in_prim];
|
||||
|
||||
varray->middle = middle;
|
||||
middle->prepare(middle,
|
||||
varray->output_prim,
|
||||
opt, &varray->driver_fetch_max );
|
||||
|
||||
/* check that the max is even */
|
||||
assert((varray->driver_fetch_max & 1) == 0);
|
||||
|
||||
varray->fetch_max = MIN2(FETCH_MAX, varray->driver_fetch_max);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void varray_finish(struct draw_pt_front_end *frontend)
|
||||
{
|
||||
struct varray_frontend *varray = (struct varray_frontend *)frontend;
|
||||
varray->middle->finish(varray->middle);
|
||||
varray->middle = NULL;
|
||||
}
|
||||
|
||||
static void varray_destroy(struct draw_pt_front_end *frontend)
|
||||
{
|
||||
FREE(frontend);
|
||||
}
|
||||
|
||||
|
||||
struct draw_pt_front_end *draw_pt_varray(struct draw_context *draw)
|
||||
{
|
||||
ushort i;
|
||||
struct varray_frontend *varray = CALLOC_STRUCT(varray_frontend);
|
||||
if (varray == NULL)
|
||||
return NULL;
|
||||
|
||||
varray->base.prepare = varray_prepare;
|
||||
varray->base.run = NULL;
|
||||
varray->base.finish = varray_finish;
|
||||
varray->base.destroy = varray_destroy;
|
||||
varray->draw = draw;
|
||||
|
||||
for (i = 0; i < DRAW_MAX; i++) {
|
||||
varray->draw_elts[i] = i;
|
||||
}
|
||||
|
||||
return &varray->base;
|
||||
}
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
|
||||
static void FUNC(struct draw_pt_front_end *frontend,
|
||||
pt_elt_func get_elt,
|
||||
const void *elts,
|
||||
unsigned count)
|
||||
{
|
||||
struct varray_frontend *varray = (struct varray_frontend *)frontend;
|
||||
struct draw_context *draw = varray->draw;
|
||||
unsigned start = (unsigned)elts;
|
||||
|
||||
boolean flatfirst = (draw->rasterizer->flatshade &&
|
||||
draw->rasterizer->flatshade_first);
|
||||
unsigned i, j;
|
||||
ushort flags;
|
||||
unsigned first, incr;
|
||||
|
||||
varray->fetch_start = start;
|
||||
|
||||
draw_pt_split_prim(varray->input_prim, &first, &incr);
|
||||
|
||||
#if 0
|
||||
debug_printf("%s (%d) %d/%d\n", __FUNCTION__,
|
||||
varray->input_prim,
|
||||
start, count);
|
||||
#endif
|
||||
|
||||
switch (varray->input_prim) {
|
||||
case PIPE_PRIM_POINTS:
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 0; i < end; i++) {
|
||||
POINT(varray, i + 0);
|
||||
}
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_LINES:
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 0; i+1 < end; i += 2) {
|
||||
LINE(varray, DRAW_PIPE_RESET_STIPPLE,
|
||||
i + 0, i + 1);
|
||||
}
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_LINE_LOOP:
|
||||
if (count >= 2) {
|
||||
flags = DRAW_PIPE_RESET_STIPPLE;
|
||||
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 1; i < end; i++, flags = 0) {
|
||||
LINE(varray, flags, i - 1, i);
|
||||
}
|
||||
LINE(varray, flags, i - 1, 0);
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_LINE_STRIP:
|
||||
flags = DRAW_PIPE_RESET_STIPPLE;
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 1; i < end; i++, flags = 0) {
|
||||
LINE(varray, flags, i - 1, i);
|
||||
}
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_TRIANGLES:
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 0; i+2 < end; i += 3) {
|
||||
TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
|
||||
i + 0, i + 1, i + 2);
|
||||
}
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_TRIANGLE_STRIP:
|
||||
if (flatfirst) {
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 0; i+2 < end; i++) {
|
||||
TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
|
||||
i + 0, i + 1 + (i&1), i + 2 - (i&1));
|
||||
}
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
if (j + first + i <= count) {
|
||||
varray->fetch_start -= 2;
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 0; i + 2 < end; i++) {
|
||||
TRIANGLE(varray, DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL,
|
||||
i + 0 + (i&1), i + 1 - (i&1), i + 2);
|
||||
}
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
if (j + first + i <= count) {
|
||||
varray->fetch_start -= 2;
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_TRIANGLE_FAN:
|
||||
if (count >= 3) {
|
||||
if (flatfirst) {
|
||||
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 0; i+2 < end; i++) {
|
||||
TRIANGLE(varray, flags, i + 1, i + 2, 0);
|
||||
}
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
}
|
||||
}
|
||||
else {
|
||||
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 0; i+2 < end; i++) {
|
||||
TRIANGLE(varray, flags, 0, i + 1, i + 2);
|
||||
}
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_QUADS:
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 0; i+3 < end; i += 4) {
|
||||
QUAD(varray, i + 0, i + 1, i + 2, i + 3);
|
||||
}
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_QUAD_STRIP:
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 0; i+3 < end; i += 2) {
|
||||
QUAD(varray, i + 2, i + 0, i + 1, i + 3);
|
||||
}
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
if (j + first + i <= count) {
|
||||
varray->fetch_start -= 2;
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_POLYGON:
|
||||
{
|
||||
/* These bitflags look a little odd because we submit the
|
||||
* vertices as (1,2,0) to satisfy flatshade requirements.
|
||||
*/
|
||||
const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2;
|
||||
const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0;
|
||||
const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1;
|
||||
|
||||
flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
|
||||
for (j = 0; j + first <= count; j += i) {
|
||||
unsigned end = MIN2(FETCH_MAX, count - j);
|
||||
end -= (end % incr);
|
||||
for (i = 0; i+2 < end; i++, flags = edge_middle) {
|
||||
|
||||
if (i + 3 == count)
|
||||
flags |= edge_last;
|
||||
|
||||
TRIANGLE(varray, flags, i + 1, i + 2, 0);
|
||||
}
|
||||
i = end;
|
||||
fetch_init(varray, end);
|
||||
varray_flush(varray);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
varray_flush(varray);
|
||||
}
|
||||
|
||||
#undef TRIANGLE
|
||||
#undef QUAD
|
||||
#undef POINT
|
||||
#undef LINE
|
||||
#undef FUNC
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
static unsigned trim( unsigned count, unsigned first, unsigned incr )
|
||||
{
|
||||
/*
|
||||
* count either has been trimmed in draw_pt_arrays or is set to
|
||||
* (driver)_fetch_max which is hopefully always larger than first.
|
||||
*/
|
||||
assert(count >= first);
|
||||
return count - (count - first) % incr;
|
||||
}
|
||||
|
||||
static void FUNC(struct draw_pt_front_end *frontend,
|
||||
pt_elt_func get_elt,
|
||||
const void *elts,
|
||||
int elt_bias,
|
||||
unsigned count)
|
||||
{
|
||||
struct varray_frontend *varray = (struct varray_frontend *)frontend;
|
||||
unsigned start = (unsigned) ((char *) elts - (char *) NULL);
|
||||
|
||||
unsigned j;
|
||||
unsigned first, incr;
|
||||
|
||||
assert(elt_bias == 0);
|
||||
|
||||
draw_pt_split_prim(varray->input_prim, &first, &incr);
|
||||
|
||||
/* Sanitize primitive length:
|
||||
*/
|
||||
count = trim(count, first, incr);
|
||||
if (count < first)
|
||||
return;
|
||||
|
||||
#if 0
|
||||
debug_printf("%s (%d) %d/%d\n", __FUNCTION__,
|
||||
varray->input_prim,
|
||||
start, count);
|
||||
#endif
|
||||
|
||||
switch (varray->input_prim) {
|
||||
case PIPE_PRIM_POINTS:
|
||||
case PIPE_PRIM_LINES:
|
||||
case PIPE_PRIM_TRIANGLES:
|
||||
case PIPE_PRIM_LINE_STRIP:
|
||||
case PIPE_PRIM_TRIANGLE_STRIP:
|
||||
case PIPE_PRIM_QUADS:
|
||||
case PIPE_PRIM_QUAD_STRIP:
|
||||
case PIPE_PRIM_LINES_ADJACENCY:
|
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
|
||||
case PIPE_PRIM_TRIANGLES_ADJACENCY:
|
||||
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
|
||||
for (j = 0; j < count;) {
|
||||
unsigned remaining = count - j;
|
||||
unsigned nr = trim( MIN2(varray->driver_fetch_max, remaining), first, incr );
|
||||
varray_flush_linear(varray, start + j, nr);
|
||||
j += nr;
|
||||
if (nr != remaining)
|
||||
j -= (first - incr);
|
||||
}
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_LINE_LOOP:
|
||||
/* Always have to decompose as we've stated that this will be
|
||||
* emitted as a line-strip.
|
||||
*/
|
||||
for (j = 0; j < count;) {
|
||||
unsigned remaining = count - j;
|
||||
unsigned nr = trim( MIN2(varray->fetch_max-1, remaining), first, incr );
|
||||
varray_line_loop_segment(varray, start, j, nr, nr == remaining);
|
||||
j += nr;
|
||||
if (nr != remaining)
|
||||
j -= (first - incr);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case PIPE_PRIM_POLYGON:
|
||||
case PIPE_PRIM_TRIANGLE_FAN:
|
||||
if (count < varray->driver_fetch_max) {
|
||||
varray_flush_linear(varray, start, count);
|
||||
}
|
||||
else {
|
||||
for ( j = 0; j < count;) {
|
||||
unsigned remaining = count - j;
|
||||
unsigned nr = trim( MIN2(varray->fetch_max-1, remaining), first, incr );
|
||||
varray_fan_segment(varray, start, j, nr);
|
||||
j += nr;
|
||||
if (nr != remaining)
|
||||
j -= (first - incr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#undef TRIANGLE
|
||||
#undef QUAD
|
||||
#undef POINT
|
||||
#undef LINE
|
||||
#undef FUNC
|
||||
|
|
@ -1,610 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Keith Whitwell <keith@tungstengraphics.com>
|
||||
*/
|
||||
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_prim.h"
|
||||
#include "draw/draw_context.h"
|
||||
#include "draw/draw_private.h"
|
||||
#include "draw/draw_pt.h"
|
||||
|
||||
|
||||
#define CACHE_MAX 256
|
||||
#define FETCH_MAX 256
|
||||
#define DRAW_MAX (16*1024)
|
||||
|
||||
|
||||
struct vcache_frontend {
|
||||
struct draw_pt_front_end base;
|
||||
struct draw_context *draw;
|
||||
|
||||
unsigned in[CACHE_MAX];
|
||||
ushort out[CACHE_MAX];
|
||||
|
||||
ushort draw_elts[DRAW_MAX];
|
||||
unsigned fetch_elts[FETCH_MAX];
|
||||
|
||||
unsigned draw_count;
|
||||
unsigned fetch_count;
|
||||
unsigned fetch_max;
|
||||
|
||||
struct draw_pt_middle_end *middle;
|
||||
|
||||
unsigned input_prim;
|
||||
unsigned output_prim;
|
||||
|
||||
unsigned middle_prim;
|
||||
unsigned opt;
|
||||
};
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_flush( struct vcache_frontend *vcache )
|
||||
{
|
||||
if (vcache->middle_prim != vcache->output_prim) {
|
||||
vcache->middle_prim = vcache->output_prim;
|
||||
vcache->middle->prepare( vcache->middle,
|
||||
vcache->middle_prim,
|
||||
vcache->opt,
|
||||
&vcache->fetch_max );
|
||||
}
|
||||
|
||||
if (vcache->draw_count) {
|
||||
vcache->middle->run( vcache->middle,
|
||||
vcache->fetch_elts,
|
||||
vcache->fetch_count,
|
||||
vcache->draw_elts,
|
||||
vcache->draw_count );
|
||||
}
|
||||
|
||||
memset(vcache->in, ~0, sizeof(vcache->in));
|
||||
vcache->fetch_count = 0;
|
||||
vcache->draw_count = 0;
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_check_flush( struct vcache_frontend *vcache )
|
||||
{
|
||||
if (vcache->draw_count + 6 >= DRAW_MAX ||
|
||||
vcache->fetch_count + 6 >= FETCH_MAX) {
|
||||
vcache_flush( vcache );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_elt( struct vcache_frontend *vcache,
|
||||
unsigned felt,
|
||||
ushort flags )
|
||||
{
|
||||
unsigned idx = felt % CACHE_MAX;
|
||||
|
||||
if (vcache->in[idx] != felt) {
|
||||
assert(vcache->fetch_count < FETCH_MAX);
|
||||
|
||||
vcache->in[idx] = felt;
|
||||
vcache->out[idx] = (ushort)vcache->fetch_count;
|
||||
vcache->fetch_elts[vcache->fetch_count++] = felt;
|
||||
}
|
||||
|
||||
vcache->draw_elts[vcache->draw_count++] = vcache->out[idx] | flags;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_triangle( struct vcache_frontend *vcache,
|
||||
unsigned i0,
|
||||
unsigned i1,
|
||||
unsigned i2 )
|
||||
{
|
||||
vcache_elt(vcache, i0, 0);
|
||||
vcache_elt(vcache, i1, 0);
|
||||
vcache_elt(vcache, i2, 0);
|
||||
vcache_check_flush(vcache);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_triangle_flags( struct vcache_frontend *vcache,
|
||||
ushort flags,
|
||||
unsigned i0,
|
||||
unsigned i1,
|
||||
unsigned i2 )
|
||||
{
|
||||
vcache_elt(vcache, i0, flags);
|
||||
vcache_elt(vcache, i1, 0);
|
||||
vcache_elt(vcache, i2, 0);
|
||||
vcache_check_flush(vcache);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_line( struct vcache_frontend *vcache,
|
||||
unsigned i0,
|
||||
unsigned i1 )
|
||||
{
|
||||
vcache_elt(vcache, i0, 0);
|
||||
vcache_elt(vcache, i1, 0);
|
||||
vcache_check_flush(vcache);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_line_flags( struct vcache_frontend *vcache,
|
||||
ushort flags,
|
||||
unsigned i0,
|
||||
unsigned i1 )
|
||||
{
|
||||
vcache_elt(vcache, i0, flags);
|
||||
vcache_elt(vcache, i1, 0);
|
||||
vcache_check_flush(vcache);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_point( struct vcache_frontend *vcache,
|
||||
unsigned i0 )
|
||||
{
|
||||
vcache_elt(vcache, i0, 0);
|
||||
vcache_check_flush(vcache);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_line_adj_flags( struct vcache_frontend *vcache,
|
||||
unsigned flags,
|
||||
unsigned a0, unsigned i0, unsigned i1, unsigned a1 )
|
||||
{
|
||||
vcache_elt(vcache, a0, 0);
|
||||
vcache_elt(vcache, i0, flags);
|
||||
vcache_elt(vcache, i1, 0);
|
||||
vcache_elt(vcache, a1, 0);
|
||||
vcache_check_flush(vcache);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_line_adj( struct vcache_frontend *vcache,
|
||||
unsigned a0, unsigned i0, unsigned i1, unsigned a1 )
|
||||
{
|
||||
vcache_elt(vcache, a0, 0);
|
||||
vcache_elt(vcache, i0, 0);
|
||||
vcache_elt(vcache, i1, 0);
|
||||
vcache_elt(vcache, a1, 0);
|
||||
vcache_check_flush(vcache);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_triangle_adj_flags( struct vcache_frontend *vcache,
|
||||
unsigned flags,
|
||||
unsigned i0, unsigned a0,
|
||||
unsigned i1, unsigned a1,
|
||||
unsigned i2, unsigned a2 )
|
||||
{
|
||||
vcache_elt(vcache, i0, flags);
|
||||
vcache_elt(vcache, a0, 0);
|
||||
vcache_elt(vcache, i1, 0);
|
||||
vcache_elt(vcache, a1, 0);
|
||||
vcache_elt(vcache, i2, 0);
|
||||
vcache_elt(vcache, a2, 0);
|
||||
vcache_check_flush(vcache);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_triangle_adj( struct vcache_frontend *vcache,
|
||||
unsigned i0, unsigned a0,
|
||||
unsigned i1, unsigned a1,
|
||||
unsigned i2, unsigned a2 )
|
||||
{
|
||||
vcache_elt(vcache, i0, 0);
|
||||
vcache_elt(vcache, a0, 0);
|
||||
vcache_elt(vcache, i1, 0);
|
||||
vcache_elt(vcache, a1, 0);
|
||||
vcache_elt(vcache, i2, 0);
|
||||
vcache_elt(vcache, a2, 0);
|
||||
vcache_check_flush(vcache);
|
||||
}
|
||||
|
||||
|
||||
/* At least for now, we're back to using a template include file for
|
||||
* this. The two paths aren't too different though - it may be
|
||||
* possible to reunify them.
|
||||
*/
|
||||
#define TRIANGLE(flags,i0,i1,i2) vcache_triangle_flags(vcache,flags,i0,i1,i2)
|
||||
#define LINE(flags,i0,i1) vcache_line_flags(vcache,flags,i0,i1)
|
||||
#define POINT(i0) vcache_point(vcache,i0)
|
||||
#define LINE_ADJ(flags,a0,i0,i1,a1) \
|
||||
vcache_line_adj_flags(vcache,flags,a0,i0,i1,a1)
|
||||
#define TRIANGLE_ADJ(flags,i0,a0,i1,a1,i2,a2) \
|
||||
vcache_triangle_adj_flags(vcache,flags,i0,a0,i1,a1,i2,a2)
|
||||
#define FUNC vcache_run_extras
|
||||
#include "draw_pt_vcache_tmp.h"
|
||||
|
||||
#define TRIANGLE(flags,i0,i1,i2) vcache_triangle(vcache,i0,i1,i2)
|
||||
#define LINE(flags,i0,i1) vcache_line(vcache,i0,i1)
|
||||
#define POINT(i0) vcache_point(vcache,i0)
|
||||
#define LINE_ADJ(flags,a0,i0,i1,a1) \
|
||||
vcache_line_adj(vcache,a0,i0,i1,a1)
|
||||
#define TRIANGLE_ADJ(flags,i0,a0,i1,a1,i2,a2) \
|
||||
vcache_triangle_adj(vcache,i0,a0,i1,a1,i2,a2)
|
||||
#define FUNC vcache_run
|
||||
#include "draw_pt_vcache_tmp.h"
|
||||
|
||||
static INLINE void
|
||||
rebase_uint_elts( const unsigned *src,
|
||||
unsigned count,
|
||||
int delta,
|
||||
ushort *dest )
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < count; i++)
|
||||
dest[i] = (ushort)(src[i] + delta);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
rebase_ushort_elts( const ushort *src,
|
||||
unsigned count,
|
||||
int delta,
|
||||
ushort *dest )
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < count; i++)
|
||||
dest[i] = (ushort)(src[i] + delta);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
rebase_ubyte_elts( const ubyte *src,
|
||||
unsigned count,
|
||||
int delta,
|
||||
ushort *dest )
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < count; i++)
|
||||
dest[i] = (ushort)(src[i] + delta);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
translate_uint_elts( const unsigned *src,
|
||||
unsigned count,
|
||||
ushort *dest )
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < count; i++)
|
||||
dest[i] = (ushort)(src[i]);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
translate_ushort_elts( const ushort *src,
|
||||
unsigned count,
|
||||
ushort *dest )
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < count; i++)
|
||||
dest[i] = (ushort)(src[i]);
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
translate_ubyte_elts( const ubyte *src,
|
||||
unsigned count,
|
||||
ushort *dest )
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < count; i++)
|
||||
dest[i] = (ushort)(src[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
static INLINE enum pipe_format
|
||||
format_from_get_elt( pt_elt_func get_elt )
|
||||
{
|
||||
switch (draw->pt.user.eltSize) {
|
||||
case 1: return PIPE_FORMAT_R8_UNORM;
|
||||
case 2: return PIPE_FORMAT_R16_UNORM;
|
||||
case 4: return PIPE_FORMAT_R32_UNORM;
|
||||
default: return PIPE_FORMAT_NONE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Check if any vertex attributes use instance divisors.
|
||||
* Note that instance divisors complicate vertex fetching so we need
|
||||
* to take the vcache path when they're in use.
|
||||
*/
|
||||
static boolean
|
||||
any_instance_divisors(const struct draw_context *draw)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
|
||||
uint div = draw->pt.vertex_element[i].instance_divisor;
|
||||
if (div)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static INLINE void
|
||||
vcache_check_run( struct draw_pt_front_end *frontend,
|
||||
pt_elt_func get_elt,
|
||||
const void *elts,
|
||||
int elt_bias,
|
||||
unsigned draw_count )
|
||||
{
|
||||
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
|
||||
struct draw_context *draw = vcache->draw;
|
||||
const unsigned min_index = draw->pt.user.min_index;
|
||||
const unsigned max_index = draw->pt.user.max_index;
|
||||
const unsigned index_size = draw->pt.user.eltSize;
|
||||
unsigned fetch_count;
|
||||
const ushort *transformed_elts;
|
||||
ushort *storage = NULL;
|
||||
boolean ok = FALSE;
|
||||
|
||||
/* debug: verify indexes are in range [min_index, max_index] */
|
||||
if (0) {
|
||||
unsigned i;
|
||||
for (i = 0; i < draw_count; i++) {
|
||||
if (index_size == 1) {
|
||||
assert( ((const ubyte *) elts)[i] >= min_index);
|
||||
assert( ((const ubyte *) elts)[i] <= max_index);
|
||||
}
|
||||
else if (index_size == 2) {
|
||||
assert( ((const ushort *) elts)[i] >= min_index);
|
||||
assert( ((const ushort *) elts)[i] <= max_index);
|
||||
}
|
||||
else {
|
||||
assert(index_size == 4);
|
||||
assert( ((const uint *) elts)[i] >= min_index);
|
||||
assert( ((const uint *) elts)[i] <= max_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: max_index is frequently 0xffffffff so we have to be sure
|
||||
* that any arithmetic involving max_index doesn't overflow!
|
||||
*/
|
||||
if (max_index >= (unsigned) DRAW_PIPE_MAX_VERTICES)
|
||||
goto fail;
|
||||
|
||||
if (any_instance_divisors(draw))
|
||||
goto fail;
|
||||
|
||||
fetch_count = max_index + 1 - min_index;
|
||||
|
||||
if (0)
|
||||
debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count,
|
||||
vcache->fetch_max,
|
||||
draw_count);
|
||||
|
||||
if (elt_bias + max_index >= DRAW_PIPE_MAX_VERTICES ||
|
||||
fetch_count >= UNDEFINED_VERTEX_ID ||
|
||||
fetch_count > draw_count) {
|
||||
if (0) debug_printf("fail\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (vcache->middle_prim != vcache->input_prim) {
|
||||
vcache->middle_prim = vcache->input_prim;
|
||||
vcache->middle->prepare( vcache->middle,
|
||||
vcache->middle_prim,
|
||||
vcache->opt,
|
||||
&vcache->fetch_max );
|
||||
}
|
||||
|
||||
assert((elt_bias >= 0 && min_index + elt_bias >= min_index) ||
|
||||
(elt_bias < 0 && min_index + elt_bias < min_index));
|
||||
|
||||
if (min_index == 0 &&
|
||||
index_size == 2) {
|
||||
transformed_elts = (const ushort *)elts;
|
||||
}
|
||||
else {
|
||||
storage = MALLOC( draw_count * sizeof(ushort) );
|
||||
if (!storage)
|
||||
goto fail;
|
||||
|
||||
if (min_index == 0) {
|
||||
switch(index_size) {
|
||||
case 1:
|
||||
translate_ubyte_elts( (const ubyte *)elts,
|
||||
draw_count,
|
||||
storage );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
translate_ushort_elts( (const ushort *)elts,
|
||||
draw_count,
|
||||
storage );
|
||||
break;
|
||||
|
||||
case 4:
|
||||
translate_uint_elts( (const uint *)elts,
|
||||
draw_count,
|
||||
storage );
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
FREE(storage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(index_size) {
|
||||
case 1:
|
||||
rebase_ubyte_elts( (const ubyte *)elts,
|
||||
draw_count,
|
||||
0 - (int)min_index,
|
||||
storage );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
rebase_ushort_elts( (const ushort *)elts,
|
||||
draw_count,
|
||||
0 - (int)min_index,
|
||||
storage );
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rebase_uint_elts( (const uint *)elts,
|
||||
draw_count,
|
||||
0 - (int)min_index,
|
||||
storage );
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
FREE(storage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
transformed_elts = storage;
|
||||
}
|
||||
|
||||
if (fetch_count < UNDEFINED_VERTEX_ID)
|
||||
ok = vcache->middle->run_linear_elts( vcache->middle,
|
||||
min_index + elt_bias, /* start */
|
||||
fetch_count,
|
||||
transformed_elts,
|
||||
draw_count );
|
||||
|
||||
FREE(storage);
|
||||
|
||||
if (ok)
|
||||
return;
|
||||
|
||||
debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
|
||||
fetch_count, draw_count);
|
||||
|
||||
fail:
|
||||
vcache_run( frontend, get_elt, elts, elt_bias, draw_count );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
vcache_prepare( struct draw_pt_front_end *frontend,
|
||||
unsigned in_prim,
|
||||
struct draw_pt_middle_end *middle,
|
||||
unsigned opt )
|
||||
{
|
||||
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
|
||||
|
||||
if (opt & PT_PIPELINE) {
|
||||
vcache->base.run = vcache_run_extras;
|
||||
}
|
||||
else {
|
||||
vcache->base.run = vcache_check_run;
|
||||
}
|
||||
|
||||
/* VCache will always emit the reduced version of its input
|
||||
* primitive, ie STRIP/FANS become TRIS, etc.
|
||||
*
|
||||
* This is not to be confused with what the GS might be up to,
|
||||
* which is a separate issue.
|
||||
*/
|
||||
vcache->input_prim = in_prim;
|
||||
switch (in_prim) {
|
||||
case PIPE_PRIM_LINES_ADJACENCY:
|
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
|
||||
vcache->output_prim = PIPE_PRIM_LINES_ADJACENCY;
|
||||
break;
|
||||
case PIPE_PRIM_TRIANGLES_ADJACENCY:
|
||||
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
|
||||
vcache->output_prim = PIPE_PRIM_TRIANGLES_ADJACENCY;
|
||||
break;
|
||||
default:
|
||||
vcache->output_prim = u_reduced_prim(in_prim);
|
||||
}
|
||||
|
||||
vcache->middle = middle;
|
||||
vcache->opt = opt;
|
||||
|
||||
/* Have to run prepare here, but try and guess a good prim for
|
||||
* doing so:
|
||||
*/
|
||||
vcache->middle_prim = (opt & PT_PIPELINE)
|
||||
? vcache->output_prim : vcache->input_prim;
|
||||
|
||||
middle->prepare( middle,
|
||||
vcache->middle_prim,
|
||||
opt, &vcache->fetch_max );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vcache_finish( struct draw_pt_front_end *frontend )
|
||||
{
|
||||
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
|
||||
vcache->middle->finish( vcache->middle );
|
||||
vcache->middle = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vcache_destroy( struct draw_pt_front_end *frontend )
|
||||
{
|
||||
FREE(frontend);
|
||||
}
|
||||
|
||||
|
||||
struct draw_pt_front_end *draw_pt_vcache( struct draw_context *draw )
|
||||
{
|
||||
struct vcache_frontend *vcache = CALLOC_STRUCT( vcache_frontend );
|
||||
if (vcache == NULL)
|
||||
return NULL;
|
||||
|
||||
vcache->base.prepare = vcache_prepare;
|
||||
vcache->base.run = NULL;
|
||||
vcache->base.finish = vcache_finish;
|
||||
vcache->base.destroy = vcache_destroy;
|
||||
vcache->draw = draw;
|
||||
|
||||
memset(vcache->in, ~0, sizeof(vcache->in));
|
||||
|
||||
return &vcache->base;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#define FUNC_VARS \
|
||||
struct draw_pt_front_end *frontend, \
|
||||
pt_elt_func get_elt, \
|
||||
const void *elts, \
|
||||
int elt_bias, \
|
||||
unsigned count
|
||||
|
||||
#define LOCAL_VARS \
|
||||
struct vcache_frontend *vcache = (struct vcache_frontend *) frontend; \
|
||||
struct draw_context *draw = vcache->draw; \
|
||||
const unsigned prim = vcache->input_prim; \
|
||||
const boolean last_vertex_last = !(draw->rasterizer->flatshade && \
|
||||
draw->rasterizer->flatshade_first);
|
||||
|
||||
#define GET_ELT(idx) (get_elt(elts, idx) + elt_bias)
|
||||
|
||||
#define FUNC_EXIT do { vcache_flush(vcache); } while (0)
|
||||
|
||||
#include "draw_decompose_tmp.h"
|
||||
208
src/gallium/auxiliary/draw/draw_pt_vsplit.c
Normal file
208
src/gallium/auxiliary/draw/draw_pt_vsplit.c
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "draw/draw_context.h"
|
||||
#include "draw/draw_private.h"
|
||||
#include "draw/draw_pt.h"
|
||||
|
||||
#define SEGMENT_SIZE 1024
|
||||
#define MAP_SIZE 256
|
||||
|
||||
struct vsplit_frontend {
|
||||
struct draw_pt_front_end base;
|
||||
struct draw_context *draw;
|
||||
|
||||
unsigned prim;
|
||||
|
||||
struct draw_pt_middle_end *middle;
|
||||
|
||||
unsigned max_vertices;
|
||||
ushort segment_size;
|
||||
|
||||
/* buffers for splitting */
|
||||
unsigned fetch_elts[SEGMENT_SIZE];
|
||||
ushort draw_elts[SEGMENT_SIZE];
|
||||
ushort identity_draw_elts[SEGMENT_SIZE];
|
||||
|
||||
struct {
|
||||
/* map a fetch element to a draw element */
|
||||
unsigned fetches[MAP_SIZE];
|
||||
ushort draws[MAP_SIZE];
|
||||
boolean has_max_fetch;
|
||||
|
||||
ushort num_fetch_elts;
|
||||
ushort num_draw_elts;
|
||||
} cache;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
vsplit_clear_cache(struct vsplit_frontend *vsplit)
|
||||
{
|
||||
memset(vsplit->cache.fetches, 0xff, sizeof(vsplit->cache.fetches));
|
||||
vsplit->cache.has_max_fetch = FALSE;
|
||||
vsplit->cache.num_fetch_elts = 0;
|
||||
vsplit->cache.num_draw_elts = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
vsplit_flush_cache(struct vsplit_frontend *vsplit, unsigned flags)
|
||||
{
|
||||
vsplit->middle->run(vsplit->middle,
|
||||
vsplit->fetch_elts, vsplit->cache.num_fetch_elts,
|
||||
vsplit->draw_elts, vsplit->cache.num_draw_elts, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a fetch element and add it to the draw elements.
|
||||
*/
|
||||
static INLINE void
|
||||
vsplit_add_cache(struct vsplit_frontend *vsplit, unsigned fetch)
|
||||
{
|
||||
unsigned hash = fetch % MAP_SIZE;
|
||||
|
||||
if (vsplit->cache.fetches[hash] != fetch) {
|
||||
/* update cache */
|
||||
vsplit->cache.fetches[hash] = fetch;
|
||||
vsplit->cache.draws[hash] = vsplit->cache.num_fetch_elts;
|
||||
|
||||
/* add fetch */
|
||||
assert(vsplit->cache.num_fetch_elts < vsplit->segment_size);
|
||||
vsplit->fetch_elts[vsplit->cache.num_fetch_elts++] = fetch;
|
||||
}
|
||||
|
||||
vsplit->draw_elts[vsplit->cache.num_draw_elts++] = vsplit->cache.draws[hash];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a fetch element and add it to the draw elements. The fetch element is
|
||||
* in full range (uint).
|
||||
*/
|
||||
static INLINE void
|
||||
vsplit_add_cache_uint(struct vsplit_frontend *vsplit, unsigned fetch)
|
||||
{
|
||||
/* special care for 0xffffffff */
|
||||
if (fetch == 0xffffffff && !vsplit->cache.has_max_fetch) {
|
||||
unsigned hash = fetch % MAP_SIZE;
|
||||
vsplit->cache.fetches[hash] = fetch - 1; /* force update */
|
||||
vsplit->cache.has_max_fetch = TRUE;
|
||||
}
|
||||
|
||||
vsplit_add_cache(vsplit, fetch);
|
||||
}
|
||||
|
||||
|
||||
#define FUNC vsplit_run_linear
|
||||
#include "draw_pt_vsplit_tmp.h"
|
||||
|
||||
#define FUNC vsplit_run_ubyte
|
||||
#define ELT_TYPE ubyte
|
||||
#define ADD_CACHE(vsplit, fetch) vsplit_add_cache(vsplit, fetch)
|
||||
#include "draw_pt_vsplit_tmp.h"
|
||||
|
||||
#define FUNC vsplit_run_ushort
|
||||
#define ELT_TYPE ushort
|
||||
#define ADD_CACHE(vsplit, fetch) vsplit_add_cache(vsplit, fetch)
|
||||
#include "draw_pt_vsplit_tmp.h"
|
||||
|
||||
#define FUNC vsplit_run_uint
|
||||
#define ELT_TYPE uint
|
||||
#define ADD_CACHE(vsplit, fetch) vsplit_add_cache_uint(vsplit, fetch)
|
||||
#include "draw_pt_vsplit_tmp.h"
|
||||
|
||||
|
||||
static void vsplit_prepare(struct draw_pt_front_end *frontend,
|
||||
unsigned in_prim,
|
||||
struct draw_pt_middle_end *middle,
|
||||
unsigned opt)
|
||||
{
|
||||
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;
|
||||
|
||||
switch (vsplit->draw->pt.user.eltSize) {
|
||||
case 0:
|
||||
vsplit->base.run = vsplit_run_linear;
|
||||
break;
|
||||
case 1:
|
||||
vsplit->base.run = vsplit_run_ubyte;
|
||||
break;
|
||||
case 2:
|
||||
vsplit->base.run = vsplit_run_ushort;
|
||||
break;
|
||||
case 4:
|
||||
vsplit->base.run = vsplit_run_uint;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* split only */
|
||||
vsplit->prim = in_prim;
|
||||
|
||||
vsplit->middle = middle;
|
||||
middle->prepare(middle, vsplit->prim, opt, &vsplit->max_vertices);
|
||||
|
||||
vsplit->segment_size = MIN2(SEGMENT_SIZE, vsplit->max_vertices);
|
||||
}
|
||||
|
||||
|
||||
static void vsplit_finish(struct draw_pt_front_end *frontend)
|
||||
{
|
||||
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;
|
||||
vsplit->middle->finish(vsplit->middle);
|
||||
vsplit->middle = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void vsplit_destroy(struct draw_pt_front_end *frontend)
|
||||
{
|
||||
FREE(frontend);
|
||||
}
|
||||
|
||||
|
||||
struct draw_pt_front_end *draw_pt_vsplit(struct draw_context *draw)
|
||||
{
|
||||
struct vsplit_frontend *vsplit = CALLOC_STRUCT(vsplit_frontend);
|
||||
ushort i;
|
||||
|
||||
if (!vsplit)
|
||||
return NULL;
|
||||
|
||||
vsplit->base.prepare = vsplit_prepare;
|
||||
vsplit->base.run = NULL;
|
||||
vsplit->base.finish = vsplit_finish;
|
||||
vsplit->base.destroy = vsplit_destroy;
|
||||
vsplit->draw = draw;
|
||||
|
||||
for (i = 0; i < SEGMENT_SIZE; i++)
|
||||
vsplit->identity_draw_elts[i] = i;
|
||||
|
||||
return &vsplit->base;
|
||||
}
|
||||
309
src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h
Normal file
309
src/gallium/auxiliary/draw/draw_pt_vsplit_tmp.h
Normal file
|
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define CONCAT2(name, elt_type) name ## elt_type
|
||||
#define CONCAT(name, elt_type) CONCAT2(name, elt_type)
|
||||
|
||||
#ifdef ELT_TYPE
|
||||
|
||||
/**
|
||||
* Fetch all elements in [min_index, max_index] with bias, and use the
|
||||
* (rebased) index buffer as the draw elements.
|
||||
*/
|
||||
static boolean
|
||||
CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend *vsplit,
|
||||
unsigned istart, unsigned icount)
|
||||
{
|
||||
struct draw_context *draw = vsplit->draw;
|
||||
const ELT_TYPE *ib = (const ELT_TYPE *)
|
||||
((const char *) draw->pt.user.elts + draw->pt.index_buffer.offset);
|
||||
const unsigned min_index = draw->pt.user.min_index;
|
||||
const unsigned max_index = draw->pt.user.max_index;
|
||||
const int elt_bias = draw->pt.user.eltBias;
|
||||
unsigned fetch_start, fetch_count;
|
||||
const ushort *draw_elts = NULL;
|
||||
unsigned i;
|
||||
|
||||
/* use the ib directly */
|
||||
if (min_index == 0 && sizeof(ib[0]) == sizeof(draw_elts[0])) {
|
||||
if (icount > vsplit->max_vertices)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < icount; i++) {
|
||||
ELT_TYPE idx = ib[istart + i];
|
||||
assert(idx >= min_index && idx <= max_index);
|
||||
}
|
||||
draw_elts = (const ushort *) ib;
|
||||
}
|
||||
else {
|
||||
/* have to go through vsplit->draw_elts */
|
||||
if (icount > vsplit->segment_size)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* this is faster only when we fetch less elements than the normal path */
|
||||
if (max_index - min_index > icount - 1)
|
||||
return FALSE;
|
||||
|
||||
if (elt_bias < 0 && min_index < -elt_bias)
|
||||
return FALSE;
|
||||
|
||||
/* why this check? */
|
||||
for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
|
||||
if (draw->pt.vertex_element[i].instance_divisor)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fetch_start = min_index + elt_bias;
|
||||
fetch_count = max_index - min_index + 1;
|
||||
|
||||
if (!draw_elts) {
|
||||
if (min_index == 0) {
|
||||
for (i = 0; i < icount; i++) {
|
||||
ELT_TYPE idx = ib[istart + i];
|
||||
|
||||
assert(idx >= min_index && idx <= max_index);
|
||||
vsplit->draw_elts[i] = (ushort) idx;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < icount; i++) {
|
||||
ELT_TYPE idx = ib[istart + i];
|
||||
|
||||
assert(idx >= min_index && idx <= max_index);
|
||||
vsplit->draw_elts[i] = (ushort) (idx - min_index);
|
||||
}
|
||||
}
|
||||
|
||||
draw_elts = vsplit->draw_elts;
|
||||
}
|
||||
|
||||
return vsplit->middle->run_linear_elts(vsplit->middle,
|
||||
fetch_start, fetch_count,
|
||||
draw_elts, icount, 0x0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the cache to prepare the fetch and draw elements, and flush.
|
||||
*
|
||||
* When spoken is TRUE, ispoken replaces istart; When close is TRUE, iclose is
|
||||
* appended.
|
||||
*/
|
||||
static INLINE void
|
||||
CONCAT(vsplit_segment_cache_, ELT_TYPE)(struct vsplit_frontend *vsplit,
|
||||
unsigned flags,
|
||||
unsigned istart, unsigned icount,
|
||||
boolean spoken, unsigned ispoken,
|
||||
boolean close, unsigned iclose)
|
||||
{
|
||||
struct draw_context *draw = vsplit->draw;
|
||||
const ELT_TYPE *ib = (const ELT_TYPE *)
|
||||
((const char *) draw->pt.user.elts + draw->pt.index_buffer.offset);
|
||||
const int ibias = draw->pt.user.eltBias;
|
||||
unsigned i;
|
||||
|
||||
assert(icount + !!close <= vsplit->segment_size);
|
||||
|
||||
vsplit_clear_cache(vsplit);
|
||||
|
||||
spoken = !!spoken;
|
||||
if (ibias == 0) {
|
||||
if (spoken)
|
||||
ADD_CACHE(vsplit, ib[ispoken]);
|
||||
|
||||
for (i = spoken; i < icount; i++)
|
||||
ADD_CACHE(vsplit, ib[istart + i]);
|
||||
|
||||
if (close)
|
||||
ADD_CACHE(vsplit, ib[iclose]);
|
||||
}
|
||||
else if (ibias > 0) {
|
||||
if (spoken)
|
||||
ADD_CACHE(vsplit, (uint) ib[ispoken] + ibias);
|
||||
|
||||
for (i = spoken; i < icount; i++)
|
||||
ADD_CACHE(vsplit, (uint) ib[istart + i] + ibias);
|
||||
|
||||
if (close)
|
||||
ADD_CACHE(vsplit, (uint) ib[iclose] + ibias);
|
||||
}
|
||||
else {
|
||||
if (spoken) {
|
||||
if (ib[ispoken] < -ibias)
|
||||
return;
|
||||
ADD_CACHE(vsplit, ib[ispoken] + ibias);
|
||||
}
|
||||
|
||||
for (i = spoken; i < icount; i++) {
|
||||
if (ib[istart + i] < -ibias)
|
||||
return;
|
||||
ADD_CACHE(vsplit, ib[istart + i] + ibias);
|
||||
}
|
||||
|
||||
if (close) {
|
||||
if (ib[iclose] < -ibias)
|
||||
return;
|
||||
ADD_CACHE(vsplit, ib[iclose] + ibias);
|
||||
}
|
||||
}
|
||||
|
||||
vsplit_flush_cache(vsplit, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
CONCAT(vsplit_segment_simple_, ELT_TYPE)(struct vsplit_frontend *vsplit,
|
||||
unsigned flags,
|
||||
unsigned istart,
|
||||
unsigned icount)
|
||||
{
|
||||
CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
|
||||
flags, istart, icount, FALSE, 0, FALSE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
CONCAT(vsplit_segment_loop_, ELT_TYPE)(struct vsplit_frontend *vsplit,
|
||||
unsigned flags,
|
||||
unsigned istart,
|
||||
unsigned icount,
|
||||
unsigned i0)
|
||||
{
|
||||
const boolean close_loop = ((flags) == DRAW_SPLIT_BEFORE);
|
||||
|
||||
CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
|
||||
flags, istart, icount, FALSE, 0, close_loop, i0);
|
||||
}
|
||||
|
||||
static void
|
||||
CONCAT(vsplit_segment_fan_, ELT_TYPE)(struct vsplit_frontend *vsplit,
|
||||
unsigned flags,
|
||||
unsigned istart,
|
||||
unsigned icount,
|
||||
unsigned i0)
|
||||
{
|
||||
const boolean use_spoken = (((flags) & DRAW_SPLIT_BEFORE) != 0);
|
||||
|
||||
CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
|
||||
flags, istart, icount, use_spoken, i0, FALSE, 0);
|
||||
}
|
||||
|
||||
#define LOCAL_VARS \
|
||||
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend; \
|
||||
const unsigned prim = vsplit->prim; \
|
||||
const unsigned max_count_simple = vsplit->segment_size; \
|
||||
const unsigned max_count_loop = vsplit->segment_size - 1; \
|
||||
const unsigned max_count_fan = vsplit->segment_size;
|
||||
|
||||
#define PRIMITIVE(istart, icount) \
|
||||
CONCAT(vsplit_primitive_, ELT_TYPE)(vsplit, istart, icount)
|
||||
|
||||
#else /* ELT_TYPE */
|
||||
|
||||
static void
|
||||
vsplit_segment_simple_linear(struct vsplit_frontend *vsplit, unsigned flags,
|
||||
unsigned istart, unsigned icount)
|
||||
{
|
||||
assert(icount <= vsplit->max_vertices);
|
||||
vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
vsplit_segment_loop_linear(struct vsplit_frontend *vsplit, unsigned flags,
|
||||
unsigned istart, unsigned icount, unsigned i0)
|
||||
{
|
||||
boolean close_loop = (flags == DRAW_SPLIT_BEFORE);
|
||||
unsigned nr;
|
||||
|
||||
assert(icount + !!close_loop <= vsplit->segment_size);
|
||||
|
||||
if (close_loop) {
|
||||
for (nr = 0; nr < icount; nr++)
|
||||
vsplit->fetch_elts[nr] = istart + nr;
|
||||
vsplit->fetch_elts[nr++] = i0;
|
||||
|
||||
vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr,
|
||||
vsplit->identity_draw_elts, nr, flags);
|
||||
}
|
||||
else {
|
||||
vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vsplit_segment_fan_linear(struct vsplit_frontend *vsplit, unsigned flags,
|
||||
unsigned istart, unsigned icount, unsigned i0)
|
||||
{
|
||||
boolean use_spoken = ((flags & DRAW_SPLIT_BEFORE) != 0);
|
||||
unsigned nr = 0, i;
|
||||
|
||||
assert(icount + !!use_spoken <= vsplit->segment_size);
|
||||
|
||||
if (use_spoken) {
|
||||
vsplit->fetch_elts[nr++] = i0;
|
||||
for (i = 1 ; i < icount; i++)
|
||||
vsplit->fetch_elts[nr++] = istart + i;
|
||||
|
||||
vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr,
|
||||
vsplit->identity_draw_elts, nr, flags);
|
||||
}
|
||||
else {
|
||||
vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
|
||||
}
|
||||
}
|
||||
|
||||
#define LOCAL_VARS \
|
||||
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend; \
|
||||
const unsigned prim = vsplit->prim; \
|
||||
const unsigned max_count_simple = vsplit->max_vertices; \
|
||||
const unsigned max_count_loop = vsplit->segment_size - 1; \
|
||||
const unsigned max_count_fan = vsplit->segment_size;
|
||||
|
||||
#define PRIMITIVE(istart, icount) FALSE
|
||||
|
||||
#define ELT_TYPE linear
|
||||
|
||||
#endif /* ELT_TYPE */
|
||||
|
||||
#define FUNC_VARS \
|
||||
struct draw_pt_front_end *frontend, \
|
||||
unsigned start, \
|
||||
unsigned count
|
||||
|
||||
#define SEGMENT_SIMPLE(flags, istart, icount) \
|
||||
CONCAT(vsplit_segment_simple_, ELT_TYPE)(vsplit, flags, istart, icount)
|
||||
|
||||
#define SEGMENT_LOOP(flags, istart, icount, i0) \
|
||||
CONCAT(vsplit_segment_loop_, ELT_TYPE)(vsplit, flags, istart, icount, i0)
|
||||
|
||||
#define SEGMENT_FAN(flags, istart, icount, i0) \
|
||||
CONCAT(vsplit_segment_fan_, ELT_TYPE)(vsplit, flags, istart, icount, i0)
|
||||
|
||||
#include "draw_split_tmp.h"
|
||||
|
||||
#undef CONCAT2
|
||||
#undef CONCAT
|
||||
|
||||
#undef ELT_TYPE
|
||||
#undef ADD_CACHE
|
||||
|
|
@ -7,11 +7,9 @@
|
|||
|
||||
#define FUNC_ENTER \
|
||||
/* declare more local vars */ \
|
||||
struct draw_context *draw = so->draw; \
|
||||
const unsigned prim = input_prims->prim; \
|
||||
const boolean last_vertex_last = \
|
||||
!(draw->rasterizer->flatshade && \
|
||||
draw->rasterizer->flatshade_first); \
|
||||
const unsigned prim_flags = input_prims->flags; \
|
||||
const boolean last_vertex_last = TRUE; \
|
||||
do { \
|
||||
debug_assert(input_prims->primitive_count == 1); \
|
||||
switch (prim) { \
|
||||
|
|
|
|||
176
src/gallium/auxiliary/draw/draw_split_tmp.h
Normal file
176
src/gallium/auxiliary/draw/draw_split_tmp.h
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 7.9
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* Copyright (C) 2010 LunarG Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
static void
|
||||
FUNC(FUNC_VARS)
|
||||
{
|
||||
unsigned first, incr;
|
||||
LOCAL_VARS
|
||||
|
||||
/*
|
||||
* prim, start, count, and max_count_{simple,loop,fan} should have been
|
||||
* defined
|
||||
*/
|
||||
if (0) {
|
||||
debug_printf("%s: prim 0x%x, start %d, count %d, max_count_simple %d, "
|
||||
"max_count_loop %d, max_count_fan %d\n",
|
||||
__FUNCTION__, prim, start, count, max_count_simple,
|
||||
max_count_loop, max_count_fan);
|
||||
}
|
||||
|
||||
draw_pt_split_prim(prim, &first, &incr);
|
||||
/* sanitize primitive length */
|
||||
count = draw_pt_trim_count(count, first, incr);
|
||||
if (count < first)
|
||||
return;
|
||||
|
||||
/* try flushing the entire primitive */
|
||||
if (PRIMITIVE(start, count))
|
||||
return;
|
||||
|
||||
/* must be able to at least flush two complete primitives */
|
||||
assert(max_count_simple >= first + incr &&
|
||||
max_count_loop >= first + incr &&
|
||||
max_count_fan >= first + incr);
|
||||
|
||||
/* no splitting required */
|
||||
if (count <= max_count_simple) {
|
||||
SEGMENT_SIMPLE(0x0, start, count);
|
||||
}
|
||||
else {
|
||||
const unsigned rollback = first - incr;
|
||||
unsigned flags = DRAW_SPLIT_AFTER, seg_start = 0, seg_max;
|
||||
|
||||
/*
|
||||
* Both count and seg_max below are explicitly trimmed. Because
|
||||
*
|
||||
* seg_start = N * (seg_max - rollback) = N' * incr,
|
||||
*
|
||||
* we have
|
||||
*
|
||||
* remaining = count - seg_start = first + N'' * incr.
|
||||
*
|
||||
* That is, remaining is implicitly trimmed.
|
||||
*/
|
||||
switch (prim) {
|
||||
case PIPE_PRIM_POINTS:
|
||||
case PIPE_PRIM_LINES:
|
||||
case PIPE_PRIM_LINE_STRIP:
|
||||
case PIPE_PRIM_TRIANGLES:
|
||||
case PIPE_PRIM_TRIANGLE_STRIP:
|
||||
case PIPE_PRIM_QUADS:
|
||||
case PIPE_PRIM_QUAD_STRIP:
|
||||
case PIPE_PRIM_LINES_ADJACENCY:
|
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
|
||||
case PIPE_PRIM_TRIANGLES_ADJACENCY:
|
||||
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
|
||||
seg_max =
|
||||
draw_pt_trim_count(MIN2(max_count_simple, count), first, incr);
|
||||
if (prim == PIPE_PRIM_TRIANGLE_STRIP ||
|
||||
prim == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY) {
|
||||
/* make sure we flush even number of triangles at a time */
|
||||
if (seg_max < count && !(((seg_max - first) / incr) & 1))
|
||||
seg_max -= incr;
|
||||
}
|
||||
|
||||
do {
|
||||
const unsigned remaining = count - seg_start;
|
||||
|
||||
if (remaining > seg_max) {
|
||||
SEGMENT_SIMPLE(flags, start + seg_start, seg_max);
|
||||
seg_start += seg_max - rollback;
|
||||
|
||||
flags |= DRAW_SPLIT_BEFORE;
|
||||
}
|
||||
else {
|
||||
flags &= ~DRAW_SPLIT_AFTER;
|
||||
|
||||
SEGMENT_SIMPLE(flags, start + seg_start, remaining);
|
||||
seg_start += remaining;
|
||||
}
|
||||
} while (seg_start < count);
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_LINE_LOOP:
|
||||
seg_max =
|
||||
draw_pt_trim_count(MIN2(max_count_loop, count), first, incr);
|
||||
|
||||
do {
|
||||
const unsigned remaining = count - seg_start;
|
||||
|
||||
if (remaining > seg_max) {
|
||||
SEGMENT_LOOP(flags, start + seg_start, seg_max, start);
|
||||
seg_start += seg_max - rollback;
|
||||
|
||||
flags |= DRAW_SPLIT_BEFORE;
|
||||
}
|
||||
else {
|
||||
flags &= ~DRAW_SPLIT_AFTER;
|
||||
|
||||
SEGMENT_LOOP(flags, start + seg_start, remaining, start);
|
||||
seg_start += remaining;
|
||||
}
|
||||
} while (seg_start < count);
|
||||
break;
|
||||
|
||||
case PIPE_PRIM_TRIANGLE_FAN:
|
||||
case PIPE_PRIM_POLYGON:
|
||||
seg_max =
|
||||
draw_pt_trim_count(MIN2(max_count_fan, count), first, incr);
|
||||
|
||||
do {
|
||||
const unsigned remaining = count - seg_start;
|
||||
|
||||
if (remaining > seg_max) {
|
||||
SEGMENT_FAN(flags, start + seg_start, seg_max, start);
|
||||
seg_start += seg_max - rollback;
|
||||
|
||||
flags |= DRAW_SPLIT_BEFORE;
|
||||
}
|
||||
else {
|
||||
flags &= ~DRAW_SPLIT_AFTER;
|
||||
|
||||
SEGMENT_FAN(flags, start + seg_start, remaining, start);
|
||||
seg_start += remaining;
|
||||
}
|
||||
} while (seg_start < count);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef FUNC
|
||||
#undef FUNC_VARS
|
||||
#undef LOCAL_VARS
|
||||
|
||||
#undef PRIMITIVE
|
||||
#undef SEGMENT_SIMPLE
|
||||
#undef SEGMENT_LOOP
|
||||
#undef SEGMENT_FAN
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
#include "pipe/p_screen.h"
|
||||
|
||||
#include "draw_private.h"
|
||||
#include "draw_context.h"
|
||||
|
|
@ -109,6 +110,11 @@ draw_create_vs_llvm(struct draw_context *draw,
|
|||
|
||||
tgsi_scan_shader(state->tokens, &vs->base.info);
|
||||
|
||||
vs->variant_key_size =
|
||||
draw_llvm_variant_key_size(
|
||||
vs->base.info.file_max[TGSI_FILE_INPUT]+1,
|
||||
vs->base.info.file_max[TGSI_FILE_SAMPLER]+1);
|
||||
|
||||
vs->base.draw = draw;
|
||||
vs->base.prepare = vs_llvm_prepare;
|
||||
vs->base.run_linear = vs_llvm_run_linear;
|
||||
|
|
|
|||
|
|
@ -59,14 +59,6 @@
|
|||
#include "lp_bld_arit.h"
|
||||
|
||||
|
||||
/*
|
||||
* XXX: Increasing eliminates some artifacts, but adds others, most
|
||||
* noticeably corruption in the Earth halo in Google Earth.
|
||||
*/
|
||||
#define RCP_NEWTON_STEPS 0
|
||||
|
||||
#define RSQRT_NEWTON_STEPS 0
|
||||
|
||||
#define EXP_POLY_DEGREE 3
|
||||
|
||||
#define LOG_POLY_DEGREE 5
|
||||
|
|
@ -267,7 +259,7 @@ lp_build_add(struct lp_build_context *bld,
|
|||
}
|
||||
|
||||
|
||||
/** Return the sum of the elements of a */
|
||||
/** Return the scalar sum of the elements of a */
|
||||
LLVMValueRef
|
||||
lp_build_sum_vector(struct lp_build_context *bld,
|
||||
LLVMValueRef a)
|
||||
|
|
@ -278,11 +270,9 @@ lp_build_sum_vector(struct lp_build_context *bld,
|
|||
|
||||
assert(lp_check_value(type, a));
|
||||
|
||||
if (a == bld->zero)
|
||||
return bld->zero;
|
||||
if (a == bld->undef)
|
||||
return bld->undef;
|
||||
assert(type.length > 1);
|
||||
if (type.length == 1) {
|
||||
return a;
|
||||
}
|
||||
|
||||
assert(!bld->type.norm);
|
||||
|
||||
|
|
@ -546,7 +536,7 @@ lp_build_mul_imm(struct lp_build_context *bld,
|
|||
if(b == 2 && bld->type.floating)
|
||||
return lp_build_add(bld, a, a);
|
||||
|
||||
if(util_is_pot(b)) {
|
||||
if(util_is_power_of_two(b)) {
|
||||
unsigned shift = ffs(b) - 1;
|
||||
|
||||
if(bld->type.floating) {
|
||||
|
|
@ -1266,6 +1256,11 @@ lp_build_sqrt(struct lp_build_context *bld,
|
|||
*
|
||||
* x_{i+1} = x_i * (2 - a * x_i)
|
||||
*
|
||||
* XXX: Unfortunately this won't give IEEE-754 conformant results for 0 or
|
||||
* +/-Inf, giving NaN instead. Certain applications rely on this behavior,
|
||||
* such as Google Earth, which does RCP(RSQRT(0.0) when drawing the Earth's
|
||||
* halo. It would be necessary to clamp the argument to prevent this.
|
||||
*
|
||||
* See also:
|
||||
* - http://en.wikipedia.org/wiki/Division_(digital)#Newton.E2.80.93Raphson_division
|
||||
* - http://softwarecommunity.intel.com/articles/eng/1818.htm
|
||||
|
|
@ -1306,13 +1301,27 @@ lp_build_rcp(struct lp_build_context *bld,
|
|||
if(LLVMIsConstant(a))
|
||||
return LLVMConstFDiv(bld->one, a);
|
||||
|
||||
if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4) {
|
||||
/*
|
||||
* We don't use RCPPS because:
|
||||
* - it only has 10bits of precision
|
||||
* - it doesn't even get the reciprocate of 1.0 exactly
|
||||
* - doing Newton-Rapshon steps yields wrong (NaN) values for 0.0 or Inf
|
||||
* - for recent processors the benefit over DIVPS is marginal, a case
|
||||
* depedent
|
||||
*
|
||||
* We could still use it on certain processors if benchmarks show that the
|
||||
* RCPPS plus necessary workarounds are still preferrable to DIVPS; or for
|
||||
* particular uses that require less workarounds.
|
||||
*/
|
||||
|
||||
if (FALSE && util_cpu_caps.has_sse && type.width == 32 && type.length == 4) {
|
||||
const unsigned num_iterations = 0;
|
||||
LLVMValueRef res;
|
||||
unsigned i;
|
||||
|
||||
res = lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rcp.ps", bld->vec_type, a);
|
||||
|
||||
for (i = 0; i < RCP_NEWTON_STEPS; ++i) {
|
||||
for (i = 0; i < num_iterations; ++i) {
|
||||
res = lp_build_rcp_refine(bld, a, res);
|
||||
}
|
||||
|
||||
|
|
@ -1363,13 +1372,14 @@ lp_build_rsqrt(struct lp_build_context *bld,
|
|||
|
||||
assert(type.floating);
|
||||
|
||||
if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4) {
|
||||
if (util_cpu_caps.has_sse && type.width == 32 && type.length == 4) {
|
||||
const unsigned num_iterations = 0;
|
||||
LLVMValueRef res;
|
||||
unsigned i;
|
||||
|
||||
res = lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rsqrt.ps", bld->vec_type, a);
|
||||
|
||||
for (i = 0; i < RSQRT_NEWTON_STEPS; ++i) {
|
||||
for (i = 0; i < num_iterations; ++i) {
|
||||
res = lp_build_rsqrt_refine(bld, a, res);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
boolean
|
||||
lp_check_alignment(const void *ptr, unsigned alignment)
|
||||
{
|
||||
assert(util_is_pot(alignment));
|
||||
assert(util_is_power_of_two(alignment));
|
||||
return ((uintptr_t)ptr & (alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
|
|||
|
||||
if (format_matches_type(format_desc, type) &&
|
||||
format_desc->block.bits <= type.width * 4 &&
|
||||
util_is_pot(format_desc->block.bits)) {
|
||||
util_is_power_of_two(format_desc->block.bits)) {
|
||||
LLVMValueRef packed;
|
||||
|
||||
/*
|
||||
|
|
@ -416,7 +416,7 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
|
|||
format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) &&
|
||||
format_desc->block.width == 1 &&
|
||||
format_desc->block.height == 1 &&
|
||||
util_is_pot(format_desc->block.bits) &&
|
||||
util_is_power_of_two(format_desc->block.bits) &&
|
||||
format_desc->block.bits <= 32 &&
|
||||
format_desc->is_bitmask &&
|
||||
!format_desc->is_mixed &&
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include <llvm/ExecutionEngine/ExecutionEngine.h>
|
||||
#include <llvm/ExecutionEngine/JITEventListener.h>
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
#include <llvm/Support/PrettyStackTrace.h>
|
||||
|
||||
#include "pipe/p_config.h"
|
||||
#include "util/u_debug.h"
|
||||
|
|
@ -143,7 +144,6 @@ lp_set_target_options(void)
|
|||
llvm::UnsafeFPMath = true;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* LLVM will generate MMX instructions for vectors <= 64 bits, leading to
|
||||
* innefficient code, and in 32bit systems, to the corruption of the FPU
|
||||
|
|
@ -152,10 +152,8 @@ lp_set_target_options(void)
|
|||
* See also:
|
||||
* - http://llvm.org/bugs/show_bug.cgi?id=3287
|
||||
* - http://l4.me.uk/post/2009/06/07/llvm-wrinkle-3-configuration-what-configuration/
|
||||
*
|
||||
* XXX: Unfortunately this is not working.
|
||||
*/
|
||||
static boolean first = FALSE;
|
||||
static boolean first = TRUE;
|
||||
if (first) {
|
||||
static const char* options[] = {
|
||||
"prog",
|
||||
|
|
@ -164,7 +162,13 @@ lp_set_target_options(void)
|
|||
llvm::cl::ParseCommandLineOptions(2, const_cast<char**>(options));
|
||||
first = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* By default LLVM adds a signal handler to output a pretty stack trace.
|
||||
* This signal handler is never removed, causing problems when unloading the
|
||||
* shared object where the gallium driver resides.
|
||||
*/
|
||||
llvm::DisablePrettyStackTrace = true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
#define LP_BLD_PACK_H
|
||||
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
#include "gallivm/lp_bld.h"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -82,9 +82,9 @@ lp_sampler_static_state(struct lp_sampler_static_state *state,
|
|||
state->swizzle_a = view->swizzle_a;
|
||||
|
||||
state->target = texture->target;
|
||||
state->pot_width = util_is_pot(texture->width0);
|
||||
state->pot_height = util_is_pot(texture->height0);
|
||||
state->pot_depth = util_is_pot(texture->depth0);
|
||||
state->pot_width = util_is_power_of_two(texture->width0);
|
||||
state->pot_height = util_is_power_of_two(texture->height0);
|
||||
state->pot_depth = util_is_power_of_two(texture->depth0);
|
||||
|
||||
state->wrap_s = sampler->wrap_s;
|
||||
state->wrap_t = sampler->wrap_t;
|
||||
|
|
@ -123,6 +123,52 @@ lp_sampler_static_state(struct lp_sampler_static_state *state,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute the partial offset of a pixel block along an arbitrary axis.
|
||||
*
|
||||
* @param coord coordinate in pixels
|
||||
* @param stride number of bytes between rows of successive pixel blocks
|
||||
* @param block_length number of pixels in a pixels block along the coordinate
|
||||
* axis
|
||||
* @param out_offset resulting relative offset of the pixel block in bytes
|
||||
* @param out_subcoord resulting sub-block pixel coordinate
|
||||
*/
|
||||
void
|
||||
lp_build_sample_partial_offset(struct lp_build_context *bld,
|
||||
unsigned block_length,
|
||||
LLVMValueRef coord,
|
||||
LLVMValueRef stride,
|
||||
LLVMValueRef *out_offset,
|
||||
LLVMValueRef *out_subcoord)
|
||||
{
|
||||
LLVMValueRef offset;
|
||||
LLVMValueRef subcoord;
|
||||
|
||||
if (block_length == 1) {
|
||||
subcoord = bld->zero;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Pixel blocks have power of two dimensions. LLVM should convert the
|
||||
* rem/div to bit arithmetic.
|
||||
* TODO: Verify this.
|
||||
*/
|
||||
|
||||
LLVMValueRef block_width = lp_build_const_int_vec(bld->type, block_length);
|
||||
subcoord = LLVMBuildURem(bld->builder, coord, block_width, "");
|
||||
coord = LLVMBuildUDiv(bld->builder, coord, block_width, "");
|
||||
}
|
||||
|
||||
offset = lp_build_mul(bld, coord, stride);
|
||||
|
||||
assert(out_offset);
|
||||
assert(out_subcoord);
|
||||
|
||||
*out_offset = offset;
|
||||
*out_subcoord = subcoord;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute the offset of a pixel block.
|
||||
*
|
||||
|
|
@ -144,48 +190,35 @@ lp_build_sample_offset(struct lp_build_context *bld,
|
|||
{
|
||||
LLVMValueRef x_stride;
|
||||
LLVMValueRef offset;
|
||||
LLVMValueRef i;
|
||||
LLVMValueRef j;
|
||||
|
||||
/*
|
||||
* Describe the coordinates in terms of pixel blocks.
|
||||
*
|
||||
* TODO: pixel blocks are power of two. LLVM should convert rem/div to
|
||||
* bit arithmetic. Verify this.
|
||||
*/
|
||||
|
||||
if (format_desc->block.width == 1) {
|
||||
i = bld->zero;
|
||||
}
|
||||
else {
|
||||
LLVMValueRef block_width = lp_build_const_int_vec(bld->type, format_desc->block.width);
|
||||
i = LLVMBuildURem(bld->builder, x, block_width, "");
|
||||
x = LLVMBuildUDiv(bld->builder, x, block_width, "");
|
||||
}
|
||||
|
||||
if (format_desc->block.height == 1) {
|
||||
j = bld->zero;
|
||||
}
|
||||
else {
|
||||
LLVMValueRef block_height = lp_build_const_int_vec(bld->type, format_desc->block.height);
|
||||
j = LLVMBuildURem(bld->builder, y, block_height, "");
|
||||
y = LLVMBuildUDiv(bld->builder, y, block_height, "");
|
||||
}
|
||||
|
||||
x_stride = lp_build_const_vec(bld->type, format_desc->block.bits/8);
|
||||
offset = lp_build_mul(bld, x, x_stride);
|
||||
|
||||
lp_build_sample_partial_offset(bld,
|
||||
format_desc->block.width,
|
||||
x, x_stride,
|
||||
&offset, out_i);
|
||||
|
||||
if (y && y_stride) {
|
||||
LLVMValueRef y_offset = lp_build_mul(bld, y, y_stride);
|
||||
LLVMValueRef y_offset;
|
||||
lp_build_sample_partial_offset(bld,
|
||||
format_desc->block.height,
|
||||
y, y_stride,
|
||||
&y_offset, out_j);
|
||||
offset = lp_build_add(bld, offset, y_offset);
|
||||
}
|
||||
else {
|
||||
*out_j = bld->zero;
|
||||
}
|
||||
|
||||
if (z && z_stride) {
|
||||
LLVMValueRef z_offset = lp_build_mul(bld, z, z_stride);
|
||||
LLVMValueRef z_offset;
|
||||
LLVMValueRef k;
|
||||
lp_build_sample_partial_offset(bld,
|
||||
1, /* pixel blocks are always 2D */
|
||||
z, z_stride,
|
||||
&z_offset, &k);
|
||||
offset = lp_build_add(bld, offset, z_offset);
|
||||
}
|
||||
|
||||
*out_offset = offset;
|
||||
*out_i = i;
|
||||
*out_j = j;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
#define LP_BLD_SAMPLE_H
|
||||
|
||||
|
||||
#include "pipe/p_format.h"
|
||||
|
||||
#include "gallivm/lp_bld.h"
|
||||
|
||||
struct pipe_resource;
|
||||
|
|
@ -146,6 +148,15 @@ lp_sampler_static_state(struct lp_sampler_static_state *state,
|
|||
const struct pipe_sampler_state *sampler);
|
||||
|
||||
|
||||
void
|
||||
lp_build_sample_partial_offset(struct lp_build_context *bld,
|
||||
unsigned block_length,
|
||||
LLVMValueRef coord,
|
||||
LLVMValueRef stride,
|
||||
LLVMValueRef *out_offset,
|
||||
LLVMValueRef *out_i);
|
||||
|
||||
|
||||
void
|
||||
lp_build_sample_offset(struct lp_build_context *bld,
|
||||
const struct util_format_description *format_desc,
|
||||
|
|
|
|||
|
|
@ -176,6 +176,7 @@ texture_dims(enum pipe_texture_target tex)
|
|||
case PIPE_TEXTURE_1D:
|
||||
return 1;
|
||||
case PIPE_TEXTURE_2D:
|
||||
case PIPE_TEXTURE_RECT:
|
||||
case PIPE_TEXTURE_CUBE:
|
||||
return 2;
|
||||
case PIPE_TEXTURE_3D:
|
||||
|
|
@ -321,59 +322,6 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch the texels as <4n x i8> in AoS form.
|
||||
*/
|
||||
static LLVMValueRef
|
||||
lp_build_sample_packed(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef x,
|
||||
LLVMValueRef y,
|
||||
LLVMValueRef y_stride,
|
||||
LLVMValueRef data_array)
|
||||
{
|
||||
LLVMValueRef offset, i, j;
|
||||
LLVMValueRef data_ptr;
|
||||
LLVMValueRef res;
|
||||
|
||||
/* convert x,y,z coords to linear offset from start of texture, in bytes */
|
||||
lp_build_sample_offset(&bld->uint_coord_bld,
|
||||
bld->format_desc,
|
||||
x, y, NULL, y_stride, NULL,
|
||||
&offset, &i, &j);
|
||||
|
||||
/* get pointer to mipmap level 0 data */
|
||||
data_ptr = lp_build_get_const_mipmap_level(bld, data_array, 0);
|
||||
|
||||
if (util_format_is_rgba8_variant(bld->format_desc)) {
|
||||
/* Just fetch the data directly without swizzling */
|
||||
assert(bld->format_desc->block.width == 1);
|
||||
assert(bld->format_desc->block.height == 1);
|
||||
assert(bld->format_desc->block.bits <= bld->texel_type.width);
|
||||
|
||||
res = lp_build_gather(bld->builder,
|
||||
bld->texel_type.length,
|
||||
bld->format_desc->block.bits,
|
||||
bld->texel_type.width,
|
||||
data_ptr, offset);
|
||||
}
|
||||
else {
|
||||
struct lp_type type;
|
||||
|
||||
assert(bld->texel_type.width == 32);
|
||||
|
||||
memset(&type, 0, sizeof type);
|
||||
type.width = 8;
|
||||
type.length = bld->texel_type.length*4;
|
||||
type.norm = TRUE;
|
||||
|
||||
res = lp_build_fetch_rgba_aos(bld->builder, bld->format_desc, type,
|
||||
data_ptr, offset, i, j);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper to compute the mirror function for the PIPE_WRAP_MIRROR modes.
|
||||
*/
|
||||
|
|
@ -408,7 +356,7 @@ lp_build_coord_mirror(struct lp_build_sample_context *bld,
|
|||
|
||||
|
||||
/**
|
||||
* We only support a few wrap modes in lp_build_sample_wrap_int() at this time.
|
||||
* We only support a few wrap modes in lp_build_sample_wrap_linear_int() at this time.
|
||||
* Return whether the given mode is supported by that function.
|
||||
*/
|
||||
static boolean
|
||||
|
|
@ -430,13 +378,18 @@ is_simple_wrap_mode(unsigned mode)
|
|||
* \param length the texture size along one dimension
|
||||
* \param is_pot if TRUE, length is a power of two
|
||||
* \param wrap_mode one of PIPE_TEX_WRAP_x
|
||||
* \param i0 resulting sub-block pixel coordinate for coord0
|
||||
*/
|
||||
static LLVMValueRef
|
||||
lp_build_sample_wrap_int(struct lp_build_sample_context *bld,
|
||||
LLVMValueRef coord,
|
||||
LLVMValueRef length,
|
||||
boolean is_pot,
|
||||
unsigned wrap_mode)
|
||||
static void
|
||||
lp_build_sample_wrap_nearest_int(struct lp_build_sample_context *bld,
|
||||
unsigned block_length,
|
||||
LLVMValueRef coord,
|
||||
LLVMValueRef length,
|
||||
LLVMValueRef stride,
|
||||
boolean is_pot,
|
||||
unsigned wrap_mode,
|
||||
LLVMValueRef *out_offset,
|
||||
LLVMValueRef *out_i)
|
||||
{
|
||||
struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
|
||||
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
||||
|
|
@ -469,7 +422,134 @@ lp_build_sample_wrap_int(struct lp_build_sample_context *bld,
|
|||
assert(0);
|
||||
}
|
||||
|
||||
return coord;
|
||||
lp_build_sample_partial_offset(uint_coord_bld, block_length, coord, stride,
|
||||
out_offset, out_i);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build LLVM code for texture wrap mode, for scaled integer texcoords.
|
||||
* \param coord0 the incoming texcoord (s,t,r or q) scaled to the texture size
|
||||
* \param length the texture size along one dimension
|
||||
* \param stride pixel stride along the coordinate axis
|
||||
* \param block_length is the length of the pixel block along the
|
||||
* coordinate axis
|
||||
* \param is_pot if TRUE, length is a power of two
|
||||
* \param wrap_mode one of PIPE_TEX_WRAP_x
|
||||
* \param offset0 resulting relative offset for coord0
|
||||
* \param offset1 resulting relative offset for coord0 + 1
|
||||
* \param i0 resulting sub-block pixel coordinate for coord0
|
||||
* \param i1 resulting sub-block pixel coordinate for coord0 + 1
|
||||
*/
|
||||
static void
|
||||
lp_build_sample_wrap_linear_int(struct lp_build_sample_context *bld,
|
||||
unsigned block_length,
|
||||
LLVMValueRef coord0,
|
||||
LLVMValueRef length,
|
||||
LLVMValueRef stride,
|
||||
boolean is_pot,
|
||||
unsigned wrap_mode,
|
||||
LLVMValueRef *offset0,
|
||||
LLVMValueRef *offset1,
|
||||
LLVMValueRef *i0,
|
||||
LLVMValueRef *i1)
|
||||
{
|
||||
struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
|
||||
struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
|
||||
LLVMValueRef length_minus_one;
|
||||
LLVMValueRef lmask, umask, mask;
|
||||
|
||||
if (block_length != 1) {
|
||||
/*
|
||||
* If the pixel block covers more than one pixel then there is no easy
|
||||
* way to calculate offset1 relative to offset0. Instead, compute them
|
||||
* independently.
|
||||
*/
|
||||
|
||||
LLVMValueRef coord1;
|
||||
|
||||
lp_build_sample_wrap_nearest_int(bld,
|
||||
block_length,
|
||||
coord0,
|
||||
length,
|
||||
stride,
|
||||
is_pot,
|
||||
wrap_mode,
|
||||
offset0, i0);
|
||||
|
||||
coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
|
||||
|
||||
lp_build_sample_wrap_nearest_int(bld,
|
||||
block_length,
|
||||
coord1,
|
||||
length,
|
||||
stride,
|
||||
is_pot,
|
||||
wrap_mode,
|
||||
offset1, i1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scalar pixels -- try to compute offset0 and offset1 with a single stride
|
||||
* multiplication.
|
||||
*/
|
||||
|
||||
*i0 = uint_coord_bld->zero;
|
||||
*i1 = uint_coord_bld->zero;
|
||||
|
||||
length_minus_one = lp_build_sub(int_coord_bld, length, int_coord_bld->one);
|
||||
|
||||
switch(wrap_mode) {
|
||||
case PIPE_TEX_WRAP_REPEAT:
|
||||
if (is_pot) {
|
||||
coord0 = LLVMBuildAnd(bld->builder, coord0, length_minus_one, "");
|
||||
}
|
||||
else {
|
||||
/* Signed remainder won't give the right results for negative
|
||||
* dividends but unsigned remainder does.*/
|
||||
coord0 = LLVMBuildURem(bld->builder, coord0, length, "");
|
||||
}
|
||||
|
||||
mask = lp_build_compare(bld->builder, int_coord_bld->type,
|
||||
PIPE_FUNC_NOTEQUAL, coord0, length_minus_one);
|
||||
|
||||
*offset0 = lp_build_mul(uint_coord_bld, coord0, stride);
|
||||
*offset1 = LLVMBuildAnd(bld->builder,
|
||||
lp_build_add(uint_coord_bld, *offset0, stride),
|
||||
mask, "");
|
||||
break;
|
||||
|
||||
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
|
||||
lmask = lp_build_compare(int_coord_bld->builder, int_coord_bld->type,
|
||||
PIPE_FUNC_GEQUAL, coord0, int_coord_bld->zero);
|
||||
umask = lp_build_compare(int_coord_bld->builder, int_coord_bld->type,
|
||||
PIPE_FUNC_LESS, coord0, length_minus_one);
|
||||
|
||||
coord0 = lp_build_select(int_coord_bld, lmask, coord0, int_coord_bld->zero);
|
||||
coord0 = lp_build_select(int_coord_bld, umask, coord0, length_minus_one);
|
||||
|
||||
mask = LLVMBuildAnd(bld->builder, lmask, umask, "");
|
||||
|
||||
*offset0 = lp_build_mul(uint_coord_bld, coord0, stride);
|
||||
*offset1 = lp_build_add(uint_coord_bld,
|
||||
*offset0,
|
||||
LLVMBuildAnd(bld->builder, stride, mask, ""));
|
||||
break;
|
||||
|
||||
case PIPE_TEX_WRAP_CLAMP:
|
||||
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
|
||||
case PIPE_TEX_WRAP_MIRROR_REPEAT:
|
||||
case PIPE_TEX_WRAP_MIRROR_CLAMP:
|
||||
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
|
||||
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
|
||||
default:
|
||||
assert(0);
|
||||
*offset0 = uint_coord_bld->zero;
|
||||
*offset1 = uint_coord_bld->zero;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1740,16 +1820,21 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
|
|||
LLVMValueRef i32_c8, i32_c128, i32_c255;
|
||||
LLVMValueRef s_ipart, s_fpart, s_fpart_lo, s_fpart_hi;
|
||||
LLVMValueRef t_ipart, t_fpart, t_fpart_lo, t_fpart_hi;
|
||||
LLVMValueRef x0, x1;
|
||||
LLVMValueRef y0, y1;
|
||||
LLVMValueRef neighbors[2][2];
|
||||
LLVMValueRef data_ptr;
|
||||
LLVMValueRef x_stride, y_stride;
|
||||
LLVMValueRef x_offset0, x_offset1;
|
||||
LLVMValueRef y_offset0, y_offset1;
|
||||
LLVMValueRef offset[2][2];
|
||||
LLVMValueRef x_subcoord[2], y_subcoord[2];
|
||||
LLVMValueRef neighbors_lo[2][2];
|
||||
LLVMValueRef neighbors_hi[2][2];
|
||||
LLVMValueRef packed, packed_lo, packed_hi;
|
||||
LLVMValueRef unswizzled[4];
|
||||
LLVMValueRef stride;
|
||||
const unsigned level = 0;
|
||||
unsigned i, j;
|
||||
|
||||
assert(bld->static_state->target == PIPE_TEXTURE_2D);
|
||||
assert(bld->static_state->target == PIPE_TEXTURE_2D
|
||||
|| bld->static_state->target == PIPE_TEXTURE_RECT);
|
||||
assert(bld->static_state->min_img_filter == PIPE_TEX_FILTER_LINEAR);
|
||||
assert(bld->static_state->mag_img_filter == PIPE_TEX_FILTER_LINEAR);
|
||||
assert(bld->static_state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE);
|
||||
|
|
@ -1793,21 +1878,30 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
|
|||
s_fpart = LLVMBuildAnd(builder, s, i32_c255, "");
|
||||
t_fpart = LLVMBuildAnd(builder, t, i32_c255, "");
|
||||
|
||||
x0 = s_ipart;
|
||||
y0 = t_ipart;
|
||||
x_stride = lp_build_const_vec(bld->uint_coord_bld.type,
|
||||
bld->format_desc->block.bits/8);
|
||||
|
||||
x1 = lp_build_add(&bld->int_coord_bld, x0, bld->int_coord_bld.one);
|
||||
y1 = lp_build_add(&bld->int_coord_bld, y0, bld->int_coord_bld.one);
|
||||
y_stride = lp_build_get_const_level_stride_vec(bld, stride_array, level);
|
||||
|
||||
x0 = lp_build_sample_wrap_int(bld, x0, width, bld->static_state->pot_width,
|
||||
bld->static_state->wrap_s);
|
||||
y0 = lp_build_sample_wrap_int(bld, y0, height, bld->static_state->pot_height,
|
||||
bld->static_state->wrap_t);
|
||||
lp_build_sample_wrap_linear_int(bld,
|
||||
bld->format_desc->block.width,
|
||||
s_ipart, width, x_stride,
|
||||
bld->static_state->pot_width,
|
||||
bld->static_state->wrap_s,
|
||||
&x_offset0, &x_offset1,
|
||||
&x_subcoord[0], &x_subcoord[1]);
|
||||
lp_build_sample_wrap_linear_int(bld,
|
||||
bld->format_desc->block.height,
|
||||
t_ipart, height, y_stride,
|
||||
bld->static_state->pot_height,
|
||||
bld->static_state->wrap_t,
|
||||
&y_offset0, &y_offset1,
|
||||
&y_subcoord[0], &y_subcoord[1]);
|
||||
|
||||
x1 = lp_build_sample_wrap_int(bld, x1, width, bld->static_state->pot_width,
|
||||
bld->static_state->wrap_s);
|
||||
y1 = lp_build_sample_wrap_int(bld, y1, height, bld->static_state->pot_height,
|
||||
bld->static_state->wrap_t);
|
||||
offset[0][0] = lp_build_add(&bld->uint_coord_bld, x_offset0, y_offset0);
|
||||
offset[0][1] = lp_build_add(&bld->uint_coord_bld, x_offset1, y_offset0);
|
||||
offset[1][0] = lp_build_add(&bld->uint_coord_bld, x_offset0, y_offset1);
|
||||
offset[1][1] = lp_build_add(&bld->uint_coord_bld, x_offset1, y_offset1);
|
||||
|
||||
/*
|
||||
* Transform 4 x i32 in
|
||||
|
|
@ -1836,7 +1930,6 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
|
|||
LLVMValueRef shuffles_hi[LP_MAX_VECTOR_LENGTH];
|
||||
LLVMValueRef shuffle_lo;
|
||||
LLVMValueRef shuffle_hi;
|
||||
unsigned i, j;
|
||||
|
||||
for(j = 0; j < h16.type.length; j += 4) {
|
||||
#ifdef PIPE_ARCH_LITTLE_ENDIAN
|
||||
|
|
@ -1864,7 +1957,10 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
|
|||
t_fpart_hi = LLVMBuildShuffleVector(builder, t_fpart, h16.undef, shuffle_hi, "");
|
||||
}
|
||||
|
||||
stride = lp_build_get_const_level_stride_vec(bld, stride_array, 0);
|
||||
/*
|
||||
* get pointer to mipmap level 0 data
|
||||
*/
|
||||
data_ptr = lp_build_get_const_mipmap_level(bld, data_array, level);
|
||||
|
||||
/*
|
||||
* Fetch the pixels as 4 x 32bit (rgba order might differ):
|
||||
|
|
@ -1883,20 +1979,38 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
|
|||
* The higher 8 bits of the resulting elements will be zero.
|
||||
*/
|
||||
|
||||
neighbors[0][0] = lp_build_sample_packed(bld, x0, y0, stride, data_array);
|
||||
neighbors[0][1] = lp_build_sample_packed(bld, x1, y0, stride, data_array);
|
||||
neighbors[1][0] = lp_build_sample_packed(bld, x0, y1, stride, data_array);
|
||||
neighbors[1][1] = lp_build_sample_packed(bld, x1, y1, stride, data_array);
|
||||
for (j = 0; j < 2; ++j) {
|
||||
for (i = 0; i < 2; ++i) {
|
||||
LLVMValueRef rgba8;
|
||||
|
||||
neighbors[0][0] = LLVMBuildBitCast(builder, neighbors[0][0], u8n_vec_type, "");
|
||||
neighbors[0][1] = LLVMBuildBitCast(builder, neighbors[0][1], u8n_vec_type, "");
|
||||
neighbors[1][0] = LLVMBuildBitCast(builder, neighbors[1][0], u8n_vec_type, "");
|
||||
neighbors[1][1] = LLVMBuildBitCast(builder, neighbors[1][1], u8n_vec_type, "");
|
||||
if (util_format_is_rgba8_variant(bld->format_desc)) {
|
||||
/*
|
||||
* Given the format is a rgba8, just read the pixels as is,
|
||||
* without any swizzling. Swizzling will be done later.
|
||||
*/
|
||||
rgba8 = lp_build_gather(bld->builder,
|
||||
bld->texel_type.length,
|
||||
bld->format_desc->block.bits,
|
||||
bld->texel_type.width,
|
||||
data_ptr, offset[j][i]);
|
||||
|
||||
lp_build_unpack2(builder, u8n.type, h16.type, neighbors[0][0], &neighbors_lo[0][0], &neighbors_hi[0][0]);
|
||||
lp_build_unpack2(builder, u8n.type, h16.type, neighbors[0][1], &neighbors_lo[0][1], &neighbors_hi[0][1]);
|
||||
lp_build_unpack2(builder, u8n.type, h16.type, neighbors[1][0], &neighbors_lo[1][0], &neighbors_hi[1][0]);
|
||||
lp_build_unpack2(builder, u8n.type, h16.type, neighbors[1][1], &neighbors_lo[1][1], &neighbors_hi[1][1]);
|
||||
rgba8 = LLVMBuildBitCast(builder, rgba8, u8n_vec_type, "");
|
||||
|
||||
}
|
||||
else {
|
||||
rgba8 = lp_build_fetch_rgba_aos(bld->builder,
|
||||
bld->format_desc,
|
||||
u8n.type,
|
||||
data_ptr, offset[j][i],
|
||||
x_subcoord[i],
|
||||
y_subcoord[j]);
|
||||
}
|
||||
|
||||
lp_build_unpack2(builder, u8n.type, h16.type,
|
||||
rgba8,
|
||||
&neighbors_lo[j][i], &neighbors_hi[j][i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Linear interpolate with 8.8 fixed point.
|
||||
|
|
@ -2077,7 +2191,8 @@ lp_build_sample_soa(LLVMBuilderRef builder,
|
|||
}
|
||||
else if (util_format_fits_8unorm(bld.format_desc) &&
|
||||
bld.format_desc->nr_channels > 1 &&
|
||||
static_state->target == PIPE_TEXTURE_2D &&
|
||||
(static_state->target == PIPE_TEXTURE_2D ||
|
||||
static_state->target == PIPE_TEXTURE_RECT) &&
|
||||
static_state->min_img_filter == PIPE_TEX_FILTER_LINEAR &&
|
||||
static_state->mag_img_filter == PIPE_TEX_FILTER_LINEAR &&
|
||||
static_state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE &&
|
||||
|
|
|
|||
|
|
@ -200,8 +200,10 @@ static void lp_exec_mask_cond_push(struct lp_exec_mask *mask,
|
|||
}
|
||||
mask->cond_stack[mask->cond_stack_size++] = mask->cond_mask;
|
||||
assert(LLVMTypeOf(val) == mask->int_vec_type);
|
||||
mask->cond_mask = val;
|
||||
|
||||
mask->cond_mask = LLVMBuildAnd(mask->bld->builder,
|
||||
mask->cond_mask,
|
||||
val,
|
||||
"");
|
||||
lp_exec_mask_update(mask);
|
||||
}
|
||||
|
||||
|
|
@ -802,7 +804,7 @@ emit_store(
|
|||
|
||||
case TGSI_FILE_PREDICATE:
|
||||
lp_exec_mask_store(&bld->exec_mask, pred, value,
|
||||
bld->preds[index][chan_index]);
|
||||
bld->preds[reg->Register.Index][chan_index]);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -128,16 +128,16 @@ struct lp_build_context
|
|||
*/
|
||||
struct lp_type type;
|
||||
|
||||
/** Same as lp_build_undef(type) */
|
||||
/** Same as lp_build_elem_type(type) */
|
||||
LLVMTypeRef elem_type;
|
||||
|
||||
/** Same as lp_build_undef(type) */
|
||||
/** Same as lp_build_vec_type(type) */
|
||||
LLVMTypeRef vec_type;
|
||||
|
||||
/** Same as lp_build_undef(type) */
|
||||
/** Same as lp_build_int_elem_type(type) */
|
||||
LLVMTypeRef int_elem_type;
|
||||
|
||||
/** Same as lp_build_undef(type) */
|
||||
/** Same as lp_build_int_vec_type(type) */
|
||||
LLVMTypeRef int_vec_type;
|
||||
|
||||
/** Same as lp_build_undef(type) */
|
||||
|
|
|
|||
58
src/gallium/auxiliary/os/os_stream.c
Normal file
58
src/gallium/auxiliary/os/os_stream.c
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2010 Luca Barbieri
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* 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 "pipe/p_config.h"
|
||||
|
||||
#include "os_stream.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_string.h"
|
||||
|
||||
int
|
||||
os_default_stream_vprintf (struct os_stream* stream, const char *format, va_list ap)
|
||||
{
|
||||
char buf[1024];
|
||||
int retval;
|
||||
va_list ap2;
|
||||
va_copy(ap2, ap);
|
||||
retval = util_vsnprintf(buf, sizeof(buf), format, ap2);
|
||||
va_end(ap2);
|
||||
if(retval <= 0)
|
||||
{}
|
||||
else if(retval < sizeof(buf))
|
||||
stream->write(stream, buf, retval);
|
||||
else
|
||||
{
|
||||
char* str = MALLOC(retval + 1);
|
||||
if(!str)
|
||||
return -1;
|
||||
retval = util_vsnprintf(str, retval + 1, format, ap);
|
||||
if(retval > 0)
|
||||
stream->write(stream, str, retval);
|
||||
FREE(str);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -50,6 +50,9 @@ struct os_stream
|
|||
|
||||
void
|
||||
(*flush)(struct os_stream *stream);
|
||||
|
||||
int
|
||||
(*vprintf)(struct os_stream *stream, const char* format, va_list ap);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -90,6 +93,27 @@ os_stream_flush(struct os_stream *stream)
|
|||
stream->flush(stream);
|
||||
}
|
||||
|
||||
int
|
||||
os_default_stream_vprintf (struct os_stream* stream, const char *format, va_list ap);
|
||||
|
||||
static INLINE int
|
||||
os_stream_vprintf (struct os_stream* stream, const char *format, va_list ap)
|
||||
{
|
||||
return stream->vprintf(stream, format, ap);
|
||||
}
|
||||
|
||||
static INLINE int
|
||||
os_stream_printf (struct os_stream* stream, const char *format, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
retval = stream->vprintf(stream, format, args);
|
||||
va_end (args);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
struct os_stream *
|
||||
os_file_stream_create(const char *filename);
|
||||
|
|
@ -118,5 +142,4 @@ os_str_stream_get_and_close(struct os_stream *stream);
|
|||
#define os_file_stream_create(_filename) os_null_stream_create()
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _OS_STREAM_H_ */
|
||||
|
|
|
|||
|
|
@ -73,7 +73,8 @@ static struct os_stream
|
|||
os_log_stream_struct = {
|
||||
&os_log_stream_close,
|
||||
&os_log_stream_write,
|
||||
&os_log_stream_flush
|
||||
&os_log_stream_flush,
|
||||
&os_default_stream_vprintf,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -56,12 +56,18 @@ os_null_stream_flush(struct os_stream *stream)
|
|||
(void)stream;
|
||||
}
|
||||
|
||||
static int
|
||||
os_null_stream_vprintf (struct os_stream* stream, const char *format, va_list ap)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct os_stream
|
||||
os_null_stream = {
|
||||
&os_null_stream_close,
|
||||
&os_null_stream_write,
|
||||
&os_null_stream_flush
|
||||
&os_null_stream_flush,
|
||||
&os_null_stream_vprintf
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,14 @@ os_stdc_stream_flush(struct os_stream *_stream)
|
|||
fflush(stream->file);
|
||||
}
|
||||
|
||||
static int
|
||||
os_stdc_stream_vprintf (struct os_stream* _stream, const char *format, va_list ap)
|
||||
{
|
||||
struct os_stdc_stream *stream = os_stdc_stream(_stream);
|
||||
|
||||
return vfprintf(stream->file, format, ap);
|
||||
}
|
||||
|
||||
|
||||
struct os_stream *
|
||||
os_file_stream_create(const char *filename)
|
||||
|
|
@ -96,6 +104,7 @@ os_file_stream_create(const char *filename)
|
|||
stream->base.close = &os_stdc_stream_close;
|
||||
stream->base.write = &os_stdc_stream_write;
|
||||
stream->base.flush = &os_stdc_stream_flush;
|
||||
stream->base.vprintf = &os_stdc_stream_vprintf;
|
||||
|
||||
stream->file = fopen(filename, "w");
|
||||
if(!stream->file)
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ os_str_stream_create(size_t size)
|
|||
stream->base.close = &os_str_stream_close;
|
||||
stream->base.write = &os_str_stream_write;
|
||||
stream->base.flush = &os_str_stream_flush;
|
||||
stream->base.vprintf = &os_default_stream_vprintf;
|
||||
|
||||
stream->str = os_malloc(size);
|
||||
if(!stream->str)
|
||||
|
|
|
|||
|
|
@ -50,8 +50,7 @@
|
|||
#define PB_BUFMGR_H_
|
||||
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pb_buffer.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include "rtasm_cpu.h"
|
||||
|
||||
|
||||
#if defined(PIPE_ARCH_X86)
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||
static boolean rtasm_sse_enabled(void)
|
||||
{
|
||||
static boolean firsttime = 1;
|
||||
|
|
@ -49,7 +49,7 @@ static boolean rtasm_sse_enabled(void)
|
|||
int rtasm_cpu_has_sse(void)
|
||||
{
|
||||
/* FIXME: actually detect this at run-time */
|
||||
#if defined(PIPE_ARCH_X86)
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||
return rtasm_sse_enabled();
|
||||
#else
|
||||
return 0;
|
||||
|
|
@ -59,7 +59,7 @@ int rtasm_cpu_has_sse(void)
|
|||
int rtasm_cpu_has_sse2(void)
|
||||
{
|
||||
/* FIXME: actually detect this at run-time */
|
||||
#if defined(PIPE_ARCH_X86)
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||
return rtasm_sse_enabled();
|
||||
#else
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@
|
|||
**************************************************************************/
|
||||
|
||||
#include "pipe/p_config.h"
|
||||
#include "util/u_cpu_detect.h"
|
||||
|
||||
#if defined(PIPE_ARCH_X86)
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "util/u_debug.h"
|
||||
|
|
@ -231,6 +232,10 @@ static void emit_modrm( struct x86_function *p,
|
|||
|
||||
assert(reg.mod == mod_REG);
|
||||
|
||||
/* TODO: support extended x86-64 registers */
|
||||
assert(reg.idx < 8);
|
||||
assert(regmem.idx < 8);
|
||||
|
||||
val |= regmem.mod << 6; /* mod field */
|
||||
val |= reg.idx << 3; /* reg field */
|
||||
val |= regmem.idx; /* r/m field */
|
||||
|
|
@ -363,6 +368,12 @@ int x86_get_label( struct x86_function *p )
|
|||
*/
|
||||
|
||||
|
||||
void x64_rexw(struct x86_function *p)
|
||||
{
|
||||
if(x86_target(p) != X86_32)
|
||||
emit_1ub(p, 0x48);
|
||||
}
|
||||
|
||||
void x86_jcc( struct x86_function *p,
|
||||
enum x86_cc cc,
|
||||
int label )
|
||||
|
|
@ -449,6 +460,52 @@ void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm )
|
|||
emit_1i(p, imm);
|
||||
}
|
||||
|
||||
void x86_mov_imm( struct x86_function *p, struct x86_reg dst, int imm )
|
||||
{
|
||||
DUMP_RI( dst, imm );
|
||||
if(dst.mod == mod_REG)
|
||||
x86_mov_reg_imm(p, dst, imm);
|
||||
else
|
||||
{
|
||||
emit_1ub(p, 0xc7);
|
||||
emit_modrm_noreg(p, 0, dst);
|
||||
emit_1i(p, imm);
|
||||
}
|
||||
}
|
||||
|
||||
void x86_mov16_imm( struct x86_function *p, struct x86_reg dst, uint16_t imm )
|
||||
{
|
||||
DUMP_RI( dst, imm );
|
||||
emit_1ub(p, 0x66);
|
||||
if(dst.mod == mod_REG)
|
||||
{
|
||||
emit_1ub(p, 0xb8 + dst.idx);
|
||||
emit_2ub(p, imm & 0xff, imm >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_1ub(p, 0xc7);
|
||||
emit_modrm_noreg(p, 0, dst);
|
||||
emit_2ub(p, imm & 0xff, imm >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
void x86_mov8_imm( struct x86_function *p, struct x86_reg dst, uint8_t imm )
|
||||
{
|
||||
DUMP_RI( dst, imm );
|
||||
if(dst.mod == mod_REG)
|
||||
{
|
||||
emit_1ub(p, 0xb0 + dst.idx);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_1ub(p, 0xc6);
|
||||
emit_modrm_noreg(p, 0, dst);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Immediate group 1 instructions.
|
||||
*/
|
||||
|
|
@ -520,7 +577,7 @@ void x86_push( struct x86_function *p,
|
|||
}
|
||||
|
||||
|
||||
p->stack_offset += 4;
|
||||
p->stack_offset += sizeof(void*);
|
||||
}
|
||||
|
||||
void x86_push_imm32( struct x86_function *p,
|
||||
|
|
@ -530,7 +587,7 @@ void x86_push_imm32( struct x86_function *p,
|
|||
emit_1ub(p, 0x68);
|
||||
emit_1i(p, imm32);
|
||||
|
||||
p->stack_offset += 4;
|
||||
p->stack_offset += sizeof(void*);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -540,23 +597,33 @@ void x86_pop( struct x86_function *p,
|
|||
DUMP_R( reg );
|
||||
assert(reg.mod == mod_REG);
|
||||
emit_1ub(p, 0x58 + reg.idx);
|
||||
p->stack_offset -= 4;
|
||||
p->stack_offset -= sizeof(void*);
|
||||
}
|
||||
|
||||
void x86_inc( struct x86_function *p,
|
||||
struct x86_reg reg )
|
||||
{
|
||||
DUMP_R( reg );
|
||||
assert(reg.mod == mod_REG);
|
||||
emit_1ub(p, 0x40 + reg.idx);
|
||||
if(x86_target(p) == X86_32 && reg.mod == mod_REG)
|
||||
{
|
||||
emit_1ub(p, 0x40 + reg.idx);
|
||||
return;
|
||||
}
|
||||
emit_1ub(p, 0xff);
|
||||
emit_modrm_noreg(p, 0, reg);
|
||||
}
|
||||
|
||||
void x86_dec( struct x86_function *p,
|
||||
struct x86_reg reg )
|
||||
{
|
||||
DUMP_R( reg );
|
||||
assert(reg.mod == mod_REG);
|
||||
emit_1ub(p, 0x48 + reg.idx);
|
||||
if(x86_target(p) == X86_32 && reg.mod == mod_REG)
|
||||
{
|
||||
emit_1ub(p, 0x48 + reg.idx);
|
||||
return;
|
||||
}
|
||||
emit_1ub(p, 0xff);
|
||||
emit_modrm_noreg(p, 1, reg);
|
||||
}
|
||||
|
||||
void x86_ret( struct x86_function *p )
|
||||
|
|
@ -583,9 +650,82 @@ void x86_mov( struct x86_function *p,
|
|||
struct x86_reg src )
|
||||
{
|
||||
DUMP_RR( dst, src );
|
||||
/* special hack for reading arguments until we support x86-64 registers everywhere */
|
||||
if(src.mod == mod_REG && dst.mod == mod_REG && (src.idx >= 8 || dst.idx >= 8))
|
||||
{
|
||||
uint8_t rex = 0x40;
|
||||
if(dst.idx >= 8)
|
||||
{
|
||||
rex |= 4;
|
||||
dst.idx -= 8;
|
||||
}
|
||||
if(src.idx >= 8)
|
||||
{
|
||||
rex |= 1;
|
||||
src.idx -= 8;
|
||||
}
|
||||
emit_1ub(p, rex);
|
||||
}
|
||||
emit_op_modrm( p, 0x8b, 0x89, dst, src );
|
||||
}
|
||||
|
||||
void x86_mov16( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
struct x86_reg src )
|
||||
{
|
||||
DUMP_RR( dst, src );
|
||||
emit_1ub(p, 0x66);
|
||||
emit_op_modrm( p, 0x8b, 0x89, dst, src );
|
||||
}
|
||||
|
||||
void x86_mov8( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
struct x86_reg src )
|
||||
{
|
||||
DUMP_RR( dst, src );
|
||||
emit_op_modrm( p, 0x8a, 0x88, dst, src );
|
||||
}
|
||||
|
||||
void x64_mov64( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
struct x86_reg src )
|
||||
{
|
||||
uint8_t rex = 0x48;
|
||||
DUMP_RR( dst, src );
|
||||
assert(x86_target(p) != X86_32);
|
||||
|
||||
/* special hack for reading arguments until we support x86-64 registers everywhere */
|
||||
if(src.mod == mod_REG && dst.mod == mod_REG && (src.idx >= 8 || dst.idx >= 8))
|
||||
{
|
||||
if(dst.idx >= 8)
|
||||
{
|
||||
rex |= 4;
|
||||
dst.idx -= 8;
|
||||
}
|
||||
if(src.idx >= 8)
|
||||
{
|
||||
rex |= 1;
|
||||
src.idx -= 8;
|
||||
}
|
||||
}
|
||||
emit_1ub(p, rex);
|
||||
emit_op_modrm( p, 0x8b, 0x89, dst, src );
|
||||
}
|
||||
|
||||
void x86_movzx8(struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR( dst, src );
|
||||
emit_2ub(p, 0x0f, 0xb6);
|
||||
emit_modrm(p, dst, src);
|
||||
}
|
||||
|
||||
void x86_movzx16(struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR( dst, src );
|
||||
emit_2ub(p, 0x0f, 0xb7);
|
||||
emit_modrm(p, dst, src);
|
||||
}
|
||||
|
||||
void x86_xor( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
struct x86_reg src )
|
||||
|
|
@ -680,6 +820,61 @@ void x86_div( struct x86_function *p,
|
|||
emit_op_modrm(p, 0xf7, 0, x86_make_reg(file_REG32, 6), src);
|
||||
}
|
||||
|
||||
void x86_bswap( struct x86_function *p, struct x86_reg reg )
|
||||
{
|
||||
DUMP_R(reg);
|
||||
assert(reg.file == file_REG32);
|
||||
assert(reg.mod == mod_REG);
|
||||
emit_2ub(p, 0x0f, 0xc8 + reg.idx);
|
||||
}
|
||||
|
||||
void x86_shr_imm( struct x86_function *p, struct x86_reg reg, unsigned imm )
|
||||
{
|
||||
DUMP_RI(reg, imm);
|
||||
if(imm == 1)
|
||||
{
|
||||
emit_1ub(p, 0xd1);
|
||||
emit_modrm_noreg(p, 5, reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_1ub(p, 0xc1);
|
||||
emit_modrm_noreg(p, 5, reg);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
}
|
||||
|
||||
void x86_sar_imm( struct x86_function *p, struct x86_reg reg, unsigned imm )
|
||||
{
|
||||
DUMP_RI(reg, imm);
|
||||
if(imm == 1)
|
||||
{
|
||||
emit_1ub(p, 0xd1);
|
||||
emit_modrm_noreg(p, 7, reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_1ub(p, 0xc1);
|
||||
emit_modrm_noreg(p, 7, reg);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
}
|
||||
|
||||
void x86_shl_imm( struct x86_function *p, struct x86_reg reg, unsigned imm )
|
||||
{
|
||||
DUMP_RI(reg, imm);
|
||||
if(imm == 1)
|
||||
{
|
||||
emit_1ub(p, 0xd1);
|
||||
emit_modrm_noreg(p, 4, reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_1ub(p, 0xc1);
|
||||
emit_modrm_noreg(p, 4, reg);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
|
@ -1013,6 +1208,77 @@ void sse_movmskps( struct x86_function *p,
|
|||
* SSE2 instructions
|
||||
*/
|
||||
|
||||
void sse2_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR(dst, src);
|
||||
emit_2ub(p, 0x66, 0x0f);
|
||||
if(dst.mod == mod_REG && dst.file == file_REG32)
|
||||
{
|
||||
emit_1ub(p, 0x7e);
|
||||
emit_modrm(p, src, dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_op_modrm(p, 0x6e, 0x7e, dst, src);
|
||||
}
|
||||
}
|
||||
|
||||
void sse2_movq( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR(dst, src);
|
||||
switch (dst.mod) {
|
||||
case mod_REG:
|
||||
emit_3ub(p, 0xf3, 0x0f, 0x7e);
|
||||
emit_modrm(p, dst, src);
|
||||
break;
|
||||
case mod_INDIRECT:
|
||||
case mod_DISP32:
|
||||
case mod_DISP8:
|
||||
assert(src.mod == mod_REG);
|
||||
emit_3ub(p, 0x66, 0x0f, 0xd6);
|
||||
emit_modrm(p, src, dst);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sse2_movdqu( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR(dst, src);
|
||||
emit_2ub(p, 0xf3, 0x0f);
|
||||
emit_op_modrm(p, 0x6f, 0x7f, dst, src);
|
||||
}
|
||||
|
||||
void sse2_movdqa( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR(dst, src);
|
||||
emit_2ub(p, 0x66, 0x0f);
|
||||
emit_op_modrm(p, 0x6f, 0x7f, dst, src);
|
||||
}
|
||||
|
||||
void sse2_movsd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR(dst, src);
|
||||
emit_2ub(p, 0xf2, 0x0f);
|
||||
emit_op_modrm(p, 0x10, 0x11, dst, src);
|
||||
}
|
||||
|
||||
void sse2_movupd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR(dst, src);
|
||||
emit_2ub(p, 0x66, 0x0f);
|
||||
emit_op_modrm(p, 0x10, 0x11, dst, src);
|
||||
}
|
||||
|
||||
void sse2_movapd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR(dst, src);
|
||||
emit_2ub(p, 0x66, 0x0f);
|
||||
emit_op_modrm(p, 0x28, 0x29, dst, src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a reduced swizzle:
|
||||
*/
|
||||
|
|
@ -1027,6 +1293,28 @@ void sse2_pshufd( struct x86_function *p,
|
|||
emit_1ub(p, shuf);
|
||||
}
|
||||
|
||||
void sse2_pshuflw( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
struct x86_reg src,
|
||||
unsigned char shuf)
|
||||
{
|
||||
DUMP_RRI( dst, src, shuf );
|
||||
emit_3ub(p, 0xf2, X86_TWOB, 0x70);
|
||||
emit_modrm(p, dst, src);
|
||||
emit_1ub(p, shuf);
|
||||
}
|
||||
|
||||
void sse2_pshufhw( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
struct x86_reg src,
|
||||
unsigned char shuf)
|
||||
{
|
||||
DUMP_RRI( dst, src, shuf );
|
||||
emit_3ub(p, 0xf3, X86_TWOB, 0x70);
|
||||
emit_modrm(p, dst, src);
|
||||
emit_1ub(p, shuf);
|
||||
}
|
||||
|
||||
void sse2_cvttps2dq( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
struct x86_reg src )
|
||||
|
|
@ -1045,6 +1333,24 @@ void sse2_cvtps2dq( struct x86_function *p,
|
|||
emit_modrm( p, dst, src );
|
||||
}
|
||||
|
||||
void sse2_cvtsd2ss( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
struct x86_reg src )
|
||||
{
|
||||
DUMP_RR( dst, src );
|
||||
emit_3ub(p, 0xf2, 0x0f, 0x5a);
|
||||
emit_modrm( p, dst, src );
|
||||
}
|
||||
|
||||
void sse2_cvtpd2ps( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
struct x86_reg src )
|
||||
{
|
||||
DUMP_RR( dst, src );
|
||||
emit_3ub(p, 0x66, 0x0f, 0x5a);
|
||||
emit_modrm( p, dst, src );
|
||||
}
|
||||
|
||||
void sse2_packssdw( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
struct x86_reg src )
|
||||
|
|
@ -1081,6 +1387,97 @@ void sse2_punpcklbw( struct x86_function *p,
|
|||
emit_modrm( p, dst, src );
|
||||
}
|
||||
|
||||
void sse2_punpcklwd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR( dst, src );
|
||||
emit_3ub(p, 0x66, 0x0f, 0x61);
|
||||
emit_modrm( p, dst, src );
|
||||
}
|
||||
|
||||
void sse2_punpckldq( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR( dst, src );
|
||||
emit_3ub(p, 0x66, 0x0f, 0x62);
|
||||
emit_modrm( p, dst, src );
|
||||
}
|
||||
|
||||
void sse2_punpcklqdq( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR( dst, src );
|
||||
emit_3ub(p, 0x66, 0x0f, 0x6c);
|
||||
emit_modrm( p, dst, src );
|
||||
}
|
||||
|
||||
void sse2_psllw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
|
||||
{
|
||||
DUMP_RI(dst, imm);
|
||||
emit_3ub(p, 0x66, 0x0f, 0x71);
|
||||
emit_modrm_noreg(p, 6, dst);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
|
||||
void sse2_pslld_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
|
||||
{
|
||||
DUMP_RI(dst, imm);
|
||||
emit_3ub(p, 0x66, 0x0f, 0x72);
|
||||
emit_modrm_noreg(p, 6, dst);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
|
||||
void sse2_psllq_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
|
||||
{
|
||||
DUMP_RI(dst, imm);
|
||||
emit_3ub(p, 0x66, 0x0f, 0x73);
|
||||
emit_modrm_noreg(p, 6, dst);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
|
||||
void sse2_psrlw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
|
||||
{
|
||||
DUMP_RI(dst, imm);
|
||||
emit_3ub(p, 0x66, 0x0f, 0x71);
|
||||
emit_modrm_noreg(p, 2, dst);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
|
||||
void sse2_psrld_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
|
||||
{
|
||||
DUMP_RI(dst, imm);
|
||||
emit_3ub(p, 0x66, 0x0f, 0x72);
|
||||
emit_modrm_noreg(p, 2, dst);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
|
||||
void sse2_psrlq_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
|
||||
{
|
||||
DUMP_RI(dst, imm);
|
||||
emit_3ub(p, 0x66, 0x0f, 0x73);
|
||||
emit_modrm_noreg(p, 2, dst);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
|
||||
void sse2_psraw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
|
||||
{
|
||||
DUMP_RI(dst, imm);
|
||||
emit_3ub(p, 0x66, 0x0f, 0x71);
|
||||
emit_modrm_noreg(p, 4, dst);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
|
||||
void sse2_psrad_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
|
||||
{
|
||||
DUMP_RI(dst, imm);
|
||||
emit_3ub(p, 0x66, 0x0f, 0x72);
|
||||
emit_modrm_noreg(p, 4, dst);
|
||||
emit_1ub(p, imm);
|
||||
}
|
||||
|
||||
void sse2_por( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
|
||||
{
|
||||
DUMP_RR(dst, src);
|
||||
emit_3ub(p, 0x66, 0x0f, 0xeb);
|
||||
emit_modrm(p, dst, src);
|
||||
}
|
||||
|
||||
void sse2_rcpps( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
|
|
@ -1100,18 +1497,6 @@ void sse2_rcpss( struct x86_function *p,
|
|||
emit_modrm( p, dst, src );
|
||||
}
|
||||
|
||||
void sse2_movd( struct x86_function *p,
|
||||
struct x86_reg dst,
|
||||
struct x86_reg src )
|
||||
{
|
||||
DUMP_RR( dst, src );
|
||||
emit_2ub(p, 0x66, X86_TWOB);
|
||||
emit_op_modrm( p, 0x6e, 0x7e, dst, src );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* x87 instructions
|
||||
*/
|
||||
|
|
@ -1702,23 +2087,80 @@ void x86_cdecl_caller_pop_regs( struct x86_function *p )
|
|||
}
|
||||
|
||||
|
||||
/* Retreive a reference to one of the function arguments, taking into
|
||||
* account any push/pop activity:
|
||||
*/
|
||||
struct x86_reg x86_fn_arg( struct x86_function *p,
|
||||
unsigned arg )
|
||||
unsigned arg )
|
||||
{
|
||||
return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
|
||||
switch(x86_target(p))
|
||||
{
|
||||
case X86_64_WIN64_ABI:
|
||||
/* Microsoft uses a different calling convention than the rest of the world */
|
||||
switch(arg)
|
||||
{
|
||||
case 1:
|
||||
return x86_make_reg(file_REG32, reg_CX);
|
||||
case 2:
|
||||
return x86_make_reg(file_REG32, reg_DX);
|
||||
case 3:
|
||||
return x86_make_reg(file_REG32, reg_R8);
|
||||
case 4:
|
||||
return x86_make_reg(file_REG32, reg_R9);
|
||||
default:
|
||||
/* Win64 allocates stack slots as if it pushed the first 4 arguments too */
|
||||
return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
|
||||
p->stack_offset + arg * 8);
|
||||
}
|
||||
case X86_64_STD_ABI:
|
||||
switch(arg)
|
||||
{
|
||||
case 1:
|
||||
return x86_make_reg(file_REG32, reg_DI);
|
||||
case 2:
|
||||
return x86_make_reg(file_REG32, reg_SI);
|
||||
case 3:
|
||||
return x86_make_reg(file_REG32, reg_DX);
|
||||
case 4:
|
||||
return x86_make_reg(file_REG32, reg_CX);
|
||||
case 5:
|
||||
return x86_make_reg(file_REG32, reg_R8);
|
||||
case 6:
|
||||
return x86_make_reg(file_REG32, reg_R9);
|
||||
default:
|
||||
return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
|
||||
p->stack_offset + (arg - 6) * 8); /* ??? */
|
||||
}
|
||||
case X86_32:
|
||||
return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
|
||||
p->stack_offset + arg * 4); /* ??? */
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void x86_init_func_common( struct x86_function *p )
|
||||
{
|
||||
util_cpu_detect();
|
||||
p->caps = 0;
|
||||
if(util_cpu_caps.has_mmx)
|
||||
p->caps |= X86_MMX;
|
||||
if(util_cpu_caps.has_mmx2)
|
||||
p->caps |= X86_MMX2;
|
||||
if(util_cpu_caps.has_sse)
|
||||
p->caps |= X86_SSE;
|
||||
if(util_cpu_caps.has_sse2)
|
||||
p->caps |= X86_SSE2;
|
||||
if(util_cpu_caps.has_sse3)
|
||||
p->caps |= X86_SSE3;
|
||||
if(util_cpu_caps.has_sse4_1)
|
||||
p->caps |= X86_SSE4_1;
|
||||
p->csr = p->store;
|
||||
DUMP_START();
|
||||
}
|
||||
|
||||
void x86_init_func( struct x86_function *p )
|
||||
{
|
||||
p->size = 0;
|
||||
p->store = NULL;
|
||||
p->csr = p->store;
|
||||
DUMP_START();
|
||||
x86_init_func_common(p);
|
||||
}
|
||||
|
||||
void x86_init_func_size( struct x86_function *p, unsigned code_size )
|
||||
|
|
@ -1728,8 +2170,7 @@ void x86_init_func_size( struct x86_function *p, unsigned code_size )
|
|||
if (p->store == NULL) {
|
||||
p->store = p->error_overflow;
|
||||
}
|
||||
p->csr = p->store;
|
||||
DUMP_START();
|
||||
x86_init_func_common(p);
|
||||
}
|
||||
|
||||
void x86_release_func( struct x86_function *p )
|
||||
|
|
|
|||
|
|
@ -24,22 +24,31 @@
|
|||
#ifndef _RTASM_X86SSE_H_
|
||||
#define _RTASM_X86SSE_H_
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_config.h"
|
||||
|
||||
#if defined(PIPE_ARCH_X86)
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||
|
||||
/* It is up to the caller to ensure that instructions issued are
|
||||
* suitable for the host cpu. There are no checks made in this module
|
||||
* for mmx/sse/sse2 support on the cpu.
|
||||
*/
|
||||
struct x86_reg {
|
||||
unsigned file:3;
|
||||
unsigned idx:3;
|
||||
unsigned file:2;
|
||||
unsigned idx:4;
|
||||
unsigned mod:2; /* mod_REG if this is just a register */
|
||||
int disp:24; /* only +/- 23bits of offset - should be enough... */
|
||||
};
|
||||
|
||||
#define X86_MMX 1
|
||||
#define X86_MMX2 2
|
||||
#define X86_SSE 4
|
||||
#define X86_SSE2 8
|
||||
#define X86_SSE3 0x10
|
||||
#define X86_SSE4_1 0x20
|
||||
|
||||
struct x86_function {
|
||||
unsigned caps;
|
||||
unsigned size;
|
||||
unsigned char *store;
|
||||
unsigned char *csr;
|
||||
|
|
@ -75,7 +84,15 @@ enum x86_reg_name {
|
|||
reg_SP,
|
||||
reg_BP,
|
||||
reg_SI,
|
||||
reg_DI
|
||||
reg_DI,
|
||||
reg_R8,
|
||||
reg_R9,
|
||||
reg_R10,
|
||||
reg_R11,
|
||||
reg_R12,
|
||||
reg_R13,
|
||||
reg_R14,
|
||||
reg_R15
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -110,6 +127,29 @@ typedef void (*x86_func)(void);
|
|||
/* Begin/end/retrieve function creation:
|
||||
*/
|
||||
|
||||
enum x86_target
|
||||
{
|
||||
X86_32,
|
||||
X86_64_STD_ABI,
|
||||
X86_64_WIN64_ABI
|
||||
};
|
||||
|
||||
/* make this read a member of x86_function if target != host is desired */
|
||||
static INLINE enum x86_target x86_target( struct x86_function* p )
|
||||
{
|
||||
#ifdef PIPE_ARCH_X86
|
||||
return X86_32;
|
||||
#elif defined(_WIN64)
|
||||
return X86_64_WIN64_ABI;
|
||||
#elif defined(PIPE_ARCH_X86_64)
|
||||
return X86_64_STD_ABI;
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE unsigned x86_target_caps( struct x86_function* p )
|
||||
{
|
||||
return p->caps;
|
||||
}
|
||||
|
||||
void x86_init_func( struct x86_function *p );
|
||||
void x86_init_func_size( struct x86_function *p, unsigned code_size );
|
||||
|
|
@ -138,6 +178,8 @@ struct x86_reg x86_get_base_reg( struct x86_reg reg );
|
|||
*/
|
||||
int x86_get_label( struct x86_function *p );
|
||||
|
||||
void x64_rexw(struct x86_function *p);
|
||||
|
||||
void x86_jcc( struct x86_function *p,
|
||||
enum x86_cc cc,
|
||||
int label );
|
||||
|
|
@ -178,18 +220,54 @@ void mmx_movq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
|||
void mmx_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void mmx_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
|
||||
void sse2_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_movq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_movdqu( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_movdqa( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_movsd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_movupd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_movapd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
|
||||
void sse2_cvtps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_cvttps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_cvtdq2ps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_cvtsd2ss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_cvtpd2ps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
|
||||
void sse2_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_packsswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_pshufd( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0,
|
||||
unsigned char shuf );
|
||||
void sse2_pshuflw( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0,
|
||||
unsigned char shuf );
|
||||
void sse2_pshufhw( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0,
|
||||
unsigned char shuf );
|
||||
void sse2_rcpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_rcpss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
|
||||
void sse2_punpcklbw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_punpcklwd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_punpckldq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_punpcklqdq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
|
||||
void sse2_psllw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
|
||||
void sse2_pslld_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
|
||||
void sse2_psllq_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
|
||||
|
||||
void sse2_psrlw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
|
||||
void sse2_psrld_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
|
||||
void sse2_psrlq_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
|
||||
|
||||
void sse2_psraw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
|
||||
void sse2_psrad_imm( struct x86_function *p, struct x86_reg dst, unsigned imm );
|
||||
|
||||
void sse2_por( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
|
||||
void sse2_pshuflw( struct x86_function *p, struct x86_reg dst, struct x86_reg src, uint8_t imm );
|
||||
void sse2_pshufhw( struct x86_function *p, struct x86_reg dst, struct x86_reg src, uint8_t imm );
|
||||
void sse2_pshufd( struct x86_function *p, struct x86_reg dst, struct x86_reg src, uint8_t imm );
|
||||
|
||||
void sse_prefetchnta( struct x86_function *p, struct x86_reg ptr);
|
||||
void sse_prefetch0( struct x86_function *p, struct x86_reg ptr);
|
||||
|
|
@ -227,7 +305,6 @@ void sse_shufps( struct x86_function *p, struct x86_reg dest, struct x86_reg arg
|
|||
void sse_unpckhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_unpcklps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_pmovmskb( struct x86_function *p, struct x86_reg dest, struct x86_reg src );
|
||||
void sse2_punpcklbw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_movmskps( struct x86_function *p, struct x86_reg dst, struct x86_reg src);
|
||||
|
||||
void x86_add( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
|
|
@ -237,6 +314,14 @@ void x86_dec( struct x86_function *p, struct x86_reg reg );
|
|||
void x86_inc( struct x86_function *p, struct x86_reg reg );
|
||||
void x86_lea( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_mov( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x64_mov64( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_mov8( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_mov16( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_movzx8(struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_movzx16(struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_mov_imm(struct x86_function *p, struct x86_reg dst, int imm );
|
||||
void x86_mov8_imm(struct x86_function *p, struct x86_reg dst, uint8_t imm );
|
||||
void x86_mov16_imm(struct x86_function *p, struct x86_reg dst, uint16_t imm );
|
||||
void x86_mul( struct x86_function *p, struct x86_reg src );
|
||||
void x86_imul( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_or( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
|
|
@ -250,7 +335,10 @@ void x86_test( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
|||
void x86_xor( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_sahf( struct x86_function *p );
|
||||
void x86_div( struct x86_function *p, struct x86_reg src );
|
||||
|
||||
void x86_bswap( struct x86_function *p, struct x86_reg src );
|
||||
void x86_shr_imm( struct x86_function *p, struct x86_reg reg, unsigned imm );
|
||||
void x86_sar_imm( struct x86_function *p, struct x86_reg reg, unsigned imm );
|
||||
void x86_shl_imm( struct x86_function *p, struct x86_reg reg, unsigned imm );
|
||||
|
||||
void x86_cdecl_caller_push_regs( struct x86_function *p );
|
||||
void x86_cdecl_caller_pop_regs( struct x86_function *p );
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#ifndef TGSI_DUMP_H
|
||||
#define TGSI_DUMP_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
|
|
|
|||
|
|
@ -3239,6 +3239,8 @@ exec_instruction(
|
|||
|
||||
if (mach->CallStackTop == 0) {
|
||||
/* returning from main() */
|
||||
mach->CondStackTop = 0;
|
||||
mach->LoopStackTop = 0;
|
||||
*pc = -1;
|
||||
return;
|
||||
}
|
||||
|
|
@ -3767,6 +3769,9 @@ tgsi_exec_machine_run( struct tgsi_exec_machine *mach )
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Strictly speaking, these assertions aren't really needed but they
|
||||
* can potentially catch some bugs in the control flow code.
|
||||
*/
|
||||
assert(mach->CondStackTop == 0);
|
||||
assert(mach->LoopStackTop == 0);
|
||||
assert(mach->ContStackTop == 0);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#ifndef TGSI_INFO_H
|
||||
#define TGSI_INFO_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
|
|
|
|||
|
|
@ -282,17 +282,6 @@ tgsi_parse_token(
|
|||
}
|
||||
|
||||
|
||||
unsigned
|
||||
tgsi_num_tokens(const struct tgsi_token *tokens)
|
||||
{
|
||||
struct tgsi_parse_context ctx;
|
||||
if (tgsi_parse_init(&ctx, tokens) == TGSI_PARSE_OK) {
|
||||
unsigned len = (ctx.FullHeader.Header.HeaderSize +
|
||||
ctx.FullHeader.Header.BodySize);
|
||||
return len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -319,3 +308,19 @@ tgsi_alloc_tokens(unsigned num_tokens)
|
|||
unsigned bytes = num_tokens * sizeof(struct tgsi_token);
|
||||
return (struct tgsi_token *) MALLOC(bytes);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tgsi_dump_tokens(const struct tgsi_token *tokens)
|
||||
{
|
||||
const unsigned *dwords = (const unsigned *)tokens;
|
||||
int nr = tgsi_num_tokens(tokens);
|
||||
int i;
|
||||
|
||||
assert(sizeof(*tokens) == sizeof(unsigned));
|
||||
|
||||
debug_printf("const unsigned tokens[%d] = {\n", nr);
|
||||
for (i = 0; i < nr; i++)
|
||||
debug_printf("0x%08x,\n", dwords[i]);
|
||||
debug_printf("};\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#ifndef TGSI_PARSE_H
|
||||
#define TGSI_PARSE_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
|
||||
#if defined __cplusplus
|
||||
|
|
@ -132,8 +133,15 @@ void
|
|||
tgsi_parse_token(
|
||||
struct tgsi_parse_context *ctx );
|
||||
|
||||
unsigned
|
||||
tgsi_num_tokens(const struct tgsi_token *tokens);
|
||||
static INLINE unsigned
|
||||
tgsi_num_tokens(const struct tgsi_token *tokens)
|
||||
{
|
||||
struct tgsi_header header = *(const struct tgsi_header *) tokens;
|
||||
return header.HeaderSize + header.BodySize;
|
||||
}
|
||||
|
||||
void
|
||||
tgsi_dump_tokens(const struct tgsi_token *tokens);
|
||||
|
||||
struct tgsi_token *
|
||||
tgsi_dup_tokens(const struct tgsi_token *tokens);
|
||||
|
|
|
|||
|
|
@ -32,9 +32,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
struct tgsi_exec_machine;
|
||||
struct tgsi_interp_coef;
|
||||
struct tgsi_token;
|
||||
struct x86_function;
|
||||
struct tgsi_interp_coef;
|
||||
|
||||
unsigned
|
||||
tgsi_emit_sse2(
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ struct translate *translate_create( const struct translate_key *key )
|
|||
{
|
||||
struct translate *translate = NULL;
|
||||
|
||||
#if defined(PIPE_ARCH_X86)
|
||||
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
|
||||
translate = translate_sse2_create( key );
|
||||
if (translate)
|
||||
return translate;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue