Merge remote branch 'origin/master' into glsl2

This pulls in multiple i965 driver fixes which will help ensure better
testing coverage during development, and also gets past the conflicts
of the src/mesa/shader -> src/mesa/program move.

Conflicts:
	src/mesa/Makefile
	src/mesa/main/shaderapi.c
	src/mesa/main/shaderobj.h
This commit is contained in:
Eric Anholt
2010-07-26 17:47:59 -07:00
798 changed files with 35504 additions and 23336 deletions
+7 -7
View File
@@ -243,13 +243,13 @@ MAIN_FILES = \
$(DIRECTORY)/src/mesa/main/descrip.mms \
$(DIRECTORY)/src/mesa/math/*.[ch] \
$(DIRECTORY)/src/mesa/math/descrip.mms \
$(DIRECTORY)/src/mesa/shader/*.[chly] \
$(DIRECTORY)/src/mesa/shader/Makefile \
$(DIRECTORY)/src/mesa/shader/descrip.mms \
$(DIRECTORY)/src/mesa/shader/slang/*.[ch] \
$(DIRECTORY)/src/mesa/shader/slang/descrip.mms \
$(DIRECTORY)/src/mesa/shader/slang/library/*.gc \
$(DIRECTORY)/src/mesa/shader/slang/library/Makefile \
$(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] \
+2
View File
@@ -131,6 +131,8 @@ if 'trace' not in env['drivers']:
env['drivers'].append('trace')
if 'rbug' not in env['drivers']:
env['drivers'].append('rbug')
if 'galahad' not in env['drivers']:
env['drivers'].append('galahad')
if 'identity' not in env['drivers']:
env['drivers'].append('identity')
if 'softpipe' not in env['drivers']:
+1 -1
View File
@@ -87,7 +87,7 @@ def AddOptions(opts):
opts.Add(EnumOption('machine', 'use machine-specific assembly code', default_machine,
allowed_values=('generic', 'ppc', 'x86', 'x86_64')))
opts.Add(EnumOption('platform', 'target platform', default_platform,
allowed_values=('linux', 'cell', 'windows', 'winddk', 'wince', 'darwin', 'embedded', 'cygwin')))
allowed_values=('linux', 'cell', 'windows', 'winddk', 'wince', 'darwin', 'embedded', 'cygwin', 'sunos5')))
opts.Add('toolchain', 'compiler toolchain', 'default')
opts.Add(BoolOption('llvm', 'use LLVM', default_llvm))
opts.Add(BoolOption('dri', 'build DRI drivers', default_dri))
+8 -2
View File
@@ -31,7 +31,11 @@ X11_CFLAGS = @X11_CFLAGS@
LLVM_CFLAGS = @LLVM_CFLAGS@
LLVM_LDFLAGS = @LLVM_LDFLAGS@
LLVM_LIBS = @LLVM_LIBS@
GLW_CFLAGS = @GLW_CFLAGS@
GLUT_CFLAGS = @GLUT_CFLAGS@
# dlopen
DLOPEN_LIBS = @DLOPEN_LIBS@
# Source selection
MESA_ASM_SOURCES = @MESA_ASM_SOURCES@
@@ -176,8 +180,10 @@ EGL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@
EGL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@
EGL_PC_CFLAGS = @GL_PC_CFLAGS@
EGL_DRI2_CFLAGS = @EGL_DRI2_CFLAGS@
EGL_DRI2_LIBS = @EGL_DRI2_LIBS@
XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@
XCB_DRI2_LIBS = @XCB_DRI2_LIBS@
LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@
LIBUDEV_LIBS = @LIBUDEV_LIBS@
MESA_LLVM = @MESA_LLVM@
+2
View File
@@ -131,6 +131,8 @@ VG_LIB_DEPS = $(EXTRA_LIB_PATH) -lpthread
APP_LIB_DEPS = -lm
X11_LIBS = -lX11
DLOPEN_LIBS = -ldl
# Installation directories (for make install)
INSTALL_DIR = /usr/local
INSTALL_LIB_DIR = $(INSTALL_DIR)/$(LIB_DIR)
+61 -36
View File
@@ -410,6 +410,7 @@ dnl Check to see if dlopen is in default libraries (like Solaris, which
dnl has it in libc), or if libdl is needed to get it.
AC_CHECK_FUNC([dlopen], [],
[AC_CHECK_LIB([dl], [dlopen], [DLOPEN_LIBS="-ldl"])])
AC_SUBST([DLOPEN_LIBS])
dnl See if posix_memalign is available
AC_CHECK_FUNC([posix_memalign], [DEFINES="$DEFINES -DHAVE_POSIX_MEMALIGN"])
@@ -476,7 +477,7 @@ GLU_DIRS="sgi"
GALLIUM_DIRS="auxiliary drivers state_trackers"
GALLIUM_TARGET_DIRS=""
GALLIUM_WINSYS_DIRS="sw"
GALLIUM_DRIVERS_DIRS="softpipe failover trace rbug identity"
GALLIUM_DRIVERS_DIRS="softpipe failover galahad trace rbug identity"
GALLIUM_STATE_TRACKERS_DIRS=""
case "$mesa_driver" in
@@ -488,7 +489,7 @@ xlib)
dri)
SRC_DIRS="$SRC_DIRS glx"
DRIVER_DIRS="dri"
GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/xlib sw/dri sw/drm"
GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/xlib sw/dri"
;;
osmesa)
DRIVER_DIRS="osmesa"
@@ -682,7 +683,7 @@ AC_SUBST([DRI_DRIVER_SEARCH_DIR])
dnl Direct rendering or just indirect rendering
AC_ARG_ENABLE([driglx-direct],
[AS_HELP_STRING([--disable-driglx-direct],
[enable direct rendering in GLX for DRI @<:@default=enabled@:>@])],
[enable direct rendering in GLX and EGL for DRI @<:@default=enabled@:>@])],
[driglx_direct="$enableval"],
[driglx_direct="yes"])
dnl Which drivers to build - default is chosen by platform
@@ -963,12 +964,23 @@ if test "x$enable_egl" = xyes; then
EGL_DRIVERS_DIRS="glx"
fi
# build egl_dri2 when xcb-dri2 is available
PKG_CHECK_MODULES([EGL_DRI2], [x11-xcb xcb-dri2 xcb-xfixes libdrm],
[have_xcb_dri2=yes],[have_xcb_dri2=no])
if test "$have_xcb_dri2" = yes; then
EGL_DRIVERS_DIRS="$EGL_DRIVERS_DIRS dri2"
fi
if test "$mesa_driver" = dri; then
# build egl_dri2 when xcb-dri2 is available
PKG_CHECK_MODULES([XCB_DRI2], [x11-xcb xcb-dri2 xcb-xfixes],
[have_xcb_dri2=yes],[have_xcb_dri2=no])
PKG_CHECK_MODULES([LIBUDEV], [libudev > 150],
[have_libudev=yes],[have_libudev=no])
if test "$have_xcb_dri2" = yes; then
EGL_DRIVER_DRI2=dri2
DEFINES="$DEFINES -DHAVE_XCB_DRI2"
if test "$have_libudev" = yes; then
DEFINES="$DEFINES -DHAVE_LIBUDEV"
fi
fi
fi
EGL_DRIVERS_DIRS="$EGL_DRIVERS_DIRS $EGL_DRIVER_DRI2"
fi
fi
AC_SUBST([EGL_LIB_DEPS])
@@ -1120,10 +1132,6 @@ fi
if test "x$enable_glut" = xyes; then
SRC_DIRS="$SRC_DIRS glut/glx"
GLUT_CFLAGS=""
if test "x$GCC" = xyes; then
GLUT_CFLAGS="-fexceptions"
fi
if test "$x11_pkgconfig" = yes; then
PKG_CHECK_MODULES([GLUT],[x11 xmu xi])
GLUT_PC_REQ_PRIV="x11 xmu xi"
@@ -1134,6 +1142,9 @@ if test "x$enable_glut" = xyes; then
GLUT_PC_LIB_PRIV="$GLUT_LIB_DEPS"
GLUT_PC_CFLAGS="$X11_INCLUDES"
fi
if test "x$GCC" = xyes; then
GLUT_CFLAGS="$GLUT_CFLAGS -fexceptions"
fi
GLUT_LIB_DEPS="$GLUT_LIB_DEPS -lm"
GLUT_PC_LIB_PRIV="$GLUT_PC_LIB_PRIV -lm"
@@ -1253,6 +1264,7 @@ yes)
HAVE_ST_EGL="yes"
;;
xorg)
PKG_CHECK_MODULES([XORG], [xorg-server >= 1.6.0])
PKG_CHECK_MODULES([LIBDRM_XORG], [libdrm >= $LIBDRM_XORG_REQUIRED])
PKG_CHECK_MODULES([LIBKMS_XORG], [libkms >= $LIBKMS_XORG_REQUIRED])
HAVE_ST_XORG="yes"
@@ -1294,7 +1306,11 @@ AC_SUBST([VG_LIB_DEPS])
AC_SUBST([EGL_CLIENT_APIS])
if test "x$HAVE_ST_EGL" = xyes; then
GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS egl-apis"
GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS egl"
# define GLX_DIRECT_RENDERING even when the driver is not dri
if test "x$mesa_driver" != xdri -a "x$driglx_direct" = xyes; then
DEFINES="$DEFINES -DGLX_DIRECT_RENDERING"
fi
fi
if test "x$HAVE_ST_XORG" = xyes; then
@@ -1401,18 +1417,15 @@ dnl
dnl Gallium helper functions
dnl
gallium_check_st() {
if test "x$HAVE_ST_DRI" = xyes || test "x$HAVE_ST_EGL" = xyes || test "x$HAVE_ST_XORG" = xyes; then
if test "x$HAVE_ST_DRI" = xyes || test "x$HAVE_ST_XORG" = xyes; then
GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS $1"
fi
if test "x$HAVE_ST_DRI" = xyes && test "x$2" != x; then
GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $2"
fi
if test "x$HAVE_ST_EGL" = xyes && test "x$3" != x; then
if test "x$HAVE_ST_XORG" = xyes && test "x$3" != x; then
GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $3"
fi
if test "x$HAVE_ST_XORG" = xyes && test "x$4" != x; then
GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $4"
fi
}
@@ -1426,26 +1439,41 @@ AC_ARG_ENABLE([gallium-svga],
[enable_gallium_svga=auto])
if test "x$enable_gallium_svga" = xyes; then
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS svga"
gallium_check_st "svga/drm" "dri-vmwgfx" "egl-vmwgfx" "xorg-vmwgfx"
gallium_check_st "svga/drm" "dri-vmwgfx" "xorg-vmwgfx"
elif test "x$enable_gallium_svga" = xauto; then
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS svga"
fi
dnl
dnl Gallium Intel configuration
dnl Gallium i915 configuration
dnl
AC_ARG_ENABLE([gallium-intel],
[AS_HELP_STRING([--enable-gallium-intel],
[build gallium intel @<:@default=disabled@:>@])],
[enable_gallium_intel="$enableval"],
[enable_gallium_intel=auto])
if test "x$enable_gallium_intel" = xyes; then
AC_ARG_ENABLE([gallium-i915],
[AS_HELP_STRING([--enable-gallium-i915],
[build gallium i915 @<:@default=disabled@:>@])],
[enable_gallium_i915="$enableval"],
[enable_gallium_i915=auto])
if test "x$enable_gallium_i915" = xyes; then
GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS i915/sw"
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915 i965"
gallium_check_st "i915/drm i965/drm" "dri-i915 dri-i965" "egl-i915 egl-i965" "xorg-i915 xorg-i965"
elif test "x$enable_gallium_intel" = xauto; then
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915"
gallium_check_st "i915/drm" "dri-i915" "xorg-i915"
elif test "x$enable_gallium_i915" = xauto; then
GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS i915/sw"
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915 i965"
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915"
fi
dnl
dnl Gallium i965 configuration
dnl
AC_ARG_ENABLE([gallium-i965],
[AS_HELP_STRING([--enable-gallium-i965],
[build gallium i965 @<:@default=disabled@:>@])],
[enable_gallium_i965="$enableval"],
[enable_gallium_i965=auto])
if test "x$enable_gallium_i965" = xyes; then
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i965"
gallium_check_st "i965/drm" "dri-i965" "xorg-i965"
elif test "x$enable_gallium_i965" = xauto; then
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i965"
fi
dnl
@@ -1458,7 +1486,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" "egl-radeon" "xorg-radeon"
gallium_check_st "radeon/drm" "dri-radeong" "xorg-radeon"
elif test "x$enable_gallium_radeon" = xauto; then
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300"
fi
@@ -1486,7 +1514,7 @@ AC_ARG_ENABLE([gallium-nouveau],
[enable_gallium_nouveau=no])
if test "x$enable_gallium_nouveau" = xyes; then
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau nvfx nv50"
gallium_check_st "nouveau/drm" "dri-nouveau" "egl-nouveau" "xorg-nouveau"
gallium_check_st "nouveau/drm" "dri-nouveau" "xorg-nouveau"
fi
dnl
@@ -1501,9 +1529,6 @@ if test "x$enable_gallium_swrast" = xyes || test "x$enable_gallium_swrast" = xau
if test "x$HAVE_ST_DRI" = xyes; then
GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS dri-swrast"
fi
if test "x$HAVE_ST_EGL" = xyes; then
GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS egl-swrast"
fi
fi
dnl prepend CORE_DIRS to SRC_DIRS
+19 -50
View File
@@ -32,7 +32,7 @@ cards.</p>
the Gallium driver for your hardware. For example</p>
<pre>
$ ./configure --enable-gles-overlay --with-state-trackers=egl,vega --enable-gallium-{swrast,intel}
$ ./configure --enable-gles-overlay --with-state-trackers=egl,vega --enable-gallium-intel
</pre>
<p>The main library and OpenGL is enabled by default. The first option enables
@@ -71,12 +71,12 @@ drivers will be installed to <code>${libdir}/egl</code>.</p>
<li><code>--with-egl-platforms</code>
<p>List the native platform window system(s) to support. It is by default
<code>x11</code>, which supports the X Window System. Its argument is a comma
separated string like, for example, <code>--with-egl-platforms=x11,kms</code>.
Because an EGL driver decides which window system to support, this example will
enable two (sets of) EGL drivers. One supports the X window system and the
other supports bare KMS (kernel modesetting).</p>
<p>List the platforms (window systems) to support. Its argument is a comma
seprated string such as <code>--with-egl-platforms=x11,kms</code>. It decides
the platforms a driver may support. The first listed platform is also used by
the main library to decide the native platform: the platform the EGL native
types such as <code>EGLNativeDisplayType</code> or
<code>EGLNativeWindowType</code> defined for.</p>
<p>The available platforms are <code>x11</code>, <code>kms</code>,
<code>fbdev</code>, and <code>gdi</code>. The <code>gdi</code> platform can
@@ -87,9 +87,8 @@ only be built with SCons.</p>
<li><code>--with-state-trackers</code>
<p>The argument is a comma separated string. It is usually used to specify the
rendering APIs, such as OpenVG, to build. But it should be noted that a number
of EGL drivers depend on the <code>egl</code> state tracker. They will
<em>not</em> be built without the <code>egl</code> state tracker.</p>
rendering APIs, such as OpenVG, to build. But it is also used to specify
<code>egl</code> state tracker that <code>egl_gallium</code> depends on.</p>
</li>
@@ -105,19 +104,10 @@ ES, this option must be explicitly given.</p>
<p>Unlike <code>--enable-gles-overlay</code>, which builds one library for each
rendering API, these options enable OpenGL ES support in OpenGL. The result is
one big library that supports multiple APIs. This is used by DRI drivers and
<code>egl_dri2</code> EGL driver.
one big library that supports multiple APIs.</p>
</li>
<li><code>--enable-gallium-swrast</code>
<p>This option is not specific to EGL. But if there is no driver for your
hardware, or you are experiencing problems with the hardware driver, you can
enable the swrast DRM driver. It is a dummy driver and EGL will fallback to
software rendering automatically.</p>
</li>
</ul>
<h2>Use EGL</h2>
@@ -153,12 +143,10 @@ specific driver. This variable is ignored for setuid/setgid binaries.</p>
<li><code>EGL_PLATFORM</code>
<p>When <code>EGL_DRIVER</code> is not set, the main library loads <em>all</em>
EGL drivers that support a certain window system. <code>EGL_PLATFORM</code>
can be used to specify the window system and the valid values are, for example,
<code>x11</code> or <code>kms</code>. When the variable is not set, the main
library defaults the value to the first window system listed in
<code>--with-egl-platforms</code> at configuration time.
<p>This variable specifies the native platform. The valid values are the same
as those for <code>--with-egl-platforms</code>. When the variable is not set,
the main library uses the first platform listed in
<code>--with-egl-platforms</code> as the native platform</p>
</li>
@@ -180,31 +168,15 @@ variable to true forces the use of software rendering.</p>
<h2>EGL Drivers</h2>
<p>There are two categories of EGL drivers: Gallium and classic.</p>
<p>Gallium EGL drivers supports all rendering APIs specified in EGL 1.4. These
drivers depend on the <code>egl</code> state tracker to build. The available
drivers are</p>
<ul>
<li><code>egl_&lt;dpy&gt;_i915</code></li>
<li><code>egl_&lt;dpy&gt;_i965</code></li>
<li><code>egl_&lt;dpy&gt;_nouveau</code></li>
<li><code>egl_&lt;dpy&gt;_radeon</code></li>
<li><code>egl_&lt;dpy&gt;_swrast</code></li>
<li><code>egl_&lt;dpy&gt;_vmwgfx</code></li>
</ul>
<li><code>egl_gallium</code>
<p><code>&lt;dpy&gt;</code> is given by <code>--with-egl-platforms</code> at
configuration time. There is usually one EGL driver for each combination of
the platforms listed and the pipe drivers enabled. When the platform is pure
software or pure hardware, non-working combinations will not be built.</p>
<p>This driver is based on Gallium3D. It supports all rendering APIs and
hardwares supported by Gallium3D. It is the only driver that supports OpenVG.
The supported platforms are X11, KMS, FBDEV, and GDI.</p>
<p>Classic EGL drivers, on the other hand, support only a subset of the
available rendering APIs. They can be found under
<code>src/egl/drivers/</code>. There are 3 of them</p>
</li>
<ul>
<li><code>egl_glx</code>
<p>This driver provides a wrapper to GLX. It uses exclusively GLX to implement
@@ -231,9 +203,6 @@ are phasing out, it might eventually be replaced by <code>egl_dri2</code>.</p>
</li>
</ul>
<p>To use the classic drivers, one must manually set <code>EGL_DRIVER</code> at
runtime.</p>
<h2>Developers</h2>
<p>The sources of the main library and the classic drivers can be found at
+2
View File
@@ -36,6 +36,8 @@ tbd
<ul>
<li>GL_EXT_timer_query extension (i965 driver only)
<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
</ul>
+11
View File
@@ -208,6 +208,17 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLCOPYCONTEXTMESA) (EGLDisplay dpy, EGLCont
#endif /* EGL_MESA_copy_context */
#ifndef EGL_MESA_drm_display
#define EGL_MESA_drm_display 1
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLDisplay EGLAPIENTRY eglGetDRMDisplayMESA(int fd);
#endif /* EGL_EGLEXT_PROTOTYPES */
typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETDRMDISPLAYMESA) (int fd);
#endif /* EGL_MESA_drm_display */
#ifndef EGL_KHR_image_base
#define EGL_KHR_image_base 1
/* Most interfaces defined by EGL_KHR_image_pixmap above */
+10
View File
@@ -80,6 +80,14 @@ typedef void *EGLNativePixmapType;
#elif defined(__unix__) || defined(__unix)
#ifdef MESA_EGL_NO_X11_HEADERS
typedef void *EGLNativeDisplayType;
typedef khronos_uint32_t EGLNativePixmapType;
typedef khronos_uint32_t EGLNativeWindowType;
#else
/* X11 (tentative) */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -88,6 +96,8 @@ typedef Display *EGLNativeDisplayType;
typedef Pixmap EGLNativePixmapType;
typedef Window EGLNativeWindowType;
#endif /* MESA_EGL_NO_X11_HEADERS */
#else
#error "Platform not recognized"
#endif
-16
View File
@@ -367,22 +367,6 @@ typedef void ( * PFNGLXFREEMEMORYNVPROC) (GLvoid *pointer);
#endif /* GLX_NV_vertex_array_range */
/*
* ???. GLX_MESA_allocate_memory
*/
#ifndef GLX_MESA_allocate_memory
#define GLX_MESA_allocate_memory 1
extern void *glXAllocateMemoryMESA(Display *dpy, int scrn, size_t size, float readfreq, float writefreq, float priority);
extern void glXFreeMemoryMESA(Display *dpy, int scrn, void *pointer);
extern GLuint glXGetMemoryOffsetMESA(Display *dpy, int scrn, const void *pointer);
typedef void * ( * PFNGLXALLOCATEMEMORYMESAPROC) (Display *dpy, int scrn, size_t size, float readfreq, float writefreq, float priority);
typedef void ( * PFNGLXFREEMEMORYMESAPROC) (Display *dpy, int scrn, void *pointer);
typedef GLuint (* PFNGLXGETMEMORYOFFSETMESAPROC) (Display *dpy, int scrn, const void *pointer);
#endif /* GLX_MESA_allocate_memory */
/*
* ARB ?. GLX_ARB_render_texture
* XXX This was never finalized!
-18
View File
@@ -74,7 +74,6 @@ typedef struct __DRIcoreExtensionRec __DRIcoreExtension;
typedef struct __DRIextensionRec __DRIextension;
typedef struct __DRIcopySubBufferExtensionRec __DRIcopySubBufferExtension;
typedef struct __DRIswapControlExtensionRec __DRIswapControlExtension;
typedef struct __DRIallocateExtensionRec __DRIallocateExtension;
typedef struct __DRIframeTrackingExtensionRec __DRIframeTrackingExtension;
typedef struct __DRImediaStreamCounterExtensionRec __DRImediaStreamCounterExtension;
typedef struct __DRItexOffsetExtensionRec __DRItexOffsetExtension;
@@ -149,23 +148,6 @@ struct __DRIswapControlExtensionRec {
unsigned int (*getSwapInterval)(__DRIdrawable *drawable);
};
/**
* Used by drivers that implement the GLX_MESA_allocate_memory.
*/
#define __DRI_ALLOCATE "DRI_Allocate"
#define __DRI_ALLOCATE_VERSION 1
struct __DRIallocateExtensionRec {
__DRIextension base;
void *(*allocateMemory)(__DRIscreen *screen, GLsizei size,
GLfloat readfreq, GLfloat writefreq,
GLfloat priority);
void (*freeMemory)(__DRIscreen *screen, GLvoid *pointer);
GLuint (*memoryOffset)(__DRIscreen *screen, const GLvoid *pointer);
};
/**
* Used by drivers that implement the GLX_MESA_swap_frame_usage extension.
*/
+7 -1
View File
@@ -282,6 +282,9 @@ def generate(env):
ccflags += [
'-mmmx', '-msse', '-msse2', # enable SIMD intrinsics
]
if platform in ['windows', 'darwin']:
# Workaround http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37216
ccflags += ['-fno-common']
if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('4.2'):
ccflags += [
'-mstackrealign', # ensure stack is aligned
@@ -292,7 +295,6 @@ def generate(env):
# - http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
ccflags += [
'-Wall',
'-Wmissing-field-initializers',
'-Wno-long-long',
'-ffast-math',
'-fmessage-length=0', # be nice to Eclipse
@@ -301,6 +303,10 @@ def generate(env):
'-Wmissing-prototypes',
'-std=gnu99',
]
if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('4.0'):
ccflags += [
'-Wmissing-field-initializers',
]
if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('4.2'):
ccflags += [
'-Werror=pointer-arith',
-1
View File
@@ -36,7 +36,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* THIS IS NOT AN X CONSORTIUM STANDARD */
#define NEED_REPLIES
#include <X11/Xlibint.h>
#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>
+4 -2
View File
@@ -11,8 +11,10 @@ EGL_INCLUDES = \
-I$(TOP)/src/egl/main \
-I$(TOP)/src/mapi \
-DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" \
$(EGL_DRI2_CFLAGS)
$(XCB_DRI2_CFLAGS) \
$(LIBUDEV_CFLAGS) \
$(LIBDRM_CFLAGS)
EGL_LIBS = $(EGL_DRI2_LIBS)
EGL_LIBS = $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(LIBDRM_LIBS)
include ../Makefile.template
+226 -42
View File
@@ -40,6 +40,12 @@
#include <xcb/dri2.h>
#include <xcb/xfixes.h>
#include <X11/Xlib-xcb.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_LIBUDEV
#include <libudev.h>
#endif
#include <glapi/glapi.h>
#include "eglconfig.h"
@@ -79,7 +85,6 @@ struct dri2_egl_display
char *driver_name;
__DRIdri2LoaderExtension loader_extension;
__DRIimageLookupExtension image_lookup_extension;
const __DRIextension *extensions[3];
};
@@ -117,6 +122,10 @@ struct dri2_egl_image
_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl)
_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
static const __DRIuseInvalidateExtension use_invalidate = {
{ __DRI_USE_INVALIDATE, 1 }
};
EGLint dri2_to_egl_attribute_map[] = {
0,
EGL_BUFFER_SIZE, /* __DRI_ATTRIB_BUFFER_SIZE */
@@ -381,6 +390,11 @@ dri2_lookup_egl_image(__DRIcontext *context, void *image, void *data)
return dri2_img->dri_image;
}
static const __DRIimageLookupExtension image_lookup_extension = {
{ __DRI_IMAGE_LOOKUP, 1 },
dri2_lookup_egl_image
};
static __DRIbuffer *
dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
int *width, int *height,
@@ -620,7 +634,7 @@ dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
xcb_depth_next(&d);
}
if (!disp->NumConfigs) {
if (!_eglGetArraySize(disp->Configs)) {
_eglLog(_EGL_WARNING, "DRI2: failed to create any config");
return EGL_FALSE;
}
@@ -690,27 +704,63 @@ dri2_load_driver(_EGLDisplay *disp)
return EGL_TRUE;
}
/**
* Called via eglInitialize(), GLX_drv->API.Initialize().
*/
static EGLBoolean
dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
EGLint *major, EGLint *minor)
dri2_create_screen(_EGLDisplay *disp)
{
const __DRIextension **extensions;
struct dri2_egl_display *dri2_dpy;
unsigned int api_mask;
dri2_dpy = disp->DriverData;
dri2_dpy->dri_screen =
dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
&dri2_dpy->driver_configs, dri2_dpy);
if (dri2_dpy->dri_screen == NULL) {
_eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
return EGL_FALSE;
}
extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
goto cleanup_dri_screen;
if (dri2_dpy->dri2->base.version >= 2)
api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
else
api_mask = __DRI_API_OPENGL;
disp->ClientAPIsMask = 0;
if (api_mask & (1 <<__DRI_API_OPENGL))
disp->ClientAPIsMask |= EGL_OPENGL_BIT;
if (api_mask & (1 <<__DRI_API_GLES))
disp->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
if (api_mask & (1 << __DRI_API_GLES2))
disp->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
return EGL_TRUE;
cleanup_dri_screen:
dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
return EGL_FALSE;
}
static EGLBoolean
dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp,
EGLint *major, EGLint *minor)
{
struct dri2_egl_display *dri2_dpy;
dri2_dpy = malloc(sizeof *dri2_dpy);
if (!dri2_dpy)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
disp->DriverData = (void *) dri2_dpy;
if (disp->NativeDisplay == NULL) {
if (disp->PlatformDisplay == NULL) {
dri2_dpy->conn = xcb_connect(0, 0);
} else {
dri2_dpy->conn = XGetXCBConnection(disp->NativeDisplay);
dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
}
if (xcb_connection_has_error(dri2_dpy->conn)) {
@@ -754,39 +804,12 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
dri2_dpy->loader_extension.getBuffersWithFormat = NULL;
}
dri2_dpy->image_lookup_extension.base.name = __DRI_IMAGE_LOOKUP;
dri2_dpy->image_lookup_extension.base.version = 1;
dri2_dpy->image_lookup_extension.lookupEGLImage = dri2_lookup_egl_image;
dri2_dpy->extensions[0] = &dri2_dpy->loader_extension.base;
dri2_dpy->extensions[1] = &dri2_dpy->image_lookup_extension.base;
dri2_dpy->extensions[1] = &image_lookup_extension.base;
dri2_dpy->extensions[2] = NULL;
dri2_dpy->dri_screen =
dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
&dri2_dpy->driver_configs, dri2_dpy);
if (dri2_dpy->dri_screen == NULL) {
_eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
if (!dri2_create_screen(disp))
goto cleanup_fd;
}
extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
goto cleanup_dri_screen;
if (dri2_dpy->dri2->base.version >= 2)
api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
else
api_mask = __DRI_API_OPENGL;
disp->ClientAPIsMask = 0;
if (api_mask & (1 <<__DRI_API_OPENGL))
disp->ClientAPIsMask |= EGL_OPENGL_BIT;
if (api_mask & (1 <<__DRI_API_GLES))
disp->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
if (api_mask & (1 << __DRI_API_GLES2))
disp->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
if (dri2_dpy->conn) {
if (!dri2_add_configs_for_visuals(dri2_dpy, disp))
@@ -808,14 +831,13 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
cleanup_configs:
_eglCleanupDisplay(disp);
cleanup_dri_screen:
dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
cleanup_fd:
close(dri2_dpy->fd);
cleanup_driver:
dlclose(dri2_dpy->driver);
cleanup_conn:
if (disp->NativeDisplay == NULL)
if (disp->PlatformDisplay == NULL)
xcb_disconnect(dri2_dpy->conn);
cleanup_dpy:
free(dri2_dpy);
@@ -823,6 +845,168 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
return EGL_FALSE;
}
#ifdef HAVE_LIBUDEV
struct dri2_driver_map {
int vendor_id;
const char *driver;
const int *chip_ids;
int num_chips_ids;
};
const int i915_chip_ids[] = {
0x3577, /* PCI_CHIP_I830_M */
0x2562, /* PCI_CHIP_845_G */
0x3582, /* PCI_CHIP_I855_GM */
0x2572, /* PCI_CHIP_I865_G */
0x2582, /* PCI_CHIP_I915_G */
0x258a, /* PCI_CHIP_E7221_G */
0x2592, /* PCI_CHIP_I915_GM */
0x2772, /* PCI_CHIP_I945_G */
0x27a2, /* PCI_CHIP_I945_GM */
0x27ae, /* PCI_CHIP_I945_GME */
0x29b2, /* PCI_CHIP_Q35_G */
0x29c2, /* PCI_CHIP_G33_G */
0x29d2, /* PCI_CHIP_Q33_G */
};
const int i965_chip_ids[] = {
0x29a2, /* PCI_CHIP_I965_G */
0x2992, /* PCI_CHIP_I965_Q */
0x2982, /* PCI_CHIP_I965_G_1 */
0x2972, /* PCI_CHIP_I946_GZ */
0x2a02, /* PCI_CHIP_I965_GM */
0x2a12, /* PCI_CHIP_I965_GME */
0x2a42, /* PCI_CHIP_GM45_GM */
0x2e02, /* PCI_CHIP_IGD_E_G */
0x2e12, /* PCI_CHIP_Q45_G */
0x2e22, /* PCI_CHIP_G45_G */
0x2e32, /* PCI_CHIP_G41_G */
};
const struct dri2_driver_map driver_map[] = {
{ 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) },
{ 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) },
};
static char *
dri2_get_driver_for_fd(int fd)
{
struct udev *udev;
struct udev_device *device, *parent;
struct stat buf;
const char *pci_id;
char *driver = NULL;
int vendor_id, chip_id, i, j;
udev = udev_new();
if (fstat(fd, &buf) < 0) {
_eglLog(_EGL_WARNING, "EGL-DRI2: failed to stat fd %d", fd);
goto out;
}
device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
if (device == NULL) {
_eglLog(_EGL_WARNING,
"EGL-DRI2: could not create udev device for fd %d", fd);
goto out;
}
parent = udev_device_get_parent(device);
if (parent == NULL) {
_eglLog(_EGL_WARNING, "DRI2: could not get parent device");
goto out;
}
pci_id = udev_device_get_property_value(parent, "PCI_ID");
if (pci_id == NULL || sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) {
_eglLog(_EGL_WARNING, "EGL-DRI2: malformed or no PCI ID");
goto out;
}
for (i = 0; i < ARRAY_SIZE(driver_map); i++) {
if (vendor_id != driver_map[i].vendor_id)
continue;
for (j = 0; j < driver_map[i].num_chips_ids; j++)
if (driver_map[i].chip_ids[j] == chip_id) {
driver = strdup(driver_map[i].driver);
_eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s",
fd, vendor_id, chip_id, driver);
goto out;
}
}
out:
udev_device_unref(device);
udev_unref(udev);
return driver;
}
static EGLBoolean
dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp,
EGLint *major, EGLint *minor)
{
struct dri2_egl_display *dri2_dpy;
dri2_dpy = malloc(sizeof *dri2_dpy);
if (!dri2_dpy)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
disp->DriverData = (void *) dri2_dpy;
dri2_dpy->fd = (int) disp->PlatformDisplay;
dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
if (dri2_dpy->driver_name == NULL)
return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
if (!dri2_load_driver(disp))
goto cleanup_driver_name;
dri2_dpy->extensions[0] = &image_lookup_extension.base;
dri2_dpy->extensions[1] = &use_invalidate.base;
dri2_dpy->extensions[2] = NULL;
if (!dri2_create_screen(disp))
goto cleanup_driver;
disp->Extensions.KHR_image_base = EGL_TRUE;
disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
return EGL_TRUE;
cleanup_driver:
dlclose(dri2_dpy->driver);
cleanup_driver_name:
free(dri2_dpy->driver_name);
return EGL_FALSE;
}
#endif
/**
* Called via eglInitialize(), GLX_drv->API.Initialize().
*/
static EGLBoolean
dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
EGLint *major, EGLint *minor)
{
switch (disp->Platform) {
case _EGL_PLATFORM_X11:
return dri2_initialize_x11(drv, disp, major, minor);
#ifdef HAVE_LIBUDEV
case _EGL_PLATFORM_DRM:
return dri2_initialize_drm(drv, disp, major, minor);
#endif
default:
return EGL_FALSE;
}
}
/**
* Called via eglTerminate(), drv->API.Terminate().
*/
@@ -837,7 +1021,7 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
close(dri2_dpy->fd);
dlclose(dri2_dpy->driver);
if (disp->NativeDisplay == NULL)
if (disp->PlatformDisplay == NULL)
xcb_disconnect(dri2_dpy->conn);
free(dri2_dpy);
disp->DriverData = NULL;
+10 -6
View File
@@ -498,11 +498,14 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
{
struct GLX_egl_display *GLX_dpy;
if (disp->Platform != _EGL_PLATFORM_X11)
return EGL_FALSE;
GLX_dpy = CALLOC_STRUCT(GLX_egl_display);
if (!GLX_dpy)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
GLX_dpy->dpy = (Display *) disp->NativeDisplay;
GLX_dpy->dpy = (Display *) disp->PlatformDisplay;
if (!GLX_dpy->dpy) {
GLX_dpy->dpy = XOpenDisplay(NULL);
if (!GLX_dpy->dpy) {
@@ -514,7 +517,7 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
if (!glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min)) {
_eglLog(_EGL_WARNING, "GLX: glXQueryVersion failed");
if (!disp->NativeDisplay)
if (!disp->PlatformDisplay)
XCloseDisplay(GLX_dpy->dpy);
free(GLX_dpy);
return EGL_FALSE;
@@ -524,9 +527,9 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
check_quirks(GLX_dpy, DefaultScreen(GLX_dpy->dpy));
create_configs(disp, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
if (!disp->NumConfigs) {
if (!_eglGetArraySize(disp->Configs)) {
_eglLog(_EGL_WARNING, "GLX: failed to create any config");
if (!disp->NativeDisplay)
if (!disp->PlatformDisplay)
XCloseDisplay(GLX_dpy->dpy);
free(GLX_dpy);
return EGL_FALSE;
@@ -558,7 +561,7 @@ GLX_eglTerminate(_EGLDriver *drv, _EGLDisplay *disp)
if (GLX_dpy->fbconfigs)
XFree(GLX_dpy->fbconfigs);
if (!disp->NativeDisplay)
if (!disp->PlatformDisplay)
XCloseDisplay(GLX_dpy->dpy);
free(GLX_dpy);
@@ -617,10 +620,11 @@ GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
static void
destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
{
struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
if (GLX_surf->destroy)
GLX_surf->destroy(disp->NativeDisplay, GLX_surf->glx_drawable);
GLX_surf->destroy(GLX_dpy->dpy, GLX_surf->glx_drawable);
free(GLX_surf);
}
+13 -2
View File
@@ -30,6 +30,7 @@ HEADERS = \
SOURCES = \
eglapi.c \
eglarray.c \
eglconfig.c \
eglconfigutil.c \
eglcontext.c \
@@ -51,10 +52,20 @@ OBJECTS = $(SOURCES:.c=.o)
# use dl*() to load drivers
LOCAL_CFLAGS = -D_EGL_OS_UNIX=1
EGL_DEFAULT_PLATFORM = $(firstword $(EGL_PLATFORMS))
# translate --with-egl-platforms to _EGLPlatformType
EGL_NATIVE_PLATFORM=_EGL_INVALID_PLATFORM
ifeq ($(firstword $(EGL_PLATFORMS)),x11)
EGL_NATIVE_PLATFORM=_EGL_PLATFORM_X11
endif
ifeq ($(firstword $(EGL_PLATFORMS)),kms)
EGL_NATIVE_PLATFORM=_EGL_PLATFORM_DRM
endif
ifeq ($(firstword $(EGL_PLATFORMS)),fbdev)
EGL_NATIVE_PLATFORM=_EGL_PLATFORM_FBDEV
endif
LOCAL_CFLAGS += \
-D_EGL_DEFAULT_PLATFORM=\"$(EGL_DEFAULT_PLATFORM)\" \
-D_EGL_NATIVE_PLATFORM=$(EGL_NATIVE_PLATFORM) \
-D_EGL_DRIVER_SEARCH_DIR=\"$(EGL_DRIVER_INSTALL_DIR)\"
.c.o:
+2 -1
View File
@@ -9,7 +9,7 @@ if env['platform'] != 'winddk':
env = env.Clone()
env.Append(CPPDEFINES = [
'_EGL_DEFAULT_DISPLAY=\\"gdi\\"',
'_EGL_NATIVE_PLATFORM=_EGL_PLATFORM_WINDOWS',
'_EGL_DRIVER_SEARCH_DIR=\\"\\"',
'_EGL_OS_WINDOWS',
'KHRONOS_DLL_EXPORTS',
@@ -21,6 +21,7 @@ if env['platform'] != 'winddk':
egl_sources = [
'eglapi.c',
'eglarray.c',
'eglconfig.c',
'eglconfigutil.c',
'eglcontext.c',
+45 -57
View File
@@ -61,7 +61,6 @@
#include "eglcontext.h"
#include "egldisplay.h"
#include "egltypedefs.h"
#include "eglglobals.h"
#include "eglcurrent.h"
#include "egldriver.h"
#include "eglsurface.h"
@@ -250,7 +249,8 @@ _eglUnlockDisplay(_EGLDisplay *dpy)
EGLDisplay EGLAPIENTRY
eglGetDisplay(EGLNativeDisplayType nativeDisplay)
{
_EGLDisplay *dpy = _eglFindDisplay(nativeDisplay);
_EGLPlatformType plat = _eglGetNativePlatform();
_EGLDisplay *dpy = _eglFindDisplay(plat, (void *) nativeDisplay);
return _eglGetDisplayHandle(dpy);
}
@@ -263,46 +263,24 @@ EGLBoolean EGLAPIENTRY
eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
EGLint major_int = 0, minor_int = 0;
if (!disp)
RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
if (!disp->Initialized) {
_EGLDriver *drv = disp->Driver;
if (!drv) {
_eglPreloadDrivers();
drv = _eglMatchDriver(disp);
/* Initialize the particular display now */
if (drv && !drv->API.Initialize(drv, disp, &major_int, &minor_int))
RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
}
if (!drv)
/* Load and initialize the first default driver that works */
drv = _eglLoadDefaultDriver(disp, &major_int, &minor_int);
if (!drv)
RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
disp->APImajor = major_int;
disp->APIminor = minor_int;
_eglsnprintf(disp->Version, sizeof(disp->Version),
"%d.%d (%s)", major_int, minor_int, drv->Name);
if (!_eglMatchDriver(disp, EGL_FALSE))
RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
_eglsnprintf(disp->Version, sizeof(disp->Version), "%d.%d (%s)",
disp->APImajor, disp->APIminor, disp->Driver->Name);
/* limit to APIs supported by core */
disp->ClientAPIsMask &= _EGL_API_ALL_BITS;
disp->Driver = drv;
disp->Initialized = EGL_TRUE;
} else {
major_int = disp->APImajor;
minor_int = disp->APIminor;
}
/* Update applications version of major and minor if not NULL */
if ((major != NULL) && (minor != NULL)) {
*major = major_int;
*minor = minor_int;
*major = disp->APImajor;
*minor = disp->APIminor;
}
RETURN_EGL_SUCCESS(disp, EGL_TRUE);
@@ -491,6 +469,8 @@ eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
EGLSurface ret;
_EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
if (disp->Platform != _eglGetNativePlatform())
RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list);
ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
@@ -510,6 +490,8 @@ eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
EGLSurface ret;
_EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
if (disp->Platform != _eglGetNativePlatform())
RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list);
ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
@@ -667,6 +649,8 @@ eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
EGLBoolean ret;
_EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
if (disp->Platform != _eglGetNativePlatform())
RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE);
ret = drv->API.CopyBuffers(drv, disp, surf, target);
RETURN_EGL_EVAL(disp, ret);
@@ -836,6 +820,9 @@ eglGetProcAddress(const char *procname)
{ "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
{ "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
#endif /* EGL_MESA_screen_surface */
#ifdef EGL_MESA_drm_display
{ "eglGetDRMDisplayMESA", (_EGLProc) eglGetDRMDisplayMESA },
#endif
#ifdef EGL_KHR_image_base
{ "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
{ "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
@@ -860,18 +847,8 @@ eglGetProcAddress(const char *procname)
}
}
}
if (ret)
RETURN_EGL_SUCCESS(NULL, ret);
_eglPreloadDrivers();
/* now loop over drivers to query their procs */
for (i = 0; i < _eglGlobal.NumDrivers; i++) {
_EGLDriver *drv = _eglGlobal.Drivers[i];
ret = drv->API.GetProcAddress(drv, procname);
if (ret)
break;
}
if (!ret)
ret = _eglGetDriverProc(procname);
RETURN_EGL_SUCCESS(NULL, ret);
}
@@ -955,7 +932,7 @@ eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest,
}
EGLBoolean
EGLBoolean EGLAPIENTRY
eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
EGLint max_screens, EGLint *num_screens)
{
@@ -970,7 +947,7 @@ eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
}
EGLSurface
EGLSurface EGLAPIENTRY
eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
const EGLint *attrib_list)
{
@@ -989,7 +966,7 @@ eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
}
EGLBoolean
EGLBoolean EGLAPIENTRY
eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
EGLSurface surface, EGLModeMESA mode)
{
@@ -1012,7 +989,7 @@ eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
}
EGLBoolean
EGLBoolean EGLAPIENTRY
eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
@@ -1027,7 +1004,7 @@ eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
}
EGLBoolean
EGLBoolean EGLAPIENTRY
eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
EGLint attribute, EGLint *value)
{
@@ -1043,7 +1020,7 @@ eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
}
EGLBoolean
EGLBoolean EGLAPIENTRY
eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
EGLSurface *surface)
{
@@ -1062,7 +1039,7 @@ eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
}
EGLBoolean
EGLBoolean EGLAPIENTRY
eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
@@ -1080,7 +1057,7 @@ eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
}
const char *
const char * EGLAPIENTRY
eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
@@ -1098,6 +1075,17 @@ eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
#endif /* EGL_MESA_screen_surface */
#ifdef EGL_MESA_drm_display
EGLDisplay EGLAPIENTRY
eglGetDRMDisplayMESA(int fd)
{
_EGLDisplay *dpy = _eglFindDisplay(_EGL_PLATFORM_DRM, (void *) fd);
return _eglGetDisplayHandle(dpy);
}
#endif /* EGL_MESA_drm_display */
/**
** EGL 1.2
**/
@@ -1116,7 +1104,7 @@ eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
* eglWaitNative()
* See section 3.7 "Rendering Context" in the EGL specification for details.
*/
EGLBoolean
EGLBoolean EGLAPIENTRY
eglBindAPI(EGLenum api)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
@@ -1136,7 +1124,7 @@ eglBindAPI(EGLenum api)
/**
* Return the last value set with eglBindAPI().
*/
EGLenum
EGLenum EGLAPIENTRY
eglQueryAPI(void)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
@@ -1149,7 +1137,7 @@ eglQueryAPI(void)
}
EGLSurface
EGLSurface EGLAPIENTRY
eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
EGLClientBuffer buffer, EGLConfig config,
const EGLint *attrib_list)
@@ -1170,7 +1158,7 @@ eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
}
EGLBoolean
EGLBoolean EGLAPIENTRY
eglReleaseThread(void)
{
/* unbind current contexts */
@@ -1209,7 +1197,7 @@ eglReleaseThread(void)
#ifdef EGL_KHR_image_base
EGLImageKHR
EGLImageKHR EGLAPIENTRY
eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
EGLClientBuffer buffer, const EGLint *attr_list)
{
@@ -1231,7 +1219,7 @@ eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
}
EGLBoolean
EGLBoolean EGLAPIENTRY
eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
@@ -1255,7 +1243,7 @@ eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
#ifdef EGL_NOK_swap_region
EGLBoolean
EGLBoolean EGLAPIENTRY
eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
EGLint numRects, const EGLint *rects)
{
+180
View File
@@ -0,0 +1,180 @@
#include <stdlib.h>
#include <string.h>
#include "egllog.h"
#include "eglarray.h"
/**
* Grow the size of the array.
*/
static EGLBoolean
_eglGrowArray(_EGLArray *array)
{
EGLint new_size;
void **elems;
new_size = array->MaxSize;
while (new_size <= array->Size)
new_size *= 2;
elems = realloc(array->Elements, new_size * sizeof(array->Elements[0]));
if (!elems) {
_eglLog(_EGL_DEBUG, "failed to grow %s array to %d",
array->Name, new_size);
return EGL_FALSE;
}
array->Elements = elems;
array->MaxSize = new_size;
return EGL_TRUE;
}
/**
* Create an array.
*/
_EGLArray *
_eglCreateArray(const char *name, EGLint init_size)
{
_EGLArray *array;
array = calloc(1, sizeof(*array));
if (array) {
array->Name = name;
array->MaxSize = (init_size > 0) ? init_size : 1;
if (!_eglGrowArray(array)) {
free(array);
array = NULL;
}
}
return array;
}
/**
* Destroy an array, optionally free the data.
*/
void
_eglDestroyArray(_EGLArray *array, void (*free_cb)(void *))
{
if (free_cb) {
EGLint i;
for (i = 0; i < array->Size; i++)
free_cb(array->Elements[i]);
}
free(array->Elements);
free(array);
}
/**
* Append a element to an array.
*/
void
_eglAppendArray(_EGLArray *array, void *elem)
{
if (array->Size >= array->MaxSize && !_eglGrowArray(array))
return;
array->Elements[array->Size++] = elem;
}
/**
* Erase an element from an array.
*/
void
_eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *))
{
if (free_cb)
free_cb(array->Elements[i]);
if (i < array->Size - 1) {
memmove(&array->Elements[i], &array->Elements[i + 1],
(array->Size - i - 1) * sizeof(array->Elements[0]));
}
array->Size--;
}
/**
* Find in an array for the given element.
*/
void *
_eglFindArray(_EGLArray *array, void *elem)
{
EGLint i;
if (!array)
return NULL;
for (i = 0; i < array->Size; i++)
if (array->Elements[i] == elem)
return elem;
return NULL;
}
/**
* Filter an array and return the filtered data. The returned data pointer
* should be freed.
*/
void **
_eglFilterArray(_EGLArray *array, EGLint *size,
_EGLArrayForEach filter, void *filter_data)
{
void **data;
EGLint count = 0, i;
if (!array) {
*size = 0;
return malloc(0);
}
data = malloc(array->Size * sizeof(array->Elements[0]));
if (!data)
return NULL;
if (filter) {
for (i = 0; i < array->Size; i++) {
if (filter(array->Elements[i], filter_data))
data[count++] = array->Elements[i];
}
}
else {
memcpy(data, array->Elements, array->Size * sizeof(array->Elements[0]));
}
*size = count;
return data;
}
/**
* Flatten an array by converting array elements into another form and store
* them in a buffer.
*/
EGLint
_eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
_EGLArrayForEach flatten)
{
EGLint i, count;
if (!array)
return 0;
count = array->Size;
if (buffer) {
/* do not exceed buffer size */
if (count > size)
count = size;
for (i = 0; i < count; i++)
flatten(array->Elements[i],
(void *) ((char *) buffer + elem_size * i));
}
return count;
}
+57
View File
@@ -0,0 +1,57 @@
#ifndef EGLARRAY_INCLUDED
#define EGLARRAY_INCLUDED
#include "egltypedefs.h"
typedef EGLBoolean (*_EGLArrayForEach)(void *elem, void *foreach_data);
struct _egl_array {
const char *Name;
EGLint MaxSize;
void **Elements;
EGLint Size;
};
extern _EGLArray *
_eglCreateArray(const char *name, EGLint init_size);
PUBLIC void
_eglDestroyArray(_EGLArray *array, void (*free_cb)(void *));
extern void
_eglAppendArray(_EGLArray *array, void *elem);
extern void
_eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *));
void *
_eglFindArray(_EGLArray *array, void *elem);
void **
_eglFilterArray(_EGLArray *array, EGLint *size,
_EGLArrayForEach filter, void *filter_data);
EGLint
_eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
_EGLArrayForEach flatten);
static INLINE EGLint
_eglGetArraySize(_EGLArray *array)
{
return (array) ? array->Size : 0;
}
#endif /* EGLARRAY_INCLUDED */
+23 -43
View File
@@ -50,26 +50,17 @@ _eglInitConfig(_EGLConfig *config, _EGLDisplay *dpy, EGLint id)
EGLConfig
_eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf)
{
_EGLConfig **configs;
/* sanity check */
assert(GET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID) > 0);
configs = dpy->Configs;
if (dpy->NumConfigs >= dpy->MaxConfigs) {
EGLint new_size = dpy->MaxConfigs + 16;
assert(dpy->NumConfigs < new_size);
configs = realloc(dpy->Configs, new_size * sizeof(dpy->Configs[0]));
if (!configs)
if (!dpy->Configs) {
dpy->Configs = _eglCreateArray("Config", 16);
if (!dpy->Configs)
return (EGLConfig) NULL;
dpy->Configs = configs;
dpy->MaxConfigs = new_size;
}
conf->Display = dpy;
dpy->Configs[dpy->NumConfigs++] = conf;
_eglAppendArray(dpy->Configs, (void *) conf);
return (EGLConfig) conf;
}
@@ -78,17 +69,13 @@ _eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf)
EGLBoolean
_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy)
{
EGLint num_configs = (dpy) ? dpy->NumConfigs : 0;
EGLint i;
_EGLConfig *conf;
for (i = 0; i < num_configs; i++) {
_EGLConfig *conf = dpy->Configs[i];
if (conf == (_EGLConfig *) config) {
assert(conf->Display == dpy);
break;
}
}
return (i < num_configs);
conf = (_EGLConfig *) _eglFindArray(dpy->Configs, (void *) config);
if (conf)
assert(conf->Display == dpy);
return (conf != NULL);
}
@@ -776,19 +763,11 @@ _eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
if (!_eglParseConfigAttribList(&criteria, attrib_list))
return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
/* allocate array of config pointers */
configList = (_EGLConfig **)
malloc(disp->NumConfigs * sizeof(_EGLConfig *));
configList = (_EGLConfig **) _eglFilterArray(disp->Configs, &count,
(_EGLArrayForEach) _eglMatchConfig, (void *) &criteria);
if (!configList)
return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
/* perform selection of configs */
count = 0;
for (i = 0; i < disp->NumConfigs; i++) {
if (_eglMatchConfig(disp->Configs[i], &criteria))
configList[count++] = disp->Configs[i];
}
/* perform sorting of configs */
if (configs && count) {
_eglSortConfigs((const _EGLConfig **) configList, count,
@@ -823,6 +802,15 @@ _eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
}
static EGLBoolean
_eglFlattenConfig(void *elem, void *buffer)
{
_EGLConfig *conf = (_EGLConfig *) elem;
EGLConfig *handle = (EGLConfig *) buffer;
*handle = _eglGetConfigHandle(conf);
return EGL_TRUE;
}
/**
* Fallback for eglGetConfigs.
*/
@@ -833,16 +821,8 @@ _eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs,
if (!num_config)
return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs");
if (configs) {
EGLint i;
*num_config = MIN2(disp->NumConfigs, config_size);
for (i = 0; i < *num_config; i++)
configs[i] = _eglGetConfigHandle(disp->Configs[i]);
}
else {
/* just return total number of supported configs */
*num_config = disp->NumConfigs;
}
*num_config = _eglFlattenArray(disp->Configs, (void *) configs,
sizeof(configs[0]), config_size, _eglFlattenConfig);
return EGL_TRUE;
}
+64 -10
View File
@@ -14,6 +14,62 @@
#include "egllog.h"
/**
* Return the native platform by parsing EGL_PLATFORM.
*/
static _EGLPlatformType
_eglGetNativePlatformFromEnv(void)
{
/* map --with-egl-platforms names to platform types */
static const struct {
_EGLPlatformType platform;
const char *name;
} egl_platforms[_EGL_NUM_PLATFORMS] = {
{ _EGL_PLATFORM_WINDOWS, "gdi" },
{ _EGL_PLATFORM_X11, "x11" },
{ _EGL_PLATFORM_DRM, "kms" },
{ _EGL_PLATFORM_FBDEV, "fbdev" }
};
_EGLPlatformType plat = _EGL_INVALID_PLATFORM;
const char *plat_name;
EGLint i;
plat_name = getenv("EGL_PLATFORM");
/* try deprecated env variable */
if (!plat_name || !plat_name[0])
plat_name = getenv("EGL_DISPLAY");
if (!plat_name || !plat_name[0])
return _EGL_INVALID_PLATFORM;
for (i = 0; i < _EGL_NUM_PLATFORMS; i++) {
if (strcmp(egl_platforms[i].name, plat_name) == 0) {
plat = egl_platforms[i].platform;
break;
}
}
return plat;
}
/**
* Return the native platform. It is the platform of the EGL native types.
*/
_EGLPlatformType
_eglGetNativePlatform(void)
{
static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM;
if (native_platform == _EGL_INVALID_PLATFORM) {
native_platform = _eglGetNativePlatformFromEnv();
if (native_platform == _EGL_INVALID_PLATFORM)
native_platform = _EGL_NATIVE_PLATFORM;
}
return native_platform;
}
/**
* Finish display management.
*/
@@ -49,16 +105,19 @@ _eglFiniDisplay(void)
* new one.
*/
_EGLDisplay *
_eglFindDisplay(EGLNativeDisplayType nativeDisplay)
_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy)
{
_EGLDisplay *dpy;
if (plat == _EGL_INVALID_PLATFORM)
return NULL;
_eglLockMutex(_eglGlobal.Mutex);
/* search the display list first */
dpy = _eglGlobal.DisplayList;
while (dpy) {
if (dpy->NativeDisplay == nativeDisplay)
if (dpy->Platform == plat && dpy->PlatformDisplay == plat_dpy)
break;
dpy = dpy->Next;
}
@@ -68,7 +127,8 @@ _eglFindDisplay(EGLNativeDisplayType nativeDisplay)
dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
if (dpy) {
_eglInitMutex(&dpy->Mutex);
dpy->NativeDisplay = nativeDisplay;
dpy->Platform = plat;
dpy->PlatformDisplay = plat_dpy;
/* add to the display list */
dpy->Next = _eglGlobal.DisplayList;
@@ -119,15 +179,9 @@ _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
void
_eglCleanupDisplay(_EGLDisplay *disp)
{
EGLint i;
if (disp->Configs) {
for (i = 0; i < disp->NumConfigs; i++)
free(disp->Configs[i]);
free(disp->Configs);
_eglDestroyArray(disp->Configs, free);
disp->Configs = NULL;
disp->NumConfigs = 0;
disp->MaxConfigs = 0;
}
/* XXX incomplete */
+24 -9
View File
@@ -5,6 +5,19 @@
#include "egltypedefs.h"
#include "egldefines.h"
#include "eglmutex.h"
#include "eglarray.h"
enum _egl_platform_type {
_EGL_PLATFORM_WINDOWS,
_EGL_PLATFORM_X11,
_EGL_PLATFORM_DRM,
_EGL_PLATFORM_FBDEV,
_EGL_NUM_PLATFORMS,
_EGL_INVALID_PLATFORM = -1
};
typedef enum _egl_platform_type _EGLPlatformType;
enum _egl_resource_type {
@@ -39,6 +52,7 @@ struct _egl_extensions
{
EGLBoolean MESA_screen_surface;
EGLBoolean MESA_copy_context;
EGLBoolean MESA_drm_display;
EGLBoolean KHR_image_base;
EGLBoolean KHR_image_pixmap;
EGLBoolean KHR_vg_parent_image;
@@ -53,14 +67,15 @@ struct _egl_extensions
};
struct _egl_display
struct _egl_display
{
/* used to link displays */
_EGLDisplay *Next;
_EGLMutex Mutex;
EGLNativeDisplayType NativeDisplay;
_EGLPlatformType Platform;
void *PlatformDisplay;
EGLBoolean Initialized; /**< True if the display is initialized */
_EGLDriver *Driver;
@@ -75,24 +90,24 @@ struct _egl_display
_EGLExtensions Extensions;
EGLint NumScreens;
_EGLScreen **Screens; /* array [NumScreens] */
EGLint MaxConfigs;
EGLint NumConfigs;
_EGLConfig **Configs; /* array [NumConfigs] of ptr to _EGLConfig */
_EGLArray *Screens;
_EGLArray *Configs;
/* lists of resources */
_EGLResource *ResourceLists[_EGL_NUM_RESOURCES];
};
extern _EGLPlatformType
_eglGetNativePlatform(void);
extern void
_eglFiniDisplay(void);
extern _EGLDisplay *
_eglFindDisplay(EGLNativeDisplayType displayName);
_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy);
PUBLIC void
+274 -232
View File
@@ -22,6 +22,7 @@
#include "eglstring.h"
#include "eglsurface.h"
#include "eglimage.h"
#include "eglmutex.h"
#if defined(_EGL_OS_UNIX)
#include <dlfcn.h>
@@ -31,17 +32,22 @@
#endif
typedef struct _egl_module {
char *Path;
void *Handle;
_EGLDriver *Driver;
} _EGLModule;
static _EGL_DECLARE_MUTEX(_eglModuleMutex);
static _EGLArray *_eglModules;
/**
* Wrappers for dlopen/dlclose()
*/
#if defined(_EGL_OS_WINDOWS)
/* XXX Need to decide how to do dynamic name lookup on Windows */
static const char *DefaultDriverNames[] = {
"egl_gdi_swrast"
};
typedef HMODULE lib_handle;
static HMODULE
@@ -67,11 +73,6 @@ library_suffix(void)
#elif defined(_EGL_OS_UNIX)
static const char *DefaultDriverNames[] = {
"egl_dri2",
"egl_glx"
};
typedef void * lib_handle;
static void *
@@ -97,13 +98,6 @@ library_suffix(void)
#endif
#define NUM_PROBE_CACHE_SLOTS 8
static struct {
EGLint keys[NUM_PROBE_CACHE_SLOTS];
const void *values[NUM_PROBE_CACHE_SLOTS];
} _eglProbeCache;
/**
* Open the named driver and find its bootstrap function: _eglMain().
*/
@@ -163,85 +157,106 @@ _eglOpenLibrary(const char *driverPath, lib_handle *handle)
/**
* Load the named driver.
* Load a module and create the driver object.
*/
static _EGLDriver *
_eglLoadDriver(const char *path, const char *args)
static EGLBoolean
_eglLoadModule(_EGLModule *mod)
{
_EGLMain_t mainFunc;
lib_handle lib;
_EGLDriver *drv = NULL;
_EGLDriver *drv;
mainFunc = _eglOpenLibrary(path, &lib);
mainFunc = _eglOpenLibrary(mod->Path, &lib);
if (!mainFunc)
return NULL;
return EGL_FALSE;
drv = mainFunc(args);
drv = mainFunc(NULL);
if (!drv) {
if (lib)
close_library(lib);
return NULL;
return EGL_FALSE;
}
if (!drv->Name) {
_eglLog(_EGL_WARNING, "Driver loaded from %s has no name", path);
_eglLog(_EGL_WARNING, "Driver loaded from %s has no name", mod->Path);
drv->Name = "UNNAMED";
}
drv->Path = _eglstrdup(path);
drv->Args = (args) ? _eglstrdup(args) : NULL;
if (!drv->Path || (args && !drv->Args)) {
if (drv->Path)
free((char *) drv->Path);
if (drv->Args)
free((char *) drv->Args);
drv->Unload(drv);
if (lib)
close_library(lib);
return NULL;
}
mod->Handle = (void *) lib;
mod->Driver = drv;
drv->LibHandle = lib;
return drv;
return EGL_TRUE;
}
/**
* Match a display to a preloaded driver.
*
* The matching is done by finding the driver with the highest score.
* Unload a module.
*/
_EGLDriver *
_eglMatchDriver(_EGLDisplay *dpy)
static void
_eglUnloadModule(_EGLModule *mod)
{
_EGLDriver *best_drv = NULL;
EGLint best_score = -1, i;
/* destroy the driver */
if (mod->Driver && mod->Driver->Unload)
mod->Driver->Unload(mod->Driver);
if (mod->Handle)
close_library(mod->Handle);
/*
* this function is called after preloading and the drivers never change
* after preloading.
*/
for (i = 0; i < _eglGlobal.NumDrivers; i++) {
_EGLDriver *drv = _eglGlobal.Drivers[i];
EGLint score;
mod->Driver = NULL;
mod->Handle = NULL;
}
score = (drv->Probe) ? drv->Probe(drv, dpy) : 0;
if (score > best_score) {
if (best_drv) {
_eglLog(_EGL_DEBUG, "driver %s has higher score than %s",
drv->Name, best_drv->Name);
}
best_drv = drv;
best_score = score;
/* perfect match */
if (score >= 100)
break;
}
/**
* Add a module to the module array.
*/
static _EGLModule *
_eglAddModule(const char *path)
{
_EGLModule *mod;
EGLint i;
if (!_eglModules) {
_eglModules = _eglCreateArray("Module", 8);
if (!_eglModules)
return NULL;
}
return best_drv;
/* find duplicates */
for (i = 0; i < _eglModules->Size; i++) {
mod = _eglModules->Elements[i];
if (strcmp(mod->Path, path) == 0)
return mod;
}
/* allocate a new one */
mod = calloc(1, sizeof(*mod));
if (mod) {
mod->Path = _eglstrdup(path);
if (!mod->Path) {
free(mod);
mod = NULL;
}
}
if (mod) {
_eglAppendArray(_eglModules, (void *) mod);
_eglLog(_EGL_DEBUG, "added %s to module array", mod->Path);
}
return mod;
}
/**
* Free a module.
*/
static void
_eglFreeModule(void *module)
{
_EGLModule *mod = (_EGLModule *) module;
_eglUnloadModule(mod);
free(mod->Path);
free(mod);
}
@@ -252,7 +267,6 @@ _eglMatchDriver(_EGLDisplay *dpy)
static EGLBoolean
_eglLoaderFile(const char *dir, size_t len, void *loader_data)
{
_EGLDriver *drv;
char path[1024];
const char *filename = (const char *) loader_data;
size_t flen = strlen(filename);
@@ -268,9 +282,7 @@ _eglLoaderFile(const char *dir, size_t len, void *loader_data)
len += flen;
path[len] = '\0';
if (library_suffix() == NULL || strstr(path, library_suffix()))
drv = _eglLoadDriver(path, NULL);
else {
if (library_suffix()) {
const char *suffix = library_suffix();
size_t slen = strlen(suffix);
const char *p;
@@ -278,19 +290,23 @@ _eglLoaderFile(const char *dir, size_t len, void *loader_data)
p = filename + flen - slen;
need_suffix = (p < filename || strcmp(p, suffix) != 0);
if (need_suffix && len + slen + 1 <= sizeof(path)) {
if (need_suffix) {
/* overflow */
if (len + slen + 1 > sizeof(path))
return EGL_TRUE;
strcpy(path + len, suffix);
drv = _eglLoadDriver(path, NULL);
} else {
drv = NULL;
}
}
if (!drv)
return EGL_TRUE;
/* remember the driver and stop */
_eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
return EGL_FALSE;
#if defined(_EGL_OS_UNIX)
/* check if the file exists */
if (access(path, F_OK))
return EGL_TRUE;
#endif
_eglAddModule(path);
return EGL_TRUE;
}
@@ -326,7 +342,6 @@ _eglLoaderPattern(const char *dir, size_t len, void *loader_data)
suffix_len = (suffix) ? strlen(suffix) : 0;
while ((dirent = readdir(dirp))) {
_EGLDriver *drv;
size_t dirent_len = strlen(dirent->d_name);
const char *p;
@@ -340,12 +355,10 @@ _eglLoaderPattern(const char *dir, size_t len, void *loader_data)
continue;
}
/* make a full path and load the driver */
/* make a full path and add it to the module array */
if (len + dirent_len + 1 <= sizeof(path)) {
strcpy(path + len, dirent->d_name);
drv = _eglLoadDriver(path, NULL);
if (drv)
_eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
_eglAddModule(path);
}
}
@@ -360,19 +373,17 @@ _eglLoaderPattern(const char *dir, size_t len, void *loader_data)
/**
* Run the preload function on each driver directory and return the number of
* drivers loaded.
* Run the callback function on each driver directory.
*
* The process may end prematurely if the callback function returns false.
*/
static EGLint
static void
_eglPreloadForEach(const char *search_path,
EGLBoolean (*loader)(const char *, size_t, void *),
void *loader_data)
{
const char *cur, *next;
size_t len;
EGLint num_drivers = _eglGlobal.NumDrivers;
cur = search_path;
while (cur) {
@@ -384,8 +395,6 @@ _eglPreloadForEach(const char *search_path,
cur = (next) ? next + 1 : NULL;
}
return (_eglGlobal.NumDrivers - num_drivers);
}
@@ -430,12 +439,12 @@ _eglGetSearchPath(void)
/**
* Preload a user driver.
* Add the user driver to the module array.
*
* A user driver can be specified by EGL_DRIVER.
* The user driver is specified by EGL_DRIVER.
*/
static EGLBoolean
_eglPreloadUserDriver(void)
static void
_eglAddUserDriver(void)
{
const char *search_path = _eglGetSearchPath();
char *env;
@@ -451,132 +460,206 @@ _eglPreloadUserDriver(void)
}
}
#endif /* _EGL_OS_UNIX */
if (!env)
return EGL_FALSE;
if (!_eglPreloadForEach(search_path, _eglLoaderFile, (void *) env)) {
_eglLog(_EGL_WARNING, "EGL_DRIVER is set to an invalid driver");
return EGL_FALSE;
}
return EGL_TRUE;
if (env)
_eglPreloadForEach(search_path, _eglLoaderFile, (void *) env);
}
/**
* Preload platform drivers.
*
* Platform drivers are a set of drivers that support a certain window system.
* The window system may be specified by EGL_PLATFORM.
*
* FIXME This makes libEGL a memory hog if an user driver is not specified and
* there are many platform drivers.
* Add default drivers to the module array.
*/
static void
_eglAddDefaultDrivers(void)
{
const char *search_path = _eglGetSearchPath();
EGLint i;
#if defined(_EGL_OS_WINDOWS)
const char *DefaultDriverNames[] = {
"egl_gallium"
};
#elif defined(_EGL_OS_UNIX)
const char *DefaultDriverNames[] = {
"egl_gallium",
"egl_dri2",
"egl_glx"
};
#endif
for (i = 0; i < ARRAY_SIZE(DefaultDriverNames); i++) {
void *name = (void *) DefaultDriverNames[i];
_eglPreloadForEach(search_path, _eglLoaderFile, name);
}
}
/**
* Add drivers to the module array. Drivers will be loaded as they are matched
* to displays.
*/
static EGLBoolean
_eglPreloadPlatformDrivers(void)
_eglAddDrivers(void)
{
const char *dpy;
char prefix[32];
int ret;
if (_eglModules)
return EGL_TRUE;
dpy = getenv("EGL_PLATFORM");
/* try deprecated env variable */
if (!dpy || !dpy[0])
dpy = getenv("EGL_DISPLAY");
if (!dpy || !dpy[0])
dpy = _EGL_DEFAULT_PLATFORM;
if (!dpy || !dpy[0])
return EGL_FALSE;
/* the order here decides the priorities of the drivers */
_eglAddUserDriver();
_eglAddDefaultDrivers();
_eglPreloadForEach(_eglGetSearchPath(), _eglLoaderPattern, (void *) "egl_");
ret = _eglsnprintf(prefix, sizeof(prefix), "egl_%s_", dpy);
if (ret < 0 || ret >= sizeof(prefix))
return EGL_FALSE;
return (_eglPreloadForEach(_eglGetSearchPath(),
_eglLoaderPattern, (void *) prefix) > 0);
return (_eglModules != NULL);
}
/**
* Preload drivers.
* Match a display to a driver. The display is initialized unless use_probe is
* true.
*
* This function loads the driver modules and creates the corresponding
* _EGLDriver objects.
* The matching is done by finding the first driver that can initialize the
* display, or when use_probe is true, the driver with highest score.
*/
EGLBoolean
_eglPreloadDrivers(void)
_EGLDriver *
_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean use_probe)
{
EGLBoolean loaded;
_EGLModule *mod;
_EGLDriver *best_drv = NULL;
EGLint best_score = 0;
EGLint major, minor, i;
/* protect the preloading process */
_eglLockMutex(_eglGlobal.Mutex);
_eglLockMutex(&_eglModuleMutex);
/* already preloaded */
if (_eglGlobal.NumDrivers) {
_eglUnlockMutex(_eglGlobal.Mutex);
return EGL_TRUE;
if (!_eglAddDrivers()) {
_eglUnlockMutex(&_eglModuleMutex);
return EGL_FALSE;
}
loaded = (_eglPreloadUserDriver() ||
_eglPreloadPlatformDrivers());
/* match the loaded modules */
for (i = 0; i < _eglModules->Size; i++) {
mod = (_EGLModule *) _eglModules->Elements[i];
if (!mod->Driver)
break;
_eglUnlockMutex(_eglGlobal.Mutex);
if (use_probe) {
EGLint score = (mod->Driver->Probe) ?
mod->Driver->Probe(mod->Driver, dpy) : 1;
if (score > best_score) {
best_drv = mod->Driver;
best_score = score;
}
}
else {
if (mod->Driver->API.Initialize(mod->Driver, dpy, &major, &minor)) {
best_drv = mod->Driver;
best_score = 100;
}
}
/* perfect match */
if (best_score >= 100)
break;
}
return loaded;
/* load more modules */
if (!best_drv) {
EGLint first_unloaded = i;
while (i < _eglModules->Size) {
mod = (_EGLModule *) _eglModules->Elements[i];
assert(!mod->Driver);
if (!_eglLoadModule(mod)) {
/* remove invalid modules */
_eglEraseArray(_eglModules, i, _eglFreeModule);
continue;
}
if (use_probe) {
best_score = (mod->Driver->Probe) ?
mod->Driver->Probe(mod->Driver, dpy) : 1;
}
else {
if (mod->Driver->API.Initialize(mod->Driver, dpy, &major, &minor))
best_score = 100;
}
if (best_score > 0) {
best_drv = mod->Driver;
/* loaded modules come before unloaded ones */
if (first_unloaded != i) {
void *tmp = _eglModules->Elements[i];
_eglModules->Elements[i] =
_eglModules->Elements[first_unloaded];
_eglModules->Elements[first_unloaded] = tmp;
}
break;
}
else {
_eglUnloadModule(mod);
i++;
}
}
}
_eglUnlockMutex(&_eglModuleMutex);
if (best_drv) {
_eglLog(_EGL_DEBUG, "the best driver is %s (score %d)",
best_drv->Name, best_score);
if (!use_probe) {
dpy->Driver = best_drv;
dpy->Initialized = EGL_TRUE;
dpy->APImajor = major;
dpy->APIminor = minor;
}
}
return best_drv;
}
__eglMustCastToProperFunctionPointerType
_eglGetDriverProc(const char *procname)
{
EGLint i;
_EGLProc proc = NULL;
if (!_eglModules) {
/* load the driver for the default display */
EGLDisplay egldpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
_EGLDisplay *dpy = _eglLookupDisplay(egldpy);
if (!dpy || !_eglMatchDriver(dpy, EGL_TRUE))
return NULL;
}
for (i = 0; i < _eglModules->Size; i++) {
_EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
if (!mod->Driver)
break;
proc = mod->Driver->API.GetProcAddress(mod->Driver, procname);
if (proc)
break;
}
return proc;
}
/**
* Unload preloaded drivers.
* Unload all drivers.
*/
void
_eglUnloadDrivers(void)
{
EGLint i;
/* this is called at atexit time */
for (i = 0; i < _eglGlobal.NumDrivers; i++) {
_EGLDriver *drv = _eglGlobal.Drivers[i];
lib_handle handle = drv->LibHandle;
if (drv->Path)
free((char *) drv->Path);
if (drv->Args)
free((char *) drv->Args);
/* destroy driver */
if (drv->Unload)
drv->Unload(drv);
if (handle)
close_library(handle);
_eglGlobal.Drivers[i] = NULL;
if (_eglModules) {
#if defined(_EGL_OS_UNIX)
_eglDestroyArray(_eglModules, _eglFreeModule);
#elif defined(_EGL_OS_WINDOWS)
/* XXX Windows unloads DLLs before atexit */
_eglDestroyArray(_eglModules, NULL);
#endif
_eglModules = NULL;
}
_eglGlobal.NumDrivers = 0;
}
_EGLDriver *
_eglLoadDefaultDriver(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
_EGLDriver *drv = NULL;
int i;
_eglLockMutex(_eglGlobal.Mutex);
for (i = 0; i < ARRAY_SIZE(DefaultDriverNames); i++) {
_eglPreloadForEach(_eglGetSearchPath(),
_eglLoaderFile, (void *) DefaultDriverNames[i]);
if (_eglGlobal.NumDrivers == 0)
continue;
drv = _eglGlobal.Drivers[0];
if (drv->API.Initialize(drv, dpy, major, minor))
break;
_eglUnloadDrivers();
}
_eglUnlockMutex(_eglGlobal.Mutex);
return _eglGlobal.NumDrivers > 0 ? drv : NULL;
}
@@ -656,44 +739,3 @@ _eglSearchPathForEach(EGLBoolean (*callback)(const char *, size_t, void *),
const char *search_path = _eglGetSearchPath();
_eglPreloadForEach(search_path, callback, callback_data);
}
/**
* Set the probe cache at the given key.
*
* A key, instead of a _EGLDriver, is used to allow the probe cache to be share
* by multiple drivers.
*/
void
_eglSetProbeCache(EGLint key, const void *val)
{
EGLint idx;
for (idx = 0; idx < NUM_PROBE_CACHE_SLOTS; idx++) {
if (!_eglProbeCache.keys[idx] || _eglProbeCache.keys[idx] == key)
break;
}
assert(key > 0);
assert(idx < NUM_PROBE_CACHE_SLOTS);
_eglProbeCache.keys[idx] = key;
_eglProbeCache.values[idx] = val;
}
/**
* Return the probe cache at the given key.
*/
const void *
_eglGetProbeCache(EGLint key)
{
EGLint idx;
for (idx = 0; idx < NUM_PROBE_CACHE_SLOTS; idx++) {
if (!_eglProbeCache.keys[idx] || _eglProbeCache.keys[idx] == key)
break;
}
return (idx < NUM_PROBE_CACHE_SLOTS && _eglProbeCache.keys[idx] == key) ?
_eglProbeCache.values[idx] : NULL;
}
+3 -19
View File
@@ -41,10 +41,6 @@ typedef _EGLDriver *(*_EGLMain_t)(const char *args);
*/
struct _egl_driver
{
void *LibHandle; /**< dlopen handle */
const char *Path; /**< path to this driver */
const char *Args; /**< args to load this driver */
const char *Name; /**< name of this driver */
/**
@@ -73,21 +69,17 @@ _eglMain(const char *args);
extern _EGLDriver *
_eglMatchDriver(_EGLDisplay *dpy);
_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean probe_only);
extern EGLBoolean
_eglPreloadDrivers(void);
extern __eglMustCastToProperFunctionPointerType
_eglGetDriverProc(const char *procname);
extern void
_eglUnloadDrivers(void);
extern _EGLDriver *
_eglLoadDefaultDriver(EGLDisplay dpy, EGLint *major, EGLint *minor);
PUBLIC void
_eglInitDriverFallbacks(_EGLDriver *drv);
@@ -97,12 +89,4 @@ _eglSearchPathForEach(EGLBoolean (*callback)(const char *, size_t, void *),
void *callback_data);
PUBLIC void
_eglSetProbeCache(EGLint key, const void *val);
PUBLIC const void *
_eglGetProbeCache(EGLint key);
#endif /* EGLDRIVER_INCLUDED */
-2
View File
@@ -12,8 +12,6 @@ struct _egl_global _eglGlobal =
&_eglGlobalMutex, /* Mutex */
NULL, /* DisplayList */
1, /* FreeScreenHandle */
0, /* NumDrivers */
{ NULL }, /* Drivers */
2, /* NumAtExitCalls */
{
/* default AtExitCalls, called in reverse order */
-4
View File
@@ -18,10 +18,6 @@ struct _egl_global
EGLScreenMESA FreeScreenHandle;
/* these never change after preloading */
EGLint NumDrivers;
_EGLDriver *Drivers[10];
EGLint NumAtExitCalls;
void (*AtExitCalls[10])(void);
};
+1
View File
@@ -84,6 +84,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(KHR_image_base);
_EGL_CHECK_EXTENSION(KHR_image_pixmap);
+5 -2
View File
@@ -22,9 +22,12 @@ _eglLookupMode(EGLModeMESA mode, _EGLDisplay *disp)
{
EGLint scrnum;
if (!disp->Screens)
return NULL;
/* loop over all screens on the display */
for (scrnum = 0; scrnum < disp->NumScreens; scrnum++) {
const _EGLScreen *scrn = disp->Screens[scrnum];
for (scrnum = 0; scrnum < disp->Screens->Size; scrnum++) {
const _EGLScreen *scrn = disp->Screens->Elements[scrnum];
EGLint i;
/* search list of modes for handle */
for (i = 0; i < scrn->NumModes; i++) {
+25 -25
View File
@@ -62,9 +62,13 @@ _eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *display)
{
EGLint i;
for (i = 0; i < display->NumScreens; i++) {
if (display->Screens[i]->Handle == screen)
return display->Screens[i];
if (!display->Screens)
return NULL;
for (i = 0; i < display->Screens->Size; i++) {
_EGLScreen *scr = (_EGLScreen *) display->Screens->Elements[i];
if (scr->Handle == screen)
return scr;
}
return NULL;
}
@@ -76,40 +80,36 @@ _eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *display)
void
_eglAddScreen(_EGLDisplay *display, _EGLScreen *screen)
{
EGLint n;
assert(display);
assert(screen);
if (!display->Screens) {
display->Screens = _eglCreateArray("Screen", 4);
if (!display->Screens)
return;
}
screen->Handle = _eglAllocScreenHandle();
n = display->NumScreens;
display->Screens = realloc(display->Screens, (n+1) * sizeof(_EGLScreen *));
display->Screens[n] = screen;
display->NumScreens++;
_eglAppendArray(display->Screens, (void *) screen);
}
static EGLBoolean
_eglFlattenScreen(void *elem, void *buffer)
{
_EGLScreen *scr = (_EGLScreen *) elem;
EGLScreenMESA *handle = (EGLScreenMESA *) buffer;
*handle = scr->Handle;
return EGL_TRUE;
}
EGLBoolean
_eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *display, EGLScreenMESA *screens,
EGLint max_screens, EGLint *num_screens)
{
EGLint n;
if (display->NumScreens > max_screens) {
n = max_screens;
}
else {
n = display->NumScreens;
}
if (screens) {
EGLint i;
for (i = 0; i < n; i++)
screens[i] = display->Screens[i]->Handle;
}
if (num_screens)
*num_screens = n;
*num_screens = _eglFlattenArray(display->Screens, (void *) screens,
sizeof(screens[0]), max_screens, _eglFlattenScreen);
return EGL_TRUE;
}
+2
View File
@@ -10,6 +10,8 @@
typedef struct _egl_api _EGLAPI;
typedef struct _egl_array _EGLArray;
typedef struct _egl_config _EGLConfig;
typedef struct _egl_context _EGLContext;
+5 -1
View File
@@ -23,6 +23,10 @@ INCLUDES = \
-I$(TOP)/src/gallium/drivers \
$(LIBRARY_INCLUDES)
ifeq ($(MESA_LLVM),1)
LIBRARY_DEFINES += $(LLVM_CFLAGS)
endif
##### TARGETS #####
@@ -45,7 +49,7 @@ tags:
# Remove .o and backup files
clean:
rm -f $(OBJECTS) $(GENERATED_SOURCES) $(PROGS) lib$(LIBNAME).a depend depend.bak
rm -f $(OBJECTS) $(GENERATED_SOURCES) $(PROGS) lib$(LIBNAME).a depend depend.bak $(CLEAN_EXTRA)
# Dummy target
install:
+6 -1
View File
@@ -124,6 +124,7 @@ C_SOURCES = \
util/u_linear.c \
util/u_network.c \
util/u_math.c \
util/u_mempool.c \
util/u_mm.c \
util/u_rect.c \
util/u_ringbuffer.c \
@@ -154,6 +155,8 @@ GALLIVM_SOURCES = \
gallivm/lp_bld_flow.c \
gallivm/lp_bld_format_aos.c \
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 \
@@ -167,8 +170,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_translate.c
draw/draw_llvm_translate.c \
draw/draw_llvm_sample.c
GALLIVM_CPP_SOURCES = \
gallivm/lp_bld_misc.cpp
+9 -4
View File
@@ -32,8 +32,8 @@ env.CodeGenerate(
env.CodeGenerate(
target = 'util/u_format_table.c',
script = 'util/u_format_table.py',
source = ['util/u_format.csv'],
script = '#src/gallium/auxiliary/util/u_format_table.py',
source = ['#src/gallium/auxiliary/util/u_format.csv'],
command = 'python $SCRIPT $SOURCE > $TARGET'
)
@@ -45,7 +45,7 @@ env.CodeGenerate(
)
env.Depends('util/u_format_table.c', [
'util/u_format_parse.py',
'#src/gallium/auxiliary/util/u_format_parse.py',
'util/u_format_pack.py',
])
@@ -172,6 +172,7 @@ source = [
'util/u_keymap.c',
'util/u_network.c',
'util/u_math.c',
'util/u_mempool.c',
'util/u_mm.c',
'util/u_rect.c',
'util/u_resource.c',
@@ -203,6 +204,8 @@ if env['llvm']:
'gallivm/lp_bld_flow.c',
'gallivm/lp_bld_format_aos.c',
'gallivm/lp_bld_format_soa.c',
'gallivm/lp_bld_format_yuv.c',
'gallivm/lp_bld_gather.c',
'gallivm/lp_bld_intr.c',
'gallivm/lp_bld_logic.c',
'gallivm/lp_bld_init.c',
@@ -218,7 +221,9 @@ if env['llvm']:
'gallivm/lp_bld_type.c',
'draw/draw_llvm.c',
'draw/draw_pt_fetch_shade_pipeline_llvm.c',
'draw/draw_llvm_translate.c'
'draw/draw_llvm_translate.c',
'draw/draw_vs_llvm.c',
'draw/draw_llvm_sample.c'
]
gallium = env.ConvenienceLibrary(
@@ -289,6 +289,9 @@ void cso_release_all( struct cso_context *ctx )
ctx->pipe->bind_fs_state( ctx->pipe, NULL );
ctx->pipe->bind_vs_state( ctx->pipe, NULL );
ctx->pipe->bind_vertex_elements_state( ctx->pipe, NULL );
ctx->pipe->set_fragment_sampler_views(ctx->pipe, 0, NULL);
if (ctx->pipe->set_vertex_sampler_views)
ctx->pipe->set_vertex_sampler_views(ctx->pipe, 0, NULL);
}
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
@@ -1029,6 +1032,7 @@ static INLINE void
clip_state_cpy(struct pipe_clip_state *dst,
const struct pipe_clip_state *src)
{
dst->depth_clamp = src->depth_clamp;
dst->nr = src->nr;
if (src->nr) {
memcpy(dst->ucp, src->ucp, src->nr * sizeof(src->ucp[0]));
@@ -1039,6 +1043,9 @@ static INLINE int
clip_state_cmp(const struct pipe_clip_state *a,
const struct pipe_clip_state *b)
{
if (a->depth_clamp != b->depth_clamp) {
return 1;
}
if (a->nr != b->nr) {
return 1;
}
+57
View File
@@ -40,6 +40,7 @@
#if HAVE_LLVM
#include "gallivm/lp_bld_init.h"
#include "draw_llvm.h"
#endif
struct draw_context *draw_create( struct pipe_context *pipe )
@@ -52,6 +53,7 @@ struct draw_context *draw_create( struct pipe_context *pipe )
lp_build_init();
assert(lp_build_engine);
draw->engine = lp_build_engine;
draw->llvm = draw_llvm_create(draw);
#endif
if (!draw_init(draw))
@@ -132,6 +134,9 @@ void draw_destroy( struct draw_context *draw )
draw_pt_destroy( draw );
draw_vs_destroy( draw );
draw_gs_destroy( draw );
#ifdef HAVE_LLVM
draw_llvm_destroy( draw->llvm );
#endif
FREE( draw );
}
@@ -211,6 +216,7 @@ void draw_set_clip_state( struct draw_context *draw,
assert(clip->nr <= PIPE_MAX_CLIP_PLANES);
memcpy(&draw->plane[6], clip->ucp, clip->nr * sizeof(clip->ucp[0]));
draw->nr_planes = 6 + clip->nr;
draw->depth_clamp = clip->depth_clamp;
}
@@ -601,3 +607,54 @@ draw_set_so_state(struct draw_context *draw,
state,
sizeof(struct pipe_stream_output_state));
}
void
draw_set_sampler_views(struct draw_context *draw,
struct pipe_sampler_view **views,
unsigned num)
{
unsigned i;
debug_assert(num <= PIPE_MAX_VERTEX_SAMPLERS);
for (i = 0; i < num; ++i)
draw->sampler_views[i] = views[i];
for (i = num; i < PIPE_MAX_VERTEX_SAMPLERS; ++i)
draw->sampler_views[i] = NULL;
draw->num_sampler_views = num;
}
void
draw_set_samplers(struct draw_context *draw,
struct pipe_sampler_state **samplers,
unsigned num)
{
unsigned i;
debug_assert(num <= PIPE_MAX_VERTEX_SAMPLERS);
for (i = 0; i < num; ++i)
draw->samplers[i] = samplers[i];
for (i = num; i < PIPE_MAX_VERTEX_SAMPLERS; ++i)
draw->samplers[i] = NULL;
draw->num_samplers = num;
}
void
draw_set_mapped_texture(struct draw_context *draw,
unsigned sampler_idx,
uint32_t width, uint32_t height, uint32_t depth,
uint32_t last_level,
uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS],
uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS],
const void *data[DRAW_MAX_TEXTURE_LEVELS])
{
#ifdef HAVE_LLVM
draw_llvm_set_mapped_texture(draw,
sampler_idx,
width, height, depth, last_level,
row_stride, img_stride, data);
#endif
}
+21 -3
View File
@@ -47,11 +47,14 @@ struct draw_vertex_shader;
struct draw_geometry_shader;
struct tgsi_sampler;
#define DRAW_MAX_TEXTURE_LEVELS 13 /* 4K x 4K for now */
struct draw_context *draw_create( struct pipe_context *pipe );
void draw_destroy( struct draw_context *draw );
void draw_flush(struct draw_context *draw);
void draw_set_viewport_state( struct draw_context *draw,
const struct pipe_viewport_state *viewport );
@@ -101,6 +104,23 @@ draw_texture_samplers(struct draw_context *draw,
uint num_samplers,
struct tgsi_sampler **samplers);
void
draw_set_sampler_views(struct draw_context *draw,
struct pipe_sampler_view **views,
unsigned num);
void
draw_set_samplers(struct draw_context *draw,
struct pipe_sampler_state **samplers,
unsigned num);
void
draw_set_mapped_texture(struct draw_context *draw,
unsigned sampler_idx,
uint32_t width, uint32_t height, uint32_t depth,
uint32_t last_level,
uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS],
uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS],
const void *data[DRAW_MAX_TEXTURE_LEVELS]);
/*
@@ -173,7 +193,7 @@ draw_set_so_state(struct draw_context *draw,
/***********************************************************************
* draw_prim.c
* draw_pt.c
*/
void draw_arrays(struct draw_context *draw, unsigned prim,
@@ -187,8 +207,6 @@ draw_arrays_instanced(struct draw_context *draw,
unsigned startInstance,
unsigned instanceCount);
void draw_flush(struct draw_context *draw);
/*******************************************************************************
* Driver backend interface
+205 -24
View File
@@ -1,3 +1,30 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
#include "draw_llvm.h"
#include "draw_context.h"
@@ -15,14 +42,13 @@
#include "tgsi/tgsi_dump.h"
#include "util/u_cpu_detect.h"
#include "util/u_string.h"
#include "util/u_pointer.h"
#include "util/u_string.h"
#include <llvm-c/Transforms/Scalar.h>
#define DEBUG_STORE 0
/* generates the draw jit function */
static void
draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *var);
@@ -36,12 +62,19 @@ init_globals(struct draw_llvm *llvm)
/* struct draw_jit_texture */
{
LLVMTypeRef elem_types[4];
LLVMTypeRef elem_types[DRAW_JIT_TEXTURE_NUM_FIELDS];
elem_types[DRAW_JIT_TEXTURE_WIDTH] = LLVMInt32Type();
elem_types[DRAW_JIT_TEXTURE_HEIGHT] = LLVMInt32Type();
elem_types[DRAW_JIT_TEXTURE_STRIDE] = LLVMInt32Type();
elem_types[DRAW_JIT_TEXTURE_DATA] = LLVMPointerType(LLVMInt8Type(), 0);
elem_types[DRAW_JIT_TEXTURE_DEPTH] = LLVMInt32Type();
elem_types[DRAW_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32Type();
elem_types[DRAW_JIT_TEXTURE_ROW_STRIDE] =
LLVMArrayType(LLVMInt32Type(), DRAW_MAX_TEXTURE_LEVELS);
elem_types[DRAW_JIT_TEXTURE_IMG_STRIDE] =
LLVMArrayType(LLVMInt32Type(), DRAW_MAX_TEXTURE_LEVELS);
elem_types[DRAW_JIT_TEXTURE_DATA] =
LLVMArrayType(LLVMPointerType(LLVMInt8Type(), 0),
DRAW_MAX_TEXTURE_LEVELS);
texture_type = LLVMStructType(elem_types, Elements(elem_types), 0);
@@ -51,9 +84,18 @@ init_globals(struct draw_llvm *llvm)
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, height,
llvm->target, texture_type,
DRAW_JIT_TEXTURE_HEIGHT);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, stride,
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, depth,
llvm->target, texture_type,
DRAW_JIT_TEXTURE_STRIDE);
DRAW_JIT_TEXTURE_DEPTH);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, last_level,
llvm->target, texture_type,
DRAW_JIT_TEXTURE_LAST_LEVEL);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, row_stride,
llvm->target, texture_type,
DRAW_JIT_TEXTURE_ROW_STRIDE);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, img_stride,
llvm->target, texture_type,
DRAW_JIT_TEXTURE_IMG_STRIDE);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, data,
llvm->target, texture_type,
DRAW_JIT_TEXTURE_DATA);
@@ -71,7 +113,8 @@ init_globals(struct draw_llvm *llvm)
elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* vs_constants */
elem_types[1] = LLVMPointerType(LLVMFloatType(), 0); /* vs_constants */
elem_types[2] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */
elem_types[2] = LLVMArrayType(texture_type,
PIPE_MAX_VERTEX_SAMPLERS); /* textures */
context_type = LLVMStructType(elem_types, Elements(elem_types), 0);
@@ -81,7 +124,7 @@ init_globals(struct draw_llvm *llvm)
llvm->target, context_type, 1);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, textures,
llvm->target, context_type,
DRAW_JIT_CONTEXT_TEXTURES_INDEX);
DRAW_JIT_CTX_TEXTURES);
LP_CHECK_STRUCT_SIZE(struct draw_jit_context,
llvm->target, context_type);
@@ -195,9 +238,22 @@ draw_llvm_create(struct draw_context *draw)
/* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
* but there are more on SVN. */
/* TODO: Add more passes */
LLVMAddCFGSimplificationPass(llvm->pass);
LLVMAddPromoteMemoryToRegisterPass(llvm->pass);
LLVMAddConstantPropagationPass(llvm->pass);
if (HAVE_LLVM >= 0x207 && sizeof(void*) == 4) {
/* For LLVM >= 2.7 and 32-bit build, use this order of passes to
* avoid generating bad code.
* Test with piglit glsl-vs-sqrt-zero test.
*/
LLVMAddConstantPropagationPass(llvm->pass);
LLVMAddPromoteMemoryToRegisterPass(llvm->pass);
}
else {
LLVMAddPromoteMemoryToRegisterPass(llvm->pass);
LLVMAddConstantPropagationPass(llvm->pass);
}
if(util_cpu_caps.has_sse4_1) {
/* FIXME: There is a bug in this pass, whereby the combination of fptosi
* and sitofp (necessary for trunc/floor/ceil/round implementation)
@@ -219,6 +275,9 @@ draw_llvm_create(struct draw_context *draw)
LLVMDumpModule(llvm->module);
}
llvm->nr_variants = 0;
make_empty_list(&llvm->vs_variants_list);
return llvm;
}
@@ -231,9 +290,13 @@ draw_llvm_destroy(struct draw_llvm *llvm)
}
struct draw_llvm_variant *
draw_llvm_prepare(struct draw_llvm *llvm, int num_inputs)
draw_llvm_create_variant(struct draw_llvm *llvm, int num_inputs)
{
struct draw_llvm_variant *variant = MALLOC(sizeof(struct draw_llvm_variant));
struct llvm_vertex_shader *shader =
llvm_vertex_shader(llvm->draw->vs.vertex_shader);
variant->llvm = llvm;
draw_llvm_make_variant_key(llvm, &variant->key);
@@ -242,6 +305,12 @@ draw_llvm_prepare(struct draw_llvm *llvm, int num_inputs)
draw_llvm_generate(llvm, variant);
draw_llvm_generate_elts(llvm, variant);
variant->shader = shader;
variant->list_item_global.base = variant;
variant->list_item_local.base = variant;
/*variant->no = */shader->variants_created++;
variant->list_item_global.base = variant;
return variant;
}
@@ -250,11 +319,13 @@ generate_vs(struct draw_llvm *llvm,
LLVMBuilderRef builder,
LLVMValueRef (*outputs)[NUM_CHANNELS],
const LLVMValueRef (*inputs)[NUM_CHANNELS],
LLVMValueRef context_ptr)
LLVMValueRef context_ptr,
struct lp_build_sampler_soa *draw_sampler)
{
const struct tgsi_token *tokens = llvm->draw->vs.vertex_shader->state.tokens;
struct lp_type vs_type;
LLVMValueRef consts_ptr = draw_jit_context_vs_constants(builder, context_ptr);
struct lp_build_sampler_soa *sampler = 0;
memset(&vs_type, 0, sizeof vs_type);
vs_type.floating = TRUE; /* floating point values */
@@ -270,6 +341,10 @@ generate_vs(struct draw_llvm *llvm,
tgsi_dump(tokens, 0);
}
if (llvm->draw->num_sampler_views &&
llvm->draw->num_samplers)
sampler = draw_sampler;
lp_build_tgsi_soa(builder,
tokens,
vs_type,
@@ -278,7 +353,7 @@ generate_vs(struct draw_llvm *llvm,
NULL /*pos*/,
inputs,
outputs,
NULL/*sampler*/,
sampler,
&llvm->draw->vs.vertex_shader->info);
}
@@ -306,7 +381,8 @@ generate_fetch(LLVMBuilderRef builder,
LLVMValueRef *res,
struct pipe_vertex_element *velem,
LLVMValueRef vbuf,
LLVMValueRef index)
LLVMValueRef index,
LLVMValueRef instance_id)
{
LLVMValueRef indices = LLVMConstInt(LLVMInt64Type(), velem->vertex_buffer_index, 0);
LLVMValueRef vbuffer_ptr = LLVMBuildGEP(builder, vbuffers_ptr,
@@ -317,8 +393,15 @@ generate_fetch(LLVMBuilderRef builder,
LLVMValueRef cond;
LLVMValueRef stride;
cond = LLVMBuildICmp(builder, LLVMIntULE, index, vb_max_index, "");
if (velem->instance_divisor) {
/* array index = instance_id / instance_divisor */
index = LLVMBuildUDiv(builder, instance_id,
LLVMConstInt(LLVMInt32Type(), velem->instance_divisor, 0),
"instance_divisor");
}
/* limit index to min(inex, vb_max_index) */
cond = LLVMBuildICmp(builder, LLVMIntULE, index, vb_max_index, "");
index = LLVMBuildSelect(builder, cond, index, vb_max_index, "");
stride = LLVMBuildMul(builder, vb_stride, index, "");
@@ -586,13 +669,14 @@ convert_to_aos(LLVMBuilderRef builder,
static void
draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
{
LLVMTypeRef arg_types[7];
LLVMTypeRef arg_types[8];
LLVMTypeRef func_type;
LLVMValueRef context_ptr;
LLVMBasicBlockRef block;
LLVMBuilderRef builder;
LLVMValueRef start, end, count, stride, step, io_itr;
LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
LLVMValueRef instance_id;
struct draw_context *draw = llvm->draw;
unsigned i, j;
struct lp_build_context bld;
@@ -601,6 +685,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
const int max_vertices = 4;
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS];
void *code;
struct lp_build_sampler_soa *sampler = 0;
arg_types[0] = llvm->context_ptr_type; /* context */
arg_types[1] = llvm->vertex_header_ptr_type; /* vertex_header */
@@ -609,6 +694,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
arg_types[4] = LLVMInt32Type(); /* count */
arg_types[5] = LLVMInt32Type(); /* stride */
arg_types[6] = llvm->vb_ptr_type; /* pipe_vertex_buffer's */
arg_types[7] = LLVMInt32Type(); /* instance_id */
func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0);
@@ -625,6 +711,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
count = LLVMGetParam(variant->function, 4);
stride = LLVMGetParam(variant->function, 5);
vb_ptr = LLVMGetParam(variant->function, 6);
instance_id = LLVMGetParam(variant->function, 7);
lp_build_name(context_ptr, "context");
lp_build_name(io_ptr, "io");
@@ -633,6 +720,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
lp_build_name(count, "count");
lp_build_name(stride, "stride");
lp_build_name(vb_ptr, "vb");
lp_build_name(instance_id, "instance_id");
/*
* Function body
@@ -648,6 +736,10 @@ 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);
#if DEBUG_STORE
lp_build_printf(builder, "start = %d, end = %d, step = %d\n",
start, end, step);
@@ -678,7 +770,8 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
LLVMValueRef vb = LLVMBuildGEP(builder, vb_ptr,
&vb_index, 1, "");
generate_fetch(builder, vbuffers_ptr,
&aos_attribs[j][i], velem, vb, true_index);
&aos_attribs[j][i], velem, vb, true_index,
instance_id);
}
}
convert_to_soa(builder, aos_attribs, inputs,
@@ -689,7 +782,8 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
builder,
outputs,
ptr_aos,
context_ptr);
context_ptr,
sampler);
convert_to_aos(builder, io, outputs,
draw->vs.vertex_shader->info.num_outputs,
@@ -697,6 +791,8 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
}
lp_build_loop_end_cond(builder, end, step, LLVMIntUGE, &lp_loop);
sampler->destroy(sampler);
LLVMBuildRetVoid(builder);
LLVMDisposeBuilder(builder);
@@ -730,13 +826,14 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
static void
draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
{
LLVMTypeRef arg_types[7];
LLVMTypeRef arg_types[8];
LLVMTypeRef func_type;
LLVMValueRef context_ptr;
LLVMBasicBlockRef block;
LLVMBuilderRef builder;
LLVMValueRef fetch_elts, fetch_count, stride, step, io_itr;
LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
LLVMValueRef instance_id;
struct draw_context *draw = llvm->draw;
unsigned i, j;
struct lp_build_context bld;
@@ -747,6 +844,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS];
LLVMValueRef fetch_max;
void *code;
struct lp_build_sampler_soa *sampler = 0;
arg_types[0] = llvm->context_ptr_type; /* context */
arg_types[1] = llvm->vertex_header_ptr_type; /* vertex_header */
@@ -755,14 +853,17 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
arg_types[4] = LLVMInt32Type(); /* fetch_count */
arg_types[5] = LLVMInt32Type(); /* stride */
arg_types[6] = llvm->vb_ptr_type; /* pipe_vertex_buffer's */
arg_types[7] = LLVMInt32Type(); /* instance_id */
func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0);
variant->function_elts = LLVMAddFunction(llvm->module, "draw_llvm_shader_elts", func_type);
variant->function_elts = LLVMAddFunction(llvm->module, "draw_llvm_shader_elts",
func_type);
LLVMSetFunctionCallConv(variant->function_elts, LLVMCCallConv);
for(i = 0; i < Elements(arg_types); ++i)
if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind)
LLVMAddAttribute(LLVMGetParam(variant->function_elts, i), LLVMNoAliasAttribute);
LLVMAddAttribute(LLVMGetParam(variant->function_elts, i),
LLVMNoAliasAttribute);
context_ptr = LLVMGetParam(variant->function_elts, 0);
io_ptr = LLVMGetParam(variant->function_elts, 1);
@@ -771,6 +872,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
fetch_count = LLVMGetParam(variant->function_elts, 4);
stride = LLVMGetParam(variant->function_elts, 5);
vb_ptr = LLVMGetParam(variant->function_elts, 6);
instance_id = LLVMGetParam(variant->function_elts, 7);
lp_build_name(context_ptr, "context");
lp_build_name(io_ptr, "io");
@@ -779,6 +881,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
lp_build_name(fetch_count, "fetch_count");
lp_build_name(stride, "stride");
lp_build_name(vb_ptr, "vb");
lp_build_name(instance_id, "instance_id");
/*
* Function body
@@ -793,6 +896,10 @@ 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);
fetch_max = LLVMBuildSub(builder, fetch_count,
LLVMConstInt(LLVMInt32Type(), 1, 0),
"fetch_max");
@@ -833,7 +940,8 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
LLVMValueRef vb = LLVMBuildGEP(builder, vb_ptr,
&vb_index, 1, "");
generate_fetch(builder, vbuffers_ptr,
&aos_attribs[j][i], velem, vb, true_index);
&aos_attribs[j][i], velem, vb, true_index,
instance_id);
}
}
convert_to_soa(builder, aos_attribs, inputs,
@@ -844,7 +952,8 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
builder,
outputs,
ptr_aos,
context_ptr);
context_ptr,
sampler);
convert_to_aos(builder, io, outputs,
draw->vs.vertex_shader->info.num_outputs,
@@ -852,6 +961,8 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
}
lp_build_loop_end_cond(builder, fetch_count, step, LLVMIntUGE, &lp_loop);
sampler->destroy(sampler);
LLVMBuildRetVoid(builder);
LLVMDisposeBuilder(builder);
@@ -885,6 +996,8 @@ void
draw_llvm_make_variant_key(struct draw_llvm *llvm,
struct draw_llvm_variant_key *key)
{
unsigned i;
memset(key, 0, sizeof(struct draw_llvm_variant_key));
key->nr_vertex_elements = llvm->draw->pt.nr_vertex_elements;
@@ -896,4 +1009,72 @@ draw_llvm_make_variant_key(struct draw_llvm *llvm,
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]);
}
}
}
void
draw_llvm_set_mapped_texture(struct draw_context *draw,
unsigned sampler_idx,
uint32_t width, uint32_t height, uint32_t depth,
uint32_t last_level,
uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS],
uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS],
const void *data[DRAW_MAX_TEXTURE_LEVELS])
{
unsigned j;
struct draw_jit_texture *jit_tex;
assert(sampler_idx < PIPE_MAX_VERTEX_SAMPLERS);
jit_tex = &draw->llvm->jit_context.textures[sampler_idx];
jit_tex->width = width;
jit_tex->height = height;
jit_tex->depth = depth;
jit_tex->last_level = last_level;
for (j = 0; j <= last_level; j++) {
jit_tex->data[j] = data[j];
jit_tex->row_stride[j] = row_stride[j];
jit_tex->img_stride[j] = img_stride[j];
}
}
void
draw_llvm_destroy_variant(struct draw_llvm_variant *variant)
{
struct draw_llvm *llvm = variant->llvm;
struct draw_context *draw = llvm->draw;
if (variant->function_elts) {
if (variant->function_elts)
LLVMFreeMachineCodeForFunction(draw->engine,
variant->function_elts);
LLVMDeleteFunction(variant->function_elts);
}
if (variant->function) {
if (variant->function)
LLVMFreeMachineCodeForFunction(draw->engine,
variant->function);
LLVMDeleteFunction(variant->function);
}
remove_from_list(&variant->list_item_local);
variant->shader->variants_cached--;
remove_from_list(&variant->list_item_global);
llvm->nr_variants--;
FREE(variant);
}
+118 -27
View File
@@ -1,28 +1,71 @@
#ifndef HAVE_LLVM_H
#define HAVE_LLVM_H
/**************************************************************************
*
* 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.
*
**************************************************************************/
#ifndef DRAW_LLVM_H
#define DRAW_LLVM_H
#include "draw/draw_private.h"
#include "draw/draw_vs.h"
#include "gallivm/lp_bld_sample.h"
#include "pipe/p_context.h"
#include "util/u_simple_list.h"
#include <llvm-c/Core.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/Target.h>
#include <llvm-c/ExecutionEngine.h>
#define DRAW_MAX_TEXTURE_LEVELS 13 /* 4K x 4K for now */
struct draw_llvm;
struct llvm_vertex_shader;
struct draw_jit_texture
{
uint32_t width;
uint32_t height;
uint32_t stride;
const void *data;
uint32_t depth;
uint32_t last_level;
uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS];
uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS];
const void *data[DRAW_MAX_TEXTURE_LEVELS];
};
enum {
DRAW_JIT_TEXTURE_WIDTH = 0,
DRAW_JIT_TEXTURE_HEIGHT,
DRAW_JIT_TEXTURE_STRIDE,
DRAW_JIT_TEXTURE_DATA
DRAW_JIT_TEXTURE_DEPTH,
DRAW_JIT_TEXTURE_LAST_LEVEL,
DRAW_JIT_TEXTURE_ROW_STRIDE,
DRAW_JIT_TEXTURE_IMG_STRIDE,
DRAW_JIT_TEXTURE_DATA,
DRAW_JIT_TEXTURE_NUM_FIELDS /* number of fields above */
};
enum {
@@ -48,7 +91,7 @@ struct draw_jit_context
const float *gs_constants;
struct draw_jit_texture textures[PIPE_MAX_SAMPLERS];
struct draw_jit_texture textures[PIPE_MAX_VERTEX_SAMPLERS];
};
@@ -58,10 +101,10 @@ struct draw_jit_context
#define draw_jit_context_gs_constants(_builder, _ptr) \
lp_build_struct_get(_builder, _ptr, 1, "gs_constants")
#define DRAW_JIT_CONTEXT_TEXTURES_INDEX 2
#define DRAW_JIT_CTX_TEXTURES 2
#define draw_jit_context_textures(_builder, _ptr) \
lp_build_struct_get_ptr(_builder, _ptr, DRAW_JIT_CONTEXT_TEXTURES_INDEX, "textures")
lp_build_struct_get_ptr(_builder, _ptr, DRAW_JIT_CTX_TEXTURES, "textures")
@@ -92,7 +135,8 @@ typedef void
unsigned start,
unsigned count,
unsigned stride,
struct pipe_vertex_buffer *vertex_buffers);
struct pipe_vertex_buffer *vertex_buffers,
unsigned instance_id);
typedef void
@@ -102,13 +146,54 @@ typedef void
const unsigned *fetch_elts,
unsigned fetch_count,
unsigned stride,
struct pipe_vertex_buffer *vertex_buffers);
struct pipe_vertex_buffer *vertex_buffers,
unsigned instance_id);
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];
};
struct draw_llvm_variant_list_item
{
struct draw_llvm_variant *base;
struct draw_llvm_variant_list_item *next, *prev;
};
struct draw_llvm_variant
{
struct draw_llvm_variant_key key;
LLVMValueRef function;
LLVMValueRef function_elts;
draw_jit_vert_func jit_func;
draw_jit_vert_func_elts jit_func_elts;
struct llvm_vertex_shader *shader;
struct draw_llvm *llvm;
struct draw_llvm_variant_list_item list_item_global;
struct draw_llvm_variant_list_item list_item_local;
};
struct llvm_vertex_shader {
struct draw_vertex_shader base;
struct draw_llvm_variant_list_item variants;
unsigned variants_created;
unsigned variants_cached;
};
struct draw_llvm {
struct draw_context *draw;
struct draw_jit_context jit_context;
struct draw_llvm_variant_list_item vs_variants_list;
int nr_variants;
LLVMModuleRef module;
LLVMExecutionEngineRef engine;
LLVMModuleProviderRef provider;
@@ -121,23 +206,12 @@ struct draw_llvm {
LLVMTypeRef vb_ptr_type;
};
struct draw_llvm_variant_key
static INLINE struct llvm_vertex_shader *
llvm_vertex_shader(struct draw_vertex_shader *vs)
{
struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
unsigned nr_vertex_elements;
struct pipe_shader_state vs;
};
return (struct llvm_vertex_shader *)vs;
}
struct draw_llvm_variant
{
struct draw_llvm_variant_key key;
LLVMValueRef function;
LLVMValueRef function_elts;
draw_jit_vert_func jit_func;
draw_jit_vert_func_elts jit_func_elts;
struct draw_llvm_variant *next;
};
struct draw_llvm *
draw_llvm_create(struct draw_context *draw);
@@ -146,7 +220,10 @@ void
draw_llvm_destroy(struct draw_llvm *llvm);
struct draw_llvm_variant *
draw_llvm_prepare(struct draw_llvm *llvm, int num_inputs);
draw_llvm_create_variant(struct draw_llvm *llvm, int num_inputs);
void
draw_llvm_destroy_variant(struct draw_llvm_variant *variant);
void
draw_llvm_make_variant_key(struct draw_llvm *llvm,
@@ -156,4 +233,18 @@ LLVMValueRef
draw_llvm_translate_from(LLVMBuilderRef builder,
LLVMValueRef vbuffer,
enum pipe_format from_format);
struct lp_build_sampler_soa *
draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
LLVMValueRef context_ptr);
void
draw_llvm_set_mapped_texture(struct draw_context *draw,
unsigned sampler_idx,
uint32_t width, uint32_t height, uint32_t depth,
uint32_t last_level,
uint32_t row_stride[DRAW_MAX_TEXTURE_LEVELS],
uint32_t img_stride[DRAW_MAX_TEXTURE_LEVELS],
const void *data[DRAW_MAX_TEXTURE_LEVELS]);
#endif
@@ -0,0 +1,215 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* Texture sampling code generation
* @author Jose Fonseca <jfonseca@vmware.com>
*/
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "gallivm/lp_bld_debug.h"
#include "gallivm/lp_bld_type.h"
#include "gallivm/lp_bld_sample.h"
#include "gallivm/lp_bld_tgsi.h"
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_pointer.h"
#include "util/u_string.h"
#include "draw_llvm.h"
/**
* This provides the bridge between the sampler state store in
* lp_jit_context and lp_jit_texture and the sampler code
* generator. It provides the texture layout information required by
* the texture sampler code generator in terms of the state stored in
* lp_jit_context and lp_jit_texture in runtime.
*/
struct draw_llvm_sampler_dynamic_state
{
struct lp_sampler_dynamic_state base;
const struct lp_sampler_static_state *static_state;
LLVMValueRef context_ptr;
};
/**
* This is the bridge between our sampler and the TGSI translator.
*/
struct draw_llvm_sampler_soa
{
struct lp_build_sampler_soa base;
struct draw_llvm_sampler_dynamic_state dynamic_state;
};
/**
* Fetch the specified member of the lp_jit_texture structure.
* \param emit_load if TRUE, emit the LLVM load instruction to actually
* fetch the field's value. Otherwise, just emit the
* GEP code to address the field.
*
* @sa http://llvm.org/docs/GetElementPtr.html
*/
static LLVMValueRef
draw_llvm_texture_member(const struct lp_sampler_dynamic_state *base,
LLVMBuilderRef builder,
unsigned unit,
unsigned member_index,
const char *member_name,
boolean emit_load)
{
struct draw_llvm_sampler_dynamic_state *state =
(struct draw_llvm_sampler_dynamic_state *)base;
LLVMValueRef indices[4];
LLVMValueRef ptr;
LLVMValueRef res;
debug_assert(unit < PIPE_MAX_VERTEX_SAMPLERS);
/* context[0] */
indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0);
/* context[0].textures */
indices[1] = LLVMConstInt(LLVMInt32Type(), DRAW_JIT_CTX_TEXTURES, 0);
/* context[0].textures[unit] */
indices[2] = LLVMConstInt(LLVMInt32Type(), unit, 0);
/* context[0].textures[unit].member */
indices[3] = LLVMConstInt(LLVMInt32Type(), member_index, 0);
ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
if (emit_load)
res = LLVMBuildLoad(builder, ptr, "");
else
res = ptr;
lp_build_name(res, "context.texture%u.%s", unit, member_name);
return res;
}
/**
* Helper macro to instantiate the functions that generate the code to
* fetch the members of lp_jit_texture to fulfill the sampler code
* generator requests.
*
* This complexity is the price we have to pay to keep the texture
* sampler code generator a reusable module without dependencies to
* llvmpipe internals.
*/
#define DRAW_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \
static LLVMValueRef \
draw_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \
LLVMBuilderRef builder, \
unsigned unit) \
{ \
return draw_llvm_texture_member(base, builder, unit, _index, #_name, _emit_load ); \
}
DRAW_LLVM_TEXTURE_MEMBER(width, DRAW_JIT_TEXTURE_WIDTH, TRUE)
DRAW_LLVM_TEXTURE_MEMBER(height, DRAW_JIT_TEXTURE_HEIGHT, TRUE)
DRAW_LLVM_TEXTURE_MEMBER(depth, DRAW_JIT_TEXTURE_DEPTH, TRUE)
DRAW_LLVM_TEXTURE_MEMBER(last_level, DRAW_JIT_TEXTURE_LAST_LEVEL, TRUE)
DRAW_LLVM_TEXTURE_MEMBER(row_stride, DRAW_JIT_TEXTURE_ROW_STRIDE, FALSE)
DRAW_LLVM_TEXTURE_MEMBER(img_stride, DRAW_JIT_TEXTURE_IMG_STRIDE, FALSE)
DRAW_LLVM_TEXTURE_MEMBER(data_ptr, DRAW_JIT_TEXTURE_DATA, FALSE)
static void
draw_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
{
FREE(sampler);
}
/**
* Fetch filtered values from texture.
* The 'texel' parameter returns four vectors corresponding to R, G, B, A.
*/
static void
draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
LLVMBuilderRef builder,
struct lp_type type,
unsigned unit,
unsigned num_coords,
const LLVMValueRef *coords,
const LLVMValueRef *ddx,
const LLVMValueRef *ddy,
LLVMValueRef lod_bias, /* optional */
LLVMValueRef explicit_lod, /* optional */
LLVMValueRef *texel)
{
struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;
assert(unit < PIPE_MAX_VERTEX_SAMPLERS);
lp_build_sample_soa(builder,
&sampler->dynamic_state.static_state[unit],
&sampler->dynamic_state.base,
type,
unit,
num_coords, coords,
ddx, ddy,
lod_bias, explicit_lod,
texel);
}
struct lp_build_sampler_soa *
draw_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state,
LLVMValueRef context_ptr)
{
struct draw_llvm_sampler_soa *sampler;
sampler = CALLOC_STRUCT(draw_llvm_sampler_soa);
if(!sampler)
return NULL;
sampler->base.destroy = draw_llvm_sampler_soa_destroy;
sampler->base.emit_fetch_texel = draw_llvm_sampler_soa_emit_fetch_texel;
sampler->dynamic_state.base.width = draw_llvm_texture_width;
sampler->dynamic_state.base.height = draw_llvm_texture_height;
sampler->dynamic_state.base.depth = draw_llvm_texture_depth;
sampler->dynamic_state.base.last_level = draw_llvm_texture_last_level;
sampler->dynamic_state.base.row_stride = draw_llvm_texture_row_stride;
sampler->dynamic_state.base.img_stride = draw_llvm_texture_img_stride;
sampler->dynamic_state.base.data_ptr = draw_llvm_texture_data_ptr;
sampler->dynamic_state.static_state = static_state;
sampler->dynamic_state.context_ptr = context_ptr;
return &sampler->base;
}
@@ -7,6 +7,7 @@
#include "gallivm/lp_bld_struct.h"
#include "gallivm/lp_bld_format.h"
#include "gallivm/lp_bld_debug.h"
#include "gallivm/lp_bld_type.h"
#include "util/u_memory.h"
#include "util/u_format.h"
@@ -466,6 +467,7 @@ draw_llvm_translate_from(LLVMBuilderRef builder,
const struct util_format_description *format_desc;
LLVMValueRef zero;
int i;
struct lp_type type = lp_float32_vec4_type();
/*
* The above can only cope with straight arrays: no bitfields,
@@ -493,5 +495,5 @@ draw_llvm_translate_from(LLVMBuilderRef builder,
format_desc = util_format_description(from_format);
zero = LLVMConstNull(LLVMInt32Type());
return lp_build_fetch_rgba_aos(builder, format_desc, vbuffer, zero, zero);
return lp_build_fetch_rgba_aos(builder, format_desc, type, vbuffer, zero, zero, zero);
}
+26 -26
View File
@@ -177,15 +177,15 @@ static void do_triangle( struct draw_context *draw,
( DRAW_PIPE_RESET_STIPPLE | \
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
verts + stride * elts[i0], \
verts + stride * elts[i1], \
verts + stride * elts[i2]); \
verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_1 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
verts + stride * elts[i0], \
verts + stride * elts[i2], \
verts + stride * elts[i3])
verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK))
/* emit last quad vertex as last vertex in triangles */
#define QUAD_LAST_PV(i0,i1,i2,i3) \
@@ -193,15 +193,15 @@ static void do_triangle( struct draw_context *draw,
( DRAW_PIPE_RESET_STIPPLE | \
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
verts + stride * elts[i0], \
verts + stride * elts[i1], \
verts + stride * elts[i3]); \
verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
verts + stride * elts[i1], \
verts + stride * elts[i2], \
verts + stride * elts[i3])
verts + stride * (elts[i1] & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (elts[i2] & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (elts[i3] & ~DRAW_PIPE_FLAG_MASK))
#define TRIANGLE(flags,i0,i1,i2) \
do_triangle( draw, \
@@ -218,7 +218,7 @@ static void do_triangle( struct draw_context *draw,
#define POINT(i0) \
do_point( draw, \
verts + stride * elts[i0] )
verts + stride * (elts[i0] & ~DRAW_PIPE_FLAG_MASK) )
#define FUNC pipe_run
#define ARGS \
@@ -260,7 +260,7 @@ void draw_pipeline_run( struct draw_context *draw,
const struct draw_prim_info *prim_info)
{
unsigned i, start;
draw->pipeline.verts = (char *)vert_info->verts;
draw->pipeline.vertex_stride = vert_info->stride;
draw->pipeline.vertex_count = vert_info->count;
@@ -296,14 +296,14 @@ void draw_pipeline_run( struct draw_context *draw,
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (i1), \
verts + stride * (i2)); \
verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_1 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (i2), \
verts + stride * (i3))
verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK))
/* emit last quad vertex as last vertex in triangles */
#define QUAD_LAST_PV(i0,i1,i2,i3) \
@@ -312,31 +312,31 @@ void draw_pipeline_run( struct draw_context *draw,
DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_2 ), \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (i1), \
verts + stride * (i3)); \
verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK)); \
do_triangle( draw, \
( DRAW_PIPE_EDGE_FLAG_0 | \
DRAW_PIPE_EDGE_FLAG_1 ), \
verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (i2), \
verts + stride * (i3))
verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * ((i3) & ~DRAW_PIPE_FLAG_MASK))
#define TRIANGLE(flags,i0,i1,i2) \
do_triangle( draw, \
flags, /* flags */ \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (i1), \
verts + stride * (i2))
verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * ((i2) & ~DRAW_PIPE_FLAG_MASK))
#define LINE(flags,i0,i1) \
do_line( draw, \
flags, \
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \
verts + stride * (i1))
verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK))
#define POINT(i0) \
do_point( draw, \
verts + stride * i0 )
verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK) )
#define FUNC pipe_run_linear
#define ARGS \
@@ -425,7 +425,8 @@ aaline_create_texture(struct aaline_stage *aaline)
/* Fill in mipmap images.
* Basically each level is solid opaque, except for the outermost
* texels which are zero. Special case the 1x1 and 2x2 levels.
* texels which are zero. Special case the 1x1 and 2x2 levels
* (though, those levels shouldn't be used - see the max_lod setting).
*/
for (level = 0; level <= MAX_TEXTURE_LEVEL; level++) {
struct pipe_transfer *transfer;
@@ -497,7 +498,8 @@ aaline_create_sampler(struct aaline_stage *aaline)
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.normalized_coords = 1;
sampler.min_lod = 0.0f;
sampler.max_lod = MAX_TEXTURE_LEVEL;
/* avoid using the 1x1 and 2x2 mipmap levels */
sampler.max_lod = MAX_TEXTURE_LEVEL - 2;
aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
if (aaline->sampler_cso == NULL)
@@ -669,8 +671,8 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header)
assert(draw->rasterizer->line_smooth);
if (draw->rasterizer->line_width <= 3.0)
aaline->half_line_width = 1.5f;
if (draw->rasterizer->line_width <= 2.2)
aaline->half_line_width = 1.1f;
else
aaline->half_line_width = 0.5f * draw->rasterizer->line_width;
+10 -1
View File
@@ -262,6 +262,7 @@ do_clip_tri( struct draw_stage *stage,
clipmask &= ~(1<<plane_idx);
assert(n < MAX_CLIPPED_VERTICES);
inlist[n] = inlist[0]; /* prevent rotation of vertices */
for (i = 1; i <= n; i++) {
@@ -270,11 +271,17 @@ do_clip_tri( struct draw_stage *stage,
float dp = dot4( vert->clip, plane );
if (!IS_NEGATIVE(dp_prev)) {
assert(outcount < MAX_CLIPPED_VERTICES);
outlist[outcount++] = vert_prev;
}
if (DIFFERENT_SIGNS(dp, dp_prev)) {
struct vertex_header *new_vert = clipper->stage.tmp[tmpnr++];
struct vertex_header *new_vert;
assert(tmpnr < MAX_CLIPPED_VERTICES+1);
new_vert = clipper->stage.tmp[tmpnr++];
assert(outcount < MAX_CLIPPED_VERTICES);
outlist[outcount++] = new_vert;
if (IS_NEGATIVE(dp)) {
@@ -317,12 +324,14 @@ do_clip_tri( struct draw_stage *stage,
if (clipper->flat) {
if (stage->draw->rasterizer->flatshade_first) {
if (inlist[0] != header->v[0]) {
assert(tmpnr < MAX_CLIPPED_VERTICES + 1);
inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
copy_colors(stage, inlist[0], header->v[0]);
}
}
else {
if (inlist[0] != header->v[2]) {
assert(tmpnr < MAX_CLIPPED_VERTICES + 1);
inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
copy_colors(stage, inlist[0], header->v[2]);
}
@@ -363,8 +363,12 @@ generate_pstip_fs(struct pstip_stage *pstip)
assert(pstip->fs->sampler_unit < PIPE_MAX_SAMPLERS);
pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs);
FREE((void *)pstip_fs.tokens);
if (!pstip->fs->pstip_fs)
return FALSE;
return TRUE;
}
@@ -603,13 +607,16 @@ pstip_destroy(struct draw_stage *stage)
}
/** Create a new polygon stipple drawing stage object */
static struct pstip_stage *
draw_pstip_stage(struct draw_context *draw)
draw_pstip_stage(struct draw_context *draw, struct pipe_context *pipe)
{
struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage);
if (pstip == NULL)
goto fail;
pstip->pipe = pipe;
pstip->stage.draw = draw;
pstip->stage.name = "pstip";
pstip->stage.next = NULL;
@@ -765,14 +772,12 @@ draw_install_pstipple_stage(struct draw_context *draw,
/*
* Create / install pgon stipple drawing / prim stage
*/
pstip = draw_pstip_stage( draw );
pstip = draw_pstip_stage( draw, pipe );
if (pstip == NULL)
goto fail;
draw->pipeline.pstipple = &pstip->stage;
pstip->pipe = pipe;
/* create special texture, sampler state */
if (!pstip_create_texture(pstip))
goto fail;
@@ -226,6 +226,7 @@ static void widepoint_first_point( struct draw_stage *stage,
if (rast->gl_rasterization_rules) {
wide->xbias = 0.125;
wide->ybias = -0.125;
}
/* Disable triangle culling, stippling, unfilled mode etc. */
+11
View File
@@ -48,6 +48,7 @@
#ifdef HAVE_LLVM
#include <llvm-c/ExecutionEngine.h>
struct draw_llvm;
#endif
@@ -81,6 +82,9 @@ struct vertex_header {
#define UNDEFINED_VERTEX_ID 0xffff
/* maximum number of shader variants we can cache */
#define DRAW_MAX_SHADER_VARIANTS 1024
/**
* Private context for the drawing module.
*/
@@ -245,6 +249,7 @@ struct draw_context
*/
float plane[12][4];
unsigned nr_planes;
boolean depth_clamp;
/* If a prim stage introduces new vertex attributes, they'll be stored here
*/
@@ -259,9 +264,15 @@ struct draw_context
unsigned instance_id;
#ifdef HAVE_LLVM
struct draw_llvm *llvm;
LLVMExecutionEngineRef engine;
#endif
struct pipe_sampler_view *sampler_views[PIPE_MAX_VERTEX_SAMPLERS];
unsigned num_sampler_views;
const struct pipe_sampler_state *samplers[PIPE_MAX_VERTEX_SAMPLERS];
unsigned num_samplers;
void *driver_private;
};
+48 -24
View File
@@ -34,9 +34,11 @@
#include "draw/draw_gs.h"
#include "draw/draw_private.h"
#include "draw/draw_pt.h"
#include "draw/draw_vs.h"
#include "tgsi/tgsi_dump.h"
#include "util/u_math.h"
#include "util/u_prim.h"
#include "util/u_format.h"
DEBUG_GET_ONCE_BOOL_OPTION(draw_fse, "DRAW_FSE", FALSE)
@@ -69,7 +71,6 @@ draw_pt_arrays(struct draw_context *draw,
struct draw_pt_front_end *frontend = NULL;
struct draw_pt_middle_end *middle = NULL;
unsigned opt = 0;
unsigned out_prim = prim;
/* Sanitize primitive length:
*/
@@ -80,18 +81,19 @@ draw_pt_arrays(struct draw_context *draw,
if (count < first)
return TRUE;
}
if (draw->gs.geometry_shader) {
out_prim = draw->gs.geometry_shader->output_primitive;
}
if (!draw->force_passthrough) {
unsigned gs_out_prim = (draw->gs.geometry_shader ?
draw->gs.geometry_shader->output_primitive :
prim);
if (!draw->render) {
opt |= PT_PIPELINE;
}
if (draw_need_pipeline(draw,
draw->rasterizer,
out_prim)) {
gs_out_prim)) {
opt |= PT_PIPELINE;
}
@@ -102,7 +104,7 @@ draw_pt_arrays(struct draw_context *draw,
opt |= PT_SHADE;
}
if (draw->pt.middle.llvm && !draw->gs.geometry_shader) {
if (draw->pt.middle.llvm) {
middle = draw->pt.middle.llvm;
} else {
if (opt == 0)
@@ -122,7 +124,7 @@ draw_pt_arrays(struct draw_context *draw,
frontend = draw->pt.front.varray;
}
frontend->prepare( frontend, prim, out_prim, middle, opt );
frontend->prepare( frontend, prim, middle, opt );
frontend->run(frontend,
draw_pt_elt_func(draw),
@@ -265,31 +267,38 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
case PIPE_FORMAT_R32_FLOAT:
{
float *v = (float *) ptr;
debug_printf("%f @ %p\n", v[0], (void *) v);
debug_printf("R %f @ %p\n", v[0], (void *) v);
}
break;
case PIPE_FORMAT_R32G32_FLOAT:
{
float *v = (float *) ptr;
debug_printf("%f %f @ %p\n", v[0], v[1], (void *) v);
debug_printf("RG %f %f @ %p\n", v[0], v[1], (void *) v);
}
break;
case PIPE_FORMAT_R32G32B32_FLOAT:
{
float *v = (float *) ptr;
debug_printf("%f %f %f @ %p\n", v[0], v[1], v[2], (void *) v);
debug_printf("RGB %f %f %f @ %p\n", v[0], v[1], v[2], (void *) v);
}
break;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
{
float *v = (float *) ptr;
debug_printf("%f %f %f %f @ %p\n", v[0], v[1], v[2], v[3],
debug_printf("RGBA %f %f %f %f @ %p\n", v[0], v[1], v[2], v[3],
(void *) v);
}
break;
case PIPE_FORMAT_B8G8R8A8_UNORM:
{
ubyte *u = (ubyte *) ptr;
debug_printf("BGRA %d %d %d %d @ %p\n", u[0], u[1], u[2], u[3],
(void *) u);
}
break;
default:
debug_printf("other format (fix me)\n");
;
debug_printf("other format %s (fix me)\n",
util_format_name(draw->pt.vertex_element[j].src_format));
}
}
}
@@ -297,11 +306,8 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
/**
* Draw vertex arrays
* This is the main entrypoint into the drawing module.
* \param prim one of PIPE_PRIM_x
* \param start index of first vertex to draw
* \param count number of vertices to draw
* Non-instanced drawing.
* \sa draw_arrays_instanced
*/
void
draw_arrays(struct draw_context *draw, unsigned prim,
@@ -310,6 +316,20 @@ draw_arrays(struct draw_context *draw, unsigned prim,
draw_arrays_instanced(draw, prim, start, count, 0, 1);
}
/**
* 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)
*/
void
draw_arrays_instanced(struct draw_context *draw,
unsigned mode,
@@ -329,26 +349,30 @@ draw_arrays_instanced(struct draw_context *draw,
if (0)
draw_print_arrays(draw, mode, start, MIN2(count, 20));
#if 0
{
int i;
if (0) {
unsigned int i;
debug_printf("draw_arrays(mode=%u start=%u count=%u):\n",
mode, start, count);
tgsi_dump(draw->vs.vertex_shader->state.tokens, 0);
debug_printf("Elements:\n");
for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
debug_printf(" format=%s\n",
debug_printf(" %u: src_offset=%u inst_div=%u vbuf=%u format=%s\n",
i,
draw->pt.vertex_element[i].src_offset,
draw->pt.vertex_element[i].instance_divisor,
draw->pt.vertex_element[i].vertex_buffer_index,
util_format_name(draw->pt.vertex_element[i].src_format));
}
debug_printf("Buffers:\n");
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
debug_printf(" stride=%u offset=%u ptr=%p\n",
debug_printf(" %u: stride=%u maxindex=%u offset=%u ptr=%p\n",
i,
draw->pt.vertex_buffer[i].stride,
draw->pt.vertex_buffer[i].max_index,
draw->pt.vertex_buffer[i].buffer_offset,
draw->pt.user.vbuffer[i]);
}
}
#endif
for (instance = 0; instance < instanceCount; instance++) {
draw->instance_id = instance + startInstance;
+2 -4
View File
@@ -62,8 +62,7 @@ struct draw_vertex_info;
*/
struct draw_pt_front_end {
void (*prepare)( struct draw_pt_front_end *,
unsigned input_prim,
unsigned output_prim,
unsigned prim,
struct draw_pt_middle_end *,
unsigned opt );
@@ -87,8 +86,7 @@ struct draw_pt_front_end {
*/
struct draw_pt_middle_end {
void (*prepare)( struct draw_pt_middle_end *,
unsigned input_prim,
unsigned output_prim,
unsigned prim,
unsigned opt,
unsigned *max_vertices );
+5 -39
View File
@@ -68,31 +68,12 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
fetch->vertex_size = vertex_size;
/* Always emit/leave space for a vertex header.
*
* It's worth considering whether the vertex headers should contain
* a pointer to the 'data', rather than having it inline.
* Something to look at after we've fully switched over to the pt
* paths.
/* Leave the clipmask/edgeflags/pad/vertex_id untouched
*/
{
/* Need to set header->vertex_id = 0xffff somehow.
*/
key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
key.element[nr].input_format = PIPE_FORMAT_R32_FLOAT;
key.element[nr].input_buffer = draw->pt.nr_vertex_buffers;
key.element[nr].input_offset = 0;
key.element[nr].instance_divisor = 0;
key.element[nr].output_format = PIPE_FORMAT_R32_FLOAT;
key.element[nr].output_offset = dst_offset;
dst_offset += 1 * sizeof(float);
nr++;
/* Just leave the clip[] array untouched.
*/
dst_offset += 4 * sizeof(float);
}
dst_offset += 1 * sizeof(float);
/* Just leave the clip[] array untouched.
*/
dst_offset += 4 * sizeof(float);
if (instance_id_index != ~0) {
num_extra_inputs++;
@@ -131,26 +112,11 @@ void draw_pt_fetch_prepare( struct pt_fetch *fetch,
key.nr_elements = nr;
key.output_stride = vertex_size;
if (!fetch->translate ||
translate_key_compare(&fetch->translate->key, &key) != 0)
{
translate_key_sanitize(&key);
fetch->translate = translate_cache_find(fetch->cache, &key);
{
static struct vertex_header vh = { 0,
1,
0,
UNDEFINED_VERTEX_ID,
{ .0f, .0f, .0f, .0f } };
fetch->translate->set_buffer(fetch->translate,
draw->pt.nr_vertex_buffers,
&vh,
0,
~0);
}
}
}
@@ -36,6 +36,7 @@
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
#include "draw/draw_gs.h"
#include "translate/translate.h"
#include "translate/translate_cache.h"
@@ -90,7 +91,6 @@ struct fetch_emit_middle_end {
static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
unsigned prim,
unsigned out_prim,
unsigned opt,
unsigned *max_vertices )
{
@@ -101,9 +101,14 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
boolean ok;
struct translate_key key;
unsigned gs_out_prim = (draw->gs.geometry_shader ?
draw->gs.geometry_shader->output_primitive :
prim);
ok = draw->render->set_primitive( draw->render,
out_prim );
gs_out_prim );
if (!ok) {
assert(0);
return;
@@ -68,8 +68,7 @@ struct fetch_shade_emit {
static void fse_prepare( struct draw_pt_middle_end *middle,
unsigned in_prim,
unsigned out_prim,
unsigned prim,
unsigned opt,
unsigned *max_vertices )
{
@@ -80,9 +79,12 @@ static void fse_prepare( struct draw_pt_middle_end *middle,
unsigned i;
unsigned nr_vbs = 0;
/* Can't support geometry shader on this path.
*/
assert(!draw->gs.geometry_shader);
if (!draw->render->set_primitive( draw->render,
out_prim )) {
prim )) {
assert(0);
return;
}
@@ -48,13 +48,11 @@ struct fetch_pipeline_middle_end {
unsigned vertex_data_offset;
unsigned vertex_size;
unsigned input_prim;
unsigned output_prim;
unsigned opt;
};
static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
unsigned in_prim,
unsigned out_prim,
unsigned prim,
unsigned opt,
unsigned *max_vertices )
{
@@ -64,6 +62,10 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
unsigned i;
unsigned instance_id_index = ~0;
unsigned gs_out_prim = (draw->gs.geometry_shader ?
draw->gs.geometry_shader->output_primitive :
prim);
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
*/
@@ -79,8 +81,7 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
}
}
fpme->input_prim = in_prim;
fpme->output_prim = out_prim;
fpme->input_prim = prim;
fpme->opt = opt;
/* Always leave room for the vertex header whether we need it or
@@ -102,13 +103,13 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
(boolean)draw->bypass_clipping,
(boolean)draw->identity_viewport,
(boolean)draw->rasterizer->gl_rasterization_rules,
(draw->vs.edgeflag_output ? true : false) );
(draw->vs.edgeflag_output ? TRUE : FALSE) );
draw_pt_so_emit_prepare( fpme->so_emit );
if (!(opt & PT_PIPELINE)) {
draw_pt_emit_prepare( fpme->emit,
out_prim,
gs_out_prim,
max_vertices );
*max_vertices = MAX2( *max_vertices,
@@ -183,7 +184,7 @@ static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
output_verts->count = input_verts->count;
output_verts->verts =
(struct vertex_header *)MALLOC(output_verts->vertex_size *
output_verts->count);
align(output_verts->count, 4));
vshader->run_linear(vshader,
(const float (*)[4])input_verts->verts->data,
@@ -49,48 +49,50 @@ struct llvm_middle_end {
unsigned vertex_data_offset;
unsigned vertex_size;
unsigned input_prim;
unsigned output_prim;
unsigned opt;
struct draw_llvm *llvm;
struct draw_llvm_variant *variants;
struct draw_llvm_variant *current_variant;
int nr_variants;
};
static void
llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
unsigned in_prim,
unsigned out_prim,
unsigned opt,
unsigned *max_vertices )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
struct draw_context *draw = fpme->draw;
struct draw_vertex_shader *vs = draw->vs.vertex_shader;
struct llvm_vertex_shader *shader =
llvm_vertex_shader(draw->vs.vertex_shader);
struct draw_llvm_variant_key key;
struct draw_llvm_variant *variant = NULL;
struct draw_llvm_variant_list_item *li;
unsigned i;
unsigned instance_id_index = ~0;
unsigned out_prim = (draw->gs.geometry_shader ?
draw->gs.geometry_shader->output_primitive :
in_prim);
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
*/
unsigned nr = MAX2( vs->info.num_inputs,
vs->info.num_outputs + 1 );
unsigned nr = MAX2( shader->base.info.num_inputs,
shader->base.info.num_outputs + 1 );
/* Scan for instanceID system value.
*/
for (i = 0; i < vs->info.num_inputs; i++) {
if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
for (i = 0; i < shader->base.info.num_inputs; i++) {
if (shader->base.info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
instance_id_index = i;
break;
}
}
fpme->input_prim = in_prim;
fpme->output_prim = out_prim;
fpme->opt = opt;
/* Always leave room for the vertex header whether we need it or
@@ -107,7 +109,7 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
(boolean)draw->bypass_clipping,
(boolean)(draw->identity_viewport),
(boolean)draw->rasterizer->gl_rasterization_rules,
(draw->vs.edgeflag_output ? true : false) );
(draw->vs.edgeflag_output ? TRUE : FALSE) );
draw_pt_so_emit_prepare( fpme->so_emit );
@@ -128,20 +130,41 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
draw_llvm_make_variant_key(fpme->llvm, &key);
variant = fpme->variants;
while(variant) {
if(memcmp(&variant->key, &key, sizeof key) == 0)
li = first_elem(&shader->variants);
while(!at_end(&shader->variants, li)) {
if(memcmp(&li->base->key, &key, sizeof key) == 0) {
variant = li->base;
break;
variant = variant->next;
}
li = next_elem(li);
}
if (!variant) {
variant = draw_llvm_prepare(fpme->llvm, nr);
variant->next = fpme->variants;
fpme->variants = variant;
++fpme->nr_variants;
if (variant) {
move_to_head(&fpme->llvm->vs_variants_list, &variant->list_item_global);
}
else {
unsigned i;
if (fpme->llvm->nr_variants >= DRAW_MAX_SHADER_VARIANTS) {
/*
* XXX: should we flush here ?
*/
for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 4; i++) {
struct draw_llvm_variant_list_item *item =
last_elem(&fpme->llvm->vs_variants_list);
draw_llvm_destroy_variant(item->base);
}
}
variant = draw_llvm_create_variant(fpme->llvm, nr);
if (variant) {
insert_at_head(&shader->variants, &variant->list_item_local);
insert_at_head(&fpme->llvm->vs_variants_list, &variant->list_item_global);
fpme->llvm->nr_variants++;
shader->variants_cached++;
}
}
fpme->current_variant = variant;
/*XXX we only support one constant buffer */
@@ -210,7 +233,8 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
fetch_info->start,
fetch_info->count,
fpme->vertex_size,
draw->pt.vertex_buffer );
draw->pt.vertex_buffer,
draw->instance_id);
else
fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context,
llvm_vert_info.verts,
@@ -218,7 +242,8 @@ llvm_pipeline_generic( struct draw_pt_middle_end *middle,
fetch_info->elts,
fetch_info->count,
fpme->vertex_size,
draw->pt.vertex_buffer);
draw->pt.vertex_buffer,
draw->instance_id);
/* Finished with fetch and vs:
*/
@@ -356,31 +381,7 @@ static void llvm_middle_end_finish( struct draw_pt_middle_end *middle )
static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
struct draw_context *draw = fpme->draw;
struct draw_llvm_variant *variant = NULL;
variant = fpme->variants;
while(variant) {
struct draw_llvm_variant *next = variant->next;
if (variant->function_elts) {
if (variant->function_elts)
LLVMFreeMachineCodeForFunction(draw->engine,
variant->function_elts);
LLVMDeleteFunction(variant->function_elts);
}
if (variant->function) {
if (variant->function)
LLVMFreeMachineCodeForFunction(draw->engine,
variant->function);
LLVMDeleteFunction(variant->function);
}
FREE(variant);
variant = next;
}
if (fpme->fetch)
draw_pt_fetch_destroy( fpme->fetch );
@@ -393,14 +394,12 @@ static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle )
if (fpme->post_vs)
draw_pt_post_vs_destroy( fpme->post_vs );
if (fpme->llvm)
draw_llvm_destroy( fpme->llvm );
FREE(middle);
}
struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm( struct draw_context *draw )
struct draw_pt_middle_end *
draw_pt_fetch_pipeline_or_emit_llvm(struct draw_context *draw)
{
struct llvm_middle_end *fpme = 0;
@@ -436,13 +435,11 @@ struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm( struct draw_cont
if (!fpme->so_emit)
goto fail;
fpme->llvm = draw_llvm_create(draw);
fpme->llvm = draw->llvm;
if (!fpme->llvm)
goto fail;
fpme->variants = NULL;
fpme->current_variant = NULL;
fpme->nr_variants = 0;
return &fpme->base;
+28 -7
View File
@@ -38,7 +38,14 @@ struct pt_post_vs {
struct draw_vertex_info *info );
};
static INLINE void
initialize_vertex_header(struct vertex_header *header)
{
header->clipmask = 0;
header->edgeflag = 1;
header->pad = 0;
header->vertex_id = UNDEFINED_VERTEX_ID;
}
static INLINE float
dot4(const float *a, const float *b)
@@ -49,10 +56,9 @@ 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)
compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr,
boolean clip_depth)
{
unsigned mask = 0x0;
unsigned i;
@@ -69,8 +75,10 @@ compute_clipmask_gl(const float *clip, /*const*/ float plane[][4], unsigned nr)
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[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 */
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 */
}
/* Followed by any remaining ones:
*/
@@ -103,6 +111,7 @@ static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
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]);
@@ -114,9 +123,11 @@ static boolean post_vs_cliptest_viewport_gl( struct pt_post_vs *pvs,
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->nr_planes,
!pvs->draw->depth_clamp);
clipped += out->clipmask;
if (out->clipmask == 0)
@@ -192,6 +203,7 @@ static boolean post_vs_viewport( struct pt_post_vs *pvs,
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];
@@ -211,7 +223,16 @@ static boolean post_vs_viewport( struct pt_post_vs *pvs,
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;
}
+12 -7
View File
@@ -120,24 +120,27 @@ static void varray_fan_segment(struct varray_frontend *varray,
#define FUNC varray_run
#include "draw_pt_varray_tmp_linear.h"
static unsigned decompose_prim[PIPE_PRIM_POLYGON + 1] = {
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_TRIANGLE_FAN,
PIPE_PRIM_QUADS,
PIPE_PRIM_QUAD_STRIP,
PIPE_PRIM_POLYGON
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,
unsigned out_prim,
struct draw_pt_middle_end *middle,
unsigned opt)
{
@@ -146,11 +149,13 @@ static void varray_prepare(struct draw_pt_front_end *frontend,
varray->base.run = varray_run;
varray->input_prim = in_prim;
varray->output_prim = decompose_prim[out_prim];
assert(in_prim < Elements(decompose_prim));
varray->output_prim = decompose_prim[in_prim];
varray->middle = middle;
middle->prepare(middle, varray->input_prim,
varray->output_prim, opt, &varray->driver_fetch_max );
middle->prepare(middle,
varray->output_prim,
opt, &varray->driver_fetch_max );
/* check that the max is even */
assert((varray->driver_fetch_max & 1) == 0);
+78 -46
View File
@@ -41,6 +41,7 @@
#define FETCH_MAX 256
#define DRAW_MAX (16*1024)
struct vcache_frontend {
struct draw_pt_front_end base;
struct draw_context *draw;
@@ -64,13 +65,13 @@ struct vcache_frontend {
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->input_prim,
vcache->middle_prim,
vcache->opt,
&vcache->fetch_max );
@@ -89,12 +90,12 @@ vcache_flush( struct vcache_frontend *vcache )
vcache->draw_count = 0;
}
static INLINE void
vcache_check_flush( struct vcache_frontend *vcache )
{
if ( vcache->draw_count + 6 >= DRAW_MAX ||
vcache->fetch_count + 4 >= FETCH_MAX )
{
if (vcache->draw_count + 6 >= DRAW_MAX ||
vcache->fetch_count + 4 >= FETCH_MAX) {
vcache_flush( vcache );
}
}
@@ -146,6 +147,7 @@ vcache_triangle_flags( struct vcache_frontend *vcache,
vcache_check_flush(vcache);
}
static INLINE void
vcache_line( struct vcache_frontend *vcache,
unsigned i0,
@@ -177,6 +179,7 @@ vcache_point( struct vcache_frontend *vcache,
vcache_check_flush(vcache);
}
static INLINE void
vcache_quad( struct vcache_frontend *vcache,
unsigned i0,
@@ -196,6 +199,7 @@ vcache_quad( struct vcache_frontend *vcache,
}
}
static INLINE void
vcache_ef_quad( struct vcache_frontend *vcache,
unsigned i0,
@@ -231,6 +235,7 @@ vcache_ef_quad( struct vcache_frontend *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.
@@ -256,23 +261,23 @@ rebase_uint_elts( const unsigned *src,
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 )
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,
@@ -280,42 +285,39 @@ rebase_ubyte_elts( const ubyte *src,
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]);
}
@@ -336,6 +338,7 @@ format_from_get_elt( pt_elt_func get_elt )
}
#endif
static INLINE void
vcache_check_run( struct draw_pt_front_end *frontend,
pt_elt_func get_elt,
@@ -345,18 +348,46 @@ vcache_check_run( struct draw_pt_front_end *frontend,
{
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
struct draw_context *draw = vcache->draw;
unsigned min_index = draw->pt.user.min_index;
unsigned max_index = draw->pt.user.max_index;
unsigned index_size = draw->pt.user.eltSize;
unsigned fetch_count = max_index + 1 - min_index;
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);
}
}
}
if (0) debug_printf("fetch_count %d fetch_max %d draw_count %d\n", fetch_count,
vcache->fetch_max,
draw_count);
/* 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;
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 ||
@@ -368,23 +399,19 @@ vcache_check_run( struct draw_pt_front_end *frontend,
if (vcache->middle_prim != vcache->input_prim) {
vcache->middle_prim = vcache->input_prim;
vcache->middle->prepare( vcache->middle,
vcache->input_prim,
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)
{
index_size == 2) {
transformed_elts = (const ushort *)elts;
}
else
{
else {
storage = MALLOC( draw_count * sizeof(ushort) );
if (!storage)
goto fail;
@@ -419,23 +446,23 @@ vcache_check_run( struct draw_pt_front_end *frontend,
switch(index_size) {
case 1:
rebase_ubyte_elts( (const ubyte *)elts,
draw_count,
0 - (int)min_index,
storage );
draw_count,
0 - (int)min_index,
storage );
break;
case 2:
rebase_ushort_elts( (const ushort *)elts,
draw_count,
0 - (int)min_index,
storage );
draw_count,
0 - (int)min_index,
storage );
break;
case 4:
rebase_uint_elts( (const uint *)elts,
draw_count,
0 - (int)min_index,
storage );
draw_count,
0 - (int)min_index,
storage );
break;
default:
@@ -462,7 +489,7 @@ vcache_check_run( struct draw_pt_front_end *frontend,
debug_printf("failed to execute atomic draw elts for %d/%d, splitting up\n",
fetch_count, draw_count);
fail:
fail:
vcache_run( frontend, get_elt, elts, elt_bias, draw_count );
}
@@ -472,23 +499,26 @@ vcache_check_run( struct draw_pt_front_end *frontend,
static void
vcache_prepare( struct draw_pt_front_end *frontend,
unsigned in_prim,
unsigned out_prim,
struct draw_pt_middle_end *middle,
unsigned opt )
{
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
if (opt & PT_PIPELINE)
{
if (opt & PT_PIPELINE) {
vcache->base.run = vcache_run_extras;
}
else
{
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;
vcache->output_prim = u_reduced_prim(out_prim);
vcache->output_prim = u_reduced_prim(in_prim);
vcache->middle = middle;
vcache->opt = opt;
@@ -496,14 +526,15 @@ vcache_prepare( struct draw_pt_front_end *frontend,
/* 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->input_prim,
vcache->middle_prim, opt, &vcache->fetch_max );
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 )
{
@@ -512,6 +543,7 @@ vcache_finish( struct draw_pt_front_end *frontend )
vcache->middle = NULL;
}
static void
vcache_destroy( struct draw_pt_front_end *frontend )
{
+5
View File
@@ -98,6 +98,11 @@ draw_create_vertex_shader(struct draw_context *draw,
vs = draw_create_vs_ppc( draw, shader );
#endif
}
#if HAVE_LLVM
else {
vs = draw_create_vs_llvm(draw, shader);
}
#endif
if (!vs) {
vs = draw_create_vs_exec( draw, shader );
+5 -1
View File
@@ -165,7 +165,6 @@ draw_create_vs_ppc(struct draw_context *draw,
const struct pipe_shader_state *templ);
struct draw_vs_varient_key;
struct draw_vertex_shader;
@@ -173,6 +172,11 @@ struct draw_vs_varient *
draw_vs_create_varient_aos_sse( struct draw_vertex_shader *vs,
const struct draw_vs_varient_key *key );
#if HAVE_LLVM
struct draw_vertex_shader *
draw_create_vs_llvm(struct draw_context *draw,
const struct pipe_shader_state *state);
#endif
/********************************************************************************
+120
View File
@@ -0,0 +1,120 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
#include "util/u_math.h"
#include "util/u_memory.h"
#include "pipe/p_shader_tokens.h"
#include "draw_private.h"
#include "draw_context.h"
#include "draw_vs.h"
#include "draw_llvm.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_scan.h"
static void
vs_llvm_prepare(struct draw_vertex_shader *shader,
struct draw_context *draw)
{
/*struct llvm_vertex_shader *evs = llvm_vertex_shader(shader);*/
}
static void
vs_llvm_run_linear( struct draw_vertex_shader *shader,
const float (*input)[4],
float (*output)[4],
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
unsigned count,
unsigned input_stride,
unsigned output_stride )
{
/* we should never get here since the entire pipeline is
* generated in draw_pt_fetch_shade_pipeline_llvm.c */
debug_assert(0);
}
static void
vs_llvm_delete( struct draw_vertex_shader *dvs )
{
struct llvm_vertex_shader *shader = llvm_vertex_shader(dvs);
struct pipe_fence_handle *fence = NULL;
struct draw_llvm_variant_list_item *li;
struct pipe_context *pipe = dvs->draw->pipe;
/*
* XXX: This might be not neccessary at all.
*/
pipe->flush(pipe, 0, &fence);
if (fence) {
pipe->screen->fence_finish(pipe->screen, fence, 0);
pipe->screen->fence_reference(pipe->screen, &fence, NULL);
}
li = first_elem(&shader->variants);
while(!at_end(&shader->variants, li)) {
struct draw_llvm_variant_list_item *next = next_elem(li);
draw_llvm_destroy_variant(li->base);
li = next;
}
assert(shader->variants_cached == 0);
FREE((void*) dvs->state.tokens);
FREE( dvs );
}
struct draw_vertex_shader *
draw_create_vs_llvm(struct draw_context *draw,
const struct pipe_shader_state *state)
{
struct llvm_vertex_shader *vs = CALLOC_STRUCT( llvm_vertex_shader );
if (vs == NULL)
return NULL;
/* we make a private copy of the tokens */
vs->base.state.tokens = tgsi_dup_tokens(state->tokens);
if (!vs->base.state.tokens) {
FREE(vs);
return NULL;
}
tgsi_scan_shader(state->tokens, &vs->base.info);
vs->base.draw = draw;
vs->base.prepare = vs_llvm_prepare;
vs->base.run_linear = vs_llvm_run_linear;
vs->base.delete = vs_llvm_delete;
vs->base.create_varient = draw_vs_create_varient_generic;
make_empty_list(&vs->variants);
return &vs->base;
}
+67 -20
View File
@@ -56,7 +56,6 @@
#include "lp_bld_intr.h"
#include "lp_bld_logic.h"
#include "lp_bld_pack.h"
#include "lp_bld_debug.h"
#include "lp_bld_arit.h"
@@ -847,6 +846,11 @@ lp_build_round_sse41(struct lp_build_context *bld,
}
/**
* Return the integer part of a float (vector) value. The returned value is
* a float (vector).
* Ex: trunc(-1.5) = 1.0
*/
LLVMValueRef
lp_build_trunc(struct lp_build_context *bld,
LLVMValueRef a)
@@ -869,6 +873,12 @@ lp_build_trunc(struct lp_build_context *bld,
}
/**
* Return float (vector) rounded to nearest integer (vector). The returned
* value is a float (vector).
* Ex: round(0.9) = 1.0
* Ex: round(-1.5) = -2.0
*/
LLVMValueRef
lp_build_round(struct lp_build_context *bld,
LLVMValueRef a)
@@ -890,6 +900,11 @@ lp_build_round(struct lp_build_context *bld,
}
/**
* Return floor of float (vector), result is a float (vector)
* Ex: floor(1.1) = 1.0
* Ex: floor(-1.1) = -2.0
*/
LLVMValueRef
lp_build_floor(struct lp_build_context *bld,
LLVMValueRef a)
@@ -911,6 +926,11 @@ lp_build_floor(struct lp_build_context *bld,
}
/**
* Return ceiling of float (vector), returning float (vector).
* Ex: ceil( 1.1) = 2.0
* Ex: ceil(-1.1) = -1.0
*/
LLVMValueRef
lp_build_ceil(struct lp_build_context *bld,
LLVMValueRef a)
@@ -933,7 +953,7 @@ lp_build_ceil(struct lp_build_context *bld,
/**
* Return fractional part of 'a' computed as a - floor(f)
* Return fractional part of 'a' computed as a - floor(a)
* Typically used in texture coord arithmetic.
*/
LLVMValueRef
@@ -946,8 +966,9 @@ lp_build_fract(struct lp_build_context *bld,
/**
* Convert to integer, through whichever rounding method that's fastest,
* typically truncating toward zero.
* Return the integer part of a float (vector) value. The returned value is
* an integer (vector).
* Ex: itrunc(-1.5) = 1
*/
LLVMValueRef
lp_build_itrunc(struct lp_build_context *bld,
@@ -964,7 +985,10 @@ lp_build_itrunc(struct lp_build_context *bld,
/**
* Convert float[] to int[] with round().
* Return float (vector) rounded to nearest integer (vector). The returned
* value is an integer (vector).
* Ex: iround(0.9) = 1
* Ex: iround(-1.5) = -2
*/
LLVMValueRef
lp_build_iround(struct lp_build_context *bld,
@@ -1007,7 +1031,9 @@ lp_build_iround(struct lp_build_context *bld,
/**
* Convert float[] to int[] with floor().
* Return floor of float (vector), result is an int (vector)
* Ex: ifloor(1.1) = 1.0
* Ex: ifloor(-1.1) = -2.0
*/
LLVMValueRef
lp_build_ifloor(struct lp_build_context *bld,
@@ -1034,29 +1060,31 @@ lp_build_ifloor(struct lp_build_context *bld,
/* sign = a < 0 ? ~0 : 0 */
sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
sign = LLVMBuildAnd(bld->builder, sign, mask, "");
sign = LLVMBuildAShr(bld->builder, sign, lp_build_const_int_vec(type, type.width - 1), "");
lp_build_name(sign, "floor.sign");
sign = LLVMBuildAShr(bld->builder, sign, lp_build_const_int_vec(type, type.width - 1), "ifloor.sign");
/* offset = -0.99999(9)f */
offset = lp_build_const_vec(type, -(double)(((unsigned long long)1 << mantissa) - 1)/((unsigned long long)1 << mantissa));
offset = lp_build_const_vec(type, -(double)(((unsigned long long)1 << mantissa) - 10)/((unsigned long long)1 << mantissa));
offset = LLVMConstBitCast(offset, int_vec_type);
/* offset = a < 0 ? -0.99999(9)f : 0.0f */
/* offset = a < 0 ? offset : 0.0f */
offset = LLVMBuildAnd(bld->builder, offset, sign, "");
offset = LLVMBuildBitCast(bld->builder, offset, vec_type, "");
lp_build_name(offset, "floor.offset");
offset = LLVMBuildBitCast(bld->builder, offset, vec_type, "ifloor.offset");
res = LLVMBuildAdd(bld->builder, a, offset, "");
lp_build_name(res, "floor.res");
res = LLVMBuildAdd(bld->builder, a, offset, "ifloor.res");
}
res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, "");
lp_build_name(res, "floor");
/* round to nearest (toward zero) */
res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, "ifloor.res");
return res;
}
/**
* Return ceiling of float (vector), returning int (vector).
* Ex: iceil( 1.1) = 2
* Ex: iceil(-1.1) = -1
*/
LLVMValueRef
lp_build_iceil(struct lp_build_context *bld,
LLVMValueRef a)
@@ -1072,12 +1100,31 @@ lp_build_iceil(struct lp_build_context *bld,
res = lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_CEIL);
}
else {
/* TODO: mimic lp_build_ifloor() here */
assert(0);
res = bld->undef;
LLVMTypeRef vec_type = lp_build_vec_type(type);
unsigned mantissa = lp_mantissa(type);
LLVMValueRef mask = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1));
LLVMValueRef sign;
LLVMValueRef offset;
/* sign = a < 0 ? 0 : ~0 */
sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
sign = LLVMBuildAnd(bld->builder, sign, mask, "");
sign = LLVMBuildAShr(bld->builder, sign, lp_build_const_int_vec(type, type.width - 1), "iceil.sign");
sign = LLVMBuildNot(bld->builder, sign, "iceil.not");
/* offset = 0.99999(9)f */
offset = lp_build_const_vec(type, (double)(((unsigned long long)1 << mantissa) - 10)/((unsigned long long)1 << mantissa));
offset = LLVMConstBitCast(offset, int_vec_type);
/* offset = a < 0 ? 0.0 : offset */
offset = LLVMBuildAnd(bld->builder, offset, sign, "");
offset = LLVMBuildBitCast(bld->builder, offset, vec_type, "iceil.offset");
res = LLVMBuildAdd(bld->builder, a, offset, "iceil.res");
}
res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, "");
/* round to nearest (toward zero) */
res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, "iceil.res");
return res;
}
@@ -107,4 +107,12 @@ lp_build_const_mask_aos(struct lp_type type,
const boolean cond[4]);
static INLINE LLVMValueRef
lp_build_const_int32(int i)
{
return LLVMConstInt(LLVMInt32Type(), i, 0);
}
#endif /* !LP_BLD_CONST_H */
+25 -22
View File
@@ -83,6 +83,9 @@
*
* Although the result values can be scaled to an arbitrary bit width specified
* by dst_width, the actual result type will have the same width.
*
* Ex: src = { float, float, float, float }
* return { i32, i32, i32, i32 } where each value is in [0, 2^dst_width-1].
*/
LLVMValueRef
lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
@@ -152,6 +155,8 @@ lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder,
/**
* Inverse of lp_build_clamped_float_to_unsigned_norm above.
* Ex: src = { i32, i32, i32, i32 } with values in range [0, 2^src_width-1]
* return {float, float, float, float} with values in range [0, 1].
*/
LLVMValueRef
lp_build_unsigned_norm_to_float(LLVMBuilderRef builder,
@@ -219,18 +224,19 @@ lp_build_conv(LLVMBuilderRef builder,
unsigned num_tmps;
unsigned i;
/* Register width must remain constant */
assert(src_type.width * src_type.length == dst_type.width * dst_type.length);
/* We must not loose or gain channels. Only precision */
assert(src_type.length * num_srcs == dst_type.length * num_dsts);
assert(src_type.length <= LP_MAX_VECTOR_LENGTH);
assert(dst_type.length <= LP_MAX_VECTOR_LENGTH);
assert(num_srcs <= LP_MAX_VECTOR_LENGTH);
assert(num_dsts <= LP_MAX_VECTOR_LENGTH);
tmp_type = src_type;
for(i = 0; i < num_srcs; ++i)
for(i = 0; i < num_srcs; ++i) {
assert(lp_check_value(src_type, src[i]));
tmp[i] = src[i];
}
num_tmps = num_srcs;
/*
@@ -326,30 +332,25 @@ lp_build_conv(LLVMBuilderRef builder,
/*
* Truncate or expand bit width
*
* No data conversion should happen here, although the sign bits are
* crucial to avoid bad clamping.
*/
assert(!tmp_type.floating || tmp_type.width == dst_type.width);
{
struct lp_type new_type;
if(tmp_type.width > dst_type.width) {
assert(num_dsts == 1);
tmp[0] = lp_build_pack(builder, tmp_type, dst_type, TRUE, tmp, num_tmps);
tmp_type.width = dst_type.width;
tmp_type.length = dst_type.length;
num_tmps = 1;
}
new_type = tmp_type;
new_type.sign = dst_type.sign;
new_type.width = dst_type.width;
new_type.length = dst_type.length;
if(tmp_type.width < dst_type.width) {
assert(num_tmps == 1);
lp_build_unpack(builder, tmp_type, dst_type, tmp[0], tmp, num_dsts);
tmp_type.width = dst_type.width;
tmp_type.length = dst_type.length;
lp_build_resize(builder, tmp_type, new_type, tmp, num_srcs, tmp, num_dsts);
tmp_type = new_type;
num_tmps = num_dsts;
}
assert(tmp_type.width == dst_type.width);
assert(tmp_type.length == dst_type.length);
assert(num_tmps == num_dsts);
/*
* Scale to the widest range
*/
@@ -406,8 +407,10 @@ lp_build_conv(LLVMBuilderRef builder,
}
}
for(i = 0; i < num_dsts; ++i)
for(i = 0; i < num_dsts; ++i) {
dst[i] = tmp[i];
assert(lp_check_value(dst_type, dst[i]));
}
}
+25 -5
View File
@@ -48,9 +48,9 @@ struct lp_build_context;
*/
LLVMValueRef
lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
const struct util_format_description *desc,
LLVMValueRef packed);
lp_build_format_swizzle_aos(const struct util_format_description *desc,
struct lp_build_context *bld,
LLVMValueRef unswizzled);
LLVMValueRef
lp_build_pack_rgba_aos(LLVMBuilderRef builder,
@@ -60,7 +60,9 @@ lp_build_pack_rgba_aos(LLVMBuilderRef builder,
LLVMValueRef
lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
const struct util_format_description *format_desc,
LLVMValueRef ptr,
struct lp_type type,
LLVMValueRef base_ptr,
LLVMValueRef offset,
LLVMValueRef i,
LLVMValueRef j);
@@ -72,7 +74,7 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
void
lp_build_format_swizzle_soa(const struct util_format_description *format_desc,
struct lp_build_context *bld,
const LLVMValueRef *unswizzled,
const LLVMValueRef unswizzled[4],
LLVMValueRef swizzled_out[4]);
void
@@ -82,6 +84,11 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder,
LLVMValueRef packed,
LLVMValueRef rgba_out[4]);
void
lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder,
struct lp_type dst_type,
LLVMValueRef packed,
LLVMValueRef *rgba);
void
lp_build_fetch_rgba_soa(LLVMBuilderRef builder,
@@ -93,5 +100,18 @@ lp_build_fetch_rgba_soa(LLVMBuilderRef builder,
LLVMValueRef j,
LLVMValueRef rgba_out[4]);
/*
* YUV
*/
LLVMValueRef
lp_build_fetch_subsampled_rgba_aos(LLVMBuilderRef builder,
const struct util_format_description *format_desc,
unsigned n,
LLVMValueRef base_ptr,
LLVMValueRef offset,
LLVMValueRef i,
LLVMValueRef j);
#endif /* !LP_BLD_FORMAT_H */
+347 -85
View File
@@ -38,33 +38,122 @@
#include "util/u_math.h"
#include "util/u_string.h"
#include "lp_bld_arit.h"
#include "lp_bld_init.h"
#include "lp_bld_type.h"
#include "lp_bld_flow.h"
#include "lp_bld_const.h"
#include "lp_bld_conv.h"
#include "lp_bld_swizzle.h"
#include "lp_bld_gather.h"
#include "lp_bld_format.h"
/**
* Basic swizzling. Rearrange the order of the unswizzled array elements
* according to the format description. PIPE_SWIZZLE_ZERO/ONE are supported
* too.
* Ex: if unswizzled[4] = {B, G, R, x}, then swizzled_out[4] = {R, G, B, 1}.
*/
LLVMValueRef
lp_build_format_swizzle_aos(const struct util_format_description *desc,
struct lp_build_context *bld,
LLVMValueRef unswizzled)
{
unsigned char swizzles[4];
unsigned chan;
assert(bld->type.length % 4 == 0);
for (chan = 0; chan < 4; ++chan) {
enum util_format_swizzle swizzle;
if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
/*
* For ZS formats do RGBA = ZZZ1
*/
if (chan == 3) {
swizzle = UTIL_FORMAT_SWIZZLE_1;
} else if (desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_NONE) {
swizzle = UTIL_FORMAT_SWIZZLE_0;
} else {
swizzle = desc->swizzle[0];
}
} else {
swizzle = desc->swizzle[chan];
}
swizzles[chan] = swizzle;
}
return lp_build_swizzle_aos(bld, unswizzled, swizzles);
}
/**
* Whether the format matches the vector type, apart of swizzles.
*/
static INLINE boolean
format_matches_type(const struct util_format_description *desc,
struct lp_type type)
{
enum util_format_type chan_type;
unsigned chan;
assert(type.length % 4 == 0);
if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB ||
desc->block.width != 1 ||
desc->block.height != 1) {
return FALSE;
}
if (type.floating) {
chan_type = UTIL_FORMAT_TYPE_FLOAT;
} else if (type.fixed) {
chan_type = UTIL_FORMAT_TYPE_FIXED;
} else if (type.sign) {
chan_type = UTIL_FORMAT_TYPE_SIGNED;
} else {
chan_type = UTIL_FORMAT_TYPE_UNSIGNED;
}
for (chan = 0; chan < desc->nr_channels; ++chan) {
if (desc->channel[chan].size != type.width) {
return FALSE;
}
if (desc->channel[chan].type != UTIL_FORMAT_TYPE_VOID) {
if (desc->channel[chan].type != chan_type ||
desc->channel[chan].normalized != type.norm) {
return FALSE;
}
}
}
return TRUE;
}
/**
* Unpack a single pixel into its RGBA components.
*
* @param desc the pixel format for the packed pixel value
* @param packed integer pixel in a format such as PIPE_FORMAT_B8G8R8A8_UNORM
*
* @return RGBA in a 4 floats vector.
* @return RGBA in a float[4] or ubyte[4] or ushort[4] vector.
*/
LLVMValueRef
lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
const struct util_format_description *desc,
LLVMValueRef packed)
static INLINE LLVMValueRef
lp_build_unpack_arith_rgba_aos(LLVMBuilderRef builder,
const struct util_format_description *desc,
LLVMValueRef packed)
{
LLVMValueRef shifted, casted, scaled, masked;
LLVMValueRef shifts[4];
LLVMValueRef masks[4];
LLVMValueRef scales[4];
LLVMValueRef swizzles[4];
LLVMValueRef aux[4];
boolean normalized;
int empty_channel;
boolean needs_uitofp;
unsigned shift;
unsigned i;
@@ -77,8 +166,7 @@ lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
/* Do the intermediate integer computations with 32bit integers since it
* matches floating point size */
if (desc->block.bits < 32)
packed = LLVMBuildZExt(builder, packed, LLVMInt32Type(), "");
assert (LLVMTypeOf(packed) == LLVMInt32Type());
/* Broadcast the packed value to all four channels
* before: packed = BGRA
@@ -98,7 +186,6 @@ lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
/* Initialize vector constants */
normalized = FALSE;
needs_uitofp = FALSE;
empty_channel = -1;
shift = 0;
/* Loop over 4 color components */
@@ -109,7 +196,6 @@ lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
shifts[i] = LLVMGetUndef(LLVMInt32Type());
masks[i] = LLVMConstNull(LLVMInt32Type());
scales[i] = LLVMConstNull(LLVMFloatType());
empty_channel = i;
}
else {
unsigned long long mask = (1ULL << bits) - 1;
@@ -158,52 +244,7 @@ lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
else
scaled = casted;
for (i = 0; i < 4; ++i)
aux[i] = LLVMGetUndef(LLVMFloatType());
/* Build swizzles vector to put components into R,G,B,A order */
for (i = 0; i < 4; ++i) {
enum util_format_swizzle swizzle;
if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
/*
* For ZS formats do RGBA = ZZZ1
*/
if (i == 3) {
swizzle = UTIL_FORMAT_SWIZZLE_1;
} else if (desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_NONE) {
swizzle = UTIL_FORMAT_SWIZZLE_0;
} else {
swizzle = desc->swizzle[0];
}
} else {
swizzle = desc->swizzle[i];
}
switch (swizzle) {
case UTIL_FORMAT_SWIZZLE_X:
case UTIL_FORMAT_SWIZZLE_Y:
case UTIL_FORMAT_SWIZZLE_Z:
case UTIL_FORMAT_SWIZZLE_W:
swizzles[i] = LLVMConstInt(LLVMInt32Type(), swizzle, 0);
break;
case UTIL_FORMAT_SWIZZLE_0:
assert(empty_channel >= 0);
swizzles[i] = LLVMConstInt(LLVMInt32Type(), empty_channel, 0);
break;
case UTIL_FORMAT_SWIZZLE_1:
swizzles[i] = LLVMConstInt(LLVMInt32Type(), 4, 0);
aux[0] = LLVMConstReal(LLVMFloatType(), 1.0);
break;
case UTIL_FORMAT_SWIZZLE_NONE:
swizzles[i] = LLVMGetUndef(LLVMFloatType());
assert(0);
break;
}
}
return LLVMBuildShuffleVector(builder, scaled, LLVMConstVector(aux, 4),
LLVMConstVector(swizzles, 4), "");
return scaled;
}
@@ -310,22 +351,65 @@ lp_build_pack_rgba_aos(LLVMBuilderRef builder,
}
/**
* Fetch a pixel into a 4 float AoS.
*
* \param format_desc describes format of the image we're fetching from
* \param ptr address of the pixel block (or the texel if uncompressed)
* \param i, j the sub-block pixel coordinates. For non-compressed formats
* these will always be (0,).
* \return valueRef with the float[4] RGBA pixel
* these will always be (0, 0).
* \return a 4 element vector with the pixel's RGBA values.
*/
LLVMValueRef
lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
const struct util_format_description *format_desc,
LLVMValueRef ptr,
struct lp_type type,
LLVMValueRef base_ptr,
LLVMValueRef offset,
LLVMValueRef i,
LLVMValueRef j)
{
unsigned num_pixels = type.length / 4;
struct lp_build_context bld;
assert(type.length <= LP_MAX_VECTOR_LENGTH);
assert(type.length % 4 == 0);
lp_build_context_init(&bld, builder, type);
/*
* Trivial case
*
* The format matches the type (apart of a swizzle) so no need for
* scaling or converting.
*/
if (format_matches_type(format_desc, type) &&
format_desc->block.bits <= type.width * 4 &&
util_is_pot(format_desc->block.bits)) {
LLVMValueRef packed;
/*
* The format matches the type (apart of a swizzle) so no need for
* scaling or converting.
*/
packed = lp_build_gather(builder, type.length/4,
format_desc->block.bits, type.width*4,
base_ptr, offset);
assert(format_desc->block.bits <= type.width * type.length);
packed = LLVMBuildBitCast(builder, packed, lp_build_vec_type(type), "");
return lp_build_format_swizzle_aos(format_desc, &bld, packed);
}
/*
* Bit arithmetic
*/
if (format_desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
@@ -337,19 +421,174 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
format_desc->is_bitmask &&
!format_desc->is_mixed &&
(format_desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED ||
format_desc->channel[1].type == UTIL_FORMAT_TYPE_UNSIGNED))
{
LLVMValueRef packed;
format_desc->channel[1].type == UTIL_FORMAT_TYPE_UNSIGNED)) {
ptr = LLVMBuildBitCast(builder, ptr,
LLVMPointerType(LLVMIntType(format_desc->block.bits), 0) ,
"");
LLVMValueRef tmps[LP_MAX_VECTOR_LENGTH/4];
LLVMValueRef res;
unsigned k;
packed = LLVMBuildLoad(builder, ptr, "packed");
/*
* Unpack a pixel at a time into a <4 x float> RGBA vector
*/
return lp_build_unpack_rgba_aos(builder, format_desc, packed);
for (k = 0; k < num_pixels; ++k) {
LLVMValueRef packed;
packed = lp_build_gather_elem(builder, num_pixels,
format_desc->block.bits, 32,
base_ptr, offset, k);
tmps[k] = lp_build_unpack_arith_rgba_aos(builder, format_desc,
packed);
}
/*
* Type conversion.
*
* TODO: We could avoid floating conversion for integer to
* integer conversions.
*/
lp_build_conv(builder,
lp_float32_vec4_type(),
type,
tmps, num_pixels, &res, 1);
return lp_build_format_swizzle_aos(format_desc, &bld, res);
}
else if (format_desc->fetch_rgba_float) {
/*
* YUV / subsampled formats
*/
if (format_desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
struct lp_type tmp_type;
LLVMValueRef tmp;
memset(&tmp_type, 0, sizeof tmp_type);
tmp_type.width = 8;
tmp_type.length = num_pixels * 4;
tmp_type.norm = TRUE;
tmp = lp_build_fetch_subsampled_rgba_aos(builder,
format_desc,
num_pixels,
base_ptr,
offset,
i, j);
lp_build_conv(builder,
tmp_type, type,
&tmp, 1, &tmp, 1);
return tmp;
}
/*
* Fallback to util_format_description::fetch_rgba_8unorm().
*/
if (format_desc->fetch_rgba_8unorm &&
!type.floating && type.width == 8 && !type.sign && type.norm) {
/*
* Fallback to calling util_format_description::fetch_rgba_8unorm.
*
* This is definitely not the most efficient way of fetching pixels, as
* we miss the opportunity to do vectorization, but this it is a
* convenient for formats or scenarios for which there was no opportunity
* or incentive to optimize.
*/
LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)));
char name[256];
LLVMTypeRef i8t = LLVMInt8Type();
LLVMTypeRef pi8t = LLVMPointerType(i8t, 0);
LLVMTypeRef i32t = LLVMInt32Type();
LLVMValueRef function;
LLVMValueRef tmp_ptr;
LLVMValueRef tmp;
LLVMValueRef res;
unsigned k;
util_snprintf(name, sizeof name, "util_format_%s_fetch_rgba_8unorm",
format_desc->short_name);
/*
* Declare and bind format_desc->fetch_rgba_8unorm().
*/
function = LLVMGetNamedFunction(module, name);
if (!function) {
LLVMTypeRef ret_type;
LLVMTypeRef arg_types[4];
LLVMTypeRef function_type;
ret_type = LLVMVoidType();
arg_types[0] = pi8t;
arg_types[1] = pi8t;
arg_types[3] = arg_types[2] = LLVMIntType(sizeof(unsigned) * 8);
function_type = LLVMFunctionType(ret_type, arg_types, Elements(arg_types), 0);
function = LLVMAddFunction(module, name, function_type);
LLVMSetFunctionCallConv(function, LLVMCCallConv);
LLVMSetLinkage(function, LLVMExternalLinkage);
assert(LLVMIsDeclaration(function));
LLVMAddGlobalMapping(lp_build_engine, function,
func_to_pointer((func_pointer)format_desc->fetch_rgba_8unorm));
}
tmp_ptr = lp_build_alloca(builder, i32t, "");
res = LLVMGetUndef(LLVMVectorType(i32t, num_pixels));
/*
* Invoke format_desc->fetch_rgba_8unorm() for each pixel and insert the result
* in the SoA vectors.
*/
for (k = 0; k < num_pixels; ++k) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), k, 0);
LLVMValueRef args[4];
args[0] = LLVMBuildBitCast(builder, tmp_ptr, pi8t, "");
args[1] = lp_build_gather_elem_ptr(builder, num_pixels,
base_ptr, offset, k);
if (num_pixels == 1) {
args[2] = i;
args[3] = j;
}
else {
args[2] = LLVMBuildExtractElement(builder, i, index, "");
args[3] = LLVMBuildExtractElement(builder, j, index, "");
}
LLVMBuildCall(builder, function, args, Elements(args), "");
tmp = LLVMBuildLoad(builder, tmp_ptr, "");
if (num_pixels == 1) {
res = tmp;
}
else {
res = LLVMBuildInsertElement(builder, res, tmp, index, "");
}
}
/* Bitcast from <n x i32> to <4n x i8> */
res = LLVMBuildBitCast(builder, res, bld.vec_type, "");
return res;
}
/*
* Fallback to util_format_description::fetch_rgba_float().
*/
if (format_desc->fetch_rgba_float) {
/*
* Fallback to calling util_format_description::fetch_rgba_float.
*
@@ -361,9 +600,14 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder)));
char name[256];
LLVMTypeRef f32t = LLVMFloatType();
LLVMTypeRef f32x4t = LLVMVectorType(f32t, 4);
LLVMTypeRef pf32t = LLVMPointerType(f32t, 0);
LLVMValueRef function;
LLVMValueRef tmp;
LLVMValueRef args[4];
LLVMValueRef tmp_ptr;
LLVMValueRef tmps[LP_MAX_VECTOR_LENGTH/4];
LLVMValueRef res;
unsigned k;
util_snprintf(name, sizeof name, "util_format_%s_fetch_rgba_float",
format_desc->short_name);
@@ -379,7 +623,7 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
LLVMTypeRef function_type;
ret_type = LLVMVoidType();
arg_types[0] = LLVMPointerType(LLVMFloatType(), 0);
arg_types[0] = pf32t;
arg_types[1] = LLVMPointerType(LLVMInt8Type(), 0);
arg_types[3] = arg_types[2] = LLVMIntType(sizeof(unsigned) * 8);
function_type = LLVMFunctionType(ret_type, arg_types, Elements(arg_types), 0);
@@ -394,25 +638,43 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
func_to_pointer((func_pointer)format_desc->fetch_rgba_float));
}
tmp = lp_build_alloca(builder, LLVMVectorType(LLVMFloatType(), 4), "");
tmp_ptr = lp_build_alloca(builder, f32x4t, "");
/*
* Invoke format_desc->fetch_rgba_float() for each pixel and insert the result
* in the SoA vectors.
*/
args[0] = LLVMBuildBitCast(builder, tmp,
LLVMPointerType(LLVMFloatType(), 0), "");
args[1] = ptr;
args[2] = i;
args[3] = j;
for (k = 0; k < num_pixels; ++k) {
LLVMValueRef args[4];
LLVMBuildCall(builder, function, args, Elements(args), "");
args[0] = LLVMBuildBitCast(builder, tmp_ptr, pf32t, "");
args[1] = lp_build_gather_elem_ptr(builder, num_pixels,
base_ptr, offset, k);
return LLVMBuildLoad(builder, tmp, "");
}
else {
assert(0);
return LLVMGetUndef(LLVMVectorType(LLVMFloatType(), 4));
if (num_pixels == 1) {
args[2] = i;
args[3] = j;
}
else {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), k, 0);
args[2] = LLVMBuildExtractElement(builder, i, index, "");
args[3] = LLVMBuildExtractElement(builder, j, index, "");
}
LLVMBuildCall(builder, function, args, Elements(args), "");
tmps[k] = LLVMBuildLoad(builder, tmp_ptr, "");
}
lp_build_conv(builder,
lp_float32_vec4_type(),
type,
tmps, num_pixels, &res, 1);
return res;
}
assert(0);
return lp_build_undef(type);
}
@@ -36,7 +36,7 @@
#include "lp_bld_const.h"
#include "lp_bld_conv.h"
#include "lp_bld_swizzle.h"
#include "lp_bld_sample.h" /* for lp_build_gather */
#include "lp_bld_gather.h"
#include "lp_bld_format.h"
@@ -251,6 +251,41 @@ lp_build_unpack_rgba_soa(LLVMBuilderRef builder,
}
void
lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder,
struct lp_type dst_type,
LLVMValueRef packed,
LLVMValueRef *rgba)
{
LLVMValueRef mask = lp_build_const_int_vec(dst_type, 0xff);
unsigned chan;
packed = LLVMBuildBitCast(builder, packed,
lp_build_int_vec_type(dst_type), "");
/* Decode the input vector components */
for (chan = 0; chan < 4; ++chan) {
unsigned start = chan*8;
unsigned stop = start + 8;
LLVMValueRef input;
input = packed;
if (start)
input = LLVMBuildLShr(builder, input,
lp_build_const_int_vec(dst_type, start), "");
if (stop < 32)
input = LLVMBuildAnd(builder, input, mask, "");
input = lp_build_unsigned_norm_to_float(builder, 8, dst_type, input);
rgba[chan] = input;
}
}
/**
* Fetch a texels from a texture, returning them in SoA layout.
*
@@ -311,20 +346,49 @@ lp_build_fetch_rgba_soa(LLVMBuilderRef builder,
format_desc,
type,
packed, rgba_out);
return;
}
else {
/*
* Fallback to calling lp_build_fetch_rgba_aos for each pixel.
*
* This is not the most efficient way of fetching pixels, as we
* miss some opportunities to do vectorization, but this is
* convenient for formats or scenarios for which there was no
* opportunity or incentive to optimize.
*/
/*
* Try calling lp_build_fetch_rgba_aos for all pixels.
*/
if (util_format_fits_8unorm(format_desc) &&
type.floating && type.width == 32 && type.length == 4) {
struct lp_type tmp_type;
LLVMValueRef tmp;
memset(&tmp_type, 0, sizeof tmp_type);
tmp_type.width = 8;
tmp_type.length = type.length * 4;
tmp_type.norm = TRUE;
tmp = lp_build_fetch_rgba_aos(builder, format_desc, tmp_type,
base_ptr, offset, i, j);
lp_build_rgba8_to_f32_soa(builder,
type,
tmp,
rgba_out);
return;
}
/*
* Fallback to calling lp_build_fetch_rgba_aos for each pixel.
*
* This is not the most efficient way of fetching pixels, as we
* miss some opportunities to do vectorization, but this is
* convenient for formats or scenarios for which there was no
* opportunity or incentive to optimize.
*/
{
unsigned k, chan;
struct lp_type tmp_type;
assert(type.floating);
tmp_type = type;
tmp_type.length = 4;
for (chan = 0; chan < 4; ++chan) {
rgba_out[chan] = lp_build_undef(type);
@@ -334,18 +398,17 @@ lp_build_fetch_rgba_soa(LLVMBuilderRef builder,
for(k = 0; k < type.length; ++k) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), k, 0);
LLVMValueRef offset_elem;
LLVMValueRef ptr;
LLVMValueRef i_elem, j_elem;
LLVMValueRef tmp;
offset_elem = LLVMBuildExtractElement(builder, offset, index, "");
ptr = LLVMBuildGEP(builder, base_ptr, &offset_elem, 1, "");
i_elem = LLVMBuildExtractElement(builder, i, index, "");
j_elem = LLVMBuildExtractElement(builder, j, index, "");
/* Get a single float[4]={R,G,B,A} pixel */
tmp = lp_build_fetch_rgba_aos(builder, format_desc, ptr,
tmp = lp_build_fetch_rgba_aos(builder, format_desc, tmp_type,
base_ptr, offset_elem,
i_elem, j_elem);
/*
@@ -0,0 +1,399 @@
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
/**
* @file
* YUV pixel format manipulation.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
#include "util/u_format.h"
#include "lp_bld_arit.h"
#include "lp_bld_type.h"
#include "lp_bld_const.h"
#include "lp_bld_conv.h"
#include "lp_bld_gather.h"
#include "lp_bld_format.h"
/**
* Extract Y, U, V channels from packed UYVY.
* @param packed is a <n x i32> vector with the packed UYVY blocks
* @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
*/
static void
uyvy_to_yuv_soa(LLVMBuilderRef builder,
unsigned n,
LLVMValueRef packed,
LLVMValueRef i,
LLVMValueRef *y,
LLVMValueRef *u,
LLVMValueRef *v)
{
struct lp_type type;
LLVMValueRef shift, mask;
memset(&type, 0, sizeof type);
type.width = 32;
type.length = n;
assert(lp_check_value(type, packed));
assert(lp_check_value(type, i));
/*
* y = (uyvy >> 16*i) & 0xff
* u = (uyvy ) & 0xff
* v = (uyvy >> 16 ) & 0xff
*/
shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(type, 16), "");
shift = LLVMBuildAdd(builder, shift, lp_build_const_int_vec(type, 8), "");
*y = LLVMBuildLShr(builder, packed, shift, "");
*u = packed;
*v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 16), "");
mask = lp_build_const_int_vec(type, 0xff);
*y = LLVMBuildAnd(builder, *y, mask, "y");
*u = LLVMBuildAnd(builder, *u, mask, "u");
*v = LLVMBuildAnd(builder, *v, mask, "v");
}
/**
* Extract Y, U, V channels from packed YUYV.
* @param packed is a <n x i32> vector with the packed YUYV blocks
* @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
*/
static void
yuyv_to_yuv_soa(LLVMBuilderRef builder,
unsigned n,
LLVMValueRef packed,
LLVMValueRef i,
LLVMValueRef *y,
LLVMValueRef *u,
LLVMValueRef *v)
{
struct lp_type type;
LLVMValueRef shift, mask;
memset(&type, 0, sizeof type);
type.width = 32;
type.length = n;
assert(lp_check_value(type, packed));
assert(lp_check_value(type, i));
/*
* y = (yuyv >> 16*i) & 0xff
* u = (yuyv >> 8 ) & 0xff
* v = (yuyv >> 24 ) & 0xff
*/
shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(type, 16), "");
*y = LLVMBuildLShr(builder, packed, shift, "");
*u = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 8), "");
*v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 24), "");
mask = lp_build_const_int_vec(type, 0xff);
*y = LLVMBuildAnd(builder, *y, mask, "y");
*u = LLVMBuildAnd(builder, *u, mask, "u");
*v = LLVMBuildAnd(builder, *v, mask, "v");
}
static INLINE void
yuv_to_rgb_soa(LLVMBuilderRef builder,
unsigned n,
LLVMValueRef y, LLVMValueRef u, LLVMValueRef v,
LLVMValueRef *r, LLVMValueRef *g, LLVMValueRef *b)
{
struct lp_type type;
struct lp_build_context bld;
LLVMValueRef c0;
LLVMValueRef c8;
LLVMValueRef c16;
LLVMValueRef c128;
LLVMValueRef c255;
LLVMValueRef cy;
LLVMValueRef cug;
LLVMValueRef cub;
LLVMValueRef cvr;
LLVMValueRef cvg;
memset(&type, 0, sizeof type);
type.sign = TRUE;
type.width = 32;
type.length = n;
lp_build_context_init(&bld, builder, type);
assert(lp_check_value(type, y));
assert(lp_check_value(type, u));
assert(lp_check_value(type, v));
/*
* Constants
*/
c0 = lp_build_const_int_vec(type, 0);
c8 = lp_build_const_int_vec(type, 8);
c16 = lp_build_const_int_vec(type, 16);
c128 = lp_build_const_int_vec(type, 128);
c255 = lp_build_const_int_vec(type, 255);
cy = lp_build_const_int_vec(type, 298);
cug = lp_build_const_int_vec(type, -100);
cub = lp_build_const_int_vec(type, 516);
cvr = lp_build_const_int_vec(type, 409);
cvg = lp_build_const_int_vec(type, -208);
/*
* y -= 16;
* u -= 128;
* v -= 128;
*/
y = LLVMBuildSub(builder, y, c16, "");
u = LLVMBuildSub(builder, u, c128, "");
v = LLVMBuildSub(builder, v, c128, "");
/*
* r = 298 * _y + 409 * _v + 128;
* g = 298 * _y - 100 * _u - 208 * _v + 128;
* b = 298 * _y + 516 * _u + 128;
*/
y = LLVMBuildMul(builder, y, cy, "");
y = LLVMBuildAdd(builder, y, c128, "");
*r = LLVMBuildMul(builder, v, cvr, "");
*g = LLVMBuildAdd(builder,
LLVMBuildMul(builder, u, cug, ""),
LLVMBuildMul(builder, v, cvg, ""),
"");
*b = LLVMBuildMul(builder, u, cub, "");
*r = LLVMBuildAdd(builder, *r, y, "");
*g = LLVMBuildAdd(builder, *g, y, "");
*b = LLVMBuildAdd(builder, *b, y, "");
/*
* r >>= 8;
* g >>= 8;
* b >>= 8;
*/
*r = LLVMBuildAShr(builder, *r, c8, "r");
*g = LLVMBuildAShr(builder, *g, c8, "g");
*b = LLVMBuildAShr(builder, *b, c8, "b");
/*
* Clamp
*/
*r = lp_build_clamp(&bld, *r, c0, c255);
*g = lp_build_clamp(&bld, *g, c0, c255);
*b = lp_build_clamp(&bld, *b, c0, c255);
}
static LLVMValueRef
rgb_to_rgba_aos(LLVMBuilderRef builder,
unsigned n,
LLVMValueRef r, LLVMValueRef g, LLVMValueRef b)
{
struct lp_type type;
LLVMValueRef a;
LLVMValueRef rgba;
memset(&type, 0, sizeof type);
type.sign = TRUE;
type.width = 32;
type.length = n;
assert(lp_check_value(type, r));
assert(lp_check_value(type, g));
assert(lp_check_value(type, b));
/*
* Make a 4 x unorm8 vector
*/
r = r;
g = LLVMBuildShl(builder, g, lp_build_const_int_vec(type, 8), "");
b = LLVMBuildShl(builder, b, lp_build_const_int_vec(type, 16), "");
a = lp_build_const_int_vec(type, 0xff000000);
rgba = r;
rgba = LLVMBuildOr(builder, rgba, g, "");
rgba = LLVMBuildOr(builder, rgba, b, "");
rgba = LLVMBuildOr(builder, rgba, a, "");
rgba = LLVMBuildBitCast(builder, rgba,
LLVMVectorType(LLVMInt8Type(), 4*n), "");
return rgba;
}
/**
* Convert from <n x i32> packed UYVY to <4n x i8> RGBA AoS
*/
static LLVMValueRef
uyvy_to_rgba_aos(LLVMBuilderRef builder,
unsigned n,
LLVMValueRef packed,
LLVMValueRef i)
{
LLVMValueRef y, u, v;
LLVMValueRef r, g, b;
LLVMValueRef rgba;
uyvy_to_yuv_soa(builder, n, packed, i, &y, &u, &v);
yuv_to_rgb_soa(builder, n, y, u, v, &r, &g, &b);
rgba = rgb_to_rgba_aos(builder, n, r, g, b);
return rgba;
}
/**
* Convert from <n x i32> packed YUYV to <4n x i8> RGBA AoS
*/
static LLVMValueRef
yuyv_to_rgba_aos(LLVMBuilderRef builder,
unsigned n,
LLVMValueRef packed,
LLVMValueRef i)
{
LLVMValueRef y, u, v;
LLVMValueRef r, g, b;
LLVMValueRef rgba;
yuyv_to_yuv_soa(builder, n, packed, i, &y, &u, &v);
yuv_to_rgb_soa(builder, n, y, u, v, &r, &g, &b);
rgba = rgb_to_rgba_aos(builder, n, r, g, b);
return rgba;
}
/**
* Convert from <n x i32> packed RG_BG to <4n x i8> RGBA AoS
*/
static LLVMValueRef
rgbg_to_rgba_aos(LLVMBuilderRef builder,
unsigned n,
LLVMValueRef packed,
LLVMValueRef i)
{
LLVMValueRef r, g, b;
LLVMValueRef rgba;
uyvy_to_yuv_soa(builder, n, packed, i, &g, &r, &b);
rgba = rgb_to_rgba_aos(builder, n, r, g, b);
return rgba;
}
/**
* Convert from <n x i32> packed GR_GB to <4n x i8> RGBA AoS
*/
static LLVMValueRef
grgb_to_rgba_aos(LLVMBuilderRef builder,
unsigned n,
LLVMValueRef packed,
LLVMValueRef i)
{
LLVMValueRef r, g, b;
LLVMValueRef rgba;
yuyv_to_yuv_soa(builder, n, packed, i, &g, &r, &b);
rgba = rgb_to_rgba_aos(builder, n, r, g, b);
return rgba;
}
/**
* @param n is the number of pixels processed
* @param packed is a <n x i32> vector with the packed YUYV blocks
* @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
* @return a <4*n x i8> vector with the pixel RGBA values in AoS
*/
LLVMValueRef
lp_build_fetch_subsampled_rgba_aos(LLVMBuilderRef builder,
const struct util_format_description *format_desc,
unsigned n,
LLVMValueRef base_ptr,
LLVMValueRef offset,
LLVMValueRef i,
LLVMValueRef j)
{
LLVMValueRef packed;
LLVMValueRef rgba;
assert(format_desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED);
assert(format_desc->block.bits == 32);
assert(format_desc->block.width == 2);
assert(format_desc->block.height == 1);
packed = lp_build_gather(builder, n, 32, 32, base_ptr, offset);
(void)j;
switch (format_desc->format) {
case PIPE_FORMAT_UYVY:
rgba = uyvy_to_rgba_aos(builder, n, packed, i);
break;
case PIPE_FORMAT_YUYV:
rgba = yuyv_to_rgba_aos(builder, n, packed, i);
break;
case PIPE_FORMAT_R8G8_B8G8_UNORM:
rgba = rgbg_to_rgba_aos(builder, n, packed, i);
break;
case PIPE_FORMAT_G8R8_G8B8_UNORM:
rgba = grgb_to_rgba_aos(builder, n, packed, i);
break;
default:
assert(0);
rgba = LLVMGetUndef(LLVMVectorType(LLVMInt8Type(), 4*n));
break;
}
return rgba;
}
@@ -0,0 +1,148 @@
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
#include "util/u_debug.h"
#include "lp_bld_debug.h"
#include "lp_bld_const.h"
#include "lp_bld_format.h"
#include "lp_bld_gather.h"
/**
* Get the pointer to one element from scatter positions in memory.
*
* @sa lp_build_gather()
*/
LLVMValueRef
lp_build_gather_elem_ptr(LLVMBuilderRef builder,
unsigned length,
LLVMValueRef base_ptr,
LLVMValueRef offsets,
unsigned i)
{
LLVMValueRef offset;
LLVMValueRef ptr;
assert(LLVMTypeOf(base_ptr) == LLVMPointerType(LLVMInt8Type(), 0));
if (length == 1) {
assert(i == 0);
offset = offsets;
} else {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
offset = LLVMBuildExtractElement(builder, offsets, index, "");
}
ptr = LLVMBuildGEP(builder, base_ptr, &offset, 1, "");
return ptr;
}
/**
* Gather one element from scatter positions in memory.
*
* @sa lp_build_gather()
*/
LLVMValueRef
lp_build_gather_elem(LLVMBuilderRef builder,
unsigned length,
unsigned src_width,
unsigned dst_width,
LLVMValueRef base_ptr,
LLVMValueRef offsets,
unsigned i)
{
LLVMTypeRef src_type = LLVMIntType(src_width);
LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0);
LLVMTypeRef dst_elem_type = LLVMIntType(dst_width);
LLVMValueRef ptr;
LLVMValueRef res;
assert(LLVMTypeOf(base_ptr) == LLVMPointerType(LLVMInt8Type(), 0));
ptr = lp_build_gather_elem_ptr(builder, length, base_ptr, offsets, i);
ptr = LLVMBuildBitCast(builder, ptr, src_ptr_type, "");
res = LLVMBuildLoad(builder, ptr, "");
assert(src_width <= dst_width);
if (src_width > dst_width)
res = LLVMBuildTrunc(builder, res, dst_elem_type, "");
if (src_width < dst_width)
res = LLVMBuildZExt(builder, res, dst_elem_type, "");
return res;
}
/**
* Gather elements from scatter positions in memory into a single vector.
* Use for fetching texels from a texture.
* For SSE, typical values are length=4, src_width=32, dst_width=32.
*
* @param length length of the offsets
* @param src_width src element width in bits
* @param dst_width result element width in bits (src will be expanded to fit)
* @param base_ptr base pointer, should be a i8 pointer type.
* @param offsets vector with offsets
*/
LLVMValueRef
lp_build_gather(LLVMBuilderRef builder,
unsigned length,
unsigned src_width,
unsigned dst_width,
LLVMValueRef base_ptr,
LLVMValueRef offsets)
{
LLVMValueRef res;
if (length == 1) {
/* Scalar */
return lp_build_gather_elem(builder, length,
src_width, dst_width,
base_ptr, offsets, 0);
} else {
/* Vector */
LLVMTypeRef dst_elem_type = LLVMIntType(dst_width);
LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length);
unsigned i;
res = LLVMGetUndef(dst_vec_type);
for (i = 0; i < length; ++i) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
LLVMValueRef elem;
elem = lp_build_gather_elem(builder, length,
src_width, dst_width,
base_ptr, offsets, i);
res = LLVMBuildInsertElement(builder, res, elem, index, "");
}
}
return res;
}
@@ -0,0 +1,61 @@
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
#ifndef LP_BLD_GATHER_H_
#define LP_BLD_GATHER_H_
#include "gallivm/lp_bld.h"
LLVMValueRef
lp_build_gather_elem_ptr(LLVMBuilderRef builder,
unsigned length,
LLVMValueRef base_ptr,
LLVMValueRef offsets,
unsigned i);
LLVMValueRef
lp_build_gather_elem(LLVMBuilderRef builder,
unsigned length,
unsigned src_width,
unsigned dst_width,
LLVMValueRef base_ptr,
LLVMValueRef offsets,
unsigned i);
LLVMValueRef
lp_build_gather(LLVMBuilderRef builder,
unsigned length,
unsigned src_width,
unsigned dst_width,
LLVMValueRef base_ptr,
LLVMValueRef offsets);
#endif /* LP_BLD_GATHER_H_ */
@@ -32,6 +32,8 @@
#include "lp_bld_debug.h"
#include "lp_bld_init.h"
#include <llvm-c/Transforms/Scalar.h>
#ifdef DEBUG
unsigned gallivm_debug = 0;
@@ -50,6 +52,7 @@ LLVMModuleRef lp_build_module = NULL;
LLVMExecutionEngineRef lp_build_engine = NULL;
LLVMModuleProviderRef lp_build_provider = NULL;
LLVMTargetDataRef lp_build_target = NULL;
LLVMPassManagerRef lp_build_pass = NULL;
/*
@@ -127,6 +130,33 @@ lp_build_init(void)
if (!lp_build_target)
lp_build_target = LLVMGetExecutionEngineTargetData(lp_build_engine);
if (!lp_build_pass) {
lp_build_pass = LLVMCreateFunctionPassManager(lp_build_provider);
LLVMAddTargetData(lp_build_target, lp_build_pass);
if ((gallivm_debug & GALLIVM_DEBUG_NO_OPT) == 0) {
/* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
* but there are more on SVN. */
/* TODO: Add more passes */
LLVMAddCFGSimplificationPass(lp_build_pass);
LLVMAddPromoteMemoryToRegisterPass(lp_build_pass);
LLVMAddConstantPropagationPass(lp_build_pass);
if(util_cpu_caps.has_sse4_1) {
/* FIXME: There is a bug in this pass, whereby the combination of fptosi
* and sitofp (necessary for trunc/floor/ceil/round implementation)
* somehow becomes invalid code.
*/
LLVMAddInstructionCombiningPass(lp_build_pass);
}
LLVMAddGVNPass(lp_build_pass);
} else {
/* We need at least this pass to prevent the backends to fail in
* unexpected ways.
*/
LLVMAddPromoteMemoryToRegisterPass(lp_build_pass);
}
}
util_cpu_detect();
#if 0
@@ -38,6 +38,7 @@ extern LLVMModuleRef lp_build_module;
extern LLVMExecutionEngineRef lp_build_engine;
extern LLVMModuleProviderRef lp_build_provider;
extern LLVMTargetDataRef lp_build_target;
extern LLVMPassManagerRef lp_build_pass;
void
+44 -5
View File
@@ -34,6 +34,7 @@
#include "util/u_cpu_detect.h"
#include "util/u_memory.h"
#include "util/u_debug.h"
#include "lp_bld_type.h"
@@ -187,12 +188,10 @@ lp_build_compare(LLVMBuilderRef builder,
return lp_build_undef(type);
}
/* There are no signed byte and unsigned word/dword comparison
* instructions. So flip the sign bit so that the results match.
/* There are no unsigned comparison instructions. So flip the sign bit
* so that the results match.
*/
if(table[func].gt &&
((type.width == 8 && type.sign) ||
(type.width != 8 && !type.sign))) {
if (table[func].gt && !type.sign) {
LLVMValueRef msb = lp_build_const_int_vec(type, (unsigned long long)1 << (type.width - 1));
a = LLVMBuildXor(builder, a, msb, "");
b = LLVMBuildXor(builder, b, msb, "");
@@ -384,6 +383,46 @@ lp_build_select(struct lp_build_context *bld,
mask = LLVMBuildTrunc(bld->builder, mask, LLVMInt1Type(), "");
res = LLVMBuildSelect(bld->builder, mask, a, b, "");
}
else if (util_cpu_caps.has_sse4_1 &&
type.width * type.length == 128 &&
!LLVMIsConstant(a) &&
!LLVMIsConstant(b) &&
!LLVMIsConstant(mask)) {
const char *intrinsic;
LLVMTypeRef arg_type;
LLVMValueRef args[3];
if (type.width == 64) {
intrinsic = "llvm.x86.sse41.blendvpd";
arg_type = LLVMVectorType(LLVMDoubleType(), 2);
} else if (type.width == 32) {
intrinsic = "llvm.x86.sse41.blendvps";
arg_type = LLVMVectorType(LLVMFloatType(), 4);
} else {
intrinsic = "llvm.x86.sse41.pblendvb";
arg_type = LLVMVectorType(LLVMInt8Type(), 16);
}
if (arg_type != bld->int_vec_type) {
mask = LLVMBuildBitCast(bld->builder, mask, arg_type, "");
}
if (arg_type != bld->vec_type) {
a = LLVMBuildBitCast(bld->builder, a, arg_type, "");
b = LLVMBuildBitCast(bld->builder, b, arg_type, "");
}
args[0] = b;
args[1] = a;
args[2] = mask;
res = lp_build_intrinsic(bld->builder, intrinsic,
arg_type, args, Elements(args));
if (arg_type != bld->vec_type) {
res = LLVMBuildBitCast(bld->builder, res, bld->vec_type, "");
}
}
else {
if(type.floating) {
LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
+120
View File
@@ -427,3 +427,123 @@ lp_build_pack(LLVMBuilderRef builder,
return tmp[0];
}
/**
* Truncate or expand the bitwidth.
*
* NOTE: Getting the right sign flags is crucial here, as we employ some
* intrinsics that do saturation.
*/
void
lp_build_resize(LLVMBuilderRef builder,
struct lp_type src_type,
struct lp_type dst_type,
const LLVMValueRef *src, unsigned num_srcs,
LLVMValueRef *dst, unsigned num_dsts)
{
LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH];
unsigned i;
/*
* We don't support float <-> int conversion here. That must be done
* before/after calling this function.
*/
assert(src_type.floating == dst_type.floating);
/*
* We don't support double <-> float conversion yet, although it could be
* added with little effort.
*/
assert((!src_type.floating && !dst_type.floating) ||
src_type.width == dst_type.width);
/* We must not loose or gain channels. Only precision */
assert(src_type.length * num_srcs == dst_type.length * num_dsts);
/* We don't support M:N conversion, only 1:N, M:1, or 1:1 */
assert(num_srcs == 1 || num_dsts == 1);
assert(src_type.length <= LP_MAX_VECTOR_LENGTH);
assert(dst_type.length <= LP_MAX_VECTOR_LENGTH);
assert(num_srcs <= LP_MAX_VECTOR_LENGTH);
assert(num_dsts <= LP_MAX_VECTOR_LENGTH);
if (src_type.width > dst_type.width) {
/*
* Truncate bit width.
*/
assert(num_dsts == 1);
if (src_type.width * src_type.length == dst_type.width * dst_type.length) {
/*
* Register width remains constant -- use vector packing intrinsics
*/
tmp[0] = lp_build_pack(builder, src_type, dst_type, TRUE, src, num_srcs);
}
else {
/*
* Do it element-wise.
*/
assert(src_type.length == dst_type.length);
tmp[0] = lp_build_undef(dst_type);
for (i = 0; i < dst_type.length; ++i) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
LLVMValueRef val = LLVMBuildExtractElement(builder, src[0], index, "");
val = LLVMBuildTrunc(builder, val, lp_build_elem_type(dst_type), "");
tmp[0] = LLVMBuildInsertElement(builder, tmp[0], val, index, "");
}
}
}
else if (src_type.width < dst_type.width) {
/*
* Expand bit width.
*/
assert(num_srcs == 1);
if (src_type.width * src_type.length == dst_type.width * dst_type.length) {
/*
* Register width remains constant -- use vector unpack intrinsics
*/
lp_build_unpack(builder, src_type, dst_type, src[0], tmp, num_dsts);
}
else {
/*
* Do it element-wise.
*/
assert(src_type.length == dst_type.length);
tmp[0] = lp_build_undef(dst_type);
for (i = 0; i < dst_type.length; ++i) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
LLVMValueRef val = LLVMBuildExtractElement(builder, src[0], index, "");
if (src_type.sign && dst_type.sign) {
val = LLVMBuildSExt(builder, val, lp_build_elem_type(dst_type), "");
} else {
val = LLVMBuildZExt(builder, val, lp_build_elem_type(dst_type), "");
}
tmp[0] = LLVMBuildInsertElement(builder, tmp[0], val, index, "");
}
}
}
else {
/*
* No-op
*/
assert(num_srcs == 1);
assert(num_dsts == 1);
tmp[0] = src[0];
}
for(i = 0; i < num_dsts; ++i)
dst[i] = tmp[i];
}
@@ -92,4 +92,12 @@ lp_build_pack(LLVMBuilderRef builder,
const LLVMValueRef *src, unsigned num_srcs);
void
lp_build_resize(LLVMBuilderRef builder,
struct lp_type src_type,
struct lp_type dst_type,
const LLVMValueRef *src, unsigned num_srcs,
LLVMValueRef *dst, unsigned num_dsts);
#endif /* !LP_BLD_PACK_H */
+4 -4
View File
@@ -61,8 +61,8 @@ LLVMValueRef
lp_build_ddx(struct lp_build_context *bld,
LLVMValueRef a)
{
LLVMValueRef a_left = lp_build_swizzle1_aos(bld, a, swizzle_left);
LLVMValueRef a_right = lp_build_swizzle1_aos(bld, a, swizzle_right);
LLVMValueRef a_left = lp_build_swizzle_aos(bld, a, swizzle_left);
LLVMValueRef a_right = lp_build_swizzle_aos(bld, a, swizzle_right);
return lp_build_sub(bld, a_right, a_left);
}
@@ -71,8 +71,8 @@ LLVMValueRef
lp_build_ddy(struct lp_build_context *bld,
LLVMValueRef a)
{
LLVMValueRef a_top = lp_build_swizzle1_aos(bld, a, swizzle_top);
LLVMValueRef a_bottom = lp_build_swizzle1_aos(bld, a, swizzle_bottom);
LLVMValueRef a_top = lp_build_swizzle_aos(bld, a, swizzle_top);
LLVMValueRef a_bottom = lp_build_swizzle_aos(bld, a, swizzle_bottom);
return lp_build_sub(bld, a_bottom, a_top);
}
+38 -57
View File
@@ -40,7 +40,6 @@
#include "lp_bld_const.h"
#include "lp_bld_arit.h"
#include "lp_bld_type.h"
#include "lp_bld_format.h"
#include "lp_bld_sample.h"
@@ -124,74 +123,54 @@ lp_sampler_static_state(struct lp_sampler_static_state *state,
}
/**
* Gather elements from scatter positions in memory into a single vector.
* Use for fetching texels from a texture.
* For SSE, typical values are length=4, src_width=32, dst_width=32.
*
* @param length length of the offsets
* @param src_width src element width in bits
* @param dst_width result element width in bits (src will be expanded to fit)
* @param base_ptr base pointer, should be a i8 pointer type.
* @param offsets vector with offsets
*/
LLVMValueRef
lp_build_gather(LLVMBuilderRef builder,
unsigned length,
unsigned src_width,
unsigned dst_width,
LLVMValueRef base_ptr,
LLVMValueRef offsets)
{
LLVMTypeRef src_type = LLVMIntType(src_width);
LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0);
LLVMTypeRef dst_elem_type = LLVMIntType(dst_width);
LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length);
LLVMValueRef res;
unsigned i;
res = LLVMGetUndef(dst_vec_type);
for(i = 0; i < length; ++i) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
LLVMValueRef elem_offset;
LLVMValueRef elem_ptr;
LLVMValueRef elem;
elem_offset = LLVMBuildExtractElement(builder, offsets, index, "");
elem_ptr = LLVMBuildGEP(builder, base_ptr, &elem_offset, 1, "");
elem_ptr = LLVMBuildBitCast(builder, elem_ptr, src_ptr_type, "");
elem = LLVMBuildLoad(builder, elem_ptr, "");
assert(src_width <= dst_width);
if(src_width > dst_width)
elem = LLVMBuildTrunc(builder, elem, dst_elem_type, "");
if(src_width < dst_width)
elem = LLVMBuildZExt(builder, elem, dst_elem_type, "");
res = LLVMBuildInsertElement(builder, res, elem, index, "");
}
return res;
}
/**
* Compute the offset of a pixel block.
*
* x, y, z, y_stride, z_stride are vectors, and they refer to pixel blocks, as
* per format description, and not individual pixels.
* x, y, z, y_stride, z_stride are vectors, and they refer to pixels.
*
* Returns the relative offset and i,j sub-block coordinates
*/
LLVMValueRef
void
lp_build_sample_offset(struct lp_build_context *bld,
const struct util_format_description *format_desc,
LLVMValueRef x,
LLVMValueRef y,
LLVMValueRef z,
LLVMValueRef y_stride,
LLVMValueRef z_stride)
LLVMValueRef z_stride,
LLVMValueRef *out_offset,
LLVMValueRef *out_i,
LLVMValueRef *out_j)
{
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);
@@ -206,5 +185,7 @@ lp_build_sample_offset(struct lp_build_context *bld,
offset = lp_build_add(bld, offset, z_offset);
}
return offset;
*out_offset = offset;
*out_i = i;
*out_j = j;
}
+5 -11
View File
@@ -146,23 +146,17 @@ lp_sampler_static_state(struct lp_sampler_static_state *state,
const struct pipe_sampler_state *sampler);
LLVMValueRef
lp_build_gather(LLVMBuilderRef builder,
unsigned length,
unsigned src_width,
unsigned dst_width,
LLVMValueRef base_ptr,
LLVMValueRef offsets);
LLVMValueRef
void
lp_build_sample_offset(struct lp_build_context *bld,
const struct util_format_description *format_desc,
LLVMValueRef x,
LLVMValueRef y,
LLVMValueRef z,
LLVMValueRef y_stride,
LLVMValueRef z_stride);
LLVMValueRef z_stride,
LLVMValueRef *out_offset,
LLVMValueRef *out_i,
LLVMValueRef *out_j);
void
+106 -113
View File
@@ -50,8 +50,10 @@
#include "lp_bld_swizzle.h"
#include "lp_bld_pack.h"
#include "lp_bld_flow.h"
#include "lp_bld_gather.h"
#include "lp_bld_format.h"
#include "lp_bld_sample.h"
#include "lp_bld_quad.h"
/**
@@ -264,35 +266,11 @@ lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
}
}
/*
* 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 (bld->format_desc->block.width == 1) {
i = bld->uint_coord_bld.zero;
}
else {
LLVMValueRef block_width = lp_build_const_int_vec(bld->uint_coord_bld.type, bld->format_desc->block.width);
i = LLVMBuildURem(bld->builder, x, block_width, "");
x = LLVMBuildUDiv(bld->builder, x, block_width, "");
}
if (bld->format_desc->block.height == 1) {
j = bld->uint_coord_bld.zero;
}
else {
LLVMValueRef block_height = lp_build_const_int_vec(bld->uint_coord_bld.type, bld->format_desc->block.height);
j = LLVMBuildURem(bld->builder, y, block_height, "");
y = LLVMBuildUDiv(bld->builder, y, block_height, "");
}
/* convert x,y,z coords to linear offset from start of texture, in bytes */
offset = lp_build_sample_offset(&bld->uint_coord_bld,
bld->format_desc,
x, y, z, y_stride, z_stride);
lp_build_sample_offset(&bld->uint_coord_bld,
bld->format_desc,
x, y, z, y_stride, z_stride,
&offset, &i, &j);
if (use_border) {
/* If we can sample the border color, it means that texcoords may
@@ -344,6 +322,9 @@ 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,
@@ -351,25 +332,46 @@ lp_build_sample_packed(struct lp_build_sample_context *bld,
LLVMValueRef y_stride,
LLVMValueRef data_array)
{
LLVMValueRef offset;
LLVMValueRef offset, i, j;
LLVMValueRef data_ptr;
LLVMValueRef res;
offset = lp_build_sample_offset(&bld->uint_coord_bld,
bld->format_desc,
x, y, NULL, y_stride, NULL);
assert(bld->format_desc->block.width == 1);
assert(bld->format_desc->block.height == 1);
assert(bld->format_desc->block.bits <= bld->texel_type.width);
/* 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);
return lp_build_gather(bld->builder,
bld->texel_type.length,
bld->format_desc->block.bits,
bld->texel_type.width,
data_ptr, offset);
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;
}
@@ -817,9 +819,8 @@ lp_build_minify(struct lp_build_sample_context *bld,
/**
* Generate code to compute texture level of detail (lambda).
* \param s vector of texcoord s values
* \param t vector of texcoord t values
* \param r vector of texcoord r values
* \param ddx partial derivatives of (s, t, r, q) with respect to X
* \param ddy partial derivatives of (s, t, r, q) with respect to Y
* \param lod_bias optional float vector with the shader lod bias
* \param explicit_lod optional float vector with the explicit lod
* \param width scalar int texture width
@@ -831,11 +832,8 @@ lp_build_minify(struct lp_build_sample_context *bld,
*/
static LLVMValueRef
lp_build_lod_selector(struct lp_build_sample_context *bld,
LLVMValueRef s,
LLVMValueRef t,
LLVMValueRef r,
const LLVMValueRef *ddx,
const LLVMValueRef *ddy,
const LLVMValueRef ddx[4],
const LLVMValueRef ddy[4],
LLVMValueRef lod_bias, /* optional */
LLVMValueRef explicit_lod, /* optional */
LLVMValueRef width,
@@ -870,14 +868,6 @@ lp_build_lod_selector(struct lp_build_sample_context *bld,
LLVMValueRef dtdx = NULL, dtdy = NULL, drdx = NULL, drdy = NULL;
LLVMValueRef rho;
/*
* dsdx = abs(s[1] - s[0]);
* dsdy = abs(s[2] - s[0]);
* dtdx = abs(t[1] - t[0]);
* dtdy = abs(t[2] - t[0]);
* drdx = abs(r[1] - r[0]);
* drdy = abs(r[2] - r[0]);
*/
dsdx = LLVMBuildExtractElement(bld->builder, ddx[0], index0, "dsdx");
dsdx = lp_build_abs(float_bld, dsdx);
dsdy = LLVMBuildExtractElement(bld->builder, ddy[0], index0, "dsdy");
@@ -1287,7 +1277,7 @@ lp_build_cube_face(struct lp_build_sample_context *bld,
/**
* Generate code to do cube face selection and per-face texcoords.
* Generate code to do cube face selection and compute per-face texcoords.
*/
static void
lp_build_cube_lookup(struct lp_build_sample_context *bld,
@@ -1411,7 +1401,6 @@ lp_build_cube_lookup(struct lp_build_sample_context *bld,
lp_build_endif(&if_ctx2);
lp_build_flow_scope_end(flow_ctx2);
lp_build_flow_destroy(flow_ctx2);
*face_s = face_s2;
*face_t = face_t2;
*face = face2;
@@ -1457,13 +1446,14 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
int chan;
if (img_filter == PIPE_TEX_FILTER_NEAREST) {
/* sample the first mipmap level */
lp_build_sample_image_nearest(bld,
width0_vec, height0_vec, depth0_vec,
row_stride0_vec, img_stride0_vec,
data_ptr0, s, t, r, colors0);
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
/* sample the second mipmap level, and interp */
/* sample the second mipmap level */
lp_build_sample_image_nearest(bld,
width1_vec, height1_vec, depth1_vec,
row_stride1_vec, img_stride1_vec,
@@ -1473,13 +1463,14 @@ lp_build_sample_mipmap(struct lp_build_sample_context *bld,
else {
assert(img_filter == PIPE_TEX_FILTER_LINEAR);
/* sample the first mipmap level */
lp_build_sample_image_linear(bld,
width0_vec, height0_vec, depth0_vec,
row_stride0_vec, img_stride0_vec,
data_ptr0, s, t, r, colors0);
if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
/* sample the second mipmap level, and interp */
/* sample the second mipmap level */
lp_build_sample_image_linear(bld,
width1_vec, height1_vec, depth1_vec,
row_stride1_vec, img_stride1_vec,
@@ -1542,12 +1533,37 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
LLVMValueRef row_stride0_vec = NULL, row_stride1_vec = NULL;
LLVMValueRef img_stride0_vec = NULL, img_stride1_vec = NULL;
LLVMValueRef data_ptr0, data_ptr1 = NULL;
LLVMValueRef face_ddx[4], face_ddy[4];
/*
printf("%s mip %d min %d mag %d\n", __FUNCTION__,
mip_filter, min_filter, mag_filter);
*/
/*
* Choose cube face, recompute texcoords and derivatives for the chosen face.
*/
if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
LLVMValueRef face, face_s, face_t;
lp_build_cube_lookup(bld, s, t, r, &face, &face_s, &face_t);
s = face_s; /* vec */
t = face_t; /* vec */
/* use 'r' to indicate cube face */
r = lp_build_broadcast_scalar(&bld->int_coord_bld, face); /* vec */
/* recompute ddx, ddy using the new (s,t) face texcoords */
face_ddx[0] = lp_build_ddx(&bld->coord_bld, s);
face_ddx[1] = lp_build_ddx(&bld->coord_bld, t);
face_ddx[2] = NULL;
face_ddx[3] = NULL;
face_ddy[0] = lp_build_ddy(&bld->coord_bld, s);
face_ddy[1] = lp_build_ddy(&bld->coord_bld, t);
face_ddy[2] = NULL;
face_ddy[3] = NULL;
ddx = face_ddx;
ddy = face_ddy;
}
/*
* Compute the level of detail (float).
*/
@@ -1556,7 +1572,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
/* Need to compute lod either to choose mipmap levels or to
* distinguish between minification/magnification with one mipmap level.
*/
lod = lp_build_lod_selector(bld, s, t, r, ddx, ddy,
lod = lp_build_lod_selector(bld, ddx, ddy,
lod_bias, explicit_lod,
width, height, depth);
}
@@ -1566,9 +1582,20 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
*/
if (mip_filter == PIPE_TEX_MIPFILTER_NONE) {
/* always use mip level 0 */
ilevel0 = LLVMConstInt(LLVMInt32Type(), 0, 0);
if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
/* XXX this is a work-around for an apparent bug in LLVM 2.7.
* We should be able to set ilevel0 = const(0) but that causes
* bad x86 code to be emitted.
*/
lod = lp_build_const_elem(bld->coord_bld.type, 0.0);
lp_build_nearest_mip_level(bld, unit, lod, &ilevel0);
}
else {
ilevel0 = LLVMConstInt(LLVMInt32Type(), 0, 0);
}
}
else {
assert(lod);
if (mip_filter == PIPE_TEX_MIPFILTER_NEAREST) {
lp_build_nearest_mip_level(bld, unit, lod, &ilevel0);
}
@@ -1622,18 +1649,6 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
}
}
/*
* Choose cube face, recompute per-face texcoords.
*/
if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
LLVMValueRef face, face_s, face_t;
lp_build_cube_lookup(bld, s, t, r, &face, &face_s, &face_t);
s = face_s; /* vec */
t = face_t; /* vec */
/* use 'r' to indicate cube face */
r = lp_build_broadcast_scalar(&bld->int_coord_bld, face); /* vec */
}
/*
* Get pointer(s) to image data for mipmap level(s).
*/
@@ -1711,36 +1726,6 @@ lp_build_sample_general(struct lp_build_sample_context *bld,
static void
lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder,
struct lp_type dst_type,
LLVMValueRef packed,
LLVMValueRef *rgba)
{
LLVMValueRef mask = lp_build_const_int_vec(dst_type, 0xff);
unsigned chan;
/* Decode the input vector components */
for (chan = 0; chan < 4; ++chan) {
unsigned start = chan*8;
unsigned stop = start + 8;
LLVMValueRef input;
input = packed;
if(start)
input = LLVMBuildLShr(builder, input, lp_build_const_int_vec(dst_type, start), "");
if(stop < 32)
input = LLVMBuildAnd(builder, input, mask, "");
input = lp_build_unsigned_norm_to_float(builder, 8, dst_type, input);
rgba[chan] = input;
}
}
static void
lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
LLVMValueRef s,
@@ -1935,15 +1920,20 @@ lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld,
* Convert to SoA and swizzle.
*/
packed = LLVMBuildBitCast(builder, packed, i32_vec_type, "");
lp_build_rgba8_to_f32_soa(bld->builder,
bld->texel_type,
packed, unswizzled);
lp_build_format_swizzle_soa(bld->format_desc,
&bld->texel_bld,
unswizzled, texel_out);
if (util_format_is_rgba8_variant(bld->format_desc)) {
lp_build_format_swizzle_soa(bld->format_desc,
&bld->texel_bld,
unswizzled, texel_out);
} else {
texel_out[0] = unswizzled[0];
texel_out[1] = unswizzled[1];
texel_out[2] = unswizzled[2];
texel_out[3] = unswizzled[3];
}
apply_sampler_swizzle(bld, texel_out);
}
@@ -2007,6 +1997,8 @@ lp_build_sample_nop(struct lp_build_sample_context *bld,
* 'texel' will return a vector of four LLVMValueRefs corresponding to
* R, G, B, A.
* \param type vector float type to use for coords, etc.
* \param ddx partial derivatives of (s,t,r,q) with respect to x
* \param ddy partial derivatives of (s,t,r,q) with respect to y
*/
void
lp_build_sample_soa(LLVMBuilderRef builder,
@@ -2016,8 +2008,8 @@ lp_build_sample_soa(LLVMBuilderRef builder,
unsigned unit,
unsigned num_coords,
const LLVMValueRef *coords,
const LLVMValueRef *ddx,
const LLVMValueRef *ddy,
const LLVMValueRef ddx[4],
const LLVMValueRef ddy[4],
LLVMValueRef lod_bias, /* optional */
LLVMValueRef explicit_lod, /* optional */
LLVMValueRef texel_out[4])
@@ -2079,7 +2071,8 @@ lp_build_sample_soa(LLVMBuilderRef builder,
/* For debug: no-op texture sampling */
lp_build_sample_nop(&bld, texel_out);
}
else if (util_format_is_rgba8_variant(bld.format_desc) &&
else if (util_format_fits_8unorm(bld.format_desc) &&
bld.format_desc->nr_channels > 1 &&
static_state->target == PIPE_TEXTURE_2D &&
static_state->min_img_filter == PIPE_TEX_FILTER_LINEAR &&
static_state->mag_img_filter == PIPE_TEX_FILTER_LINEAR &&
+153 -56
View File
@@ -110,7 +110,7 @@ lp_build_broadcast_aos(struct lp_build_context *bld,
/* XXX: SSE3 has PSHUFB which should be better than bitmasks, but forcing
* using shuffles here actually causes worst results. More investigation is
* needed. */
if (n <= 4) {
if (type.width >= 16) {
/*
* Shuffle.
*/
@@ -132,7 +132,7 @@ lp_build_broadcast_aos(struct lp_build_context *bld,
* YY00 YY00 .... YY00
* YYYY YYYY .... YYYY <= output
*/
struct lp_type type4 = type;
struct lp_type type4;
const char shifts[4][2] = {
{ 1, 2},
{-1, 2},
@@ -147,6 +147,13 @@ lp_build_broadcast_aos(struct lp_build_context *bld,
a = LLVMBuildAnd(bld->builder, a, lp_build_const_mask_aos(type, cond), "");
/*
* Build a type where each element is an integer that cover the four
* channels.
*/
type4 = type;
type4.floating = FALSE;
type4.width *= 4;
type4.length /= 4;
@@ -176,80 +183,170 @@ lp_build_broadcast_aos(struct lp_build_context *bld,
LLVMValueRef
lp_build_swizzle1_aos(struct lp_build_context *bld,
LLVMValueRef a,
const unsigned char swizzle[4])
lp_build_swizzle_aos(struct lp_build_context *bld,
LLVMValueRef a,
const unsigned char swizzles[4])
{
const unsigned n = bld->type.length;
const struct lp_type type = bld->type;
const unsigned n = type.length;
unsigned i, j;
if(a == bld->undef || a == bld->zero || a == bld->one)
if (swizzles[0] == PIPE_SWIZZLE_RED &&
swizzles[1] == PIPE_SWIZZLE_GREEN &&
swizzles[2] == PIPE_SWIZZLE_BLUE &&
swizzles[3] == PIPE_SWIZZLE_ALPHA) {
return a;
}
if(swizzle[0] == swizzle[1] && swizzle[1] == swizzle[2] && swizzle[2] == swizzle[3])
return lp_build_broadcast_aos(bld, a, swizzle[0]);
if (swizzles[0] == swizzles[1] &&
swizzles[1] == swizzles[2] &&
swizzles[2] == swizzles[3]) {
switch (swizzles[0]) {
case PIPE_SWIZZLE_RED:
case PIPE_SWIZZLE_GREEN:
case PIPE_SWIZZLE_BLUE:
case PIPE_SWIZZLE_ALPHA:
return lp_build_broadcast_aos(bld, a, swizzles[0]);
case PIPE_SWIZZLE_ZERO:
return bld->zero;
case PIPE_SWIZZLE_ONE:
return bld->one;
default:
assert(0);
return bld->undef;
}
}
{
if (type.width >= 16) {
/*
* Shuffle.
*/
LLVMTypeRef elem_type = LLVMInt32Type();
LLVMValueRef undef = LLVMGetUndef(lp_build_elem_type(type));
LLVMTypeRef i32t = LLVMInt32Type();
LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH];
LLVMValueRef aux[LP_MAX_VECTOR_LENGTH];
for(j = 0; j < n; j += 4)
for(i = 0; i < 4; ++i)
shuffles[j + i] = LLVMConstInt(elem_type, j + swizzle[i], 0);
memset(aux, 0, sizeof aux);
return LLVMBuildShuffleVector(bld->builder, a, bld->undef, LLVMConstVector(shuffles, n), "");
}
}
for(j = 0; j < n; j += 4) {
for(i = 0; i < 4; ++i) {
unsigned shuffle;
switch (swizzles[i]) {
default:
assert(0);
/* fall through */
case PIPE_SWIZZLE_RED:
case PIPE_SWIZZLE_GREEN:
case PIPE_SWIZZLE_BLUE:
case PIPE_SWIZZLE_ALPHA:
shuffle = j + swizzles[i];
break;
case PIPE_SWIZZLE_ZERO:
shuffle = type.length + 0;
if (!aux[0]) {
aux[0] = lp_build_const_elem(type, 0.0);
}
break;
case PIPE_SWIZZLE_ONE:
shuffle = type.length + 1;
if (!aux[1]) {
aux[1] = lp_build_const_elem(type, 1.0);
}
break;
}
shuffles[j + i] = LLVMConstInt(i32t, shuffle, 0);
}
}
for (i = 0; i < n; ++i) {
if (!aux[i]) {
aux[i] = undef;
}
}
LLVMValueRef
lp_build_swizzle2_aos(struct lp_build_context *bld,
LLVMValueRef a,
LLVMValueRef b,
const unsigned char swizzle[4])
{
const unsigned n = bld->type.length;
unsigned i, j;
if(swizzle[0] < 4 && swizzle[1] < 4 && swizzle[2] < 4 && swizzle[3] < 4)
return lp_build_swizzle1_aos(bld, a, swizzle);
if(a == b) {
unsigned char swizzle1[4];
swizzle1[0] = swizzle[0] % 4;
swizzle1[1] = swizzle[1] % 4;
swizzle1[2] = swizzle[2] % 4;
swizzle1[3] = swizzle[3] % 4;
return lp_build_swizzle1_aos(bld, a, swizzle1);
}
if(swizzle[0] % 4 == 0 &&
swizzle[1] % 4 == 1 &&
swizzle[2] % 4 == 2 &&
swizzle[3] % 4 == 3) {
return LLVMBuildShuffleVector(bld->builder, a,
LLVMConstVector(aux, n),
LLVMConstVector(shuffles, n), "");
} else {
/*
* Bit mask and shifts.
*
* For example, this will convert BGRA to RGBA by doing
*
* rgba = (bgra & 0x00ff0000) >> 16
* | (bgra & 0xff00ff00)
* | (bgra & 0x000000ff) << 16
*
* This is necessary not only for faster cause, but because X86 backend
* will refuse shuffles of <4 x i8> vectors
*/
LLVMValueRef res;
struct lp_type type4;
boolean cond[4];
cond[0] = swizzle[0] / 4;
cond[1] = swizzle[1] / 4;
cond[2] = swizzle[2] / 4;
cond[3] = swizzle[3] / 4;
return lp_build_select_aos(bld, a, b, cond);
}
unsigned chan;
int shift;
{
/*
* Shuffle.
* Start with a mixture of 1 and 0.
*/
LLVMTypeRef elem_type = LLVMInt32Type();
LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH];
for (chan = 0; chan < 4; ++chan) {
cond[chan] = swizzles[chan] == PIPE_SWIZZLE_ONE ? TRUE : FALSE;
}
res = lp_build_select_aos(bld, bld->one, bld->zero, cond);
for(j = 0; j < n; j += 4)
for(i = 0; i < 4; ++i)
shuffles[j + i] = LLVMConstInt(elem_type, j + (swizzle[i] % 4) + (swizzle[i] / 4 * n), 0);
/*
* Build a type where each element is an integer that cover the four
* channels.
*/
type4 = type;
type4.floating = FALSE;
type4.width *= 4;
type4.length /= 4;
return LLVMBuildShuffleVector(bld->builder, a, b, LLVMConstVector(shuffles, n), "");
a = LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(type4), "");
res = LLVMBuildBitCast(bld->builder, res, lp_build_vec_type(type4), "");
/*
* Mask and shift the channels, trying to group as many channels in the
* same shift as possible
*/
for (shift = -3; shift <= 3; ++shift) {
unsigned long long mask = 0;
assert(type4.width <= sizeof(mask)*8);
for (chan = 0; chan < 4; ++chan) {
/* FIXME: big endian */
if (swizzles[chan] < 4 &&
chan - swizzles[chan] == shift) {
mask |= ((1ULL << type.width) - 1) << (swizzles[chan] * type.width);
}
}
if (mask) {
LLVMValueRef masked;
LLVMValueRef shifted;
if (0)
debug_printf("shift = %i, mask = 0x%08llx\n", shift, mask);
masked = LLVMBuildAnd(bld->builder, a,
lp_build_const_int_vec(type4, mask), "");
if (shift > 0) {
shifted = LLVMBuildShl(bld->builder, masked,
lp_build_const_int_vec(type4, shift*type.width), "");
} else if (shift < 0) {
shifted = LLVMBuildLShr(bld->builder, masked,
lp_build_const_int_vec(type4, -shift*type.width), "");
} else {
shifted = masked;
}
res = LLVMBuildOr(bld->builder, res, shifted, "");
}
}
return LLVMBuildBitCast(bld->builder, res, lp_build_vec_type(type), "");
}
}
+4 -16
View File
@@ -68,24 +68,12 @@ lp_build_broadcast_aos(struct lp_build_context *bld,
/**
* Swizzle a vector consisting of an array of XYZW structs.
*
* @param swizzle is the in [0,4[ range.
* @param swizzles is the in [0,4[ range.
*/
LLVMValueRef
lp_build_swizzle1_aos(struct lp_build_context *bld,
LLVMValueRef a,
const unsigned char swizzle[4]);
/**
* Swizzle two vector consisting of an array of XYZW structs.
*
* @param swizzle is the in [0,8[ range. Values in [4,8[ range refer to b.
*/
LLVMValueRef
lp_build_swizzle2_aos(struct lp_build_context *bld,
LLVMValueRef a,
LLVMValueRef b,
const unsigned char swizzle[4]);
lp_build_swizzle_aos(struct lp_build_context *bld,
LLVMValueRef a,
const unsigned char swizzles[4]);
LLVMValueRef
+157 -52
View File
@@ -49,6 +49,7 @@
#include "lp_bld_type.h"
#include "lp_bld_const.h"
#include "lp_bld_arit.h"
#include "lp_bld_gather.h"
#include "lp_bld_logic.h"
#include "lp_bld_swizzle.h"
#include "lp_bld_flow.h"
@@ -132,10 +133,14 @@ struct lp_build_tgsi_soa_context
LLVMValueRef addr[LP_MAX_TGSI_ADDRS][NUM_CHANNELS];
LLVMValueRef preds[LP_MAX_TGSI_PREDS][NUM_CHANNELS];
/* we allocate an array of temps if we have indirect
* addressing and then the temps above is unused */
/* We allocate/use this array of temps if (1 << TGSI_FILE_TEMPORARY) is
* set in the indirect_files field.
* The temps[] array above is unused then.
*/
LLVMValueRef temps_array;
boolean has_indirect_addressing;
/** bitmask indicating which register files are accessed indirectly */
unsigned indirect_files;
struct lp_build_mask_context *mask;
struct lp_exec_mask exec_mask;
@@ -404,25 +409,92 @@ static void lp_exec_mask_endsub(struct lp_exec_mask *mask, int *pc)
lp_exec_mask_update(mask);
}
/**
* Return pointer to a temporary register channel (src or dest).
* Note that indirect addressing cannot be handled here.
* \param index which temporary register
* \param chan which channel of the temp register.
*/
static LLVMValueRef
get_temp_ptr(struct lp_build_tgsi_soa_context *bld,
unsigned index,
unsigned chan,
boolean is_indirect,
LLVMValueRef addr)
unsigned chan)
{
assert(chan < 4);
if (!bld->has_indirect_addressing) {
return bld->temps[index][chan];
} else {
LLVMValueRef lindex =
LLVMConstInt(LLVMInt32Type(), index * 4 + chan, 0);
if (is_indirect)
lindex = lp_build_add(&bld->base, lindex, addr);
if (bld->indirect_files & (1 << TGSI_FILE_TEMPORARY)) {
LLVMValueRef lindex = lp_build_const_int32(index * 4 + chan);
return LLVMBuildGEP(bld->base.builder, bld->temps_array, &lindex, 1, "");
}
else {
return bld->temps[index][chan];
}
}
/**
* Gather vector.
* XXX the lp_build_gather() function should be capable of doing this
* with a little work.
*/
static LLVMValueRef
build_gather(struct lp_build_tgsi_soa_context *bld,
LLVMValueRef base_ptr,
LLVMValueRef indexes)
{
LLVMValueRef res = bld->base.undef;
unsigned i;
/*
* Loop over elements of index_vec, load scalar value, insert it into 'res'.
*/
for (i = 0; i < bld->base.type.length; i++) {
LLVMValueRef ii = LLVMConstInt(LLVMInt32Type(), i, 0);
LLVMValueRef index = LLVMBuildExtractElement(bld->base.builder,
indexes, ii, "");
LLVMValueRef scalar_ptr = LLVMBuildGEP(bld->base.builder, base_ptr,
&index, 1, "");
LLVMValueRef scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, "");
res = LLVMBuildInsertElement(bld->base.builder, res, scalar, ii, "");
}
return res;
}
/**
* Read the current value of the ADDR register, convert the floats to
* ints, multiply by four and return the vector of offsets.
* The offsets will be used to index into the constant buffer or
* temporary register file.
*/
static LLVMValueRef
get_indirect_offsets(struct lp_build_tgsi_soa_context *bld,
const struct tgsi_src_register *indirect_reg)
{
/* always use X component of address register */
const int x = indirect_reg->SwizzleX;
LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->base.type);
uint swizzle = tgsi_util_get_src_register_swizzle(indirect_reg, x);
LLVMValueRef vec4 = lp_build_const_int_vec(bld->int_bld.type, 4);
LLVMValueRef addr_vec;
addr_vec = LLVMBuildLoad(bld->base.builder,
bld->addr[indirect_reg->Index][swizzle],
"load addr reg");
/* for indexing we want integers */
addr_vec = LLVMBuildFPToSI(bld->base.builder, addr_vec,
int_vec_type, "");
/* addr_vec = addr_vec * 4 */
addr_vec = lp_build_mul(&bld->base, addr_vec, vec4);
return addr_vec;
}
/**
* Register fetch.
*/
@@ -430,14 +502,14 @@ static LLVMValueRef
emit_fetch(
struct lp_build_tgsi_soa_context *bld,
const struct tgsi_full_instruction *inst,
unsigned index,
unsigned src_op,
const unsigned chan_index )
{
const struct tgsi_full_src_register *reg = &inst->Src[index];
const struct tgsi_full_src_register *reg = &inst->Src[src_op];
const unsigned swizzle =
tgsi_util_get_full_src_register_swizzle(reg, chan_index);
LLVMValueRef res;
LLVMValueRef addr = NULL;
LLVMValueRef addr_vec = NULL;
if (swizzle > 3) {
assert(0 && "invalid swizzle in emit_fetch()");
@@ -445,32 +517,33 @@ emit_fetch(
}
if (reg->Register.Indirect) {
LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->base.type);
unsigned swizzle = tgsi_util_get_src_register_swizzle( &reg->Indirect, chan_index );
addr = LLVMBuildLoad(bld->base.builder,
bld->addr[reg->Indirect.Index][swizzle],
"");
/* for indexing we want integers */
addr = LLVMBuildFPToSI(bld->base.builder, addr,
int_vec_type, "");
addr = LLVMBuildExtractElement(bld->base.builder,
addr, LLVMConstInt(LLVMInt32Type(), 0, 0),
"");
addr = lp_build_mul(&bld->base, addr, LLVMConstInt(LLVMInt32Type(), 4, 0));
assert(bld->indirect_files);
addr_vec = get_indirect_offsets(bld, &reg->Indirect);
}
switch (reg->Register.File) {
case TGSI_FILE_CONSTANT:
{
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(),
reg->Register.Index*4 + swizzle, 0);
if (reg->Register.Indirect) {
LLVMValueRef index_vec; /* index into the const buffer */
assert(bld->indirect_files & (1 << TGSI_FILE_CONSTANT));
/* index_vec = broadcast(reg->Register.Index * 4 + swizzle) */
index_vec = lp_build_const_int_vec(bld->int_bld.type,
reg->Register.Index * 4 + swizzle);
/* index_vec = index_vec + addr_vec */
index_vec = lp_build_add(&bld->base, index_vec, addr_vec);
/* Gather values from the constant buffer */
res = build_gather(bld, bld->consts_ptr, index_vec);
}
else {
LLVMValueRef index; /* index into the const buffer */
LLVMValueRef scalar, scalar_ptr;
if (reg->Register.Indirect) {
/*lp_build_printf(bld->base.builder,
"\taddr = %d\n", addr);*/
index = lp_build_add(&bld->base, index, addr);
}
index = lp_build_const_int32(reg->Register.Index*4 + swizzle);
scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr,
&index, 1, "");
scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, "");
@@ -490,13 +563,38 @@ emit_fetch(
break;
case TGSI_FILE_TEMPORARY:
{
LLVMValueRef temp_ptr = get_temp_ptr(bld, reg->Register.Index,
swizzle,
reg->Register.Indirect,
addr);
if (reg->Register.Indirect) {
LLVMValueRef vec_len =
lp_build_const_int_vec(bld->int_bld.type, bld->base.type.length);
LLVMValueRef index_vec; /* index into the const buffer */
LLVMValueRef temps_array;
LLVMTypeRef float4_ptr_type;
assert(bld->indirect_files & (1 << TGSI_FILE_TEMPORARY));
/* index_vec = broadcast(reg->Register.Index * 4 + swizzle) */
index_vec = lp_build_const_int_vec(bld->int_bld.type,
reg->Register.Index * 4 + swizzle);
/* index_vec += addr_vec */
index_vec = lp_build_add(&bld->int_bld, index_vec, addr_vec);
/* index_vec *= vector_length */
index_vec = lp_build_mul(&bld->int_bld, index_vec, vec_len);
/* cast temps_array pointer to float* */
float4_ptr_type = LLVMPointerType(LLVMFloatType(), 0);
temps_array = LLVMBuildBitCast(bld->int_bld.builder, bld->temps_array,
float4_ptr_type, "");
/* Gather values from the temporary register array */
res = build_gather(bld, temps_array, index_vec);
}
else {
LLVMValueRef temp_ptr;
temp_ptr = get_temp_ptr(bld, reg->Register.Index, swizzle);
res = LLVMBuildLoad(bld->base.builder, temp_ptr, "");
if(!res)
if (!res)
return bld->base.undef;
}
break;
@@ -660,8 +758,12 @@ emit_store(
}
if (reg->Register.Indirect) {
/* XXX use get_indirect_offsets() here eventually */
LLVMTypeRef int_vec_type = lp_build_int_vec_type(bld->base.type);
unsigned swizzle = tgsi_util_get_src_register_swizzle( &reg->Indirect, chan_index );
assert(bld->indirect_files);
addr = LLVMBuildLoad(bld->base.builder,
bld->addr[reg->Indirect.Index][swizzle],
"");
@@ -680,14 +782,18 @@ emit_store(
bld->outputs[reg->Register.Index][chan_index]);
break;
case TGSI_FILE_TEMPORARY: {
LLVMValueRef temp_ptr = get_temp_ptr(bld, reg->Register.Index,
chan_index,
reg->Register.Indirect,
addr);
lp_exec_mask_store(&bld->exec_mask, pred, value, temp_ptr);
case TGSI_FILE_TEMPORARY:
if (reg->Register.Indirect) {
/* XXX not done yet */
debug_printf("WARNING: LLVM scatter store of temp regs"
" not implemented\n");
}
else {
LLVMValueRef temp_ptr = get_temp_ptr(bld, reg->Register.Index,
chan_index);
lp_exec_mask_store(&bld->exec_mask, pred, value, temp_ptr);
}
break;
}
case TGSI_FILE_ADDRESS:
lp_exec_mask_store(&bld->exec_mask, pred, value,
@@ -905,7 +1011,7 @@ emit_declaration(
switch (decl->Declaration.File) {
case TGSI_FILE_TEMPORARY:
assert(idx < LP_MAX_TGSI_TEMPS);
if (bld->has_indirect_addressing) {
if (bld->indirect_files & (1 << TGSI_FILE_TEMPORARY)) {
LLVMValueRef array_size = LLVMConstInt(LLVMInt32Type(),
last*4 + 4, 0);
bld->temps_array = lp_build_array_alloca(bld->base.builder,
@@ -1929,8 +2035,7 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
bld.outputs = outputs;
bld.consts_ptr = consts_ptr;
bld.sampler = sampler;
bld.has_indirect_addressing = info->opcode_count[TGSI_OPCODE_ARR] > 0 ||
info->opcode_count[TGSI_OPCODE_ARL] > 0;
bld.indirect_files = info->indirect_files;
bld.instructions = (struct tgsi_full_instruction *)
MALLOC( LP_MAX_INSTRUCTIONS * sizeof(struct tgsi_full_instruction) );
bld.max_instructions = LP_MAX_INSTRUCTIONS;
@@ -316,6 +316,54 @@ LLVMTypeRef
lp_build_int32_vec4_type(void);
static INLINE struct lp_type
lp_float32_vec4_type(void)
{
struct lp_type type;
memset(&type, 0, sizeof(type));
type.floating = TRUE;
type.sign = TRUE;
type.norm = FALSE;
type.width = 32;
type.length = 4;
return type;
}
static INLINE struct lp_type
lp_int32_vec4_type(void)
{
struct lp_type type;
memset(&type, 0, sizeof(type));
type.floating = FALSE;
type.sign = TRUE;
type.norm = FALSE;
type.width = 32;
type.length = 4;
return type;
}
static INLINE struct lp_type
lp_unorm8_vec4_type(void)
{
struct lp_type type;
memset(&type, 0, sizeof(type));
type.floating = FALSE;
type.sign = FALSE;
type.norm = TRUE;
type.width = 8;
type.length = 4;
return type;
}
struct lp_type
lp_uint_type(struct lp_type type);
+60 -31
View File
@@ -45,7 +45,6 @@
#include <pthread.h> /* POSIX threads headers */
#include <stdio.h> /* for perror() */
#define PIPE_THREAD_HAVE_CONDVAR
/* pipe_thread
*/
@@ -168,19 +167,59 @@ typedef CRITICAL_SECTION pipe_mutex;
#define pipe_mutex_unlock(mutex) \
LeaveCriticalSection(&mutex)
/* pipe_condvar (XXX FIX THIS)
/* TODO: Need a macro to declare "I don't care about WinXP compatibilty" */
#if 0 && defined (_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
/* CONDITION_VARIABLE is only available on newer versions of Windows
* (Server 2008/Vista or later).
* http://msdn.microsoft.com/en-us/library/ms682052(VS.85).aspx
*
* pipe_condvar
*/
typedef unsigned pipe_condvar;
typedef CONDITION_VARIABLE pipe_condvar;
#define pipe_static_condvar(cond) \
/*static*/ pipe_condvar cond = CONDITION_VARIABLE_INIT
#define pipe_condvar_init(cond) \
(void) cond
InitializeConditionVariable(&(cond))
#define pipe_condvar_destroy(cond) \
(void) cond /* nothing to do */
#define pipe_condvar_wait(cond, mutex) \
SleepConditionVariableCS(&(cond), &(mutex), INFINITE)
#define pipe_condvar_signal(cond) \
WakeConditionVariable(&(cond))
#define pipe_condvar_broadcast(cond) \
WakeAllConditionVariable(&(cond))
#else /* need compatibility with pre-Vista Win32 */
/* pipe_condvar (XXX FIX THIS)
* See http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
* for potential pitfalls in implementation.
*/
typedef DWORD pipe_condvar;
#define pipe_static_condvar(cond) \
/*static*/ pipe_condvar cond = 1
#define pipe_condvar_init(cond) \
(void) (cond = 1)
#define pipe_condvar_destroy(cond) \
(void) cond
/* Poor man's pthread_cond_wait():
Just release the mutex and sleep for one millisecond.
The caller's while() loop does all the work. */
#define pipe_condvar_wait(cond, mutex) \
(void) cond; (void) mutex
do { pipe_mutex_unlock(mutex); \
Sleep(cond); \
pipe_mutex_lock(mutex); \
} while (0)
#define pipe_condvar_signal(cond) \
(void) cond
@@ -188,9 +227,12 @@ typedef unsigned pipe_condvar;
#define pipe_condvar_broadcast(cond) \
(void) cond
#endif /* pre-Vista win32 */
#else
#include "os/os_time.h"
/** Dummy definitions */
typedef unsigned pipe_thread;
@@ -214,7 +256,6 @@ static INLINE int pipe_thread_destroy( pipe_thread thread )
}
typedef unsigned pipe_mutex;
typedef unsigned pipe_condvar;
#define pipe_static_mutex(mutex) \
static pipe_mutex mutex = 0
@@ -231,17 +272,25 @@ typedef unsigned pipe_condvar;
#define pipe_mutex_unlock(mutex) \
(void) mutex
typedef int64_t pipe_condvar;
#define pipe_static_condvar(condvar) \
static unsigned condvar = 0
static pipe_condvar condvar = 1000
#define pipe_condvar_init(condvar) \
(void) condvar
(void) (condvar = 1000)
#define pipe_condvar_destroy(condvar) \
(void) condvar
/* Poor man's pthread_cond_wait():
Just release the mutex and sleep for one millisecond.
The caller's while() loop does all the work. */
#define pipe_condvar_wait(condvar, mutex) \
(void) condvar
do { pipe_mutex_unlock(mutex); \
os_time_sleep(condvar); \
pipe_mutex_lock(mutex); \
} while (0)
#define pipe_condvar_signal(condvar) \
(void) condvar
@@ -277,27 +326,7 @@ static INLINE void pipe_barrier_wait(pipe_barrier *barrier)
}
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
/* XXX FIX THIS */
typedef unsigned pipe_barrier;
static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count)
{
/* XXX we could implement barriers with a mutex and condition var */
}
static INLINE void pipe_barrier_destroy(pipe_barrier *barrier)
{
}
static INLINE void pipe_barrier_wait(pipe_barrier *barrier)
{
assert(0);
}
#else
#else /* If the OS doesn't have its own, implement barriers using a mutex and a condvar */
typedef struct {
unsigned count;
@@ -0,0 +1,44 @@
#ifndef INLINE_DEBUG_HELPER_H
#define INLINE_DEBUG_HELPER_H
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
/* Helper function to wrap a screen with
* one or more debug driver: rbug, trace.
*/
#ifdef GALLIUM_TRACE
#include "trace/tr_public.h"
#endif
#ifdef GALLIUM_RBUG
#include "rbug/rbug_public.h"
#endif
#ifdef GALLIUM_GALAHAD
#include "galahad/glhd_public.h"
#endif
static INLINE struct pipe_screen *
debug_screen_wrap(struct pipe_screen *screen)
{
#if defined(GALLIUM_RBUG)
screen = rbug_screen_create(screen);
#endif
#if defined(GALLIUM_TRACE)
screen = trace_screen_create(screen);
#endif
#if defined(GALLIUM_GALAHAD)
screen = galahad_screen_create(screen);
#endif
return screen;
}
#endif
@@ -0,0 +1,63 @@
#ifndef INLINE_SW_HELPER_H
#define INLINE_SW_HELPER_H
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
#include "state_tracker/sw_winsys.h"
/* Helper function to choose and instantiate one of the software rasterizers:
* cell, llvmpipe, softpipe.
*/
#ifdef GALLIUM_SOFTPIPE
#include "softpipe/sp_public.h"
#endif
#ifdef GALLIUM_LLVMPIPE
#include "llvmpipe/lp_public.h"
#endif
#ifdef GALLIUM_CELL
#include "cell/ppu/cell_public.h"
#endif
static INLINE struct pipe_screen *
sw_screen_create(struct sw_winsys *winsys)
{
const char *default_driver;
const char *driver;
struct pipe_screen *screen = NULL;
#if defined(GALLIUM_CELL)
default_driver = "cell";
#elif defined(GALLIUM_LLVMPIPE)
default_driver = "llvmpipe";
#elif defined(GALLIUM_SOFTPIPE)
default_driver = "softpipe";
#else
default_driver = "";
#endif
driver = debug_get_option("GALLIUM_DRIVER", default_driver);
#if defined(GALLIUM_CELL)
if (screen == NULL && strcmp(driver, "cell") == 0)
screen = cell_create_screen(winsys);
#endif
#if defined(GALLIUM_LLVMPIPE)
if (screen == NULL && strcmp(driver, "llvmpipe") == 0)
screen = llvmpipe_create_screen(winsys);
#endif
#if defined(GALLIUM_SOFTPIPE)
if (screen == NULL)
screen = softpipe_create_screen(winsys);
#endif
return screen;
}
#endif
@@ -0,0 +1,34 @@
#ifndef INLINE_WRAPPER_SW_HELPER_H
#define INLINE_WRAPPER_SW_HELPER_H
#include "target-helpers/inline_sw_helper.h"
#include "sw/wrapper/wrapper_sw_winsys.h"
/**
* Try to wrap a hw screen with a software screen.
* On failure will return given screen.
*/
static INLINE struct pipe_screen *
sw_screen_wrap(struct pipe_screen *screen)
{
struct sw_winsys *sws;
struct pipe_screen *sw_screen;
sws = wrapper_sw_winsys_warp_pipe_screen(screen);
if (!sws)
goto err;
sw_screen = sw_screen_create(sws);
if (sw_screen == screen)
goto err_winsys;
return sw_screen;
err_winsys:
sws->destroy(sws);
err:
return screen;
}
#endif
+5 -1
View File
@@ -176,7 +176,11 @@ static const char *primitive_names[] =
"TRIANGLE_FAN",
"QUADS",
"QUAD_STRIP",
"POLYGON"
"POLYGON",
"LINES_ADJACENCY",
"LINE_STRIP_ADJACENCY",
"TRIANGLES_ADJACENCY",
"TRIANGLE_STRIP_ADJACENCY"
};
static const char *fs_coord_origin_names[] =
+13
View File
@@ -109,6 +109,19 @@ tgsi_scan_shader(const struct tgsi_token *tokens,
info->input_usage_mask[ind] |= usage_mask;
}
}
/* check for indirect register reads */
if (src->Register.Indirect) {
info->indirect_files |= (1 << src->Register.File);
}
}
/* check for indirect register writes */
for (i = 0; i < fullinst->Instruction.NumDstRegs; i++) {
const struct tgsi_full_dst_register *dst = &fullinst->Dst[i];
if (dst->Register.Indirect) {
info->indirect_files |= (1 << dst->Register.File);
}
}
info->num_instructions++;
+6
View File
@@ -63,6 +63,12 @@ struct tgsi_shader_info
boolean writes_edgeflag; /**< vertex shader outputs edgeflag */
boolean uses_kill; /**< KIL or KILP instruction used? */
/**
* Bitmask indicating which register files are accessed with
* indirect addressing. The bits are (1 << TGSI_FILE_x), etc.
*/
unsigned indirect_files;
struct {
unsigned name;
unsigned data[8];
+2 -2
View File
@@ -58,7 +58,7 @@ static boolean is_digit_alpha_underscore( const char *cur )
static char uprcase( char c )
{
if (c >= 'a' && c <= 'z')
return c += 'A' - 'a';
return c + 'A' - 'a';
return c;
}
@@ -732,7 +732,7 @@ parse_optional_swizzle(
else if (uprcase( *cur ) == 'W')
swizzle[i] = TGSI_SWIZZLE_W;
else {
report_error( ctx, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" );
report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
return FALSE;
}
cur++;
+202 -139
View File
@@ -52,9 +52,8 @@
struct blitter_context_priv
{
struct blitter_context blitter;
struct blitter_context base;
struct pipe_context *pipe; /**< pipe context */
struct pipe_resource *vbuf; /**< quad */
float vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */
@@ -97,15 +96,25 @@ struct blitter_context_priv
/* Rasterizer state. */
void *rs_state;
struct pipe_sampler_view *sampler_view;
/* Viewport state. */
struct pipe_viewport_state viewport;
/* Clip state. */
struct pipe_clip_state clip;
/* Destination surface dimensions. */
unsigned dst_width;
unsigned dst_height;
};
static void blitter_draw_rectangle(struct blitter_context *blitter,
unsigned x, unsigned y,
unsigned width, unsigned height,
float depth,
enum blitter_attrib_type type,
const float attrib[4]);
struct blitter_context *util_blitter_create(struct pipe_context *pipe)
{
struct blitter_context_priv *ctx;
@@ -120,19 +129,20 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
if (!ctx)
return NULL;
ctx->pipe = pipe;
ctx->base.pipe = pipe;
ctx->base.draw_rectangle = blitter_draw_rectangle;
/* init state objects for them to be considered invalid */
ctx->blitter.saved_blend_state = INVALID_PTR;
ctx->blitter.saved_dsa_state = INVALID_PTR;
ctx->blitter.saved_rs_state = INVALID_PTR;
ctx->blitter.saved_fs = INVALID_PTR;
ctx->blitter.saved_vs = INVALID_PTR;
ctx->blitter.saved_velem_state = INVALID_PTR;
ctx->blitter.saved_fb_state.nr_cbufs = ~0;
ctx->blitter.saved_num_sampler_views = ~0;
ctx->blitter.saved_num_sampler_states = ~0;
ctx->blitter.saved_num_vertex_buffers = ~0;
ctx->base.saved_blend_state = INVALID_PTR;
ctx->base.saved_dsa_state = INVALID_PTR;
ctx->base.saved_rs_state = INVALID_PTR;
ctx->base.saved_fs = INVALID_PTR;
ctx->base.saved_vs = INVALID_PTR;
ctx->base.saved_velem_state = INVALID_PTR;
ctx->base.saved_fb_state.nr_cbufs = ~0;
ctx->base.saved_num_sampler_views = ~0;
ctx->base.saved_num_sampler_states = ~0;
ctx->base.saved_num_vertex_buffers = ~0;
/* blend state objects */
memset(&blend, 0, sizeof(blend));
@@ -219,17 +229,17 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
ctx->vertices[i][0][3] = 1; /*v.w*/
/* create the vertex buffer */
ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
ctx->vbuf = pipe_buffer_create(ctx->base.pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
sizeof(ctx->vertices));
return &ctx->blitter;
return &ctx->base;
}
void util_blitter_destroy(struct blitter_context *blitter)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->pipe;
struct pipe_context *pipe = blitter->pipe;
int i;
pipe->delete_blend_state(pipe, ctx->blend_write_color);
@@ -260,10 +270,6 @@ void util_blitter_destroy(struct blitter_context *blitter)
if (ctx->sampler_state[i])
pipe->delete_sampler_state(pipe, ctx->sampler_state[i]);
if (ctx->sampler_view) {
pipe_sampler_view_reference(&ctx->sampler_view, NULL);
}
pipe_resource_reference(&ctx->vbuf, NULL);
FREE(ctx);
}
@@ -271,112 +277,117 @@ void util_blitter_destroy(struct blitter_context *blitter)
static void blitter_check_saved_CSOs(struct blitter_context_priv *ctx)
{
/* make sure these CSOs have been saved */
assert(ctx->blitter.saved_blend_state != INVALID_PTR &&
ctx->blitter.saved_dsa_state != INVALID_PTR &&
ctx->blitter.saved_rs_state != INVALID_PTR &&
ctx->blitter.saved_fs != INVALID_PTR &&
ctx->blitter.saved_vs != INVALID_PTR &&
ctx->blitter.saved_velem_state != INVALID_PTR);
assert(ctx->base.saved_blend_state != INVALID_PTR &&
ctx->base.saved_dsa_state != INVALID_PTR &&
ctx->base.saved_rs_state != INVALID_PTR &&
ctx->base.saved_fs != INVALID_PTR &&
ctx->base.saved_vs != INVALID_PTR &&
ctx->base.saved_velem_state != INVALID_PTR);
}
static void blitter_restore_CSOs(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_context *pipe = ctx->base.pipe;
unsigned i;
/* restore the state objects which are always required to be saved */
pipe->bind_blend_state(pipe, ctx->blitter.saved_blend_state);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->blitter.saved_dsa_state);
pipe->bind_rasterizer_state(pipe, ctx->blitter.saved_rs_state);
pipe->bind_fs_state(pipe, ctx->blitter.saved_fs);
pipe->bind_vs_state(pipe, ctx->blitter.saved_vs);
pipe->bind_vertex_elements_state(pipe, ctx->blitter.saved_velem_state);
pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);
pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state);
pipe->bind_fs_state(pipe, ctx->base.saved_fs);
pipe->bind_vs_state(pipe, ctx->base.saved_vs);
pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);
ctx->blitter.saved_blend_state = INVALID_PTR;
ctx->blitter.saved_dsa_state = INVALID_PTR;
ctx->blitter.saved_rs_state = INVALID_PTR;
ctx->blitter.saved_fs = INVALID_PTR;
ctx->blitter.saved_vs = INVALID_PTR;
ctx->blitter.saved_velem_state = INVALID_PTR;
ctx->base.saved_blend_state = INVALID_PTR;
ctx->base.saved_dsa_state = INVALID_PTR;
ctx->base.saved_rs_state = INVALID_PTR;
ctx->base.saved_fs = INVALID_PTR;
ctx->base.saved_vs = INVALID_PTR;
ctx->base.saved_velem_state = INVALID_PTR;
pipe->set_stencil_ref(pipe, &ctx->blitter.saved_stencil_ref);
pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref);
pipe->set_viewport_state(pipe, &ctx->blitter.saved_viewport);
pipe->set_clip_state(pipe, &ctx->blitter.saved_clip);
pipe->set_viewport_state(pipe, &ctx->base.saved_viewport);
pipe->set_clip_state(pipe, &ctx->base.saved_clip);
/* restore the state objects which are required to be saved before copy/fill
*/
if (ctx->blitter.saved_fb_state.nr_cbufs != ~0) {
pipe->set_framebuffer_state(pipe, &ctx->blitter.saved_fb_state);
ctx->blitter.saved_fb_state.nr_cbufs = ~0;
if (ctx->base.saved_fb_state.nr_cbufs != ~0) {
pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);
util_assign_framebuffer_state(&ctx->base.saved_fb_state, NULL);
ctx->base.saved_fb_state.nr_cbufs = ~0;
}
if (ctx->blitter.saved_num_sampler_states != ~0) {
if (ctx->base.saved_num_sampler_states != ~0) {
pipe->bind_fragment_sampler_states(pipe,
ctx->blitter.saved_num_sampler_states,
ctx->blitter.saved_sampler_states);
ctx->blitter.saved_num_sampler_states = ~0;
ctx->base.saved_num_sampler_states,
ctx->base.saved_sampler_states);
ctx->base.saved_num_sampler_states = ~0;
}
if (ctx->blitter.saved_num_sampler_views != ~0) {
if (ctx->base.saved_num_sampler_views != ~0) {
pipe->set_fragment_sampler_views(pipe,
ctx->blitter.saved_num_sampler_views,
ctx->blitter.saved_sampler_views);
ctx->blitter.saved_num_sampler_views = ~0;
ctx->base.saved_num_sampler_views,
ctx->base.saved_sampler_views);
for (i = 0; i < ctx->base.saved_num_sampler_views; i++)
pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i],
NULL);
ctx->base.saved_num_sampler_views = ~0;
}
if (ctx->blitter.saved_num_vertex_buffers != ~0) {
if (ctx->base.saved_num_vertex_buffers != ~0) {
pipe->set_vertex_buffers(pipe,
ctx->blitter.saved_num_vertex_buffers,
ctx->blitter.saved_vertex_buffers);
ctx->base.saved_num_vertex_buffers,
ctx->base.saved_vertex_buffers);
for (i = 0; i < ctx->blitter.saved_num_vertex_buffers; i++) {
if (ctx->blitter.saved_vertex_buffers[i].buffer) {
pipe_resource_reference(&ctx->blitter.saved_vertex_buffers[i].buffer,
for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) {
if (ctx->base.saved_vertex_buffers[i].buffer) {
pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer,
NULL);
}
}
ctx->blitter.saved_num_vertex_buffers = ~0;
ctx->base.saved_num_vertex_buffers = ~0;
}
}
static void blitter_set_rectangle(struct blitter_context_priv *ctx,
unsigned x1, unsigned y1,
unsigned x2, unsigned y2,
unsigned width, unsigned height,
float depth)
{
int i;
/* set vertex positions */
ctx->vertices[0][0][0] = (float)x1 / width * 2.0f - 1.0f; /*v0.x*/
ctx->vertices[0][0][1] = (float)y1 / height * 2.0f - 1.0f; /*v0.y*/
ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/
ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/
ctx->vertices[1][0][0] = (float)x2 / width * 2.0f - 1.0f; /*v1.x*/
ctx->vertices[1][0][1] = (float)y1 / height * 2.0f - 1.0f; /*v1.y*/
ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/
ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/
ctx->vertices[2][0][0] = (float)x2 / width * 2.0f - 1.0f; /*v2.x*/
ctx->vertices[2][0][1] = (float)y2 / height * 2.0f - 1.0f; /*v2.y*/
ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/
ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/
ctx->vertices[3][0][0] = (float)x1 / width * 2.0f - 1.0f; /*v3.x*/
ctx->vertices[3][0][1] = (float)y2 / height * 2.0f - 1.0f; /*v3.y*/
ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/
ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/
for (i = 0; i < 4; i++)
ctx->vertices[i][0][2] = depth; /*z*/
/* viewport */
ctx->viewport.scale[0] = 0.5f * width;
ctx->viewport.scale[1] = 0.5f * height;
ctx->viewport.scale[0] = 0.5f * ctx->dst_width;
ctx->viewport.scale[1] = 0.5f * ctx->dst_height;
ctx->viewport.scale[2] = 1.0f;
ctx->viewport.scale[3] = 1.0f;
ctx->viewport.translate[0] = 0.5f * width;
ctx->viewport.translate[1] = 0.5f * height;
ctx->viewport.translate[0] = 0.5f * ctx->dst_width;
ctx->viewport.translate[1] = 0.5f * ctx->dst_height;
ctx->viewport.translate[2] = 0.0f;
ctx->viewport.translate[3] = 0.0f;
ctx->pipe->set_viewport_state(ctx->pipe, &ctx->viewport);
ctx->base.pipe->set_viewport_state(ctx->base.pipe, &ctx->viewport);
/* clip */
ctx->pipe->set_clip_state(ctx->pipe, &ctx->clip);
ctx->base.pipe->set_clip_state(ctx->base.pipe, &ctx->clip);
}
static void blitter_set_clear_color(struct blitter_context_priv *ctx,
@@ -401,29 +412,45 @@ static void blitter_set_clear_color(struct blitter_context_priv *ctx,
}
}
static void get_normalized_texcoords(struct pipe_resource *src,
struct pipe_subresource subsrc,
unsigned x1, unsigned y1,
unsigned x2, unsigned y2,
float out[4])
{
out[0] = x1 / (float)u_minify(src->width0, subsrc.level);
out[1] = y1 / (float)u_minify(src->height0, subsrc.level);
out[2] = x2 / (float)u_minify(src->width0, subsrc.level);
out[3] = y2 / (float)u_minify(src->height0, subsrc.level);
}
static void set_texcoords_in_vertices(const float coord[4],
float *out, unsigned stride)
{
out[0] = coord[0]; /*t0.s*/
out[1] = coord[1]; /*t0.t*/
out += stride;
out[0] = coord[2]; /*t1.s*/
out[1] = coord[1]; /*t1.t*/
out += stride;
out[0] = coord[2]; /*t2.s*/
out[1] = coord[3]; /*t2.t*/
out += stride;
out[0] = coord[0]; /*t3.s*/
out[1] = coord[3]; /*t3.t*/
}
static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx,
struct pipe_resource *src,
struct pipe_subresource subsrc,
unsigned x1, unsigned y1,
unsigned x2, unsigned y2)
{
int i;
float s1 = x1 / (float)u_minify(src->width0, subsrc.level);
float t1 = y1 / (float)u_minify(src->height0, subsrc.level);
float s2 = x2 / (float)u_minify(src->width0, subsrc.level);
float t2 = y2 / (float)u_minify(src->height0, subsrc.level);
unsigned i;
float coord[4];
ctx->vertices[0][1][0] = s1; /*t0.s*/
ctx->vertices[0][1][1] = t1; /*t0.t*/
ctx->vertices[1][1][0] = s2; /*t1.s*/
ctx->vertices[1][1][1] = t1; /*t1.t*/
ctx->vertices[2][1][0] = s2; /*t2.s*/
ctx->vertices[2][1][1] = t2; /*t2.t*/
ctx->vertices[3][1][0] = s1; /*t3.s*/
ctx->vertices[3][1][1] = t2; /*t3.t*/
get_normalized_texcoords(src, subsrc, x1, y1, x2, y2, coord);
set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8);
for (i = 0; i < 4; i++) {
ctx->vertices[i][1][2] = 0; /*r*/
@@ -454,20 +481,11 @@ static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx,
unsigned x2, unsigned y2)
{
int i;
float s1 = x1 / (float)u_minify(src->width0, subsrc.level);
float t1 = y1 / (float)u_minify(src->height0, subsrc.level);
float s2 = x2 / (float)u_minify(src->width0, subsrc.level);
float t2 = y2 / (float)u_minify(src->height0, subsrc.level);
float coord[4];
float st[4][2];
st[0][0] = s1;
st[0][1] = t1;
st[1][0] = s2;
st[1][1] = t1;
st[2][0] = s2;
st[2][1] = t2;
st[3][0] = s1;
st[3][1] = t2;
get_normalized_texcoords(src, subsrc, x1, y1, x2, y2, coord);
set_texcoords_in_vertices(coord, &st[0][0], 2);
util_map_texcoords2d_onto_cubemap(subsrc.face,
/* pointer, stride in floats */
@@ -478,9 +496,16 @@ static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx,
ctx->vertices[i][1][3] = 1; /*q*/
}
static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,
unsigned width, unsigned height)
{
ctx->dst_width = width;
ctx->dst_height = height;
}
static void blitter_draw_quad(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_context *pipe = ctx->base.pipe;
/* write vertices and draw them */
pipe_buffer_write(pipe, ctx->vbuf,
@@ -495,7 +520,7 @@ static INLINE
void **blitter_get_sampler_state(struct blitter_context_priv *ctx,
int miplevel)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_sampler_state *sampler_state = &ctx->template_sampler_state;
assert(miplevel < PIPE_MAX_TEXTURE_LEVELS);
@@ -518,7 +543,7 @@ void **blitter_get_sampler_state(struct blitter_context_priv *ctx,
static INLINE
void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_context *pipe = ctx->base.pipe;
assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
@@ -531,7 +556,7 @@ void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs)
/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
static unsigned
pipe_tex_to_tgsi_tex(unsigned pipe_tex_target)
pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target)
{
switch (pipe_tex_target) {
case PIPE_TEXTURE_1D:
@@ -553,7 +578,7 @@ static INLINE
void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
unsigned tex_target)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_context *pipe = ctx->base.pipe;
assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
@@ -572,7 +597,7 @@ static INLINE
void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
unsigned tex_target)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_context *pipe = ctx->base.pipe;
assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
@@ -588,6 +613,31 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
return ctx->fs_texfetch_depth[tex_target];
}
static void blitter_draw_rectangle(struct blitter_context *blitter,
unsigned x1, unsigned y1,
unsigned x2, unsigned y2,
float depth,
enum blitter_attrib_type type,
const float attrib[4])
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
switch (type) {
case UTIL_BLITTER_ATTRIB_COLOR:
blitter_set_clear_color(ctx, attrib);
break;
case UTIL_BLITTER_ATTRIB_TEXCOORD:
set_texcoords_in_vertices(attrib, &ctx->vertices[0][1][0], 8);
break;
default:;
}
blitter_set_rectangle(ctx, x1, y1, x2, y2, depth);
blitter_draw_quad(ctx);
}
void util_blitter_clear(struct blitter_context *blitter,
unsigned width, unsigned height,
unsigned num_cbufs,
@@ -596,7 +646,7 @@ void util_blitter_clear(struct blitter_context *blitter,
double depth, unsigned stencil)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->pipe;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_stencil_ref sr = { { 0 } };
assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
@@ -630,9 +680,9 @@ void util_blitter_clear(struct blitter_context *blitter,
pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs));
pipe->bind_vs_state(pipe, ctx->vs_col);
blitter_set_clear_color(ctx, rgba);
blitter_set_rectangle(ctx, 0, 0, width, height, width, height, depth);
blitter_draw_quad(ctx);
blitter_set_dst_dimensions(ctx, width, height);
blitter->draw_rectangle(blitter, 0, 0, width, height, depth,
UTIL_BLITTER_ATTRIB_COLOR, rgba);
blitter_restore_CSOs(ctx);
}
@@ -654,7 +704,7 @@ void util_blitter_copy_region(struct blitter_context *blitter,
boolean ignore_stencil)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->pipe;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_surface *dstsurf;
struct pipe_framebuffer_state fb_state;
@@ -736,11 +786,6 @@ void util_blitter_copy_region(struct blitter_context *blitter,
u_sampler_view_default_template(&viewTempl, src, src->format);
view = pipe->create_sampler_view(pipe, src, &viewTempl);
if (ctx->sampler_view) {
pipe_sampler_view_reference(&ctx->sampler_view, NULL);
}
ctx->sampler_view = view;
/* Set rasterizer state, shaders, and textures. */
pipe->bind_rasterizer_state(pipe, ctx->rs_state);
pipe->bind_vs_state(pipe, ctx->vs_tex);
@@ -750,32 +795,49 @@ void util_blitter_copy_region(struct blitter_context *blitter,
pipe->set_fragment_sampler_views(pipe, 1, &view);
pipe->set_framebuffer_state(pipe, &fb_state);
/* Set texture coordinates. */
blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
switch (src->target) {
/* Draw the quad with the draw_rectangle callback. */
case PIPE_TEXTURE_1D:
case PIPE_TEXTURE_2D:
blitter_set_texcoords_2d(ctx, src, subsrc,
srcx, srcy, srcx+width, srcy+height);
{
/* Set texture coordinates. */
float coord[4];
get_normalized_texcoords(src, subsrc, srcx, srcy,
srcx+width, srcy+height, coord);
/* Draw. */
blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
UTIL_BLITTER_ATTRIB_TEXCOORD, coord);
}
break;
/* Draw the quad with the generic codepath. */
case PIPE_TEXTURE_3D:
blitter_set_texcoords_3d(ctx, src, subsrc, srcz,
srcx, srcy, srcx+width, srcy+height);
break;
case PIPE_TEXTURE_CUBE:
blitter_set_texcoords_cube(ctx, src, subsrc,
srcx, srcy, srcx+width, srcy+height);
/* Set texture coordinates. */
if (src->target == PIPE_TEXTURE_3D)
blitter_set_texcoords_3d(ctx, src, subsrc, srcz,
srcx, srcy, srcx+width, srcy+height);
else
blitter_set_texcoords_cube(ctx, src, subsrc,
srcx, srcy, srcx+width, srcy+height);
/* Draw. */
blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0);
blitter_draw_quad(ctx);
break;
default:
assert(0);
return;
}
blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height,
dstsurf->width, dstsurf->height, 0);
blitter_draw_quad(ctx);
blitter_restore_CSOs(ctx);
pipe_surface_reference(&dstsurf, NULL);
pipe_sampler_view_reference(&view, NULL);
}
/* Clear a region of a color surface to a constant value. */
@@ -786,7 +848,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
unsigned width, unsigned height)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->pipe;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_framebuffer_state fb_state;
assert(dstsurf->texture);
@@ -813,9 +875,9 @@ void util_blitter_clear_render_target(struct blitter_context *blitter,
fb_state.zsbuf = 0;
pipe->set_framebuffer_state(pipe, &fb_state);
blitter_set_clear_color(ctx, rgba);
blitter_set_rectangle(ctx, 0, 0, width, height, dstsurf->width, dstsurf->height, 0);
blitter_draw_quad(ctx);
blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
UTIL_BLITTER_ATTRIB_COLOR, rgba);
blitter_restore_CSOs(ctx);
}
@@ -829,7 +891,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
unsigned width, unsigned height)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->pipe;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_framebuffer_state fb_state;
struct pipe_stencil_ref sr = { { 0 } };
@@ -873,7 +935,8 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
fb_state.zsbuf = dstsurf;
pipe->set_framebuffer_state(pipe, &fb_state);
blitter_set_rectangle(ctx, 0, 0, width, height, dstsurf->width, dstsurf->height, depth);
blitter_draw_quad(ctx);
blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth,
UTIL_BLITTER_ATTRIB_NONE, NULL);
blitter_restore_CSOs(ctx);
}
+88 -5
View File
@@ -39,9 +39,48 @@ extern "C" {
struct pipe_context;
enum blitter_attrib_type {
UTIL_BLITTER_ATTRIB_NONE,
UTIL_BLITTER_ATTRIB_COLOR,
UTIL_BLITTER_ATTRIB_TEXCOORD
};
struct blitter_context
{
/**
* Draw a rectangle.
*
* \param x1 An X coordinate of the top-left corner.
* \param y1 A Y coordinate of the top-left corner.
* \param x2 An X coordinate of the bottom-right corner.
* \param y2 A Y coordinate of the bottom-right corner.
* \param depth A depth which the rectangle is rendered at.
*
* \param type Semantics of the attributes "attrib".
* If type is UTIL_BLITTER_ATTRIB_NONE, ignore them.
* If type is UTIL_BLITTER_ATTRIB_COLOR, the attributes
* make up a constant RGBA color, and should go to the COLOR0
* varying slot of a fragment shader.
* If type is UTIL_BLITTER_ATTRIB_TEXCOORD, {a1, a2} and
* {a3, a4} specify top-left and bottom-right texture
* coordinates of the rectangle, respectively, and should go
* to the GENERIC0 varying slot of a fragment shader.
*
* \param attrib See type.
*
* \note A driver may optionally override this callback to implement
* a specialized hardware path for drawing a rectangle, e.g. using
* a rectangular point sprite.
*/
void (*draw_rectangle)(struct blitter_context *blitter,
unsigned x1, unsigned y1, unsigned x2, unsigned y2,
float depth,
enum blitter_attrib_type type,
const float attrib[4]);
/* Private members, really. */
struct pipe_context *pipe; /**< pipe context */
void *saved_blend_state; /**< blend state */
void *saved_dsa_state; /**< depth stencil alpha state */
void *saved_velem_state; /**< vertex elements state */
@@ -73,6 +112,15 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe);
*/
void util_blitter_destroy(struct blitter_context *blitter);
/**
* Return the pipe context associated with a blitter context.
*/
static INLINE
struct pipe_context *util_blitter_get_pipe(struct blitter_context *blitter)
{
return blitter->pipe;
}
/*
* These CSOs must be saved before any of the following functions is called:
* - blend state
@@ -208,11 +256,45 @@ void util_blitter_save_vertex_shader(struct blitter_context *blitter,
blitter->saved_vs = vs;
}
/* XXX This should probably be moved elsewhere. */
static INLINE
void util_assign_framebuffer_state(struct pipe_framebuffer_state *dst,
const struct pipe_framebuffer_state *src)
{
unsigned i;
if (src) {
/* Reference all surfaces. */
for (i = 0; i < src->nr_cbufs; i++) {
pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
}
for (; i < dst->nr_cbufs; i++) {
pipe_surface_reference(&dst->cbufs[i], NULL);
}
pipe_surface_reference(&dst->zsbuf, src->zsbuf);
dst->nr_cbufs = src->nr_cbufs;
dst->width = src->width;
dst->height = src->height;
} else {
/* Set all surfaces to NULL. */
for (i = 0; i < dst->nr_cbufs; i++) {
pipe_surface_reference(&dst->cbufs[i], NULL);
}
pipe_surface_reference(&dst->zsbuf, NULL);
dst->nr_cbufs = 0;
}
}
static INLINE
void util_blitter_save_framebuffer(struct blitter_context *blitter,
struct pipe_framebuffer_state *state)
const struct pipe_framebuffer_state *state)
{
blitter->saved_fb_state = *state;
blitter->saved_fb_state.nr_cbufs = 0; /* It's ~0 now, meaning it's unsaved. */
util_assign_framebuffer_state(&blitter->saved_fb_state, state);
}
static INLINE
@@ -247,12 +329,13 @@ util_blitter_save_fragment_sampler_views(struct blitter_context *blitter,
int num_views,
struct pipe_sampler_view **views)
{
unsigned i;
assert(num_views <= Elements(blitter->saved_sampler_views));
blitter->saved_num_sampler_views = num_views;
memcpy(blitter->saved_sampler_views,
views,
num_views * sizeof(struct pipe_sampler_view *));
for (i = 0; i < num_views; i++)
pipe_sampler_view_reference(&blitter->saved_sampler_views[i],
views[i]);
}
static INLINE void
+17
View File
@@ -186,6 +186,22 @@ static unsigned caps_opengl_2_1[] = {
/* OpenGL 3.0 */
/* UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8), */
/* Shader Model 3 */
static unsigned caps_sm3[] = {
UTIL_CHECK_INT(MAX_FS_INSTRUCTIONS, 512),
UTIL_CHECK_INT(MAX_FS_INPUTS, 10),
UTIL_CHECK_INT(MAX_FS_TEMPS, 32),
UTIL_CHECK_INT(MAX_FS_ADDRS, 1),
UTIL_CHECK_INT(MAX_FS_CONSTS, 224),
UTIL_CHECK_INT(MAX_VS_INSTRUCTIONS, 512),
UTIL_CHECK_INT(MAX_VS_INPUTS, 16),
UTIL_CHECK_INT(MAX_VS_TEMPS, 32),
UTIL_CHECK_INT(MAX_VS_ADDRS, 2),
UTIL_CHECK_INT(MAX_VS_CONSTS, 256),
UTIL_CHECK_TERMINATE
};
/**
* Demo function which checks against theoretical caps needed for different APIs.
@@ -203,6 +219,7 @@ void util_caps_demo_print(struct pipe_screen *screen)
{"DX 11", caps_dx_11},
{"OpenGL 2.1", caps_opengl_2_1},
/* {"OpenGL 3.0", caps_opengl_3_0},*/
{"SM3", caps_sm3},
{NULL, NULL}
};
int i, out = 0;
+6 -6
View File
@@ -38,7 +38,7 @@
#include "u_cpu_detect.h"
#if defined(PIPE_ARCH_PPC)
#if defined(PIPE_OS_DARWIN)
#if defined(PIPE_OS_APPLE)
#include <sys/sysctl.h>
#else
#include <signal.h>
@@ -132,7 +132,7 @@ win32_sig_handler_sse(EXCEPTION_POINTERS* ep)
#endif /* PIPE_ARCH_X86 */
#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_DARWIN)
#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_APPLE)
static jmp_buf __lv_powerpc_jmpbuf;
static volatile sig_atomic_t __lv_powerpc_canjump = 0;
@@ -153,7 +153,7 @@ sigill_handler(int sig)
static void
check_os_altivec_support(void)
{
#if defined(PIPE_OS_DARWIN)
#if defined(PIPE_OS_APPLE)
int sels[2] = {CTL_HW, HW_VECTORUNIT};
int has_vu = 0;
int len = sizeof (has_vu);
@@ -166,8 +166,8 @@ check_os_altivec_support(void)
util_cpu_caps.has_altivec = 1;
}
}
#else /* !PIPE_OS_DARWIN */
/* no Darwin, do it the brute-force way */
#else /* !PIPE_OS_APPLE */
/* not on Apple/Darwin, do it the brute-force way */
/* this is borrowed from the libmpeg2 library */
signal(SIGILL, sigill_handler);
if (setjmp(__lv_powerpc_jmpbuf)) {
@@ -184,7 +184,7 @@ check_os_altivec_support(void)
signal(SIGILL, SIG_DFL);
util_cpu_caps.has_altivec = 1;
}
#endif /* PIPE_OS_DARWIN */
#endif /* !PIPE_OS_APPLE */
}
#endif /* PIPE_ARCH_PPC */
+2 -2
View File
@@ -190,11 +190,11 @@ debug_get_flags_option(const char *name,
result = dfault;
else if (!util_strcmp(str, "help")) {
result = dfault;
debug_printf("%s: help for %s:\n", __FUNCTION__, name);
_debug_printf("%s: help for %s:\n", __FUNCTION__, name);
for (; flags->name; ++flags)
namealign = MAX2(namealign, strlen(flags->name));
for (flags = orig; flags->name; ++flags)
debug_printf("| %*s [0x%0*lx]%s%s\n", namealign, flags->name,
_debug_printf("| %*s [0x%0*lx]%s%s\n", namealign, flags->name,
(int)sizeof(unsigned long)*CHAR_BIT/4, flags->value,
flags->desc ? " " : "", flags->desc ? flags->desc : "");
}
@@ -98,5 +98,20 @@ struct list_head
#define LIST_IS_EMPTY(__list) \
((__list)->next == (__list))
#ifndef container_of
#define container_of(ptr, sample, member) \
(void *)((char *)(ptr) \
- ((char *)&(sample)->member - (char *)(sample)))
#endif
#define LIST_FOR_EACH_ENTRY(pos, head, member) \
for (pos = container_of((head)->next, pos, member); \
&pos->member != (head); \
pos = container_of(pos->member.next, pos, member))
#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \
for (pos = container_of((head)->next, pos, member), \
storage = container_of(pos->member.next, pos, member); \
&pos->member != (head); \
pos = storage, storage = container_of(storage->member.next, storage, member))
#endif /*_U_DOUBLE_LIST_H_*/
+1 -1
View File
@@ -120,7 +120,7 @@ util_format_write_4ub(enum pipe_format format, const uint8_t *src, unsigned src_
}
static INLINE boolean
boolean
util_format_fits_8unorm(const struct util_format_description *format_desc)
{
unsigned chan;
+13
View File
@@ -212,6 +212,16 @@ struct util_format_description
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height);
/**
* Fetch a single pixel (i, j) from a block.
*
* XXX: Only defined for a very few select formats.
*/
void
(*fetch_rgba_8unorm)(uint8_t *dst,
const uint8_t *src,
unsigned i, unsigned j);
/**
* Unpack pixel blocks to R32G32B32A32_FLOAT.
* Note: strides are in bytes.
@@ -663,6 +673,9 @@ util_format_write_4ub(enum pipe_format format,
* Generic format conversion;
*/
boolean
util_format_fits_8unorm(const struct util_format_description *format_desc);
void
util_format_translate(enum pipe_format dst_format,
void *dst, unsigned dst_stride,

Some files were not shown because too many files have changed in this diff Show More