Merge remote branch 'origin/master' into nv50-compiler

Conflicts:
	src/gallium/drivers/nv50/nv50_program.c
This commit is contained in:
Christoph Bumiller 2010-09-02 18:31:49 +02:00
commit 222d2f2ac2
1069 changed files with 116927 additions and 48446 deletions

View file

@ -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 \

View file

@ -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'],

View file

@ -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

View file

@ -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

View file

@ -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@

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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
View 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.

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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&ouml;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&ouml;m of Tungsten Graphics has written a whitepaper
describing the new DRI memory management system</a>.
</p>
<h2>December 5, 2006</h2>

View file

@ -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

View file

@ -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>

View file

@ -16,8 +16,7 @@
</h3>
</center>
</h2>
<p> Copyright &copy; 2002-2003 by <a
href="http://www.tungstengraphics.com/">Tungsten Graphics, Inc.</a>,
<p> Copyright &copy; 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

View file

@ -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

View file

@ -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
View 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_ ]

View file

@ -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_ ]

View file

@ -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 += [

View file

@ -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')

View file

@ -14,7 +14,7 @@ Contact
Status
Preliminary - totally subject to change.
Obsolete.
Version

View file

@ -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;

View file

@ -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)

View file

@ -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
View 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

View file

@ -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

View file

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

View file

@ -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;
}
}

View file

@ -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");

View file

@ -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;

View file

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

View file

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

View file

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

View file

@ -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

View file

@ -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(

View 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

View file

@ -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);

View file

@ -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 );

View file

@ -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);

View file

@ -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;

View file

@ -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) { \

View file

@ -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

View file

@ -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,

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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,

View file

@ -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);
}
}

View file

@ -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

View file

@ -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;
}
}

View file

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

View file

@ -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 ))

View file

@ -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 ))

View file

@ -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;

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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"

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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"

View 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;
}

View 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

View file

@ -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) { \

View 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

View file

@ -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;

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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 &&

View file

@ -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;
}

View file

@ -37,6 +37,8 @@
#define LP_BLD_PACK_H
#include "pipe/p_compiler.h"
#include "gallivm/lp_bld.h"

View file

@ -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;
}

View file

@ -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,

View file

@ -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 &&

View file

@ -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:

View file

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

View 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;
}

View file

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

View file

@ -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,
};

View file

@ -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
};

View file

@ -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)

View 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)

View file

@ -50,8 +50,7 @@
#define PB_BUFMGR_H_
#include "pipe/p_compiler.h"
#include "pipe/p_defines.h"
#include "pb_buffer.h"
#ifdef __cplusplus

View file

@ -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;

View file

@ -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 )

View file

@ -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 );

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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");
}

View file

@ -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);

View file

@ -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(

View file

@ -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