mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 11:48:06 +02:00
Merge branch 'upstream-gallium-0.1' into nouveau-gallium-0.1
Conflicts: src/gallium/drivers/Makefile
This commit is contained in:
commit
f7922db610
190 changed files with 7472 additions and 2053 deletions
2
Makefile
2
Makefile
|
|
@ -12,6 +12,8 @@ default: $(TOP)/configs/current
|
|||
fi \
|
||||
done
|
||||
|
||||
all: default
|
||||
|
||||
|
||||
doxygen:
|
||||
cd doxygen && $(MAKE)
|
||||
|
|
|
|||
70
SConstruct
70
SConstruct
|
|
@ -28,12 +28,22 @@ import sys
|
|||
# to get the full list of options. See scons manpage for more info.
|
||||
#
|
||||
|
||||
platform_map = {
|
||||
'linux2': 'linux',
|
||||
'win32': 'winddk',
|
||||
}
|
||||
|
||||
platform = platform_map.get(sys.platform, sys.platform)
|
||||
|
||||
# TODO: auto-detect defaults
|
||||
opts = Options('config.py')
|
||||
opts.Add(BoolOption('debug', 'build debug version', False))
|
||||
opts.Add(BoolOption('dri', 'build dri drivers', False))
|
||||
opts.Add(BoolOption('llvm', 'use llvm', False))
|
||||
opts.Add(EnumOption('machine', 'use machine-specific assembly code', 'x86',
|
||||
allowed_values=('generic', 'x86', 'x86-64')))
|
||||
opts.Add(EnumOption('platform', 'target platform', platform,
|
||||
allowed_values=('linux', 'cell', 'winddk')))
|
||||
|
||||
env = Environment(
|
||||
options = opts,
|
||||
|
|
@ -43,29 +53,23 @@ Help(opts.GenerateHelpText(env))
|
|||
# for debugging
|
||||
#print env.Dump()
|
||||
|
||||
if 0:
|
||||
# platform will be typically 'posix' or 'win32'
|
||||
platform = env['PLATFORM']
|
||||
else:
|
||||
# platform will be one of 'linux', 'freebsd', 'win32', 'darwin', etc.
|
||||
platform = sys.platform
|
||||
if platform == 'linux2':
|
||||
platform = 'linux'
|
||||
|
||||
# replicate options values in local variables
|
||||
debug = env['debug']
|
||||
dri = env['dri']
|
||||
llvm = env['llvm']
|
||||
machine = env['machine']
|
||||
platform = env['platform']
|
||||
|
||||
# derived options
|
||||
x86 = machine == 'x86'
|
||||
gcc = platform in ('posix', 'linux', 'freebsd', 'darwin')
|
||||
msvc = platform == 'win32'
|
||||
gcc = platform in ('linux', 'freebsd', 'darwin')
|
||||
msvc = platform in ('win32', 'winddk')
|
||||
|
||||
Export([
|
||||
'debug',
|
||||
'x86',
|
||||
'dri',
|
||||
'llvm',
|
||||
'platform',
|
||||
'gcc',
|
||||
'msvc',
|
||||
|
|
@ -75,10 +79,32 @@ Export([
|
|||
#######################################################################
|
||||
# Environment setup
|
||||
#
|
||||
# TODO: put the compiler specific settings in seperate files
|
||||
# TODO: put the compiler specific settings in separate files
|
||||
# TODO: auto-detect as much as possible
|
||||
|
||||
|
||||
|
||||
if platform == 'winddk':
|
||||
import ntpath
|
||||
escape = env['ESCAPE']
|
||||
env.Tool('msvc')
|
||||
if 'BASEDIR' in os.environ:
|
||||
WINDDK = os.environ['BASEDIR']
|
||||
else:
|
||||
WINDDK = "C:\\WINDDK\\3790.1830"
|
||||
# NOTE: We need this elaborate construct to get the absolute paths and
|
||||
# forward slashes to msvc unharmed when cross compiling from posix platforms
|
||||
env.Append(CPPFLAGS = [
|
||||
escape('/I' + ntpath.join(WINDDK, 'inc\\ddk\\wxp')),
|
||||
escape('/I' + ntpath.join(WINDDK, 'inc\\ddk\\wdm\\wxp')),
|
||||
escape('/I' + ntpath.join(WINDDK, 'inc\\crt')),
|
||||
])
|
||||
env.Append(CPPDEFINES = [
|
||||
('i386', '1'),
|
||||
])
|
||||
if debug:
|
||||
env.Append(CPPDEFINES = ['DBG'])
|
||||
|
||||
|
||||
# Optimization flags
|
||||
if gcc:
|
||||
if debug:
|
||||
|
|
@ -106,9 +132,9 @@ else:
|
|||
# Includes
|
||||
env.Append(CPPPATH = [
|
||||
'#/include',
|
||||
'#/src/mesa',
|
||||
'#/src/mesa/main',
|
||||
'#/src/mesa/pipe',
|
||||
'#/src/gallium/include',
|
||||
'#/src/gallium/auxiliary',
|
||||
'#/src/gallium/drivers',
|
||||
])
|
||||
|
||||
|
||||
|
|
@ -157,6 +183,14 @@ if dri:
|
|||
'GLX_INDIRECT_RENDERING',
|
||||
])
|
||||
|
||||
# LLVM
|
||||
if llvm:
|
||||
# See also http://www.scons.org/wiki/UsingPkgConfig
|
||||
env.ParseConfig('llvm-config --cflags --ldflags --libs')
|
||||
env.Append(CPPDEFINES = ['MESA_LLVM'])
|
||||
env.Append(CXXFLAGS = ['-Wno-long-long'])
|
||||
|
||||
|
||||
# libGL
|
||||
if 1:
|
||||
env.Append(LIBS = [
|
||||
|
|
@ -212,6 +246,8 @@ build_topdir = 'build'
|
|||
build_subdir = platform
|
||||
if dri:
|
||||
build_subdir += "-dri"
|
||||
if llvm:
|
||||
build_subdir += "-llvm"
|
||||
if x86:
|
||||
build_subdir += "-x86"
|
||||
if debug:
|
||||
|
|
@ -222,7 +258,7 @@ build_dir = os.path.join(build_topdir, build_subdir)
|
|||
# http://www.scons.org/wiki/SimultaneousVariantBuilds
|
||||
|
||||
SConscript(
|
||||
'src/mesa/SConscript',
|
||||
'src/SConscript',
|
||||
build_dir = build_dir,
|
||||
duplicate = 0 # http://www.scons.org/doc/0.97/HTML/scons-user/x2261.html
|
||||
)
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ ifeq ($(CPU), x86)
|
|||
-DUSE_3DNOW_ASM \
|
||||
-DUSE_SSE_ASM
|
||||
|
||||
ASM_SOURCES = $(X86_SOURCES)
|
||||
ASM_API = $(X86_API)
|
||||
MESA_ASM_SOURCES = $(X86_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86_API)
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ OSMESA_LIB_NAME = lib$(OSMESA_LIB).so
|
|||
|
||||
|
||||
# Optional assembly language optimization files for libGL
|
||||
ASM_SOURCES =
|
||||
MESA_ASM_SOURCES =
|
||||
|
||||
# GLw widget sources (Append "GLwMDrawA.c" here and add -lXm to GLW_LIB_DEPS in
|
||||
# order to build the Motif widget too)
|
||||
|
|
@ -60,13 +60,21 @@ GLW_SOURCES = GLwDrawA.c
|
|||
|
||||
# Directories to build
|
||||
LIB_DIR = lib
|
||||
SRC_DIRS = gallium mesa glu glut/glx glw
|
||||
SRC_DIRS = gallium mesa gallium/winsys glu glut/glx glw
|
||||
GLU_DIRS = sgi
|
||||
DRIVER_DIRS = x11 osmesa
|
||||
DRIVER_DIRS =
|
||||
# Which subdirs under $(TOP)/progs/ to enter:
|
||||
PROGRAM_DIRS = demos redbook samples glsl xdemos
|
||||
|
||||
|
||||
# Gallium directories and
|
||||
GALLIUM_AUXILIARY_DIRS = draw cso_cache pipebuffer tgsi rtasm util
|
||||
GALLIUM_AUXILIARIES = $(foreach DIR,$(GALLIUM_AUXILIARY_DIRS),$(TOP)/src/gallium/auxiliary/$(DIR)/lib$(DIR).a)
|
||||
GALLIUM_DRIVER_DIRS = softpipe i915simple i965simple failover
|
||||
GALLIUM_DRIVERS = $(foreach DIR,$(GALLIUM_DRIVER_DIRS),$(TOP)/src/gallium/drivers/$(DIR)/lib$(DIR).a)
|
||||
GALLIUM_WINSYS_DIRS = xlib
|
||||
|
||||
|
||||
# Library/program dependencies
|
||||
#EXTRA_LIB_PATH ?=
|
||||
GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ CFLAGS = $(WARN_FLAGS) $(OPT_FLAGS) $(PIC_FLAGS) -Wmissing-prototypes -std=c99 -
|
|||
|
||||
CXXFLAGS = $(WARN_FLAGS) $(OPT_FLAGS) $(PIC_FLAGS) $(DEFINES) -Wall -ansi -pedantic $(ASM_FLAGS) $(X11_INCLUDES)
|
||||
|
||||
ASM_SOURCES =
|
||||
MESA_ASM_SOURCES =
|
||||
|
||||
# Library/program dependencies
|
||||
LIBDRM_CFLAGS = `pkg-config --cflags libdrm`
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@ include $(TOP)/configs/freebsd-dri
|
|||
CONFIG_NAME = freebsd-dri-x86-64
|
||||
|
||||
ASM_FLAGS = -DUSE_X86_64_ASM
|
||||
ASM_SOURCES = $(X86-64_SOURCES)
|
||||
ASM_API = $(X86-64_API)
|
||||
MESA_ASM_SOURCES = $(X86-64_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86-64_API)
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ CONFIG_NAME = freebsd-dri-x86
|
|||
PIC_FLAGS =
|
||||
|
||||
ASM_FLAGS = -DUSE_X86_ASM -DUSE_MMX_ASM -DUSE_3DNOW_ASM -DUSE_SSE_ASM
|
||||
ASM_SOURCES = $(X86_SOURCES)
|
||||
ASM_API = $(X86_API)
|
||||
MESA_ASM_SOURCES = $(X86_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86_API)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ include $(TOP)/configs/default
|
|||
CONFIG_NAME = linux-cell
|
||||
|
||||
|
||||
GALLIUM_DRIVER_DIRS += cell
|
||||
|
||||
|
||||
# Compiler and flags
|
||||
CC = ppu32-gcc
|
||||
CXX = ppu32-g++
|
||||
|
|
@ -21,7 +24,7 @@ CFLAGS = $(OPT_FLAGS) -Wall -Winline -fPIC -m32 -mabi=altivec -maltivec -I. -I$(
|
|||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
# Omitting glw here:
|
||||
SRC_DIRS = gallium mesa glu glut/glx
|
||||
SRC_DIRS = gallium mesa gallium/winsys glu glut/glx
|
||||
|
||||
|
||||
MKDEP_OPTIONS = -fdepend -Y
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ HAVE_X86 = $(shell uname -m | grep 'i[3-6]86' >/dev/null && echo yes)
|
|||
ifeq ($(HAVE_X86), yes)
|
||||
CFLAGS += -DUSE_X86_ASM -DUSE_MMX_ASM -DUSE_3DNOW_ASM -DUSE_SSE_ASM
|
||||
CXXFLAGS += -DUSE_X86_ASM -DUSE_MMX_ASM -DUSE_3DNOW_ASM -DUSE_SSE_ASM
|
||||
ASM_SOURCES = $(X86_SOURCES)
|
||||
ASM_API = $(X86_API)
|
||||
MESA_ASM_SOURCES = $(X86_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86_API)
|
||||
endif
|
||||
|
||||
# Directories
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ CFLAGS = -Wall -Wmissing-prototypes -std=c99 -ffast-math \
|
|||
CXXFLAGS = -Wall $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES)
|
||||
|
||||
|
||||
ASM_SOURCES =
|
||||
MESA_ASM_SOURCES =
|
||||
|
||||
# Library/program dependencies
|
||||
EXTRA_LIB_PATH=-L/usr/X11R6/lib
|
||||
|
|
@ -53,16 +53,15 @@ GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
|
|||
USING_EGL=0
|
||||
|
||||
# Directories
|
||||
SRC_DIRS := glx/x11 $(SRC_DIRS)
|
||||
ifeq ($(USING_EGL), 1)
|
||||
SRC_DIRS = egl glx/x11 gallium mesa glu glut/glx glw
|
||||
SRC_DIRS := egl $(SRC_DIRS)
|
||||
PROGRAM_DIRS = egl
|
||||
else
|
||||
SRC_DIRS = glx/x11 gallium mesa glu glut/glx glw
|
||||
PROGRAM_DIRS =
|
||||
endif
|
||||
|
||||
DRIVER_DIRS = dri
|
||||
WINDOW_SYSTEM=dri
|
||||
GALLIUM_WINSYS_DIRS = dri
|
||||
|
||||
# gamma are missing because they have not been converted to use the new
|
||||
# interface.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ OPT_FLAGS = -Os -mcpu=603
|
|||
PIC_FLAGS = -fPIC
|
||||
|
||||
ASM_FLAGS = -DUSE_PPC_ASM -DUSE_VMX_ASM
|
||||
ASM_SOURCES = $(PPC_SOURCES)
|
||||
MESA_ASM_SOURCES = $(PPC_SOURCES)
|
||||
|
||||
# Build only the drivers for cards that exist on PowerPC. At some point MGA
|
||||
# will be added, but not yet.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ PIC_FLAGS =
|
|||
ARCH_FLAGS = -m32
|
||||
|
||||
ASM_FLAGS = -DUSE_X86_ASM -DUSE_MMX_ASM -DUSE_3DNOW_ASM -DUSE_SSE_ASM
|
||||
ASM_SOURCES = $(X86_SOURCES)
|
||||
ASM_API = $(X86_API)
|
||||
MESA_ASM_SOURCES = $(X86_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86_API)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ CONFIG_NAME = linux-dri-x86-64
|
|||
ARCH_FLAGS = -m64
|
||||
|
||||
ASM_FLAGS = -DUSE_X86_64_ASM
|
||||
ASM_SOURCES = $(X86-64_SOURCES)
|
||||
ASM_API = $(X86-64_API)
|
||||
MESA_ASM_SOURCES = $(X86-64_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86-64_API)
|
||||
|
||||
LIB_DIR = lib64
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ CFLAGS = -Wall -Wmissing-prototypes $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) \
|
|||
CXXFLAGS = -Wall $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES)
|
||||
|
||||
|
||||
ASM_SOURCES =
|
||||
MESA_ASM_SOURCES =
|
||||
|
||||
# Library/program dependencies
|
||||
EXTRA_LIB_PATH=$(shell pkg-config --libs-only-L x11)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ GL_LIB_DEPS = -L/usr/X11R6/lib -lX11 -lXext -lm -lpthread
|
|||
GLUT_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GLU_LIB) -l$(GL_LIB) -L/usr/X11R6/lib -lX11 -lXmu -lXt -lXi -lm
|
||||
APP_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -lm
|
||||
|
||||
ASM_SOURCES = $(X86_SOURCES)
|
||||
ASM_API = $(X86_API)
|
||||
MESA_ASM_SOURCES = $(X86_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86_API)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -23,5 +23,5 @@ GL_LIB_DEPS =
|
|||
GLUT_LIB_DEPS =
|
||||
APP_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -L/usr/X11R6/lib -lX11 -lXmu -lXt -lXi -lm -lpthread -lcxa -lunwind
|
||||
|
||||
ASM_SOURCES = $(X86_SOURCES)
|
||||
ASM_API = $(X86_API)
|
||||
MESA_ASM_SOURCES = $(X86_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86_API)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ CFLAGS = $(WARN_FLAGS) $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES) \
|
|||
CXXFLAGS = $(WARN_FLAGS) $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES)
|
||||
|
||||
|
||||
ASM_SOURCES =
|
||||
MESA_ASM_SOURCES =
|
||||
|
||||
# Library/program dependencies
|
||||
EXTRA_LIB_PATH=-L/usr/X11R6/lib
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ include $(TOP)/configs/linux
|
|||
|
||||
CONFIG_NAME = linux-llvm
|
||||
|
||||
GALLIUM_AUXILIARY_DIRS += gallivm
|
||||
|
||||
OPT_FLAGS = -g -ansi -pedantic
|
||||
DEFINES += -DDEBUG -DDEBUG_MATH -DMESA_LLVM=1
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ CFLAGS = $(WARN_FLAGS) $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES) \
|
|||
CXXFLAGS = $(WARN_FLAGS) $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES)
|
||||
|
||||
|
||||
ASM_SOURCES =
|
||||
MESA_ASM_SOURCES =
|
||||
|
||||
# Library/program dependencies
|
||||
DRI_LIB_DEPS = -lm -lpthread -lexpat -ldl -L$(TOP)/$(LIB_DIR) $(PCIACCESS_LIB)
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ CONFIG_NAME = linux-solo-x86
|
|||
PIC_FLAGS =
|
||||
|
||||
ASM_FLAGS = -DUSE_X86_ASM -DUSE_MMX_ASM -DUSE_3DNOW_ASM -DUSE_SSE_ASM
|
||||
ASM_SOURCES = $(X86_SOURCES)
|
||||
ASM_API = $(X86_API)
|
||||
MESA_ASM_SOURCES = $(X86_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86_API)
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ include $(TOP)/configs/linux
|
|||
CONFIG_NAME = linux-sparc
|
||||
|
||||
#ASM_FLAGS = -DUSE_SPARC_ASM
|
||||
#ASM_SOURCES = $(SPARC_SOURCES)
|
||||
#ASM_API = $(SPARC_API)
|
||||
#MESA_ASM_SOURCES = $(SPARC_SOURCES)
|
||||
#GLAPI_ASM_SOURCES = $(SPARC_API)
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ include $(TOP)/configs/linux
|
|||
CONFIG_NAME = linux-x86
|
||||
|
||||
ASM_FLAGS = -DUSE_X86_ASM -DUSE_MMX_ASM -DUSE_3DNOW_ASM -DUSE_SSE_ASM
|
||||
ASM_SOURCES = $(X86_SOURCES)
|
||||
ASM_API = $(X86_API)
|
||||
MESA_ASM_SOURCES = $(X86_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86_API)
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ CONFIG_NAME = linux-x86-64
|
|||
|
||||
ARCH_FLAGS = -m64
|
||||
|
||||
ASM_SOURCES = $(X86-64_SOURCES)
|
||||
ASM_API = $(X86-64_API)
|
||||
MESA_ASM_SOURCES = $(X86-64_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86-64_API)
|
||||
ASM_FLAGS = -DUSE_X86_64_ASM
|
||||
|
||||
LIB_DIR = lib64
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ CXXFLAGS = -Wall -O3 -ansi -pedantic -fPIC -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199
|
|||
GLUT_CFLAGS = -fexceptions
|
||||
|
||||
|
||||
ASM_SOURCES = $(X86_SOURCES)
|
||||
ASM_API = $(X86_API)
|
||||
MESA_ASM_SOURCES = $(X86_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(X86_API)
|
||||
|
||||
# Library/program dependencies
|
||||
GL_LIB_DEPS = -L/usr/X11R6/lib -lX11 -lXext -L/usr/local/glide/lib -lglide3x -lm -lpthread
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ ARCH_FLAGS ?=
|
|||
|
||||
DEFINES = -D_REENTRANT -DUSE_XSHM
|
||||
|
||||
ASM_SOURCES = $(SPARC_SOURCES)
|
||||
ASM_API = $(SPARC_API)
|
||||
MESA_ASM_SOURCES = $(SPARC_SOURCES)
|
||||
GLAPI_ASM_SOURCES = $(SPARC_API)
|
||||
ASM_FLAGS = -DUSE_SPARC_ASM
|
||||
|
||||
CFLAGS = $(WARN_FLAGS) $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES) \
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ FULL_PATH_NAMES = YES
|
|||
# If left blank the directory from which doxygen is run is used as the
|
||||
# path to strip.
|
||||
|
||||
STRIP_FROM_PATH = ../src/mesa
|
||||
STRIP_FROM_PATH = ../src
|
||||
|
||||
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
|
||||
# the path mentioned in the documentation of a class, which tells
|
||||
|
|
@ -478,9 +478,9 @@ WARN_LOGFILE =
|
|||
# with spaces.
|
||||
|
||||
INPUT = gallium.doc \
|
||||
../src/mesa/pipe \
|
||||
../src/gallium \
|
||||
../src/mesa/state_tracker \
|
||||
../src/mesa/drivers/dri/intel_winsys
|
||||
../src/mesa/x86/rtasm
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files that
|
||||
# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ SOURCES = \
|
|||
sharedtex.c \
|
||||
stencilwrap.c \
|
||||
stencil_wrap.c \
|
||||
subtex \
|
||||
subtexrate.c \
|
||||
tex1d.c \
|
||||
texcompress2.c \
|
||||
|
|
|
|||
223
progs/tests/subtex.c
Normal file
223
progs/tests/subtex.c
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* Test glTexSubImage mid-way through a frame.
|
||||
*
|
||||
* The same texture is used for both quads but it gets redefined
|
||||
* with glTexSubImage (or glTexImage) after the first quad.
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "GL/glut.h"
|
||||
|
||||
static GLuint Window = 0;
|
||||
static GLboolean Anim = GL_FALSE;
|
||||
static GLfloat Angle = 0.0f;
|
||||
|
||||
|
||||
|
||||
static void
|
||||
first_texture(void)
|
||||
{
|
||||
static int width=8, height=8;
|
||||
static GLubyte tex1[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
GLubyte tex[64][3];
|
||||
GLint i, j;
|
||||
|
||||
/* red on white */
|
||||
for (i=0;i<height;i++) {
|
||||
for (j=0;j<width;j++) {
|
||||
int p = i*width+j;
|
||||
if (tex1[(height-i-1)*width+j]) {
|
||||
tex[p][0] = 255; tex[p][1] = 0; tex[p][2] = 0;
|
||||
}
|
||||
else {
|
||||
tex[p][0] = 255; tex[p][1] = 255; tex[p][2] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, 3, width, height, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, tex );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
second_texture(void)
|
||||
{
|
||||
static int width=8, height=8;
|
||||
|
||||
static GLubyte tex2[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 2, 2, 0, 0, 0,
|
||||
0, 0, 2, 0, 0, 2, 0, 0,
|
||||
0, 0, 0, 0, 0, 2, 0, 0,
|
||||
0, 0, 0, 0, 2, 0, 0, 0,
|
||||
0, 0, 0, 2, 0, 0, 0, 0,
|
||||
0, 0, 2, 2, 2, 2, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
GLubyte tex[64][3];
|
||||
GLint i, j;
|
||||
|
||||
/* green on blue */
|
||||
for (i=0;i<height;i++) {
|
||||
for (j=0;j<width;j++) {
|
||||
int p = i*width+j;
|
||||
if (tex2[(height-i-1)*width+j]) {
|
||||
tex[p][0] = 0; tex[p][1] = 255; tex[p][2] = 0;
|
||||
}
|
||||
else {
|
||||
tex[p][0] = 0; tex[p][1] = 0; tex[p][2] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, 3, width, height, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, tex );
|
||||
#else
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, tex );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void draw( void )
|
||||
{
|
||||
glClear( GL_COLOR_BUFFER_BIT );
|
||||
|
||||
glColor3f( 1.0, 1.0, 1.0 );
|
||||
|
||||
/* draw first polygon */
|
||||
glPushMatrix();
|
||||
glTranslatef( -1.0, 0.0, 0.0 );
|
||||
glRotatef( Angle, 0.0, 0.0, 1.0 );
|
||||
|
||||
first_texture();
|
||||
|
||||
glBegin( GL_POLYGON );
|
||||
glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, -1.0 );
|
||||
glTexCoord2f( 1.0, 0.0 ); glVertex2f( 1.0, -1.0 );
|
||||
glTexCoord2f( 1.0, 1.0 ); glVertex2f( 1.0, 1.0 );
|
||||
glTexCoord2f( 0.0, 1.0 ); glVertex2f( -1.0, 1.0 );
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
|
||||
/* draw second polygon */
|
||||
glPushMatrix();
|
||||
glTranslatef( 1.0, 0.0, 0.0 );
|
||||
glRotatef( Angle-90.0, 0.0, 1.0, 0.0 );
|
||||
|
||||
second_texture();
|
||||
|
||||
glBegin( GL_POLYGON );
|
||||
glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, -1.0 );
|
||||
glTexCoord2f( 1.0, 0.0 ); glVertex2f( 1.0, -1.0 );
|
||||
glTexCoord2f( 1.0, 1.0 ); glVertex2f( 1.0, 1.0 );
|
||||
glTexCoord2f( 0.0, 1.0 ); glVertex2f( -1.0, 1.0 );
|
||||
glEnd();
|
||||
glPopMatrix();
|
||||
|
||||
glutSwapBuffers();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void idle( void )
|
||||
{
|
||||
static double t0 = -1.;
|
||||
double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
|
||||
if (t0 < 0.0)
|
||||
t0 = t;
|
||||
dt = t - t0;
|
||||
t0 = t;
|
||||
Angle += 120.0*dt;
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* change view Angle, exit upon ESC */
|
||||
static void key(unsigned char k, int x, int y)
|
||||
{
|
||||
(void) x;
|
||||
(void) y;
|
||||
switch (k) {
|
||||
case 'a':
|
||||
Anim = !Anim;
|
||||
if (Anim)
|
||||
glutIdleFunc( idle );
|
||||
else
|
||||
glutIdleFunc( NULL );
|
||||
break;
|
||||
case 27:
|
||||
glutDestroyWindow(Window);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* new window size or exposure */
|
||||
static void reshape( int width, int height )
|
||||
{
|
||||
glViewport(0, 0, (GLint)width, (GLint)height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
/* glOrtho( -3.0, 3.0, -3.0, 3.0, -10.0, 10.0 );*/
|
||||
glFrustum( -2.0, 2.0, -2.0, 2.0, 6.0, 20.0 );
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef( 0.0, 0.0, -8.0 );
|
||||
}
|
||||
|
||||
|
||||
static void init( void )
|
||||
{
|
||||
/* Setup texturing */
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
|
||||
|
||||
|
||||
glBindTexture( GL_TEXTURE_2D, 0 );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
glutInit(&argc, argv);
|
||||
glutInitWindowPosition(0, 0);
|
||||
glutInitWindowSize(300, 300);
|
||||
glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE );
|
||||
|
||||
Window = glutCreateWindow("Texture Objects");
|
||||
if (!Window) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
glutReshapeFunc( reshape );
|
||||
glutKeyboardFunc( key );
|
||||
if (Anim)
|
||||
glutIdleFunc( idle );
|
||||
glutDisplayFunc( draw );
|
||||
glutMainLoop();
|
||||
return 0;
|
||||
}
|
||||
7
src/SConscript
Normal file
7
src/SConscript
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Import('*')
|
||||
|
||||
SConscript([
|
||||
'gallium/SConscript',
|
||||
'mesa/SConscript',
|
||||
'gallium/winsys/SConscript',
|
||||
])
|
||||
|
|
@ -18,3 +18,4 @@ subdirs:
|
|||
|
||||
clean:
|
||||
rm -f `find . -name \*.[oa]`
|
||||
rm -f `find . -name depend`
|
||||
|
|
|
|||
|
|
@ -16,10 +16,8 @@ OBJECTS = $(C_SOURCES:.c=.o) \
|
|||
INCLUDES = \
|
||||
-I. \
|
||||
-I$(TOP)/src/gallium/include \
|
||||
-I$(TOP)/src/gallium/include/pipe \
|
||||
-I$(TOP)/src/gallium/auxiliary \
|
||||
-I$(TOP)/src/gallium/drivers \
|
||||
-I$(TOP)/src/mesa \
|
||||
-I$(TOP)/include \
|
||||
$(DRIVER_INCLUDES)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,29 @@
|
|||
Import('*')
|
||||
|
||||
#env = env.Clone()
|
||||
env = env.Clone()
|
||||
|
||||
auxiliaries = []
|
||||
|
||||
Export('auxiliaries')
|
||||
|
||||
|
||||
SConscript([
|
||||
'softpipe/SConscript',
|
||||
'i915simple/SConscript',
|
||||
'i965simple/SConscript',
|
||||
# NOTE: order matters!
|
||||
'auxiliary/util/SConscript',
|
||||
'auxiliary/rtasm/SConscript',
|
||||
'auxiliary/tgsi/SConscript',
|
||||
'auxiliary/cso_cache/SConscript',
|
||||
'auxiliary/draw/SConscript',
|
||||
'auxiliary/pipebuffer/SConscript',
|
||||
])
|
||||
|
||||
if llvm:
|
||||
SConscript(['auxiliary/gallivm/SConscript'])
|
||||
|
||||
SConscript([
|
||||
'drivers/softpipe/SConscript',
|
||||
'drivers/i915simple/SConscript',
|
||||
'drivers/i965simple/SConscript',
|
||||
'drivers/failover/SConscript',
|
||||
#'drivers/cell/SConscript',
|
||||
])
|
||||
|
|
|
|||
|
|
@ -2,11 +2,7 @@ TOP = ../../..
|
|||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
ifeq ($(CONFIG_NAME), linux-llvm)
|
||||
LLVM_DIR = llvm
|
||||
endif
|
||||
|
||||
SUBDIRS = pipebuffer $(LLVM_DIR)
|
||||
SUBDIRS = $(GALLIUM_AUXILIARY_DIRS)
|
||||
|
||||
|
||||
default: subdirs
|
||||
|
|
|
|||
13
src/gallium/auxiliary/cso_cache/Makefile
Normal file
13
src/gallium/auxiliary/cso_cache/Makefile
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
TOP = ../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
LIBNAME = cso_cache
|
||||
|
||||
C_SOURCES = \
|
||||
cso_cache.c \
|
||||
cso_hash.c
|
||||
|
||||
include ../../Makefile.template
|
||||
|
||||
symlinks:
|
||||
|
||||
10
src/gallium/auxiliary/cso_cache/SConscript
Normal file
10
src/gallium/auxiliary/cso_cache/SConscript
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
Import('*')
|
||||
|
||||
cso_cache = env.ConvenienceLibrary(
|
||||
target = 'cso_cache',
|
||||
source = [
|
||||
'cso_cache.c',
|
||||
'cso_hash.c',
|
||||
])
|
||||
|
||||
auxiliaries.insert(0, cso_cache)
|
||||
|
|
@ -158,11 +158,14 @@ static void cso_data_rehash(struct cso_hash_data *hash, int hint)
|
|||
while (firstNode != e) {
|
||||
unsigned h = firstNode->key;
|
||||
struct cso_node *lastNode = firstNode;
|
||||
struct cso_node *afterLastNode;
|
||||
struct cso_node **beforeFirstNode;
|
||||
|
||||
while (lastNode->next != e && lastNode->next->key == h)
|
||||
lastNode = lastNode->next;
|
||||
|
||||
struct cso_node *afterLastNode = lastNode->next;
|
||||
struct cso_node **beforeFirstNode = &hash->buckets[h % hash->numBuckets];
|
||||
afterLastNode = lastNode->next;
|
||||
beforeFirstNode = &hash->buckets[h % hash->numBuckets];
|
||||
while (*beforeFirstNode != e)
|
||||
beforeFirstNode = &(*beforeFirstNode)->next;
|
||||
lastNode->next = *beforeFirstNode;
|
||||
|
|
@ -222,10 +225,12 @@ struct cso_hash_iter cso_hash_insert(struct cso_hash *hash,
|
|||
{
|
||||
cso_data_might_grow(hash->data.d);
|
||||
|
||||
struct cso_node **nextNode = cso_hash_find_node(hash, key);
|
||||
struct cso_node *node = cso_hash_create_node(hash, key, data, nextNode);
|
||||
struct cso_hash_iter iter = {hash, node};
|
||||
return iter;
|
||||
{
|
||||
struct cso_node **nextNode = cso_hash_find_node(hash, key);
|
||||
struct cso_node *node = cso_hash_create_node(hash, key, data, nextNode);
|
||||
struct cso_hash_iter iter = {hash, node};
|
||||
return iter;
|
||||
}
|
||||
}
|
||||
|
||||
struct cso_hash * cso_hash_create(void)
|
||||
|
|
@ -290,6 +295,10 @@ static struct cso_node *cso_hash_data_next(struct cso_node *node)
|
|||
struct cso_node *e;
|
||||
struct cso_hash_data *d;
|
||||
} a;
|
||||
int start;
|
||||
struct cso_node **bucket;
|
||||
int n;
|
||||
|
||||
a.next = node->next;
|
||||
if (!a.next) {
|
||||
fprintf(stderr, "iterating beyond the last element\n");
|
||||
|
|
@ -298,9 +307,9 @@ static struct cso_node *cso_hash_data_next(struct cso_node *node)
|
|||
if (a.next->next)
|
||||
return a.next;
|
||||
|
||||
int start = (node->key % a.d->numBuckets) + 1;
|
||||
struct cso_node **bucket = a.d->buckets + start;
|
||||
int n = a.d->numBuckets - start;
|
||||
start = (node->key % a.d->numBuckets) + 1;
|
||||
bucket = a.d->buckets + start;
|
||||
n = a.d->numBuckets - start;
|
||||
while (n--) {
|
||||
if (*bucket != a.e)
|
||||
return *bucket;
|
||||
|
|
@ -316,19 +325,21 @@ static struct cso_node *cso_hash_data_prev(struct cso_node *node)
|
|||
struct cso_node *e;
|
||||
struct cso_hash_data *d;
|
||||
} a;
|
||||
int start;
|
||||
struct cso_node *sentinel;
|
||||
struct cso_node **bucket;
|
||||
|
||||
a.e = node;
|
||||
while (a.e->next)
|
||||
a.e = a.e->next;
|
||||
|
||||
int start;
|
||||
if (node == a.e)
|
||||
start = a.d->numBuckets - 1;
|
||||
else
|
||||
start = node->key % a.d->numBuckets;
|
||||
|
||||
struct cso_node *sentinel = node;
|
||||
struct cso_node **bucket = a.d->buckets + start;
|
||||
sentinel = node;
|
||||
bucket = a.d->buckets + start;
|
||||
while (start >= 0) {
|
||||
if (*bucket != sentinel) {
|
||||
struct cso_node *prev = *bucket;
|
||||
|
|
|
|||
|
|
@ -1,2 +1,37 @@
|
|||
default:
|
||||
cd ../../../mesa ; make
|
||||
TOP = ../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
LIBNAME = draw
|
||||
|
||||
C_SOURCES = \
|
||||
draw_aaline.c \
|
||||
draw_aapoint.c \
|
||||
draw_clip.c \
|
||||
draw_vs_exec.c \
|
||||
draw_vs_sse.c \
|
||||
draw_vs_llvm.c \
|
||||
draw_context.c\
|
||||
draw_cull.c \
|
||||
draw_debug.c \
|
||||
draw_flatshade.c \
|
||||
draw_offset.c \
|
||||
draw_prim.c \
|
||||
draw_pstipple.c \
|
||||
draw_stipple.c \
|
||||
draw_twoside.c \
|
||||
draw_unfilled.c \
|
||||
draw_validate.c \
|
||||
draw_vbuf.c \
|
||||
draw_vertex.c \
|
||||
draw_vertex_cache.c \
|
||||
draw_vertex_fetch.c \
|
||||
draw_vertex_shader.c \
|
||||
draw_vf.c \
|
||||
draw_vf_generic.c \
|
||||
draw_vf_sse.c \
|
||||
draw_wide_prims.c
|
||||
|
||||
include ../../Makefile.template
|
||||
|
||||
symlinks:
|
||||
|
||||
|
|
|
|||
31
src/gallium/auxiliary/draw/SConscript
Normal file
31
src/gallium/auxiliary/draw/SConscript
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
Import('*')
|
||||
|
||||
draw = env.ConvenienceLibrary(
|
||||
target = 'draw',
|
||||
source = [
|
||||
'draw_clip.c',
|
||||
'draw_vs_exec.c',
|
||||
'draw_vs_sse.c',
|
||||
'draw_vs_llvm.c',
|
||||
'draw_context.c',
|
||||
'draw_cull.c',
|
||||
'draw_debug.c',
|
||||
'draw_flatshade.c',
|
||||
'draw_offset.c',
|
||||
'draw_prim.c',
|
||||
'draw_stipple.c',
|
||||
'draw_twoside.c',
|
||||
'draw_unfilled.c',
|
||||
'draw_validate.c',
|
||||
'draw_vbuf.c',
|
||||
'draw_vertex.c',
|
||||
'draw_vertex_cache.c',
|
||||
'draw_vertex_fetch.c',
|
||||
'draw_vertex_shader.c',
|
||||
'draw_vf.c',
|
||||
'draw_vf_generic.c',
|
||||
'draw_vf_sse.c',
|
||||
'draw_wide_prims.c',
|
||||
])
|
||||
|
||||
auxiliaries.insert(0, draw)
|
||||
832
src/gallium/auxiliary/draw/draw_aaline.c
Normal file
832
src/gallium/auxiliary/draw/draw_aaline.c
Normal file
|
|
@ -0,0 +1,832 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* AA line stage: AA lines are converted to texture mapped triangles.
|
||||
*
|
||||
* Authors: Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include "pipe/p_util.h"
|
||||
#include "pipe/p_inlines.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
|
||||
#include "tgsi/util/tgsi_transform.h"
|
||||
#include "tgsi/util/tgsi_dump.h"
|
||||
|
||||
#include "draw_context.h"
|
||||
#include "draw_private.h"
|
||||
|
||||
|
||||
/**
|
||||
* Max texture level for the alpha texture used for antialiasing
|
||||
*/
|
||||
#define MAX_TEXTURE_LEVEL 5 /* 32 x 32 */
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of pipe_shader_state to carry extra fragment shader info.
|
||||
*/
|
||||
struct aaline_fragment_shader
|
||||
{
|
||||
struct pipe_shader_state state;
|
||||
void *driver_fs;
|
||||
void *aaline_fs;
|
||||
void *aapoint_fs; /* not yet */
|
||||
void *sprite_fs; /* not yet */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of draw_stage
|
||||
*/
|
||||
struct aaline_stage
|
||||
{
|
||||
struct draw_stage stage;
|
||||
|
||||
float half_line_width;
|
||||
|
||||
/** For AA lines, this is the vertex attrib slot for the new texcoords */
|
||||
uint tex_slot;
|
||||
|
||||
void *sampler_cso;
|
||||
struct pipe_texture *texture;
|
||||
uint sampler_unit;
|
||||
|
||||
|
||||
/*
|
||||
* Currently bound state
|
||||
*/
|
||||
struct aaline_fragment_shader *fs;
|
||||
struct {
|
||||
void *sampler[PIPE_MAX_SAMPLERS];
|
||||
struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
|
||||
} state;
|
||||
|
||||
/*
|
||||
* Driver interface/override functions
|
||||
*/
|
||||
void * (*driver_create_fs_state)(struct pipe_context *,
|
||||
const struct pipe_shader_state *);
|
||||
void (*driver_bind_fs_state)(struct pipe_context *, void *);
|
||||
void (*driver_delete_fs_state)(struct pipe_context *, void *);
|
||||
|
||||
void (*driver_bind_sampler_state)(struct pipe_context *, unsigned, void *);
|
||||
|
||||
void (*driver_set_sampler_texture)(struct pipe_context *,
|
||||
unsigned sampler,
|
||||
struct pipe_texture *);
|
||||
|
||||
struct pipe_context *pipe;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of tgsi_transform_context, used for transforming the
|
||||
* user's fragment shader to add the special AA instructions.
|
||||
*/
|
||||
struct aa_transform_context {
|
||||
struct tgsi_transform_context base;
|
||||
uint tempsUsed; /**< bitmask */
|
||||
int colorOutput; /**< which output is the primary color */
|
||||
int maxSampler; /**< max sampler index found */
|
||||
int maxInput, maxGeneric; /**< max input index found */
|
||||
int colorTemp, texTemp; /**< temp registers */
|
||||
boolean firstInstruction;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TGSI declaration transform callback.
|
||||
* Look for a free sampler, a free input attrib, and two free temp regs.
|
||||
*/
|
||||
static void
|
||||
aa_transform_decl(struct tgsi_transform_context *ctx,
|
||||
struct tgsi_full_declaration *decl)
|
||||
{
|
||||
struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
|
||||
|
||||
if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
|
||||
decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR &&
|
||||
decl->Semantic.SemanticIndex == 0) {
|
||||
aactx->colorOutput = decl->u.DeclarationRange.First;
|
||||
}
|
||||
else if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
|
||||
if ((int) decl->u.DeclarationRange.Last > aactx->maxSampler)
|
||||
aactx->maxSampler = decl->u.DeclarationRange.Last + 1;
|
||||
}
|
||||
else if (decl->Declaration.File == TGSI_FILE_INPUT) {
|
||||
if ((int) decl->u.DeclarationRange.Last > aactx->maxInput)
|
||||
aactx->maxInput = decl->u.DeclarationRange.Last;
|
||||
if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC &&
|
||||
(int) decl->Semantic.SemanticIndex > aactx->maxGeneric) {
|
||||
aactx->maxGeneric = decl->Semantic.SemanticIndex;
|
||||
}
|
||||
}
|
||||
else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
|
||||
uint i;
|
||||
for (i = decl->u.DeclarationRange.First;
|
||||
i <= decl->u.DeclarationRange.Last; i++) {
|
||||
aactx->tempsUsed |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
ctx->emit_declaration(ctx, decl);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TGSI instruction transform callback.
|
||||
* Replace writes to result.color w/ a temp reg.
|
||||
* Upon END instruction, insert texture sampling code for antialiasing.
|
||||
*/
|
||||
static void
|
||||
aa_transform_inst(struct tgsi_transform_context *ctx,
|
||||
struct tgsi_full_instruction *inst)
|
||||
{
|
||||
struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
|
||||
|
||||
if (aactx->firstInstruction) {
|
||||
/* emit our new declarations before the first instruction */
|
||||
|
||||
struct tgsi_full_declaration decl;
|
||||
uint i;
|
||||
|
||||
/* find two free temp regs */
|
||||
for (i = 0; i < 32; i++) {
|
||||
if ((aactx->tempsUsed & (1 << i)) == 0) {
|
||||
/* found a free temp */
|
||||
if (aactx->colorTemp < 0)
|
||||
aactx->colorTemp = i;
|
||||
else if (aactx->texTemp < 0)
|
||||
aactx->texTemp = i;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(aactx->colorTemp >= 0);
|
||||
assert(aactx->texTemp >= 0);
|
||||
|
||||
/* declare new generic input/texcoord */
|
||||
decl = tgsi_default_full_declaration();
|
||||
decl.Declaration.File = TGSI_FILE_INPUT;
|
||||
decl.Declaration.Semantic = 1;
|
||||
decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
|
||||
decl.Semantic.SemanticIndex = aactx->maxGeneric + 1;
|
||||
decl.Declaration.Interpolate = 1;
|
||||
/* XXX this could be linear... */
|
||||
decl.Interpolation.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
|
||||
decl.u.DeclarationRange.First =
|
||||
decl.u.DeclarationRange.Last = aactx->maxInput + 1;
|
||||
ctx->emit_declaration(ctx, &decl);
|
||||
|
||||
/* declare new sampler */
|
||||
decl = tgsi_default_full_declaration();
|
||||
decl.Declaration.File = TGSI_FILE_SAMPLER;
|
||||
decl.u.DeclarationRange.First =
|
||||
decl.u.DeclarationRange.Last = aactx->maxSampler + 1;
|
||||
ctx->emit_declaration(ctx, &decl);
|
||||
|
||||
/* declare new temp regs */
|
||||
decl = tgsi_default_full_declaration();
|
||||
decl.Declaration.File = TGSI_FILE_TEMPORARY;
|
||||
decl.u.DeclarationRange.First =
|
||||
decl.u.DeclarationRange.Last = aactx->texTemp;
|
||||
ctx->emit_declaration(ctx, &decl);
|
||||
|
||||
decl = tgsi_default_full_declaration();
|
||||
decl.Declaration.File = TGSI_FILE_TEMPORARY;
|
||||
decl.u.DeclarationRange.First =
|
||||
decl.u.DeclarationRange.Last = aactx->colorTemp;
|
||||
ctx->emit_declaration(ctx, &decl);
|
||||
|
||||
aactx->firstInstruction = FALSE;
|
||||
}
|
||||
|
||||
if (inst->Instruction.Opcode == TGSI_OPCODE_END &&
|
||||
aactx->colorOutput != -1) {
|
||||
struct tgsi_full_instruction newInst;
|
||||
|
||||
/* TEX */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = aactx->texTemp;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->maxInput + 1;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->maxSampler + 1;
|
||||
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* MOV rgb */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_MOV;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XYZ;
|
||||
newInst.Instruction.NumSrcRegs = 1;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* MUL alpha */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->texTemp;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* END */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_END;
|
||||
newInst.Instruction.NumDstRegs = 0;
|
||||
newInst.Instruction.NumSrcRegs = 0;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
}
|
||||
else {
|
||||
/* Not an END instruction.
|
||||
* Look for writes to result.color and replace with colorTemp reg.
|
||||
*/
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
|
||||
struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
|
||||
if (dst->DstRegister.File == TGSI_FILE_OUTPUT &&
|
||||
dst->DstRegister.Index == aactx->colorOutput) {
|
||||
dst->DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
dst->DstRegister.Index = aactx->colorTemp;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->emit_instruction(ctx, inst);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the frag shader we'll use for drawing AA lines.
|
||||
* This will be the user's shader plus some texture/modulate instructions.
|
||||
*/
|
||||
static void
|
||||
generate_aaline_fs(struct aaline_stage *aaline)
|
||||
{
|
||||
const struct pipe_shader_state *orig_fs = &aaline->fs->state;
|
||||
struct draw_context *draw = aaline->stage.draw;
|
||||
struct pipe_shader_state aaline_fs;
|
||||
struct aa_transform_context transform;
|
||||
|
||||
#define MAX 1000
|
||||
|
||||
aaline_fs = *orig_fs; /* copy to init */
|
||||
aaline_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
|
||||
|
||||
memset(&transform, 0, sizeof(transform));
|
||||
transform.colorOutput = -1;
|
||||
transform.maxSampler = -1;
|
||||
transform.maxInput = -1;
|
||||
transform.maxGeneric = -1;
|
||||
transform.colorTemp = -1;
|
||||
transform.texTemp = -1;
|
||||
transform.firstInstruction = TRUE;
|
||||
transform.base.transform_instruction = aa_transform_inst;
|
||||
transform.base.transform_declaration = aa_transform_decl;
|
||||
|
||||
tgsi_transform_shader(orig_fs->tokens,
|
||||
(struct tgsi_token *) aaline_fs.tokens,
|
||||
MAX, &transform.base);
|
||||
|
||||
#if 0 /* DEBUG */
|
||||
tgsi_dump(orig_fs->tokens, 0);
|
||||
tgsi_dump(aaline_fs.tokens, 0);
|
||||
#endif
|
||||
|
||||
aaline_fs.input_semantic_name[aaline_fs.num_inputs] = TGSI_SEMANTIC_GENERIC;
|
||||
aaline_fs.input_semantic_index[aaline_fs.num_inputs] = transform.maxGeneric + 1;
|
||||
aaline_fs.num_inputs++;
|
||||
|
||||
aaline->fs->aaline_fs
|
||||
= aaline->driver_create_fs_state(aaline->pipe, &aaline_fs);
|
||||
|
||||
/* advertise the extra post-transform vertex attributes which will have
|
||||
* the texcoords.
|
||||
*/
|
||||
draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
|
||||
draw->extra_vp_outputs.semantic_index = transform.maxGeneric + 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the texture map we'll use for antialiasing the lines.
|
||||
*/
|
||||
static void
|
||||
aaline_create_texture(struct aaline_stage *aaline)
|
||||
{
|
||||
struct pipe_context *pipe = aaline->pipe;
|
||||
struct pipe_texture texTemp;
|
||||
uint level;
|
||||
|
||||
memset(&texTemp, 0, sizeof(texTemp));
|
||||
texTemp.target = PIPE_TEXTURE_2D;
|
||||
texTemp.format = PIPE_FORMAT_U_A8; /* XXX verify supported by driver! */
|
||||
texTemp.last_level = MAX_TEXTURE_LEVEL;
|
||||
texTemp.width[0] = 1 << MAX_TEXTURE_LEVEL;
|
||||
texTemp.height[0] = 1 << MAX_TEXTURE_LEVEL;
|
||||
texTemp.depth[0] = 1;
|
||||
texTemp.cpp = 1;
|
||||
|
||||
aaline->texture = pipe->texture_create(pipe, &texTemp);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
for (level = 0; level <= MAX_TEXTURE_LEVEL; level++) {
|
||||
struct pipe_surface *surface;
|
||||
const uint size = aaline->texture->width[level];
|
||||
ubyte *data;
|
||||
uint i, j;
|
||||
|
||||
assert(aaline->texture->width[level] == aaline->texture->height[level]);
|
||||
|
||||
surface = pipe->get_tex_surface(pipe, aaline->texture, 0, level, 0);
|
||||
data = pipe_surface_map(surface);
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
for (j = 0; j < size; j++) {
|
||||
ubyte d;
|
||||
if (size == 1) {
|
||||
d = 255;
|
||||
}
|
||||
else if (size == 2) {
|
||||
d = 200; /* tuneable */
|
||||
}
|
||||
else if (i == 0 || j == 0 || i == size - 1 || j == size - 1) {
|
||||
d = 0;
|
||||
}
|
||||
else {
|
||||
d = 255;
|
||||
}
|
||||
data[i * surface->pitch + j] = d;
|
||||
}
|
||||
}
|
||||
|
||||
/* unmap */
|
||||
pipe_surface_unmap(surface);
|
||||
pipe_surface_reference(&surface, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the sampler CSO that'll be used for antialiasing.
|
||||
* By using a mipmapped texture, we don't have to generate a different
|
||||
* texture image for each line size.
|
||||
*/
|
||||
static void
|
||||
aaline_create_sampler(struct aaline_stage *aaline)
|
||||
{
|
||||
struct pipe_sampler_state sampler;
|
||||
struct pipe_context *pipe = aaline->pipe;
|
||||
|
||||
memset(&sampler, 0, sizeof(sampler));
|
||||
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
|
||||
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
|
||||
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
|
||||
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR;
|
||||
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
|
||||
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
|
||||
sampler.normalized_coords = 1;
|
||||
sampler.min_lod = 0.0f;
|
||||
sampler.max_lod = MAX_TEXTURE_LEVEL;
|
||||
|
||||
aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When we're about to draw our first AA line in a batch, this function is
|
||||
* called to tell the driver to bind our modified fragment shader.
|
||||
*/
|
||||
static void
|
||||
bind_aaline_fragment_shader(struct aaline_stage *aaline)
|
||||
{
|
||||
if (!aaline->fs->aaline_fs) {
|
||||
generate_aaline_fs(aaline);
|
||||
}
|
||||
aaline->driver_bind_fs_state(aaline->pipe, aaline->fs->aaline_fs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static INLINE struct aaline_stage *
|
||||
aaline_stage( struct draw_stage *stage )
|
||||
{
|
||||
return (struct aaline_stage *) stage;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
passthrough_point(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
stage->next->point(stage->next, header);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
passthrough_tri(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
stage->next->tri(stage->next, header);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw a wide line by drawing a quad, using geometry which will
|
||||
* fullfill GL's antialiased line requirements.
|
||||
*/
|
||||
static void
|
||||
aaline_line(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
const struct aaline_stage *aaline = aaline_stage(stage);
|
||||
const float half_width = aaline->half_line_width;
|
||||
struct prim_header tri;
|
||||
struct vertex_header *v[8];
|
||||
uint texPos = aaline->tex_slot;
|
||||
float *pos, *tex;
|
||||
float dx = header->v[1]->data[0][0] - header->v[0]->data[0][0];
|
||||
float dy = header->v[1]->data[0][1] - header->v[0]->data[0][1];
|
||||
double a = atan2(dy, dx);
|
||||
float c_a = (float) cos(a), s_a = (float) sin(a);
|
||||
uint i;
|
||||
|
||||
/* XXX the ends of lines aren't quite perfect yet, but probably passable */
|
||||
dx = 0.5F * half_width;
|
||||
dy = half_width;
|
||||
|
||||
/* allocate/dup new verts */
|
||||
for (i = 0; i < 8; i++) {
|
||||
v[i] = dup_vert(stage, header->v[i/4], i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Quad strip for line from v0 to v1 (*=endpoints):
|
||||
*
|
||||
* 1 3 5 7
|
||||
* +---+---------------------+---+
|
||||
* | |
|
||||
* | *v0 v1* |
|
||||
* | |
|
||||
* +---+---------------------+---+
|
||||
* 0 2 4 6
|
||||
*/
|
||||
|
||||
/* new verts */
|
||||
pos = v[0]->data[0];
|
||||
pos[0] += (-dx * c_a - dy * s_a);
|
||||
pos[1] += (-dx * s_a + dy * c_a);
|
||||
|
||||
pos = v[1]->data[0];
|
||||
pos[0] += (-dx * c_a - -dy * s_a);
|
||||
pos[1] += (-dx * s_a + -dy * c_a);
|
||||
|
||||
pos = v[2]->data[0];
|
||||
pos[0] += ( dx * c_a - dy * s_a);
|
||||
pos[1] += ( dx * s_a + dy * c_a);
|
||||
|
||||
pos = v[3]->data[0];
|
||||
pos[0] += ( dx * c_a - -dy * s_a);
|
||||
pos[1] += ( dx * s_a + -dy * c_a);
|
||||
|
||||
pos = v[4]->data[0];
|
||||
pos[0] += (-dx * c_a - dy * s_a);
|
||||
pos[1] += (-dx * s_a + dy * c_a);
|
||||
|
||||
pos = v[5]->data[0];
|
||||
pos[0] += (-dx * c_a - -dy * s_a);
|
||||
pos[1] += (-dx * s_a + -dy * c_a);
|
||||
|
||||
pos = v[6]->data[0];
|
||||
pos[0] += ( dx * c_a - dy * s_a);
|
||||
pos[1] += ( dx * s_a + dy * c_a);
|
||||
|
||||
pos = v[7]->data[0];
|
||||
pos[0] += ( dx * c_a - -dy * s_a);
|
||||
pos[1] += ( dx * s_a + -dy * c_a);
|
||||
|
||||
/* new texcoords */
|
||||
tex = v[0]->data[texPos];
|
||||
ASSIGN_4V(tex, 0, 0, 0, 1);
|
||||
|
||||
tex = v[1]->data[texPos];
|
||||
ASSIGN_4V(tex, 0, 1, 0, 1);
|
||||
|
||||
tex = v[2]->data[texPos];
|
||||
ASSIGN_4V(tex, .5, 0, 0, 1);
|
||||
|
||||
tex = v[3]->data[texPos];
|
||||
ASSIGN_4V(tex, .5, 1, 0, 1);
|
||||
|
||||
tex = v[4]->data[texPos];
|
||||
ASSIGN_4V(tex, .5, 0, 0, 1);
|
||||
|
||||
tex = v[5]->data[texPos];
|
||||
ASSIGN_4V(tex, .5, 1, 0, 1);
|
||||
|
||||
tex = v[6]->data[texPos];
|
||||
ASSIGN_4V(tex, 1, 0, 0, 1);
|
||||
|
||||
tex = v[7]->data[texPos];
|
||||
ASSIGN_4V(tex, 1, 1, 0, 1);
|
||||
|
||||
/* emit 6 tris for the quad strip */
|
||||
tri.v[0] = v[2]; tri.v[1] = v[1]; tri.v[2] = v[0];
|
||||
stage->next->tri( stage->next, &tri );
|
||||
|
||||
tri.v[0] = v[3]; tri.v[1] = v[1]; tri.v[2] = v[2];
|
||||
stage->next->tri( stage->next, &tri );
|
||||
|
||||
tri.v[0] = v[4]; tri.v[1] = v[3]; tri.v[2] = v[2];
|
||||
stage->next->tri( stage->next, &tri );
|
||||
|
||||
tri.v[0] = v[5]; tri.v[1] = v[3]; tri.v[2] = v[4];
|
||||
stage->next->tri( stage->next, &tri );
|
||||
|
||||
tri.v[0] = v[6]; tri.v[1] = v[5]; tri.v[2] = v[4];
|
||||
stage->next->tri( stage->next, &tri );
|
||||
|
||||
tri.v[0] = v[7]; tri.v[1] = v[5]; tri.v[2] = v[6];
|
||||
stage->next->tri( stage->next, &tri );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aaline_first_line(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
auto struct aaline_stage *aaline = aaline_stage(stage);
|
||||
struct draw_context *draw = stage->draw;
|
||||
struct pipe_context *pipe = aaline->pipe;
|
||||
|
||||
assert(draw->rasterizer->line_smooth);
|
||||
|
||||
if (draw->rasterizer->line_width <= 3.0)
|
||||
aaline->half_line_width = 1.5f;
|
||||
else
|
||||
aaline->half_line_width = 0.5f * draw->rasterizer->line_width;
|
||||
|
||||
aaline->tex_slot = draw->num_vs_outputs;
|
||||
assert(aaline->tex_slot > 0); /* output[0] is vertex pos */
|
||||
draw->extra_vp_outputs.slot = aaline->tex_slot;
|
||||
|
||||
/*
|
||||
* Bind our fragprog, sampler and texture
|
||||
*/
|
||||
bind_aaline_fragment_shader(aaline);
|
||||
|
||||
aaline->driver_bind_sampler_state(pipe, aaline->sampler_unit, aaline->sampler_cso);
|
||||
aaline->driver_set_sampler_texture(pipe, aaline->sampler_unit, aaline->texture);
|
||||
|
||||
/* now really draw first line */
|
||||
stage->line = aaline_line;
|
||||
stage->line(stage, header);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aaline_flush(struct draw_stage *stage, unsigned flags)
|
||||
{
|
||||
struct draw_context *draw = stage->draw;
|
||||
struct aaline_stage *aaline = aaline_stage(stage);
|
||||
struct pipe_context *pipe = aaline->pipe;
|
||||
|
||||
stage->line = aaline_first_line;
|
||||
stage->next->flush( stage->next, flags );
|
||||
|
||||
/* restore original frag shader */
|
||||
aaline->driver_bind_fs_state(pipe, aaline->fs->driver_fs);
|
||||
|
||||
/* XXX restore original texture, sampler state */
|
||||
aaline->driver_bind_sampler_state(pipe, aaline->sampler_unit,
|
||||
aaline->state.sampler[aaline->sampler_unit]);
|
||||
aaline->driver_set_sampler_texture(pipe, aaline->sampler_unit,
|
||||
aaline->state.texture[aaline->sampler_unit]);
|
||||
|
||||
draw->extra_vp_outputs.slot = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aaline_reset_stipple_counter(struct draw_stage *stage)
|
||||
{
|
||||
stage->next->reset_stipple_counter( stage->next );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aaline_destroy(struct draw_stage *stage)
|
||||
{
|
||||
draw_free_temp_verts( stage );
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
|
||||
static struct aaline_stage *
|
||||
draw_aaline_stage(struct draw_context *draw)
|
||||
{
|
||||
struct aaline_stage *aaline = CALLOC_STRUCT(aaline_stage);
|
||||
|
||||
draw_alloc_temp_verts( &aaline->stage, 8 );
|
||||
|
||||
aaline->stage.draw = draw;
|
||||
aaline->stage.next = NULL;
|
||||
aaline->stage.point = passthrough_point;
|
||||
aaline->stage.line = aaline_first_line;
|
||||
aaline->stage.tri = passthrough_tri;
|
||||
aaline->stage.flush = aaline_flush;
|
||||
aaline->stage.reset_stipple_counter = aaline_reset_stipple_counter;
|
||||
aaline->stage.destroy = aaline_destroy;
|
||||
|
||||
return aaline;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XXX temporary? solution to mapping a pipe_context to a aaline_stage.
|
||||
*/
|
||||
|
||||
#define MAX_CONTEXTS 10
|
||||
|
||||
static struct pipe_context *Pipe[MAX_CONTEXTS];
|
||||
static struct aaline_stage *Stage[MAX_CONTEXTS];
|
||||
static uint NumContexts;
|
||||
|
||||
static void
|
||||
add_aa_pipe_context(struct pipe_context *pipe, struct aaline_stage *aa)
|
||||
{
|
||||
assert(NumContexts < MAX_CONTEXTS);
|
||||
Pipe[NumContexts] = pipe;
|
||||
Stage[NumContexts] = aa;
|
||||
NumContexts++;
|
||||
}
|
||||
|
||||
static struct aaline_stage *
|
||||
aaline_stage_from_pipe(struct pipe_context *pipe)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < NumContexts; i++) {
|
||||
if (Pipe[i] == pipe)
|
||||
return Stage[i];
|
||||
}
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function overrides the driver's create_fs_state() function and
|
||||
* will typically be called by the state tracker.
|
||||
*/
|
||||
static void *
|
||||
aaline_create_fs_state(struct pipe_context *pipe,
|
||||
const struct pipe_shader_state *fs)
|
||||
{
|
||||
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
|
||||
struct aaline_fragment_shader *aafs = CALLOC_STRUCT(aaline_fragment_shader);
|
||||
|
||||
if (aafs) {
|
||||
aafs->state = *fs;
|
||||
|
||||
/* pass-through */
|
||||
aafs->driver_fs = aaline->driver_create_fs_state(aaline->pipe, fs);
|
||||
}
|
||||
|
||||
return aafs;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aaline_bind_fs_state(struct pipe_context *pipe, void *fs)
|
||||
{
|
||||
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
|
||||
struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
|
||||
/* save current */
|
||||
aaline->fs = aafs;
|
||||
/* pass-through */
|
||||
aaline->driver_bind_fs_state(aaline->pipe, aafs->driver_fs);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aaline_delete_fs_state(struct pipe_context *pipe, void *fs)
|
||||
{
|
||||
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
|
||||
struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
|
||||
/* pass-through */
|
||||
aaline->driver_delete_fs_state(aaline->pipe, aafs->driver_fs);
|
||||
FREE(aafs);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aaline_bind_sampler_state(struct pipe_context *pipe,
|
||||
unsigned unit, void *sampler)
|
||||
{
|
||||
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
|
||||
/* save current */
|
||||
aaline->state.sampler[unit] = sampler;
|
||||
/* pass-through */
|
||||
aaline->driver_bind_sampler_state(aaline->pipe, unit, sampler);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aaline_set_sampler_texture(struct pipe_context *pipe,
|
||||
unsigned sampler, struct pipe_texture *texture)
|
||||
{
|
||||
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
|
||||
/* save current */
|
||||
aaline->state.texture[sampler] = texture;
|
||||
/* pass-through */
|
||||
aaline->driver_set_sampler_texture(aaline->pipe, sampler, texture);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by drivers that want to install this AA line prim stage
|
||||
* into the draw module's pipeline. This will not be used if the
|
||||
* hardware has native support for AA lines.
|
||||
*/
|
||||
void
|
||||
draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe)
|
||||
{
|
||||
struct aaline_stage *aaline;
|
||||
|
||||
/*
|
||||
* Create / install AA line drawing / prim stage
|
||||
*/
|
||||
aaline = draw_aaline_stage( draw );
|
||||
assert(aaline);
|
||||
draw->pipeline.aaline = &aaline->stage;
|
||||
|
||||
aaline->pipe = pipe;
|
||||
|
||||
/* create special texture, sampler state */
|
||||
aaline_create_texture(aaline);
|
||||
aaline_create_sampler(aaline);
|
||||
|
||||
/* save original driver functions */
|
||||
aaline->driver_create_fs_state = pipe->create_fs_state;
|
||||
aaline->driver_bind_fs_state = pipe->bind_fs_state;
|
||||
aaline->driver_delete_fs_state = pipe->delete_fs_state;
|
||||
|
||||
aaline->driver_bind_sampler_state = pipe->bind_sampler_state;
|
||||
aaline->driver_set_sampler_texture = pipe->set_sampler_texture;
|
||||
|
||||
/* override the driver's functions */
|
||||
pipe->create_fs_state = aaline_create_fs_state;
|
||||
pipe->bind_fs_state = aaline_bind_fs_state;
|
||||
pipe->delete_fs_state = aaline_delete_fs_state;
|
||||
|
||||
pipe->bind_sampler_state = aaline_bind_sampler_state;
|
||||
pipe->set_sampler_texture = aaline_set_sampler_texture;
|
||||
|
||||
add_aa_pipe_context(pipe, aaline);
|
||||
}
|
||||
875
src/gallium/auxiliary/draw/draw_aapoint.c
Normal file
875
src/gallium/auxiliary/draw/draw_aapoint.c
Normal file
|
|
@ -0,0 +1,875 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* AA point stage: AA points are converted to quads and rendered with a
|
||||
* special fragment shader. Another approach would be to use a texture
|
||||
* map image of a point, but experiments indicate the quality isn't nearly
|
||||
* as good as this approach.
|
||||
*
|
||||
* Note: this looks a lot like draw_aaline.c but there's actually little
|
||||
* if any code that can be shared.
|
||||
*
|
||||
* Authors: Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include "pipe/p_util.h"
|
||||
#include "pipe/p_inlines.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
|
||||
#include "tgsi/util/tgsi_transform.h"
|
||||
#include "tgsi/util/tgsi_dump.h"
|
||||
|
||||
#include "draw_context.h"
|
||||
#include "draw_private.h"
|
||||
|
||||
|
||||
/*
|
||||
* Enabling NORMALIZE might give _slightly_ better results.
|
||||
* Basically, it controls whether we compute distance as d=sqrt(x*x+y*y) or
|
||||
* d=x*x+y*y. Since we're working with a unit circle, the later seems
|
||||
* close enough and saves some costly instructions.
|
||||
*/
|
||||
#define NORMALIZE 0
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of pipe_shader_state to carry extra fragment shader info.
|
||||
*/
|
||||
struct aapoint_fragment_shader
|
||||
{
|
||||
struct pipe_shader_state state;
|
||||
void *driver_fs; /**< the regular shader */
|
||||
void *aapoint_fs; /**< the aa point-augmented shader */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of draw_stage
|
||||
*/
|
||||
struct aapoint_stage
|
||||
{
|
||||
struct draw_stage stage;
|
||||
|
||||
int psize_slot;
|
||||
float radius;
|
||||
|
||||
/** this is the vertex attrib slot for the new texcoords */
|
||||
uint tex_slot;
|
||||
|
||||
/*
|
||||
* Currently bound state
|
||||
*/
|
||||
struct aapoint_fragment_shader *fs;
|
||||
|
||||
/*
|
||||
* Driver interface/override functions
|
||||
*/
|
||||
void * (*driver_create_fs_state)(struct pipe_context *,
|
||||
const struct pipe_shader_state *);
|
||||
void (*driver_bind_fs_state)(struct pipe_context *, void *);
|
||||
void (*driver_delete_fs_state)(struct pipe_context *, void *);
|
||||
|
||||
struct pipe_context *pipe;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of tgsi_transform_context, used for transforming the
|
||||
* user's fragment shader to add the special AA instructions.
|
||||
*/
|
||||
struct aa_transform_context {
|
||||
struct tgsi_transform_context base;
|
||||
uint tempsUsed; /**< bitmask */
|
||||
int colorOutput; /**< which output is the primary color */
|
||||
int maxInput, maxGeneric; /**< max input index found */
|
||||
int tmp0, colorTemp; /**< temp registers */
|
||||
boolean firstInstruction;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TGSI declaration transform callback.
|
||||
* Look for two free temp regs and available input reg for new texcoords.
|
||||
*/
|
||||
static void
|
||||
aa_transform_decl(struct tgsi_transform_context *ctx,
|
||||
struct tgsi_full_declaration *decl)
|
||||
{
|
||||
struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
|
||||
|
||||
if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
|
||||
decl->Semantic.SemanticName == TGSI_SEMANTIC_COLOR &&
|
||||
decl->Semantic.SemanticIndex == 0) {
|
||||
aactx->colorOutput = decl->u.DeclarationRange.First;
|
||||
}
|
||||
else if (decl->Declaration.File == TGSI_FILE_INPUT) {
|
||||
if ((int) decl->u.DeclarationRange.Last > aactx->maxInput)
|
||||
aactx->maxInput = decl->u.DeclarationRange.Last;
|
||||
if (decl->Semantic.SemanticName == TGSI_SEMANTIC_GENERIC &&
|
||||
(int) decl->Semantic.SemanticIndex > aactx->maxGeneric) {
|
||||
aactx->maxGeneric = decl->Semantic.SemanticIndex;
|
||||
}
|
||||
}
|
||||
else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
|
||||
uint i;
|
||||
for (i = decl->u.DeclarationRange.First;
|
||||
i <= decl->u.DeclarationRange.Last; i++) {
|
||||
aactx->tempsUsed |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
ctx->emit_declaration(ctx, decl);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TGSI instruction transform callback.
|
||||
* Replace writes to result.color w/ a temp reg.
|
||||
* Upon END instruction, insert texture sampling code for antialiasing.
|
||||
*/
|
||||
static void
|
||||
aa_transform_inst(struct tgsi_transform_context *ctx,
|
||||
struct tgsi_full_instruction *inst)
|
||||
{
|
||||
struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
|
||||
struct tgsi_full_instruction newInst;
|
||||
|
||||
if (aactx->firstInstruction) {
|
||||
/* emit our new declarations before the first instruction */
|
||||
|
||||
struct tgsi_full_declaration decl;
|
||||
const int texInput = aactx->maxInput + 1;
|
||||
int tmp0;
|
||||
uint i;
|
||||
|
||||
/* find two free temp regs */
|
||||
for (i = 0; i < 32; i++) {
|
||||
if ((aactx->tempsUsed & (1 << i)) == 0) {
|
||||
/* found a free temp */
|
||||
if (aactx->tmp0 < 0)
|
||||
aactx->tmp0 = i;
|
||||
else if (aactx->colorTemp < 0)
|
||||
aactx->colorTemp = i;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(aactx->colorTemp != aactx->tmp0);
|
||||
|
||||
tmp0 = aactx->tmp0;
|
||||
|
||||
/* declare new generic input/texcoord */
|
||||
decl = tgsi_default_full_declaration();
|
||||
decl.Declaration.File = TGSI_FILE_INPUT;
|
||||
decl.Declaration.Semantic = 1;
|
||||
decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC;
|
||||
decl.Semantic.SemanticIndex = aactx->maxGeneric + 1;
|
||||
decl.Declaration.Interpolate = 1;
|
||||
/* XXX this could be linear... */
|
||||
decl.Interpolation.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
|
||||
decl.u.DeclarationRange.First =
|
||||
decl.u.DeclarationRange.Last = texInput;
|
||||
ctx->emit_declaration(ctx, &decl);
|
||||
|
||||
/* declare new temp regs */
|
||||
decl = tgsi_default_full_declaration();
|
||||
decl.Declaration.File = TGSI_FILE_TEMPORARY;
|
||||
decl.u.DeclarationRange.First =
|
||||
decl.u.DeclarationRange.Last = tmp0;
|
||||
ctx->emit_declaration(ctx, &decl);
|
||||
|
||||
decl = tgsi_default_full_declaration();
|
||||
decl.Declaration.File = TGSI_FILE_TEMPORARY;
|
||||
decl.u.DeclarationRange.First =
|
||||
decl.u.DeclarationRange.Last = aactx->colorTemp;
|
||||
ctx->emit_declaration(ctx, &decl);
|
||||
|
||||
aactx->firstInstruction = FALSE;
|
||||
|
||||
|
||||
/*
|
||||
* Emit code to compute fragment coverage, kill if outside point radius
|
||||
*
|
||||
* Temp reg0 usage:
|
||||
* t0.x = distance of fragment from center point
|
||||
* t0.y = boolean, is t0.x > 1 ?
|
||||
* t0.z = temporary for computing 1/(1-k) value
|
||||
* t0.w = final coverage value
|
||||
*/
|
||||
|
||||
/* MUL t0.xy, tex, tex; # compute x^2, y^2 */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XY;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = texInput;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = texInput;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* ADD t0.x, t0.x, t0.y; # x^2 + y^2 */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_ADD;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
#if NORMALIZE /* OPTIONAL normalization of length */
|
||||
/* RSQ t0.x, t0.x; */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_RSQ;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X;
|
||||
newInst.Instruction.NumSrcRegs = 1;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* RCP t0.x, t0.x; */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_RCP;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X;
|
||||
newInst.Instruction.NumSrcRegs = 1;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
#endif
|
||||
|
||||
/* SGT t0.y, t0.xxxx, t0.wwww; # bool b = d > 1 (NOTE t0.w == 1) */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_SGT;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Y;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = texInput;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_W;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* KILP -t0.yyyy; # if b, KILL */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_KILP;
|
||||
newInst.Instruction.NumDstRegs = 0;
|
||||
newInst.Instruction.NumSrcRegs = 1;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Negate = 1;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* SGT t0.y, t0.x, tex.z; # bool b = distance > k */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_SGT;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Y;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = texInput;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Z;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* IF t0.y # if b then */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_IF;
|
||||
newInst.Instruction.NumDstRegs = 0;
|
||||
newInst.Instruction.NumSrcRegs = 1;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
{
|
||||
/* compute coverage factor = (1-d)/(1-k) */
|
||||
|
||||
/* SUB t0.z, tex.w, tex.z; # m = 1 - k */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_SUB;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Z;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = texInput;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_W;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_INPUT;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = texInput;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* RCP t0.z, t0.z; # t0.z = 1 / m */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_RCP;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_Z;
|
||||
newInst.Instruction.NumSrcRegs = 1;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Z;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* SUB t0.x, 1, t0.x; # d = 1 - d */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_SUB;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = texInput;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_W;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* MUL t0.w, t0.x, t0.z; # coverage = d * m */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = tmp0;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = tmp0;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Z;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
}
|
||||
|
||||
/* ELSE */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_ELSE;
|
||||
newInst.Instruction.NumDstRegs = 0;
|
||||
newInst.Instruction.NumSrcRegs = 0;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
{
|
||||
/* MOV t0.w, tex.w; # coverage = 1.0 */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_MOV;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = tmp0;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W;
|
||||
newInst.Instruction.NumSrcRegs = 1;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = texInput;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
}
|
||||
|
||||
/* ENDIF */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_ENDIF;
|
||||
newInst.Instruction.NumDstRegs = 0;
|
||||
newInst.Instruction.NumSrcRegs = 0;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
}
|
||||
|
||||
if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
|
||||
/* add alpha modulation code at tail of program */
|
||||
|
||||
/* MOV result.color.xyz, colorTemp; */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_MOV;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_XYZ;
|
||||
newInst.Instruction.NumSrcRegs = 1;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* MUL result.color.w, colorTemp, tmp0.w; */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = aactx->colorOutput;
|
||||
newInst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_W;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = aactx->colorTemp;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = aactx->tmp0;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
}
|
||||
else {
|
||||
/* Not an END instruction.
|
||||
* Look for writes to result.color and replace with colorTemp reg.
|
||||
*/
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
|
||||
struct tgsi_full_dst_register *dst = &inst->FullDstRegisters[i];
|
||||
if (dst->DstRegister.File == TGSI_FILE_OUTPUT &&
|
||||
dst->DstRegister.Index == aactx->colorOutput) {
|
||||
dst->DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
dst->DstRegister.Index = aactx->colorTemp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->emit_instruction(ctx, inst);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the frag shader we'll use for drawing AA lines.
|
||||
* This will be the user's shader plus some texture/modulate instructions.
|
||||
*/
|
||||
static void
|
||||
generate_aapoint_fs(struct aapoint_stage *aapoint)
|
||||
{
|
||||
const struct pipe_shader_state *orig_fs = &aapoint->fs->state;
|
||||
struct draw_context *draw = aapoint->stage.draw;
|
||||
struct pipe_shader_state aapoint_fs;
|
||||
struct aa_transform_context transform;
|
||||
|
||||
#define MAX 1000
|
||||
|
||||
aapoint_fs = *orig_fs; /* copy to init */
|
||||
aapoint_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
|
||||
|
||||
memset(&transform, 0, sizeof(transform));
|
||||
transform.colorOutput = -1;
|
||||
transform.maxInput = -1;
|
||||
transform.maxGeneric = -1;
|
||||
transform.colorTemp = -1;
|
||||
transform.tmp0 = -1;
|
||||
transform.firstInstruction = TRUE;
|
||||
transform.base.transform_instruction = aa_transform_inst;
|
||||
transform.base.transform_declaration = aa_transform_decl;
|
||||
|
||||
tgsi_transform_shader(orig_fs->tokens,
|
||||
(struct tgsi_token *) aapoint_fs.tokens,
|
||||
MAX, &transform.base);
|
||||
|
||||
#if 0 /* DEBUG */
|
||||
tgsi_dump(orig_fs->tokens, 0);
|
||||
tgsi_dump(aapoint_fs.tokens, 0);
|
||||
#endif
|
||||
|
||||
aapoint_fs.input_semantic_name[aapoint_fs.num_inputs] = TGSI_SEMANTIC_GENERIC;
|
||||
aapoint_fs.input_semantic_index[aapoint_fs.num_inputs] = transform.maxGeneric + 1;
|
||||
aapoint_fs.num_inputs++;
|
||||
|
||||
aapoint->fs->aapoint_fs
|
||||
= aapoint->driver_create_fs_state(aapoint->pipe, &aapoint_fs);
|
||||
|
||||
/* advertise the extra post-transform vertex attributes which will have
|
||||
* the texcoords.
|
||||
*/
|
||||
draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC;
|
||||
draw->extra_vp_outputs.semantic_index = transform.maxGeneric + 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When we're about to draw our first AA line in a batch, this function is
|
||||
* called to tell the driver to bind our modified fragment shader.
|
||||
*/
|
||||
static void
|
||||
bind_aapoint_fragment_shader(struct aapoint_stage *aapoint)
|
||||
{
|
||||
if (!aapoint->fs->aapoint_fs) {
|
||||
generate_aapoint_fs(aapoint);
|
||||
}
|
||||
aapoint->driver_bind_fs_state(aapoint->pipe, aapoint->fs->aapoint_fs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static INLINE struct aapoint_stage *
|
||||
aapoint_stage( struct draw_stage *stage )
|
||||
{
|
||||
return (struct aapoint_stage *) stage;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
passthrough_line(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
stage->next->line(stage->next, header);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
passthrough_tri(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
stage->next->tri(stage->next, header);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw an AA point by drawing a quad.
|
||||
*/
|
||||
static void
|
||||
aapoint_point(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
const struct aapoint_stage *aapoint = aapoint_stage(stage);
|
||||
struct prim_header tri;
|
||||
struct vertex_header *v[4];
|
||||
uint texPos = aapoint->tex_slot;
|
||||
float radius, *pos, *tex;
|
||||
uint i;
|
||||
float k;
|
||||
|
||||
if (aapoint->psize_slot >= 0) {
|
||||
radius = 0.5f * header->v[0]->data[aapoint->psize_slot][0];
|
||||
}
|
||||
else {
|
||||
radius = aapoint->radius;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the texcoords (generic attrib, really) we use are special:
|
||||
* The S and T components simply vary from -1 to +1.
|
||||
* The R component is k, below.
|
||||
* The Q component is 1.0 and will used as a handy constant in the
|
||||
* fragment shader.
|
||||
*/
|
||||
|
||||
/*
|
||||
* k is the threshold distance from the point's center at which
|
||||
* we begin alpha attenuation (the coverage value).
|
||||
* Operating within a unit circle, we'll compute the fragment's
|
||||
* distance 'd' from the center point using the texcoords.
|
||||
* IF d > 1.0 THEN
|
||||
* KILL fragment
|
||||
* ELSE IF d > k THEN
|
||||
* compute coverage in [0,1] proportional to d in [k, 1].
|
||||
* ELSE
|
||||
* coverage = 1.0; // full coverage
|
||||
* ENDIF
|
||||
*/
|
||||
|
||||
#if !NORMALIZE
|
||||
k = 1.0 / radius;
|
||||
k = 1.0 - 2.0 * k + k * k;
|
||||
#else
|
||||
k = 1.0 - 1.0 / radius;
|
||||
#endif
|
||||
|
||||
/* allocate/dup new verts */
|
||||
for (i = 0; i < 4; i++) {
|
||||
v[i] = dup_vert(stage, header->v[0], i);
|
||||
}
|
||||
|
||||
/* new verts */
|
||||
pos = v[0]->data[0];
|
||||
pos[0] -= radius;
|
||||
pos[1] -= radius;
|
||||
|
||||
pos = v[1]->data[0];
|
||||
pos[0] += radius;
|
||||
pos[1] -= radius;
|
||||
|
||||
pos = v[2]->data[0];
|
||||
pos[0] += radius;
|
||||
pos[1] += radius;
|
||||
|
||||
pos = v[3]->data[0];
|
||||
pos[0] -= radius;
|
||||
pos[1] += radius;
|
||||
|
||||
/* new texcoords */
|
||||
tex = v[0]->data[texPos];
|
||||
ASSIGN_4V(tex, -1, -1, k, 1);
|
||||
|
||||
tex = v[1]->data[texPos];
|
||||
ASSIGN_4V(tex, 1, -1, k, 1);
|
||||
|
||||
tex = v[2]->data[texPos];
|
||||
ASSIGN_4V(tex, 1, 1, k, 1);
|
||||
|
||||
tex = v[3]->data[texPos];
|
||||
ASSIGN_4V(tex, -1, 1, k, 1);
|
||||
|
||||
/* emit 2 tris for the quad strip */
|
||||
tri.v[0] = v[0];
|
||||
tri.v[1] = v[1];
|
||||
tri.v[2] = v[2];
|
||||
stage->next->tri( stage->next, &tri );
|
||||
|
||||
tri.v[0] = v[0];
|
||||
tri.v[1] = v[2];
|
||||
tri.v[2] = v[3];
|
||||
stage->next->tri( stage->next, &tri );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aapoint_first_point(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
auto struct aapoint_stage *aapoint = aapoint_stage(stage);
|
||||
struct draw_context *draw = stage->draw;
|
||||
|
||||
assert(draw->rasterizer->point_smooth);
|
||||
|
||||
if (draw->rasterizer->point_size <= 2.0)
|
||||
aapoint->radius = 1.0;
|
||||
else
|
||||
aapoint->radius = 0.5f * draw->rasterizer->point_size;
|
||||
|
||||
aapoint->tex_slot = draw->num_vs_outputs;
|
||||
assert(aapoint->tex_slot > 0); /* output[0] is vertex pos */
|
||||
draw->extra_vp_outputs.slot = aapoint->tex_slot;
|
||||
|
||||
/*
|
||||
* Bind our fragprog.
|
||||
*/
|
||||
bind_aapoint_fragment_shader(aapoint);
|
||||
|
||||
/* find psize slot in post-transform vertex */
|
||||
aapoint->psize_slot = -1;
|
||||
if (draw->rasterizer->point_size_per_vertex) {
|
||||
/* find PSIZ vertex output */
|
||||
const struct draw_vertex_shader *vs = draw->vertex_shader;
|
||||
uint i;
|
||||
for (i = 0; i < vs->state->num_outputs; i++) {
|
||||
if (vs->state->output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) {
|
||||
aapoint->psize_slot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now really draw first line */
|
||||
stage->point = aapoint_point;
|
||||
stage->point(stage, header);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aapoint_flush(struct draw_stage *stage, unsigned flags)
|
||||
{
|
||||
struct draw_context *draw = stage->draw;
|
||||
struct aapoint_stage *aapoint = aapoint_stage(stage);
|
||||
struct pipe_context *pipe = aapoint->pipe;
|
||||
|
||||
stage->point = aapoint_first_point;
|
||||
stage->next->flush( stage->next, flags );
|
||||
|
||||
/* restore original frag shader */
|
||||
aapoint->driver_bind_fs_state(pipe, aapoint->fs->driver_fs);
|
||||
|
||||
draw->extra_vp_outputs.slot = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aapoint_reset_stipple_counter(struct draw_stage *stage)
|
||||
{
|
||||
stage->next->reset_stipple_counter( stage->next );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aapoint_destroy(struct draw_stage *stage)
|
||||
{
|
||||
draw_free_temp_verts( stage );
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
|
||||
static struct aapoint_stage *
|
||||
draw_aapoint_stage(struct draw_context *draw)
|
||||
{
|
||||
struct aapoint_stage *aapoint = CALLOC_STRUCT(aapoint_stage);
|
||||
|
||||
draw_alloc_temp_verts( &aapoint->stage, 4 );
|
||||
|
||||
aapoint->stage.draw = draw;
|
||||
aapoint->stage.next = NULL;
|
||||
aapoint->stage.point = aapoint_first_point;
|
||||
aapoint->stage.line = passthrough_line;
|
||||
aapoint->stage.tri = passthrough_tri;
|
||||
aapoint->stage.flush = aapoint_flush;
|
||||
aapoint->stage.reset_stipple_counter = aapoint_reset_stipple_counter;
|
||||
aapoint->stage.destroy = aapoint_destroy;
|
||||
|
||||
return aapoint;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XXX temporary? solution to mapping a pipe_context to a aapoint_stage.
|
||||
*/
|
||||
|
||||
#define MAX_CONTEXTS 10
|
||||
|
||||
static struct pipe_context *Pipe[MAX_CONTEXTS];
|
||||
static struct aapoint_stage *Stage[MAX_CONTEXTS];
|
||||
static uint NumContexts;
|
||||
|
||||
static void
|
||||
add_aa_pipe_context(struct pipe_context *pipe, struct aapoint_stage *aa)
|
||||
{
|
||||
assert(NumContexts < MAX_CONTEXTS);
|
||||
Pipe[NumContexts] = pipe;
|
||||
Stage[NumContexts] = aa;
|
||||
NumContexts++;
|
||||
}
|
||||
|
||||
static struct aapoint_stage *
|
||||
aapoint_stage_from_pipe(struct pipe_context *pipe)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < NumContexts; i++) {
|
||||
if (Pipe[i] == pipe)
|
||||
return Stage[i];
|
||||
}
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function overrides the driver's create_fs_state() function and
|
||||
* will typically be called by the state tracker.
|
||||
*/
|
||||
static void *
|
||||
aapoint_create_fs_state(struct pipe_context *pipe,
|
||||
const struct pipe_shader_state *fs)
|
||||
{
|
||||
struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
|
||||
struct aapoint_fragment_shader *aafs = CALLOC_STRUCT(aapoint_fragment_shader);
|
||||
|
||||
if (aafs) {
|
||||
aafs->state = *fs;
|
||||
|
||||
/* pass-through */
|
||||
aafs->driver_fs = aapoint->driver_create_fs_state(aapoint->pipe, fs);
|
||||
}
|
||||
|
||||
return aafs;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aapoint_bind_fs_state(struct pipe_context *pipe, void *fs)
|
||||
{
|
||||
struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
|
||||
struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs;
|
||||
/* save current */
|
||||
aapoint->fs = aafs;
|
||||
/* pass-through */
|
||||
aapoint->driver_bind_fs_state(aapoint->pipe, aafs->driver_fs);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aapoint_delete_fs_state(struct pipe_context *pipe, void *fs)
|
||||
{
|
||||
struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
|
||||
struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs;
|
||||
/* pass-through */
|
||||
aapoint->driver_delete_fs_state(aapoint->pipe, aafs->driver_fs);
|
||||
FREE(aafs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by drivers that want to install this AA point prim stage
|
||||
* into the draw module's pipeline. This will not be used if the
|
||||
* hardware has native support for AA points.
|
||||
*/
|
||||
void
|
||||
draw_install_aapoint_stage(struct draw_context *draw,
|
||||
struct pipe_context *pipe)
|
||||
{
|
||||
struct aapoint_stage *aapoint;
|
||||
|
||||
/*
|
||||
* Create / install AA point drawing / prim stage
|
||||
*/
|
||||
aapoint = draw_aapoint_stage( draw );
|
||||
assert(aapoint);
|
||||
draw->pipeline.aapoint = &aapoint->stage;
|
||||
|
||||
aapoint->pipe = pipe;
|
||||
|
||||
/* save original driver functions */
|
||||
aapoint->driver_create_fs_state = pipe->create_fs_state;
|
||||
aapoint->driver_bind_fs_state = pipe->bind_fs_state;
|
||||
aapoint->driver_delete_fs_state = pipe->delete_fs_state;
|
||||
|
||||
/* override the driver's functions */
|
||||
pipe->create_fs_state = aapoint_create_fs_state;
|
||||
pipe->bind_fs_state = aapoint_bind_fs_state;
|
||||
pipe->delete_fs_state = aapoint_delete_fs_state;
|
||||
|
||||
add_aa_pipe_context(pipe, aapoint);
|
||||
}
|
||||
|
|
@ -72,10 +72,10 @@ struct draw_context *draw_create( void )
|
|||
{
|
||||
uint i;
|
||||
const unsigned size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f;
|
||||
char *tmp = align_malloc(Elements(draw->vcache.vertex) * size, 16);
|
||||
char *tmp = align_malloc(Elements(draw->vs.queue) * size, 16);
|
||||
|
||||
for (i = 0; i < Elements(draw->vcache.vertex); i++)
|
||||
draw->vcache.vertex[i] = (struct vertex_header *)(tmp + i * size);
|
||||
for (i = 0; i < Elements(draw->vs.queue); i++)
|
||||
draw->vs.queue[i].vertex = (struct vertex_header *)(tmp + i * size);
|
||||
}
|
||||
|
||||
draw->shader_queue_flush = draw_vertex_shader_queue_flush;
|
||||
|
|
@ -103,10 +103,14 @@ void draw_destroy( struct draw_context *draw )
|
|||
draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
|
||||
draw->pipeline.cull->destroy( draw->pipeline.cull );
|
||||
draw->pipeline.validate->destroy( draw->pipeline.validate );
|
||||
if (draw->pipeline.aaline)
|
||||
draw->pipeline.aaline->destroy( draw->pipeline.aaline );
|
||||
if (draw->pipeline.aapoint)
|
||||
draw->pipeline.aapoint->destroy( draw->pipeline.aapoint );
|
||||
if (draw->pipeline.rasterize)
|
||||
draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );
|
||||
tgsi_exec_machine_free_data(&draw->machine);
|
||||
align_free( draw->vcache.vertex[0] ); /* Frees all the vertices. */
|
||||
align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */
|
||||
FREE( draw );
|
||||
}
|
||||
|
||||
|
|
@ -239,6 +243,26 @@ draw_convert_wide_lines(struct draw_context *draw, boolean enable)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* The draw module may sometimes generate vertices with extra attributes
|
||||
* (such as texcoords for AA lines). The driver can call this function
|
||||
* to find those attributes.
|
||||
*/
|
||||
int
|
||||
draw_find_vs_output(struct draw_context *draw,
|
||||
uint semantic_name, uint semantic_index)
|
||||
{
|
||||
/* XXX there may be more than one extra vertex attrib.
|
||||
* For example, simulated gl_FragCoord and gl_PointCoord.
|
||||
*/
|
||||
if (draw->extra_vp_outputs.semantic_name == semantic_name &&
|
||||
draw->extra_vp_outputs.semantic_index == semantic_index) {
|
||||
return draw->extra_vp_outputs.slot;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allocate space for temporary post-transform vertices, such as for clipping.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "pipe/p_state.h"
|
||||
|
||||
|
||||
struct pipe_context;
|
||||
struct vertex_buffer;
|
||||
struct vertex_info;
|
||||
struct draw_context;
|
||||
|
|
@ -93,6 +94,26 @@ void draw_convert_wide_points(struct draw_context *draw, boolean enable);
|
|||
|
||||
void draw_convert_wide_lines(struct draw_context *draw, boolean enable);
|
||||
|
||||
boolean draw_use_sse(struct draw_context *draw);
|
||||
|
||||
void
|
||||
draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe);
|
||||
|
||||
void
|
||||
draw_install_aapoint_stage(struct draw_context *draw, struct pipe_context *pipe);
|
||||
|
||||
void
|
||||
draw_install_pstipple_stage(struct draw_context *draw, struct pipe_context *pipe);
|
||||
|
||||
|
||||
int
|
||||
draw_find_vs_output(struct draw_context *draw,
|
||||
uint semantic_name, uint semantic_index);
|
||||
|
||||
|
||||
/*
|
||||
* Vertex shader functions
|
||||
*/
|
||||
|
||||
struct draw_vertex_shader *
|
||||
draw_create_vertex_shader(struct draw_context *draw,
|
||||
|
|
@ -102,7 +123,11 @@ void draw_bind_vertex_shader(struct draw_context *draw,
|
|||
void draw_delete_vertex_shader(struct draw_context *draw,
|
||||
struct draw_vertex_shader *dvs);
|
||||
|
||||
boolean draw_use_sse(struct draw_context *draw);
|
||||
|
||||
|
||||
/*
|
||||
* Vertex data functions
|
||||
*/
|
||||
|
||||
void draw_set_vertex_buffer(struct draw_context *draw,
|
||||
unsigned attr,
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ static void draw_prim_queue_flush( struct draw_context *draw )
|
|||
}
|
||||
|
||||
draw->pq.queue_nr = 0;
|
||||
draw->vs.post_nr = 0;
|
||||
draw_vertex_cache_unreference( draw );
|
||||
}
|
||||
|
||||
|
|
@ -121,11 +122,15 @@ static void draw_prim_queue_flush( struct draw_context *draw )
|
|||
|
||||
void draw_do_flush( struct draw_context *draw, unsigned flags )
|
||||
{
|
||||
static boolean flushing = FALSE;
|
||||
|
||||
if (0)
|
||||
debug_printf("Flushing with %d verts, %d prims\n",
|
||||
draw->vs.queue_nr,
|
||||
draw->pq.queue_nr );
|
||||
|
||||
if (!flushing) {
|
||||
flushing = TRUE;
|
||||
|
||||
if (flags >= DRAW_FLUSH_SHADER_QUEUE) {
|
||||
if (draw->vs.queue_nr)
|
||||
|
|
@ -146,6 +151,9 @@ void draw_do_flush( struct draw_context *draw, unsigned flags )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
flushing = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -219,6 +227,7 @@ static void do_triangle( struct draw_context *draw,
|
|||
{
|
||||
struct prim_header *prim = get_queued_prim( draw, 3 );
|
||||
|
||||
// _mesa_printf("tri %d %d %d\n", i0, i1, i2);
|
||||
prim->reset_line_stipple = 1;
|
||||
prim->edgeflags = ~0;
|
||||
prim->pad = 0;
|
||||
|
|
|
|||
|
|
@ -44,10 +44,11 @@
|
|||
#include "pipe/p_state.h"
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
#include "x86/rtasm/x86sse.h"
|
||||
#include "rtasm/rtasm_x86sse.h"
|
||||
#include "tgsi/exec/tgsi_exec.h"
|
||||
|
||||
|
||||
struct pipe_context;
|
||||
struct gallivm_prog;
|
||||
struct gallivm_cpu_engine;
|
||||
|
||||
|
|
@ -119,7 +120,7 @@ struct draw_stage
|
|||
};
|
||||
|
||||
|
||||
#define PRIM_QUEUE_LENGTH 16
|
||||
#define PRIM_QUEUE_LENGTH 32
|
||||
#define VCACHE_SIZE 32
|
||||
#define VCACHE_OVERFLOW 4
|
||||
#define VS_QUEUE_LENGTH (VCACHE_SIZE + VCACHE_OVERFLOW + 1) /* can never fill up */
|
||||
|
|
@ -179,6 +180,9 @@ struct draw_context
|
|||
struct draw_stage *offset;
|
||||
struct draw_stage *unfilled;
|
||||
struct draw_stage *stipple;
|
||||
struct draw_stage *aapoint;
|
||||
struct draw_stage *aaline;
|
||||
struct draw_stage *pstipple;
|
||||
struct draw_stage *wide;
|
||||
struct draw_stage *rasterize;
|
||||
} pipeline;
|
||||
|
|
@ -212,9 +216,17 @@ struct draw_context
|
|||
unsigned nr_planes;
|
||||
|
||||
boolean convert_wide_points; /**< convert wide points to tris? */
|
||||
boolean convert_wide_lines; /**< convert side lines to tris? */
|
||||
boolean convert_wide_lines; /**< convert wide lines to tris? */
|
||||
boolean use_sse;
|
||||
|
||||
/* If a prim stage introduces new vertex attributes, they'll be stored here
|
||||
*/
|
||||
struct {
|
||||
uint semantic_name;
|
||||
uint semantic_index;
|
||||
int slot;
|
||||
} extra_vp_outputs;
|
||||
|
||||
unsigned reduced_prim;
|
||||
|
||||
/** TGSI program interpreter runtime state */
|
||||
|
|
@ -234,8 +246,12 @@ struct draw_context
|
|||
*/
|
||||
struct {
|
||||
unsigned referenced; /**< bitfield */
|
||||
unsigned idx[VCACHE_SIZE + VCACHE_OVERFLOW];
|
||||
struct vertex_header *vertex[VCACHE_SIZE + VCACHE_OVERFLOW];
|
||||
|
||||
struct {
|
||||
unsigned in; /* client array element */
|
||||
unsigned out; /* index in vs queue/array */
|
||||
} idx[VCACHE_SIZE + VCACHE_OVERFLOW];
|
||||
|
||||
unsigned overflow;
|
||||
|
||||
/** To find space in the vertex cache: */
|
||||
|
|
@ -248,9 +264,10 @@ struct draw_context
|
|||
struct {
|
||||
struct {
|
||||
unsigned elt; /**< index into the user's vertex arrays */
|
||||
struct vertex_header *dest; /**< points into vcache.vertex[] array */
|
||||
struct vertex_header *vertex;
|
||||
} queue[VS_QUEUE_LENGTH];
|
||||
unsigned queue_nr;
|
||||
unsigned post_nr;
|
||||
} vs;
|
||||
|
||||
/**
|
||||
|
|
|
|||
717
src/gallium/auxiliary/draw/draw_pstipple.c
Normal file
717
src/gallium/auxiliary/draw/draw_pstipple.c
Normal file
|
|
@ -0,0 +1,717 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Polygon stipple stage: implement polygon stipple with texture map and
|
||||
* fragment program. The fragment program samples the texture and does
|
||||
* a fragment kill for the stipple-failing fragments.
|
||||
*
|
||||
* Authors: Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include "pipe/p_util.h"
|
||||
#include "pipe/p_inlines.h"
|
||||
#include "pipe/p_context.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_shader_tokens.h"
|
||||
|
||||
#include "tgsi/util/tgsi_transform.h"
|
||||
#include "tgsi/util/tgsi_dump.h"
|
||||
|
||||
#include "draw_context.h"
|
||||
#include "draw_private.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of pipe_shader_state to carry extra fragment shader info.
|
||||
*/
|
||||
struct pstip_fragment_shader
|
||||
{
|
||||
struct pipe_shader_state state;
|
||||
void *driver_fs;
|
||||
void *pstip_fs;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of draw_stage
|
||||
*/
|
||||
struct pstip_stage
|
||||
{
|
||||
struct draw_stage stage;
|
||||
|
||||
void *sampler_cso;
|
||||
struct pipe_texture *texture;
|
||||
uint sampler_unit;
|
||||
|
||||
/*
|
||||
* Currently bound state
|
||||
*/
|
||||
struct pstip_fragment_shader *fs;
|
||||
struct {
|
||||
void *sampler[PIPE_MAX_SAMPLERS];
|
||||
struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
|
||||
const struct pipe_poly_stipple *stipple;
|
||||
} state;
|
||||
|
||||
/*
|
||||
* Driver interface/override functions
|
||||
*/
|
||||
void * (*driver_create_fs_state)(struct pipe_context *,
|
||||
const struct pipe_shader_state *);
|
||||
void (*driver_bind_fs_state)(struct pipe_context *, void *);
|
||||
void (*driver_delete_fs_state)(struct pipe_context *, void *);
|
||||
|
||||
void (*driver_bind_sampler_state)(struct pipe_context *, unsigned, void *);
|
||||
|
||||
void (*driver_set_sampler_texture)(struct pipe_context *,
|
||||
unsigned sampler,
|
||||
struct pipe_texture *);
|
||||
|
||||
void (*driver_set_polygon_stipple)(struct pipe_context *,
|
||||
const struct pipe_poly_stipple *);
|
||||
|
||||
struct pipe_context *pipe;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of tgsi_transform_context, used for transforming the
|
||||
* user's fragment shader to add the special AA instructions.
|
||||
*/
|
||||
struct pstip_transform_context {
|
||||
struct tgsi_transform_context base;
|
||||
uint tempsUsed; /**< bitmask */
|
||||
int wincoordInput;
|
||||
int maxInput;
|
||||
int maxSampler; /**< max sampler index found */
|
||||
int texTemp; /**< temp registers */
|
||||
int numImmed;
|
||||
boolean firstInstruction;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TGSI declaration transform callback.
|
||||
* Look for a free sampler, a free input attrib, and two free temp regs.
|
||||
*/
|
||||
static void
|
||||
pstip_transform_decl(struct tgsi_transform_context *ctx,
|
||||
struct tgsi_full_declaration *decl)
|
||||
{
|
||||
struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
|
||||
|
||||
if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
|
||||
if ((int) decl->u.DeclarationRange.Last > pctx->maxSampler)
|
||||
pctx->maxSampler = (int) decl->u.DeclarationRange.Last;
|
||||
}
|
||||
else if (decl->Declaration.File == TGSI_FILE_INPUT) {
|
||||
pctx->maxInput = MAX2(pctx->maxInput, decl->u.DeclarationRange.Last);
|
||||
if (decl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION)
|
||||
pctx->wincoordInput = (int) decl->u.DeclarationRange.First;
|
||||
}
|
||||
else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
|
||||
uint i;
|
||||
for (i = decl->u.DeclarationRange.First;
|
||||
i <= decl->u.DeclarationRange.Last; i++) {
|
||||
pctx->tempsUsed |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
ctx->emit_declaration(ctx, decl);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pstip_transform_immed(struct tgsi_transform_context *ctx,
|
||||
struct tgsi_full_immediate *immed)
|
||||
{
|
||||
struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
|
||||
pctx->numImmed++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TGSI instruction transform callback.
|
||||
* Replace writes to result.color w/ a temp reg.
|
||||
* Upon END instruction, insert texture sampling code for antialiasing.
|
||||
*/
|
||||
static void
|
||||
pstip_transform_inst(struct tgsi_transform_context *ctx,
|
||||
struct tgsi_full_instruction *inst)
|
||||
{
|
||||
struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
|
||||
|
||||
if (pctx->firstInstruction) {
|
||||
/* emit our new declarations before the first instruction */
|
||||
|
||||
struct tgsi_full_declaration decl;
|
||||
struct tgsi_full_instruction newInst;
|
||||
uint i;
|
||||
int wincoordInput;
|
||||
const int sampler = pctx->maxSampler + 1;
|
||||
|
||||
if (pctx->wincoordInput < 0)
|
||||
wincoordInput = pctx->maxInput + 1;
|
||||
else
|
||||
wincoordInput = pctx->wincoordInput;
|
||||
|
||||
/* find one free temp reg */
|
||||
for (i = 0; i < 32; i++) {
|
||||
if ((pctx->tempsUsed & (1 << i)) == 0) {
|
||||
/* found a free temp */
|
||||
if (pctx->texTemp < 0)
|
||||
pctx->texTemp = i;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(pctx->texTemp >= 0);
|
||||
|
||||
if (pctx->wincoordInput < 0) {
|
||||
/* declare new position input reg */
|
||||
decl = tgsi_default_full_declaration();
|
||||
decl.Declaration.File = TGSI_FILE_INPUT;
|
||||
decl.Declaration.Semantic = 1;
|
||||
decl.Semantic.SemanticName = TGSI_SEMANTIC_POSITION;
|
||||
decl.Semantic.SemanticIndex = 0;
|
||||
decl.Declaration.Interpolate = 1;
|
||||
decl.Interpolation.Interpolate = TGSI_INTERPOLATE_LINEAR; /* XXX? */
|
||||
decl.u.DeclarationRange.First =
|
||||
decl.u.DeclarationRange.Last = wincoordInput;
|
||||
ctx->emit_declaration(ctx, &decl);
|
||||
}
|
||||
|
||||
/* declare new sampler */
|
||||
decl = tgsi_default_full_declaration();
|
||||
decl.Declaration.File = TGSI_FILE_SAMPLER;
|
||||
decl.u.DeclarationRange.First =
|
||||
decl.u.DeclarationRange.Last = sampler;
|
||||
ctx->emit_declaration(ctx, &decl);
|
||||
|
||||
/* declare new temp regs */
|
||||
decl = tgsi_default_full_declaration();
|
||||
decl.Declaration.File = TGSI_FILE_TEMPORARY;
|
||||
decl.u.DeclarationRange.First =
|
||||
decl.u.DeclarationRange.Last = pctx->texTemp;
|
||||
ctx->emit_declaration(ctx, &decl);
|
||||
|
||||
/* emit immediate = {1/32, 1/32, 1, 1}
|
||||
* The index/position of this immediate will be pctx->numImmed
|
||||
*/
|
||||
{
|
||||
static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 };
|
||||
struct tgsi_full_immediate immed;
|
||||
uint size = 4;
|
||||
immed = tgsi_default_full_immediate();
|
||||
immed.Immediate.Size = 1 + size; /* one for the token itself */
|
||||
immed.u.ImmediateFloat32 = (struct tgsi_immediate_float32 *) value;
|
||||
ctx->emit_immediate(ctx, &immed);
|
||||
}
|
||||
|
||||
pctx->firstInstruction = FALSE;
|
||||
|
||||
|
||||
/*
|
||||
* Insert new MUL/TEX/KILP instructions at start of program
|
||||
* Take gl_FragCoord, divide by 32 (stipple size), sample the
|
||||
* texture and kill fragment if needed.
|
||||
*
|
||||
* We'd like to use non-normalized texcoords to index into a RECT
|
||||
* texture, but we can only use GL_REPEAT wrap mode with normalized
|
||||
* texcoords. Darn.
|
||||
*/
|
||||
|
||||
/* MUL texTemp, INPUT[wincoord], 1/32; */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = pctx->texTemp;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = wincoordInput;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_IMMEDIATE;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = pctx->numImmed;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* TEX texTemp, texTemp, sampler; */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
|
||||
newInst.Instruction.NumDstRegs = 1;
|
||||
newInst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullDstRegisters[0].DstRegister.Index = pctx->texTemp;
|
||||
newInst.Instruction.NumSrcRegs = 2;
|
||||
newInst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = pctx->texTemp;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
|
||||
newInst.FullSrcRegisters[1].SrcRegister.Index = sampler;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
|
||||
/* KILP texTemp; # if texTemp < 0, KILL fragment */
|
||||
newInst = tgsi_default_full_instruction();
|
||||
newInst.Instruction.Opcode = TGSI_OPCODE_KILP;
|
||||
newInst.Instruction.NumDstRegs = 0;
|
||||
newInst.Instruction.NumSrcRegs = 1;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Index = pctx->texTemp;
|
||||
newInst.FullSrcRegisters[0].SrcRegister.Negate = 1;
|
||||
ctx->emit_instruction(ctx, &newInst);
|
||||
}
|
||||
|
||||
/* emit this instruction */
|
||||
ctx->emit_instruction(ctx, inst);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the frag shader we'll use for doing polygon stipple.
|
||||
* This will be the user's shader prefixed with a TEX and KIL instruction.
|
||||
*/
|
||||
static void
|
||||
generate_pstip_fs(struct pstip_stage *pstip)
|
||||
{
|
||||
const struct pipe_shader_state *orig_fs = &pstip->fs->state;
|
||||
/*struct draw_context *draw = pstip->stage.draw;*/
|
||||
struct pipe_shader_state pstip_fs;
|
||||
struct pstip_transform_context transform;
|
||||
|
||||
#define MAX 1000
|
||||
|
||||
pstip_fs = *orig_fs; /* copy to init */
|
||||
pstip_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX);
|
||||
|
||||
memset(&transform, 0, sizeof(transform));
|
||||
transform.wincoordInput = -1;
|
||||
transform.maxInput = -1;
|
||||
transform.maxSampler = -1;
|
||||
transform.texTemp = -1;
|
||||
transform.firstInstruction = TRUE;
|
||||
transform.base.transform_instruction = pstip_transform_inst;
|
||||
transform.base.transform_declaration = pstip_transform_decl;
|
||||
transform.base.transform_immediate = pstip_transform_immed;
|
||||
|
||||
tgsi_transform_shader(orig_fs->tokens,
|
||||
(struct tgsi_token *) pstip_fs.tokens,
|
||||
MAX, &transform.base);
|
||||
|
||||
#if 1 /* DEBUG */
|
||||
tgsi_dump(orig_fs->tokens, 0);
|
||||
tgsi_dump(pstip_fs.tokens, 0);
|
||||
#endif
|
||||
|
||||
pstip->sampler_unit = transform.maxSampler + 1;
|
||||
|
||||
if (transform.wincoordInput < 0) {
|
||||
pstip_fs.input_semantic_name[pstip_fs.num_inputs] = TGSI_SEMANTIC_POSITION;
|
||||
pstip_fs.input_semantic_index[pstip_fs.num_inputs] = transform.maxInput;
|
||||
pstip_fs.num_inputs++;
|
||||
}
|
||||
|
||||
pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load texture image with current stipple pattern.
|
||||
*/
|
||||
static void
|
||||
pstip_update_texture(struct pstip_stage *pstip)
|
||||
{
|
||||
static const uint bit31 = 1 << 31;
|
||||
struct pipe_context *pipe = pstip->pipe;
|
||||
struct pipe_surface *surface;
|
||||
const uint *stipple = pstip->state.stipple->stipple;
|
||||
uint i, j;
|
||||
ubyte *data;
|
||||
|
||||
surface = pipe->get_tex_surface(pipe, pstip->texture, 0, 0, 0);
|
||||
data = pipe_surface_map(surface);
|
||||
|
||||
/*
|
||||
* Load alpha texture.
|
||||
* Note: 0 means keep the fragment, 255 means kill it.
|
||||
* We'll negate the texel value and use KILP which kills if value
|
||||
* is negative.
|
||||
*/
|
||||
for (i = 0; i < 32; i++) {
|
||||
for (j = 0; j < 32; j++) {
|
||||
if (stipple[i] & (bit31 >> j)) {
|
||||
/* fragment "on" */
|
||||
data[i * surface->pitch + j] = 0;
|
||||
}
|
||||
else {
|
||||
/* fragment "off" */
|
||||
data[i * surface->pitch + j] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* unmap */
|
||||
pipe_surface_unmap(surface);
|
||||
pipe_surface_reference(&surface, NULL);
|
||||
pipe->texture_update(pipe, pstip->texture);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the texture map we'll use for stippling.
|
||||
*/
|
||||
static void
|
||||
pstip_create_texture(struct pstip_stage *pstip)
|
||||
{
|
||||
struct pipe_context *pipe = pstip->pipe;
|
||||
struct pipe_texture texTemp;
|
||||
|
||||
memset(&texTemp, 0, sizeof(texTemp));
|
||||
texTemp.target = PIPE_TEXTURE_2D;
|
||||
texTemp.format = PIPE_FORMAT_U_A8; /* XXX verify supported by driver! */
|
||||
texTemp.last_level = 0;
|
||||
texTemp.width[0] = 32;
|
||||
texTemp.height[0] = 32;
|
||||
texTemp.depth[0] = 1;
|
||||
texTemp.cpp = 1;
|
||||
|
||||
pstip->texture = pipe->texture_create(pipe, &texTemp);
|
||||
|
||||
//pstip_update_texture(pstip);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the sampler CSO that'll be used for antialiasing.
|
||||
* By using a mipmapped texture, we don't have to generate a different
|
||||
* texture image for each line size.
|
||||
*/
|
||||
static void
|
||||
pstip_create_sampler(struct pstip_stage *pstip)
|
||||
{
|
||||
struct pipe_sampler_state sampler;
|
||||
struct pipe_context *pipe = pstip->pipe;
|
||||
|
||||
memset(&sampler, 0, sizeof(sampler));
|
||||
sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
|
||||
sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
|
||||
sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
|
||||
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
|
||||
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
|
||||
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
|
||||
sampler.normalized_coords = 1;
|
||||
sampler.min_lod = 0.0f;
|
||||
sampler.max_lod = 0.0f;
|
||||
|
||||
pstip->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When we're about to draw our first AA line in a batch, this function is
|
||||
* called to tell the driver to bind our modified fragment shader.
|
||||
*/
|
||||
static void
|
||||
bind_pstip_fragment_shader(struct pstip_stage *pstip)
|
||||
{
|
||||
if (!pstip->fs->pstip_fs) {
|
||||
generate_pstip_fs(pstip);
|
||||
}
|
||||
pstip->driver_bind_fs_state(pstip->pipe, pstip->fs->pstip_fs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static INLINE struct pstip_stage *
|
||||
pstip_stage( struct draw_stage *stage )
|
||||
{
|
||||
return (struct pstip_stage *) stage;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
passthrough_point(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
stage->next->point(stage->next, header);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
passthrough_line(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
stage->next->line(stage->next, header);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
passthrough_tri(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
stage->next->tri(stage->next, header);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
|
||||
{
|
||||
struct pstip_stage *pstip = pstip_stage(stage);
|
||||
struct draw_context *draw = stage->draw;
|
||||
struct pipe_context *pipe = pstip->pipe;
|
||||
|
||||
assert(draw->rasterizer->poly_stipple_enable);
|
||||
|
||||
/*
|
||||
* Bind our fragprog, sampler and texture
|
||||
*/
|
||||
bind_pstip_fragment_shader(pstip);
|
||||
|
||||
pstip->driver_bind_sampler_state(pipe, pstip->sampler_unit, pstip->sampler_cso);
|
||||
pstip->driver_set_sampler_texture(pipe, pstip->sampler_unit, pstip->texture);
|
||||
|
||||
/* now really draw first line */
|
||||
stage->tri = passthrough_tri;
|
||||
stage->tri(stage, header);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pstip_flush(struct draw_stage *stage, unsigned flags)
|
||||
{
|
||||
/*struct draw_context *draw = stage->draw;*/
|
||||
struct pstip_stage *pstip = pstip_stage(stage);
|
||||
struct pipe_context *pipe = pstip->pipe;
|
||||
|
||||
stage->tri = pstip_first_tri;
|
||||
stage->next->flush( stage->next, flags );
|
||||
|
||||
/* restore original frag shader */
|
||||
pstip->driver_bind_fs_state(pipe, pstip->fs->driver_fs);
|
||||
|
||||
/* XXX restore original texture, sampler state */
|
||||
pstip->driver_bind_sampler_state(pipe, pstip->sampler_unit,
|
||||
pstip->state.sampler[pstip->sampler_unit]);
|
||||
pstip->driver_set_sampler_texture(pipe, pstip->sampler_unit,
|
||||
pstip->state.texture[pstip->sampler_unit]);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pstip_reset_stipple_counter(struct draw_stage *stage)
|
||||
{
|
||||
stage->next->reset_stipple_counter( stage->next );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pstip_destroy(struct draw_stage *stage)
|
||||
{
|
||||
draw_free_temp_verts( stage );
|
||||
FREE( stage );
|
||||
}
|
||||
|
||||
|
||||
static struct pstip_stage *
|
||||
draw_pstip_stage(struct draw_context *draw)
|
||||
{
|
||||
struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage);
|
||||
|
||||
draw_alloc_temp_verts( &pstip->stage, 8 );
|
||||
|
||||
pstip->stage.draw = draw;
|
||||
pstip->stage.next = NULL;
|
||||
pstip->stage.point = passthrough_point;
|
||||
pstip->stage.line = passthrough_line;
|
||||
pstip->stage.tri = pstip_first_tri;
|
||||
pstip->stage.flush = pstip_flush;
|
||||
pstip->stage.reset_stipple_counter = pstip_reset_stipple_counter;
|
||||
pstip->stage.destroy = pstip_destroy;
|
||||
|
||||
return pstip;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XXX temporary? solution to mapping a pipe_context to a pstip_stage.
|
||||
*/
|
||||
|
||||
#define MAX_CONTEXTS 10
|
||||
|
||||
static struct pipe_context *Pipe[MAX_CONTEXTS];
|
||||
static struct pstip_stage *Stage[MAX_CONTEXTS];
|
||||
static uint NumContexts;
|
||||
|
||||
static void
|
||||
add_pstip_pipe_context(struct pipe_context *pipe, struct pstip_stage *pstip)
|
||||
{
|
||||
assert(NumContexts < MAX_CONTEXTS);
|
||||
Pipe[NumContexts] = pipe;
|
||||
Stage[NumContexts] = pstip;
|
||||
NumContexts++;
|
||||
}
|
||||
|
||||
static struct pstip_stage *
|
||||
pstip_stage_from_pipe(struct pipe_context *pipe)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < NumContexts; i++) {
|
||||
if (Pipe[i] == pipe)
|
||||
return Stage[i];
|
||||
}
|
||||
assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function overrides the driver's create_fs_state() function and
|
||||
* will typically be called by the state tracker.
|
||||
*/
|
||||
static void *
|
||||
pstip_create_fs_state(struct pipe_context *pipe,
|
||||
const struct pipe_shader_state *fs)
|
||||
{
|
||||
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
|
||||
struct pstip_fragment_shader *aafs = CALLOC_STRUCT(pstip_fragment_shader);
|
||||
|
||||
if (aafs) {
|
||||
aafs->state = *fs;
|
||||
|
||||
/* pass-through */
|
||||
aafs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs);
|
||||
}
|
||||
|
||||
return aafs;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pstip_bind_fs_state(struct pipe_context *pipe, void *fs)
|
||||
{
|
||||
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
|
||||
struct pstip_fragment_shader *aafs = (struct pstip_fragment_shader *) fs;
|
||||
/* save current */
|
||||
pstip->fs = aafs;
|
||||
/* pass-through */
|
||||
pstip->driver_bind_fs_state(pstip->pipe, aafs->driver_fs);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pstip_delete_fs_state(struct pipe_context *pipe, void *fs)
|
||||
{
|
||||
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
|
||||
struct pstip_fragment_shader *aafs = (struct pstip_fragment_shader *) fs;
|
||||
/* pass-through */
|
||||
pstip->driver_delete_fs_state(pstip->pipe, aafs->driver_fs);
|
||||
FREE(aafs);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pstip_bind_sampler_state(struct pipe_context *pipe,
|
||||
unsigned unit, void *sampler)
|
||||
{
|
||||
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
|
||||
/* save current */
|
||||
pstip->state.sampler[unit] = sampler;
|
||||
/* pass-through */
|
||||
pstip->driver_bind_sampler_state(pstip->pipe, unit, sampler);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pstip_set_sampler_texture(struct pipe_context *pipe,
|
||||
unsigned sampler, struct pipe_texture *texture)
|
||||
{
|
||||
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
|
||||
/* save current */
|
||||
pstip->state.texture[sampler] = texture;
|
||||
/* pass-through */
|
||||
pstip->driver_set_sampler_texture(pstip->pipe, sampler, texture);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pstip_set_polygon_stipple(struct pipe_context *pipe,
|
||||
const struct pipe_poly_stipple *stipple)
|
||||
{
|
||||
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
|
||||
/* save current */
|
||||
pstip->state.stipple = stipple;
|
||||
/* pass-through */
|
||||
pstip->driver_set_polygon_stipple(pstip->pipe, stipple);
|
||||
|
||||
pstip_update_texture(pstip);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Called by drivers that want to install this AA line prim stage
|
||||
* into the draw module's pipeline. This will not be used if the
|
||||
* hardware has native support for AA lines.
|
||||
*/
|
||||
void
|
||||
draw_install_pstipple_stage(struct draw_context *draw,
|
||||
struct pipe_context *pipe)
|
||||
{
|
||||
struct pstip_stage *pstip;
|
||||
|
||||
/*
|
||||
* Create / install AA line drawing / prim stage
|
||||
*/
|
||||
pstip = draw_pstip_stage( draw );
|
||||
assert(pstip);
|
||||
draw->pipeline.pstipple = &pstip->stage;
|
||||
|
||||
pstip->pipe = pipe;
|
||||
|
||||
/* create special texture, sampler state */
|
||||
pstip_create_texture(pstip);
|
||||
pstip_create_sampler(pstip);
|
||||
|
||||
/* save original driver functions */
|
||||
pstip->driver_create_fs_state = pipe->create_fs_state;
|
||||
pstip->driver_bind_fs_state = pipe->bind_fs_state;
|
||||
pstip->driver_delete_fs_state = pipe->delete_fs_state;
|
||||
|
||||
pstip->driver_bind_sampler_state = pipe->bind_sampler_state;
|
||||
pstip->driver_set_sampler_texture = pipe->set_sampler_texture;
|
||||
pstip->driver_set_polygon_stipple = pipe->set_polygon_stipple;
|
||||
|
||||
/* override the driver's functions */
|
||||
pipe->create_fs_state = pstip_create_fs_state;
|
||||
pipe->bind_fs_state = pstip_bind_fs_state;
|
||||
pipe->delete_fs_state = pstip_delete_fs_state;
|
||||
|
||||
pipe->bind_sampler_state = pstip_bind_sampler_state;
|
||||
pipe->set_sampler_texture = pstip_set_sampler_texture;
|
||||
pipe->set_polygon_stipple = pstip_set_polygon_stipple;
|
||||
|
||||
add_pstip_pipe_context(pipe, pstip);
|
||||
}
|
||||
|
|
@ -58,7 +58,18 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage )
|
|||
* shorter pipelines for lines & points.
|
||||
*/
|
||||
|
||||
if ((draw->rasterizer->line_width != 1.0 && draw->convert_wide_lines) ||
|
||||
if (draw->rasterizer->line_smooth && draw->pipeline.aaline) {
|
||||
draw->pipeline.aaline->next = next;
|
||||
next = draw->pipeline.aaline;
|
||||
}
|
||||
|
||||
if (draw->rasterizer->point_smooth && draw->pipeline.aapoint) {
|
||||
draw->pipeline.aapoint->next = next;
|
||||
next = draw->pipeline.aapoint;
|
||||
}
|
||||
|
||||
if ((draw->rasterizer->line_width != 1.0 && draw->convert_wide_lines
|
||||
&& !draw->rasterizer->line_smooth) ||
|
||||
(draw->rasterizer->point_size != 1.0 && draw->convert_wide_points) ||
|
||||
draw->rasterizer->point_sprite) {
|
||||
draw->pipeline.wide->next = next;
|
||||
|
|
@ -71,6 +82,12 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage )
|
|||
precalc_flat = 1; /* only needed for lines really */
|
||||
}
|
||||
|
||||
if (draw->rasterizer->poly_stipple_enable
|
||||
&& draw->pipeline.pstipple) {
|
||||
draw->pipeline.pstipple->next = next;
|
||||
next = draw->pipeline.pstipple;
|
||||
}
|
||||
|
||||
if (draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
|
||||
draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) {
|
||||
draw->pipeline.unfilled->next = next;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ void draw_vertex_cache_invalidate( struct draw_context *draw )
|
|||
assert(draw->vs.queue_nr == 0);
|
||||
assert(draw->vcache.referenced == 0);
|
||||
|
||||
memset(draw->vcache.idx, ~0, sizeof(draw->vcache.idx));
|
||||
// memset(draw->vcache.idx, ~0, sizeof(draw->vcache.idx));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -62,43 +62,51 @@ static struct vertex_header *get_vertex( struct draw_context *draw,
|
|||
|
||||
assert(slot < 32); /* so we don't exceed the bitfield size below */
|
||||
|
||||
/* Cache miss?
|
||||
*/
|
||||
if (draw->vcache.idx[slot] != i) {
|
||||
|
||||
/* If slot is in use, use the overflow area:
|
||||
if (draw->vcache.referenced & (1<<slot))
|
||||
{
|
||||
/* Cache hit?
|
||||
*/
|
||||
if (draw->vcache.referenced & (1 << slot)) {
|
||||
slot = VCACHE_SIZE + draw->vcache.overflow++;
|
||||
if (draw->vcache.idx[slot].in == i) {
|
||||
// _mesa_printf("HIT %d %d\n", slot, i);
|
||||
assert(draw->vcache.idx[slot].out < draw->vs.queue_nr);
|
||||
return draw->vs.queue[draw->vcache.idx[slot].out].vertex;
|
||||
}
|
||||
|
||||
/* Otherwise a collision
|
||||
*/
|
||||
slot = VCACHE_SIZE + draw->vcache.overflow++;
|
||||
// _mesa_printf("XXX %d --> %d\n", i, slot);
|
||||
}
|
||||
|
||||
/* Deal with the cache miss:
|
||||
*/
|
||||
{
|
||||
unsigned out;
|
||||
|
||||
assert(slot < Elements(draw->vcache.idx));
|
||||
|
||||
draw->vcache.idx[slot] = i;
|
||||
// _mesa_printf("NEW %d %d\n", slot, i);
|
||||
draw->vcache.idx[slot].in = i;
|
||||
draw->vcache.idx[slot].out = out = draw->vs.queue_nr++;
|
||||
draw->vcache.referenced |= (1 << slot);
|
||||
|
||||
|
||||
/* Add to vertex shader queue:
|
||||
*/
|
||||
assert(draw->vs.queue_nr < VS_QUEUE_LENGTH);
|
||||
draw->vs.queue[draw->vs.queue_nr].dest = draw->vcache.vertex[slot];
|
||||
draw->vs.queue[draw->vs.queue_nr].elt = i;
|
||||
draw->vs.queue_nr++;
|
||||
|
||||
draw->vs.queue[out].elt = i;
|
||||
draw->vs.queue[out].vertex->clipmask = 0;
|
||||
draw->vs.queue[out].vertex->edgeflag = 1; /*XXX use user's edge flag! */
|
||||
draw->vs.queue[out].vertex->pad = 0;
|
||||
draw->vs.queue[out].vertex->vertex_id = UNDEFINED_VERTEX_ID;
|
||||
|
||||
/* Need to set the vertex's edge flag here. If we're being called
|
||||
* by do_ef_triangle(), that function needs edge flag info!
|
||||
*/
|
||||
draw->vcache.vertex[slot]->clipmask = 0;
|
||||
draw->vcache.vertex[slot]->edgeflag = 1; /*XXX use user's edge flag! */
|
||||
draw->vcache.vertex[slot]->pad = 0;
|
||||
draw->vcache.vertex[slot]->vertex_id = UNDEFINED_VERTEX_ID;
|
||||
|
||||
return draw->vs.queue[draw->vcache.idx[slot].out].vertex;
|
||||
}
|
||||
|
||||
|
||||
/* primitive flushing may have cleared the bitfield but did not
|
||||
* clear the idx[] array values. Set the bit now. This fixes a
|
||||
* bug found when drawing long triangle fans.
|
||||
*/
|
||||
draw->vcache.referenced |= (1 << slot);
|
||||
return draw->vcache.vertex[slot];
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -130,8 +138,8 @@ void draw_vertex_cache_reset_vertex_ids( struct draw_context *draw )
|
|||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < Elements(draw->vcache.vertex); i++)
|
||||
draw->vcache.vertex[i]->vertex_id = UNDEFINED_VERTEX_ID;
|
||||
for (i = 0; i < draw->vs.post_nr; i++)
|
||||
draw->vs.queue[i].vertex->vertex_id = UNDEFINED_VERTEX_ID;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ draw_vertex_shader_queue_flush(struct draw_context *draw)
|
|||
*/
|
||||
shader->prepare( shader, draw );
|
||||
|
||||
// fprintf(stderr, " q(%d) ", draw->vs.queue_nr );
|
||||
// fprintf(stderr, "%s %d\n", __FUNCTION__, draw->vs.queue_nr );
|
||||
|
||||
/* run vertex shader on vertex cache entries, four per invokation */
|
||||
for (i = 0; i < draw->vs.queue_nr; i += 4) {
|
||||
|
|
@ -65,12 +65,12 @@ draw_vertex_shader_queue_flush(struct draw_context *draw)
|
|||
|
||||
for (j = 0; j < n; j++) {
|
||||
elts[j] = draw->vs.queue[i + j].elt;
|
||||
dests[j] = draw->vs.queue[i + j].dest;
|
||||
dests[j] = draw->vs.queue[i + j].vertex;
|
||||
}
|
||||
|
||||
for ( ; j < 4; j++) {
|
||||
elts[j] = elts[0];
|
||||
dests[j] = dests[0];
|
||||
dests[j] = draw->vs.queue[i + j].vertex;
|
||||
}
|
||||
|
||||
assert(n > 0);
|
||||
|
|
@ -79,6 +79,7 @@ draw_vertex_shader_queue_flush(struct draw_context *draw)
|
|||
shader->run(shader, draw, elts, n, dests);
|
||||
}
|
||||
|
||||
draw->vs.post_nr = draw->vs.queue_nr;
|
||||
draw->vs.queue_nr = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_util.h"
|
||||
#include "rtasm/rtasm_execmem.h"
|
||||
|
||||
#include "draw_vf.h"
|
||||
|
||||
|
|
@ -37,11 +38,6 @@
|
|||
#define DRAW_VF_DBG 0
|
||||
|
||||
|
||||
/* TODO: remove this */
|
||||
extern void
|
||||
_mesa_exec_free( void *addr );
|
||||
|
||||
|
||||
static boolean match_fastpath( struct draw_vertex_fetch *vf,
|
||||
const struct draw_vf_fastpath *fp)
|
||||
{
|
||||
|
|
@ -414,12 +410,12 @@ void draw_vf_destroy( struct draw_vertex_fetch *vf )
|
|||
FREE(fp->attr);
|
||||
|
||||
/* KW: At the moment, fp->func is constrained to be allocated by
|
||||
* _mesa_exec_alloc(), as the hardwired fastpaths in
|
||||
* rtasm_exec_alloc(), as the hardwired fastpaths in
|
||||
* t_vertex_generic.c are handled specially. It would be nice
|
||||
* to unify them, but this probably won't change until this
|
||||
* module gets another overhaul.
|
||||
*/
|
||||
//_mesa_exec_free((void *) fp->func);
|
||||
//rtasm_exec_free((void *) fp->func);
|
||||
FREE(fp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,17 +26,16 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "simple_list.h"
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "util/u_simple_list.h"
|
||||
|
||||
#include "draw_vf.h"
|
||||
|
||||
|
||||
#if defined(USE_SSE_ASM)
|
||||
|
||||
#include "x86/rtasm/x86sse.h"
|
||||
#include "x86/common_x86_asm.h"
|
||||
#include "rtasm/rtasm_cpu.h"
|
||||
#include "rtasm/rtasm_x86sse.h"
|
||||
|
||||
|
||||
#define X 0
|
||||
|
|
@ -576,7 +575,7 @@ void draw_vf_generate_sse_emit( struct draw_vertex_fetch *vf )
|
|||
{
|
||||
struct x86_program p;
|
||||
|
||||
if (!cpu_has_xmm) {
|
||||
if (!rtasm_cpu_has_sse()) {
|
||||
vf->codegen_emit = NULL;
|
||||
return;
|
||||
}
|
||||
|
|
@ -586,7 +585,7 @@ void draw_vf_generate_sse_emit( struct draw_vertex_fetch *vf )
|
|||
p.vf = vf;
|
||||
p.inputs_safe = 0; /* for now */
|
||||
p.outputs_safe = 1; /* for now */
|
||||
p.have_sse2 = cpu_has_xmm2;
|
||||
p.have_sse2 = rtasm_cpu_has_sse2();
|
||||
p.identity = x86_make_reg(file_XMM, 6);
|
||||
p.chan0 = x86_make_reg(file_XMM, 7);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
#ifdef MESA_LLVM
|
||||
|
||||
#include "llvm/gallivm.h"
|
||||
#include "gallivm/gallivm.h"
|
||||
|
||||
struct draw_llvm_vertex_shader {
|
||||
struct draw_vertex_shader base;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
#include "draw_private.h"
|
||||
#include "draw_context.h"
|
||||
|
||||
#include "x86/rtasm/x86sse.h"
|
||||
#include "rtasm/rtasm_x86sse.h"
|
||||
#include "tgsi/exec/tgsi_sse2.h"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -161,70 +161,6 @@ static void wide_line( struct draw_stage *stage,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw a wide line by drawing a quad, using geometry which will
|
||||
* fullfill GL's antialiased line requirements.
|
||||
*/
|
||||
static void wide_line_aa(struct draw_stage *stage,
|
||||
struct prim_header *header)
|
||||
{
|
||||
const struct wide_stage *wide = wide_stage(stage);
|
||||
const float half_width = wide->half_line_width;
|
||||
struct prim_header tri;
|
||||
struct vertex_header *v[4];
|
||||
float *pos;
|
||||
float dx = header->v[1]->data[0][0] - header->v[0]->data[0][0];
|
||||
float dy = header->v[1]->data[0][1] - header->v[0]->data[0][1];
|
||||
const float len = (float) sqrt(dx * dx + dy * dy);
|
||||
uint i;
|
||||
|
||||
dx = dx * half_width / len;
|
||||
dy = dy * half_width / len;
|
||||
|
||||
/* allocate/dup new verts */
|
||||
for (i = 0; i < 4; i++) {
|
||||
v[i] = dup_vert(stage, header->v[i/2], i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Quad for line from v0 to v1:
|
||||
*
|
||||
* 1 3
|
||||
* +-------------------------+
|
||||
* | |
|
||||
* *v0 v1*
|
||||
* | |
|
||||
* +-------------------------+
|
||||
* 0 2
|
||||
*/
|
||||
|
||||
pos = v[0]->data[0];
|
||||
pos[0] += dy;
|
||||
pos[1] -= dx;
|
||||
|
||||
pos = v[1]->data[0];
|
||||
pos[0] -= dy;
|
||||
pos[1] += dx;
|
||||
|
||||
pos = v[2]->data[0];
|
||||
pos[0] += dy;
|
||||
pos[1] -= dx;
|
||||
|
||||
pos = v[3]->data[0];
|
||||
pos[0] -= dy;
|
||||
pos[1] += dx;
|
||||
|
||||
tri.det = header->det; /* only the sign matters */
|
||||
|
||||
tri.v[0] = v[2]; tri.v[1] = v[1]; tri.v[2] = v[0];
|
||||
stage->next->tri( stage->next, &tri );
|
||||
|
||||
tri.v[0] = v[3]; tri.v[1] = v[1]; tri.v[2] = v[2];
|
||||
stage->next->tri( stage->next, &tri );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the vertex texcoords for sprite mode.
|
||||
* Coords may be left untouched or set to a right-side-up or upside-down
|
||||
|
|
@ -379,10 +315,7 @@ static void wide_first_line( struct draw_stage *stage,
|
|||
wide->half_line_width = 0.5f * draw->rasterizer->line_width;
|
||||
|
||||
if (draw->rasterizer->line_width != 1.0) {
|
||||
if (draw->rasterizer->line_smooth)
|
||||
wide->stage.line = wide_line_aa;
|
||||
else
|
||||
wide->stage.line = wide_line;
|
||||
wide->stage.line = wide_line;
|
||||
}
|
||||
else {
|
||||
wide->stage.line = passthrough_line;
|
||||
|
|
|
|||
16
src/gallium/auxiliary/gallivm/SConscript
Normal file
16
src/gallium/auxiliary/gallivm/SConscript
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
Import('*')
|
||||
|
||||
gallivm = env.ConvenienceLibrary(
|
||||
target = 'gallivm',
|
||||
source = [
|
||||
'gallivm.cpp',
|
||||
'gallivm_cpu.cpp',
|
||||
'instructions.cpp',
|
||||
'loweringpass.cpp',
|
||||
'tgsitollvm.cpp',
|
||||
'storage.cpp',
|
||||
'storagesoa.cpp',
|
||||
'instructionssoa.cpp',
|
||||
])
|
||||
|
||||
auxiliaries.insert(0, gallivm)
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
|
||||
TOP = ../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
LIBNAME = pipebuffer
|
||||
|
||||
DRIVER_SOURCES = \
|
||||
C_SOURCES = \
|
||||
pb_buffer_fenced.c \
|
||||
pb_buffer_malloc.c \
|
||||
pb_bufmgr_fenced.c \
|
||||
|
|
@ -12,11 +11,6 @@ DRIVER_SOURCES = \
|
|||
pb_bufmgr_pool.c \
|
||||
pb_winsys.c
|
||||
|
||||
C_SOURCES = \
|
||||
$(DRIVER_SOURCES)
|
||||
|
||||
ASM_SOURCES =
|
||||
|
||||
include ../../Makefile.template
|
||||
|
||||
symlinks:
|
||||
|
|
|
|||
14
src/gallium/auxiliary/pipebuffer/SConscript
Normal file
14
src/gallium/auxiliary/pipebuffer/SConscript
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
Import('*')
|
||||
|
||||
pipebuffer = env.ConvenienceLibrary(
|
||||
target = 'pipebuffer',
|
||||
source = [
|
||||
'pb_buffer_fenced.c',
|
||||
'pb_buffer_malloc.c',
|
||||
'pb_bufmgr_fenced.c',
|
||||
'pb_bufmgr_mm.c',
|
||||
'pb_bufmgr_pool.c',
|
||||
'pb_winsys.c',
|
||||
])
|
||||
|
||||
auxiliaries.insert(0, pipebuffer)
|
||||
|
|
@ -34,13 +34,12 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "linked_list.h"
|
||||
|
||||
#include "p_compiler.h"
|
||||
#include "p_debug.h"
|
||||
#include "p_winsys.h"
|
||||
#include "p_thread.h"
|
||||
#include "p_util.h"
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_debug.h"
|
||||
#include "pipe/p_winsys.h"
|
||||
#include "pipe/p_thread.h"
|
||||
#include "pipe/p_util.h"
|
||||
#include "util/u_double_list.h"
|
||||
|
||||
#include "pb_buffer.h"
|
||||
#include "pb_buffer_fenced.h"
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "p_debug.h"
|
||||
#include "p_util.h"
|
||||
#include "pipe/p_debug.h"
|
||||
#include "pipe/p_util.h"
|
||||
|
||||
#include "pb_buffer.h"
|
||||
#include "pb_buffer_fenced.h"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* Copyright 1999 Wittawat Yamwong
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
|
@ -34,12 +33,12 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "linked_list.h"
|
||||
|
||||
#include "p_defines.h"
|
||||
#include "p_debug.h"
|
||||
#include "p_thread.h"
|
||||
#include "p_util.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_debug.h"
|
||||
#include "pipe/p_thread.h"
|
||||
#include "pipe/p_util.h"
|
||||
#include "util/u_double_list.h"
|
||||
#include "util/u_mm.h"
|
||||
#include "pb_buffer.h"
|
||||
#include "pb_bufmgr.h"
|
||||
|
||||
|
|
@ -50,306 +49,6 @@
|
|||
#define SUPER(__derived) (&(__derived)->base)
|
||||
|
||||
|
||||
struct mem_block
|
||||
{
|
||||
struct mem_block *next, *prev;
|
||||
struct mem_block *next_free, *prev_free;
|
||||
struct mem_block *heap;
|
||||
int ofs, size;
|
||||
unsigned int free:1;
|
||||
unsigned int reserved:1;
|
||||
};
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* For debugging purposes.
|
||||
*/
|
||||
static void
|
||||
mmDumpMemInfo(const struct mem_block *heap)
|
||||
{
|
||||
debug_printf("Memory heap %p:\n", (void *)heap);
|
||||
if (heap == 0) {
|
||||
debug_printf(" heap == 0\n");
|
||||
} else {
|
||||
const struct mem_block *p;
|
||||
|
||||
for(p = heap->next; p != heap; p = p->next) {
|
||||
debug_printf(" Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
|
||||
p->free ? 'F':'.',
|
||||
p->reserved ? 'R':'.');
|
||||
}
|
||||
|
||||
debug_printf("\nFree list:\n");
|
||||
|
||||
for(p = heap->next_free; p != heap; p = p->next_free) {
|
||||
debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
|
||||
p->free ? 'F':'.',
|
||||
p->reserved ? 'R':'.');
|
||||
}
|
||||
|
||||
}
|
||||
debug_printf("End of memory blocks\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* input: total size in bytes
|
||||
* return: a heap pointer if OK, NULL if error
|
||||
*/
|
||||
static struct mem_block *
|
||||
mmInit(int ofs, int size)
|
||||
{
|
||||
struct mem_block *heap, *block;
|
||||
|
||||
if (size <= 0)
|
||||
return NULL;
|
||||
|
||||
heap = CALLOC_STRUCT(mem_block);
|
||||
if (!heap)
|
||||
return NULL;
|
||||
|
||||
block = CALLOC_STRUCT(mem_block);
|
||||
if (!block) {
|
||||
FREE(heap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
heap->next = block;
|
||||
heap->prev = block;
|
||||
heap->next_free = block;
|
||||
heap->prev_free = block;
|
||||
|
||||
block->heap = heap;
|
||||
block->next = heap;
|
||||
block->prev = heap;
|
||||
block->next_free = heap;
|
||||
block->prev_free = heap;
|
||||
|
||||
block->ofs = ofs;
|
||||
block->size = size;
|
||||
block->free = 1;
|
||||
|
||||
return heap;
|
||||
}
|
||||
|
||||
|
||||
static struct mem_block *
|
||||
SliceBlock(struct mem_block *p,
|
||||
int startofs, int size,
|
||||
int reserved, int alignment)
|
||||
{
|
||||
struct mem_block *newblock;
|
||||
|
||||
/* break left [p, newblock, p->next], then p = newblock */
|
||||
if (startofs > p->ofs) {
|
||||
newblock = CALLOC_STRUCT(mem_block);
|
||||
if (!newblock)
|
||||
return NULL;
|
||||
newblock->ofs = startofs;
|
||||
newblock->size = p->size - (startofs - p->ofs);
|
||||
newblock->free = 1;
|
||||
newblock->heap = p->heap;
|
||||
|
||||
newblock->next = p->next;
|
||||
newblock->prev = p;
|
||||
p->next->prev = newblock;
|
||||
p->next = newblock;
|
||||
|
||||
newblock->next_free = p->next_free;
|
||||
newblock->prev_free = p;
|
||||
p->next_free->prev_free = newblock;
|
||||
p->next_free = newblock;
|
||||
|
||||
p->size -= newblock->size;
|
||||
p = newblock;
|
||||
}
|
||||
|
||||
/* break right, also [p, newblock, p->next] */
|
||||
if (size < p->size) {
|
||||
newblock = CALLOC_STRUCT(mem_block);
|
||||
if (!newblock)
|
||||
return NULL;
|
||||
newblock->ofs = startofs + size;
|
||||
newblock->size = p->size - size;
|
||||
newblock->free = 1;
|
||||
newblock->heap = p->heap;
|
||||
|
||||
newblock->next = p->next;
|
||||
newblock->prev = p;
|
||||
p->next->prev = newblock;
|
||||
p->next = newblock;
|
||||
|
||||
newblock->next_free = p->next_free;
|
||||
newblock->prev_free = p;
|
||||
p->next_free->prev_free = newblock;
|
||||
p->next_free = newblock;
|
||||
|
||||
p->size = size;
|
||||
}
|
||||
|
||||
/* p = middle block */
|
||||
p->free = 0;
|
||||
|
||||
/* Remove p from the free list:
|
||||
*/
|
||||
p->next_free->prev_free = p->prev_free;
|
||||
p->prev_free->next_free = p->next_free;
|
||||
|
||||
p->next_free = 0;
|
||||
p->prev_free = 0;
|
||||
|
||||
p->reserved = reserved;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allocate 'size' bytes with 2^align2 bytes alignment,
|
||||
* restrict the search to free memory after 'startSearch'
|
||||
* depth and back buffers should be in different 4mb banks
|
||||
* to get better page hits if possible
|
||||
* input: size = size of block
|
||||
* align2 = 2^align2 bytes alignment
|
||||
* startSearch = linear offset from start of heap to begin search
|
||||
* return: pointer to the allocated block, 0 if error
|
||||
*/
|
||||
static struct mem_block *
|
||||
mmAllocMem(struct mem_block *heap, int size, int align2, int startSearch)
|
||||
{
|
||||
struct mem_block *p;
|
||||
const int mask = (1 << align2)-1;
|
||||
int startofs = 0;
|
||||
int endofs;
|
||||
|
||||
if (!heap || align2 < 0 || size <= 0)
|
||||
return NULL;
|
||||
|
||||
for (p = heap->next_free; p != heap; p = p->next_free) {
|
||||
assert(p->free);
|
||||
|
||||
startofs = (p->ofs + mask) & ~mask;
|
||||
if ( startofs < startSearch ) {
|
||||
startofs = startSearch;
|
||||
}
|
||||
endofs = startofs+size;
|
||||
if (endofs <= (p->ofs+p->size))
|
||||
break;
|
||||
}
|
||||
|
||||
if (p == heap)
|
||||
return NULL;
|
||||
|
||||
assert(p->free);
|
||||
p = SliceBlock(p,startofs,size,0,mask+1);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Free block starts at offset
|
||||
* input: pointer to a heap, start offset
|
||||
* return: pointer to a block
|
||||
*/
|
||||
static struct mem_block *
|
||||
mmFindBlock(struct mem_block *heap, int start)
|
||||
{
|
||||
struct mem_block *p;
|
||||
|
||||
for (p = heap->next; p != heap; p = p->next) {
|
||||
if (p->ofs == start)
|
||||
return p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static INLINE int
|
||||
Join2Blocks(struct mem_block *p)
|
||||
{
|
||||
/* XXX there should be some assertions here */
|
||||
|
||||
/* NOTE: heap->free == 0 */
|
||||
|
||||
if (p->free && p->next->free) {
|
||||
struct mem_block *q = p->next;
|
||||
|
||||
assert(p->ofs + p->size == q->ofs);
|
||||
p->size += q->size;
|
||||
|
||||
p->next = q->next;
|
||||
q->next->prev = p;
|
||||
|
||||
q->next_free->prev_free = q->prev_free;
|
||||
q->prev_free->next_free = q->next_free;
|
||||
|
||||
FREE(q);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free block starts at offset
|
||||
* input: pointer to a block
|
||||
* return: 0 if OK, -1 if error
|
||||
*/
|
||||
static int
|
||||
mmFreeMem(struct mem_block *b)
|
||||
{
|
||||
if (!b)
|
||||
return 0;
|
||||
|
||||
if (b->free) {
|
||||
debug_printf("block already free\n");
|
||||
return -1;
|
||||
}
|
||||
if (b->reserved) {
|
||||
debug_printf("block is reserved\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
b->free = 1;
|
||||
b->next_free = b->heap->next_free;
|
||||
b->prev_free = b->heap;
|
||||
b->next_free->prev_free = b;
|
||||
b->prev_free->next_free = b;
|
||||
|
||||
Join2Blocks(b);
|
||||
if (b->prev != b->heap)
|
||||
Join2Blocks(b->prev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* destroy MM
|
||||
*/
|
||||
static void
|
||||
mmDestroy(struct mem_block *heap)
|
||||
{
|
||||
struct mem_block *p;
|
||||
|
||||
if (!heap)
|
||||
return;
|
||||
|
||||
for (p = heap->next; p != heap; ) {
|
||||
struct mem_block *next = p->next;
|
||||
FREE(p);
|
||||
p = next;
|
||||
}
|
||||
|
||||
FREE(heap);
|
||||
}
|
||||
|
||||
|
||||
struct mm_pb_manager
|
||||
{
|
||||
struct pb_manager base;
|
||||
|
|
|
|||
|
|
@ -35,13 +35,12 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "linked_list.h"
|
||||
|
||||
#include "p_compiler.h"
|
||||
#include "p_debug.h"
|
||||
#include "p_thread.h"
|
||||
#include "p_defines.h"
|
||||
#include "p_util.h"
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_debug.h"
|
||||
#include "pipe/p_thread.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "pipe/p_util.h"
|
||||
#include "util/u_double_list.h"
|
||||
|
||||
#include "pb_buffer.h"
|
||||
#include "pb_bufmgr.h"
|
||||
|
|
|
|||
15
src/gallium/auxiliary/rtasm/Makefile
Normal file
15
src/gallium/auxiliary/rtasm/Makefile
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
TOP = ../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
LIBNAME = rtasm
|
||||
|
||||
C_SOURCES = \
|
||||
rtasm_cpu.c \
|
||||
rtasm_execmem.c \
|
||||
rtasm_x86sse.c \
|
||||
rtasm_ppc_spe.c
|
||||
|
||||
include ../../Makefile.template
|
||||
|
||||
symlinks:
|
||||
|
||||
12
src/gallium/auxiliary/rtasm/SConscript
Normal file
12
src/gallium/auxiliary/rtasm/SConscript
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
Import('*')
|
||||
|
||||
rtasm = env.ConvenienceLibrary(
|
||||
target = 'rtasm',
|
||||
source = [
|
||||
'rtasm_cpu.c',
|
||||
'rtasm_execmem.c',
|
||||
'rtasm_x86sse.c',
|
||||
'rtasm_ppc_spe.c',
|
||||
])
|
||||
|
||||
auxiliaries.insert(0, rtasm)
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
|
@ -10,11 +10,11 @@
|
|||
* 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.
|
||||
|
|
@ -22,63 +22,29 @@
|
|||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/* Authors:
|
||||
* Brian Paul
|
||||
*/
|
||||
|
||||
#include "pipe/p_util.h"
|
||||
#include "draw/draw_context.h"
|
||||
#include "cell_context.h"
|
||||
#include "cell_state.h"
|
||||
#include "cell_texture.h"
|
||||
#include "rtasm_cpu.h"
|
||||
|
||||
|
||||
void *
|
||||
cell_create_sampler_state(struct pipe_context *pipe,
|
||||
const struct pipe_sampler_state *sampler)
|
||||
int rtasm_cpu_has_sse(void)
|
||||
{
|
||||
return mem_dup(sampler, sizeof(*sampler));
|
||||
/* FIXME: actually detect this at run-time */
|
||||
#if defined(__i386__) || defined(__386__)
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
cell_bind_sampler_state(struct pipe_context *pipe,
|
||||
unsigned unit, void *sampler)
|
||||
int rtasm_cpu_has_sse2(void)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
draw_flush(cell->draw);
|
||||
|
||||
assert(unit < PIPE_MAX_SAMPLERS);
|
||||
cell->sampler[unit] = (struct pipe_sampler_state *)sampler;
|
||||
|
||||
cell->dirty |= CELL_NEW_SAMPLER;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cell_delete_sampler_state(struct pipe_context *pipe,
|
||||
void *sampler)
|
||||
{
|
||||
FREE( sampler );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
cell_set_sampler_texture(struct pipe_context *pipe,
|
||||
unsigned sampler,
|
||||
struct pipe_texture *texture)
|
||||
{
|
||||
struct cell_context *cell = cell_context(pipe);
|
||||
|
||||
draw_flush(cell->draw);
|
||||
|
||||
cell->texture[sampler] = texture;
|
||||
|
||||
cell_update_texture_mapping(cell);
|
||||
|
||||
cell->dirty |= CELL_NEW_TEXTURE;
|
||||
/* FIXME: actually detect this at run-time */
|
||||
#if defined(__i386__) || defined(__386__)
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
42
src/gallium/auxiliary/rtasm/rtasm_cpu.h
Normal file
42
src/gallium/auxiliary/rtasm/rtasm_cpu.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Runtime detection of CPU capabilities.
|
||||
*/
|
||||
|
||||
#ifndef _RTASM_CPU_H_
|
||||
#define _RTASM_CPU_H_
|
||||
|
||||
|
||||
int rtasm_cpu_has_sse(void);
|
||||
|
||||
int rtasm_cpu_has_sse2(void);
|
||||
|
||||
|
||||
#endif /* _RTASM_CPU_H_ */
|
||||
135
src/gallium/auxiliary/rtasm/rtasm_execmem.c
Normal file
135
src/gallium/auxiliary/rtasm/rtasm_execmem.c
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* \file exemem.c
|
||||
* Functions for allocating executable memory.
|
||||
*
|
||||
* \author Keith Whitwell
|
||||
*/
|
||||
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_debug.h"
|
||||
#include "pipe/p_thread.h"
|
||||
#include "pipe/p_util.h"
|
||||
|
||||
#include "rtasm_execmem.h"
|
||||
|
||||
|
||||
#if defined(__linux__)
|
||||
|
||||
/*
|
||||
* Allocate a large block of memory which can hold code then dole it out
|
||||
* in pieces by means of the generic memory manager code.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include "util/u_mm.h"
|
||||
|
||||
#define EXEC_HEAP_SIZE (10*1024*1024)
|
||||
|
||||
_glthread_DECLARE_STATIC_MUTEX(exec_mutex);
|
||||
|
||||
static struct mem_block *exec_heap = NULL;
|
||||
static unsigned char *exec_mem = NULL;
|
||||
|
||||
|
||||
static void
|
||||
init_heap(void)
|
||||
{
|
||||
if (!exec_heap)
|
||||
exec_heap = mmInit( 0, EXEC_HEAP_SIZE );
|
||||
|
||||
if (!exec_mem)
|
||||
exec_mem = (unsigned char *) mmap(0, EXEC_HEAP_SIZE,
|
||||
PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
rtasm_exec_malloc(size_t size)
|
||||
{
|
||||
struct mem_block *block = NULL;
|
||||
void *addr = NULL;
|
||||
|
||||
_glthread_LOCK_MUTEX(exec_mutex);
|
||||
|
||||
init_heap();
|
||||
|
||||
if (exec_heap) {
|
||||
size = (size + 31) & ~31;
|
||||
block = mmAllocMem( exec_heap, size, 32, 0 );
|
||||
}
|
||||
|
||||
if (block)
|
||||
addr = exec_mem + block->ofs;
|
||||
else
|
||||
debug_printf("rtasm_exec_malloc failed\n");
|
||||
|
||||
_glthread_UNLOCK_MUTEX(exec_mutex);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtasm_exec_free(void *addr)
|
||||
{
|
||||
_glthread_LOCK_MUTEX(exec_mutex);
|
||||
|
||||
if (exec_heap) {
|
||||
struct mem_block *block = mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem);
|
||||
|
||||
if (block)
|
||||
mmFreeMem(block);
|
||||
}
|
||||
|
||||
_glthread_UNLOCK_MUTEX(exec_mutex);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Just use regular memory.
|
||||
*/
|
||||
|
||||
void *
|
||||
rtasm_exec_malloc(size_t size)
|
||||
{
|
||||
return MALLOC( size );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtasm_exec_free(void *addr)
|
||||
{
|
||||
FREE(addr);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
45
src/gallium/auxiliary/rtasm/rtasm_execmem.h
Normal file
45
src/gallium/auxiliary/rtasm/rtasm_execmem.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* \file exemem.c
|
||||
* Functions for allocating executable memory.
|
||||
*
|
||||
* \author Keith Whitwell
|
||||
*/
|
||||
|
||||
#ifndef _RTASM_EXECMEM_H_
|
||||
#define _RTASM_EXECMEM_H_
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
|
||||
extern void *
|
||||
rtasm_exec_malloc( size_t size );
|
||||
|
||||
|
||||
extern void
|
||||
rtasm_exec_free( void *addr );
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -23,16 +23,17 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file spe_asm.c
|
||||
* \file
|
||||
* Real-time assembly generation interface for Cell B.E. SPEs.
|
||||
*
|
||||
* \author Ian Romanick <idr@us.ibm.com>
|
||||
*/
|
||||
#ifdef GALLIUM_CELL
|
||||
#include <inttypes.h>
|
||||
#include <imports.h>
|
||||
#include "spe_asm.h"
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_util.h"
|
||||
#include "rtasm_ppc_spe.h"
|
||||
|
||||
#ifdef GALLIUM_CELL
|
||||
/**
|
||||
* SPE instruction types
|
||||
*
|
||||
|
|
@ -296,21 +297,21 @@ void _name (struct spe_function *p, int imm) \
|
|||
emit_RI16(p, _op, 0, imm); \
|
||||
}
|
||||
|
||||
#include "spe_asm.h"
|
||||
#include "rtasm_ppc_spe.h"
|
||||
|
||||
|
||||
/*
|
||||
*/
|
||||
void spe_init_func(struct spe_function *p, unsigned code_size)
|
||||
{
|
||||
p->store = _mesa_align_malloc(code_size, 16);
|
||||
p->store = align_malloc(code_size, 16);
|
||||
p->csr = p->store;
|
||||
}
|
||||
|
||||
|
||||
void spe_release_func(struct spe_function *p)
|
||||
{
|
||||
_mesa_align_free(p->store);
|
||||
align_free(p->store);
|
||||
p->store = NULL;
|
||||
p->csr = NULL;
|
||||
}
|
||||
|
|
@ -23,14 +23,14 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* \file spe_asm.h
|
||||
* \file
|
||||
* Real-time assembly generation interface for Cell B.E. SPEs.
|
||||
*
|
||||
* \author Ian Romanick <idr@us.ibm.com>
|
||||
*/
|
||||
|
||||
#ifndef SPE_ASM_H
|
||||
#define SPE_ASM_H
|
||||
#ifndef RTASM_PPC_SPE_H
|
||||
#define RTASM_PPC_SPE_H
|
||||
|
||||
struct spe_function {
|
||||
/**
|
||||
|
|
@ -44,7 +44,7 @@ struct spe_function {
|
|||
extern void spe_init_func(struct spe_function *p, unsigned code_size);
|
||||
extern void spe_release_func(struct spe_function *p);
|
||||
|
||||
#endif /* SPE_ASM_H */
|
||||
#endif /* RTASM_PPC_SPE_H */
|
||||
|
||||
#ifndef EMIT_
|
||||
#define EMIT_(name, _op) \
|
||||
1219
src/gallium/auxiliary/rtasm/rtasm_x86sse.c
Normal file
1219
src/gallium/auxiliary/rtasm/rtasm_x86sse.c
Normal file
File diff suppressed because it is too large
Load diff
278
src/gallium/auxiliary/rtasm/rtasm_x86sse.h
Normal file
278
src/gallium/auxiliary/rtasm/rtasm_x86sse.h
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION 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 _RTASM_X86SSE_H_
|
||||
#define _RTASM_X86SSE_H_
|
||||
|
||||
#if defined(__i386__) || defined(__386__) || defined(i386)
|
||||
|
||||
/* It is up to the caller to ensure that instructions issued are
|
||||
* suitable for the host cpu. There are no checks made in this module
|
||||
* for mmx/sse/sse2 support on the cpu.
|
||||
*/
|
||||
struct x86_reg {
|
||||
unsigned file:3;
|
||||
unsigned idx:3;
|
||||
unsigned mod:2; /* mod_REG if this is just a register */
|
||||
int disp:24; /* only +/- 23bits of offset - should be enough... */
|
||||
};
|
||||
|
||||
struct x86_function {
|
||||
unsigned size;
|
||||
unsigned char *store;
|
||||
unsigned char *csr;
|
||||
unsigned stack_offset;
|
||||
int need_emms;
|
||||
const char *fn;
|
||||
};
|
||||
|
||||
enum x86_reg_file {
|
||||
file_REG32,
|
||||
file_MMX,
|
||||
file_XMM,
|
||||
file_x87
|
||||
};
|
||||
|
||||
/* Values for mod field of modr/m byte
|
||||
*/
|
||||
enum x86_reg_mod {
|
||||
mod_INDIRECT,
|
||||
mod_DISP8,
|
||||
mod_DISP32,
|
||||
mod_REG
|
||||
};
|
||||
|
||||
enum x86_reg_name {
|
||||
reg_AX,
|
||||
reg_CX,
|
||||
reg_DX,
|
||||
reg_BX,
|
||||
reg_SP,
|
||||
reg_BP,
|
||||
reg_SI,
|
||||
reg_DI
|
||||
};
|
||||
|
||||
|
||||
enum x86_cc {
|
||||
cc_O, /* overflow */
|
||||
cc_NO, /* not overflow */
|
||||
cc_NAE, /* not above or equal / carry */
|
||||
cc_AE, /* above or equal / not carry */
|
||||
cc_E, /* equal / zero */
|
||||
cc_NE /* not equal / not zero */
|
||||
};
|
||||
|
||||
enum sse_cc {
|
||||
cc_Equal,
|
||||
cc_LessThan,
|
||||
cc_LessThanEqual,
|
||||
cc_Unordered,
|
||||
cc_NotEqual,
|
||||
cc_NotLessThan,
|
||||
cc_NotLessThanEqual,
|
||||
cc_Ordered
|
||||
};
|
||||
|
||||
#define cc_Z cc_E
|
||||
#define cc_NZ cc_NE
|
||||
|
||||
/* Begin/end/retreive function creation:
|
||||
*/
|
||||
|
||||
|
||||
void x86_init_func( struct x86_function *p );
|
||||
void x86_init_func_size( struct x86_function *p, unsigned code_size );
|
||||
void x86_release_func( struct x86_function *p );
|
||||
void (*x86_get_func( struct x86_function *p ))( void );
|
||||
|
||||
|
||||
|
||||
/* Create and manipulate registers and regmem values:
|
||||
*/
|
||||
struct x86_reg x86_make_reg( enum x86_reg_file file,
|
||||
enum x86_reg_name idx );
|
||||
|
||||
struct x86_reg x86_make_disp( struct x86_reg reg,
|
||||
int disp );
|
||||
|
||||
struct x86_reg x86_deref( struct x86_reg reg );
|
||||
|
||||
struct x86_reg x86_get_base_reg( struct x86_reg reg );
|
||||
|
||||
|
||||
/* Labels, jumps and fixup:
|
||||
*/
|
||||
unsigned char *x86_get_label( struct x86_function *p );
|
||||
|
||||
void x86_jcc( struct x86_function *p,
|
||||
enum x86_cc cc,
|
||||
unsigned char *label );
|
||||
|
||||
unsigned char *x86_jcc_forward( struct x86_function *p,
|
||||
enum x86_cc cc );
|
||||
|
||||
unsigned char *x86_jmp_forward( struct x86_function *p);
|
||||
|
||||
unsigned char *x86_call_forward( struct x86_function *p);
|
||||
|
||||
void x86_fixup_fwd_jump( struct x86_function *p,
|
||||
unsigned char *fixup );
|
||||
|
||||
void x86_jmp( struct x86_function *p, unsigned char *label );
|
||||
|
||||
/* void x86_call( struct x86_function *p, void (*label)() ); */
|
||||
void x86_call( struct x86_function *p, struct x86_reg reg);
|
||||
|
||||
/* michal:
|
||||
* Temporary. As I need immediate operands, and dont want to mess with the codegen,
|
||||
* I load the immediate into general purpose register and use it.
|
||||
*/
|
||||
void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm );
|
||||
|
||||
|
||||
/* Macro for sse_shufps() and sse2_pshufd():
|
||||
*/
|
||||
#define SHUF(_x,_y,_z,_w) (((_x)<<0) | ((_y)<<2) | ((_z)<<4) | ((_w)<<6))
|
||||
#define SHUF_NOOP RSW(0,1,2,3)
|
||||
#define GET_SHUF(swz, idx) (((swz) >> ((idx)*2)) & 0x3)
|
||||
|
||||
void mmx_emms( struct x86_function *p );
|
||||
void mmx_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void mmx_movq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void mmx_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void mmx_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
|
||||
void sse2_cvtps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_cvttps2dq( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_packssdw( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_packsswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_packuswb( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_pshufd( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0,
|
||||
unsigned char shuf );
|
||||
void sse2_rcpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse2_rcpss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
|
||||
void sse_addps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_addss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_cvtps2pi( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_divss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_andnps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_andps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_cmpps( struct x86_function *p, struct x86_reg dst, struct x86_reg src,
|
||||
unsigned char cc );
|
||||
void sse_maxps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_maxss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_minps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_movaps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_movhlps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_movhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_movlhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_movlps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_movss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_movups( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_mulps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_mulss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_orps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_xorps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_subps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_rsqrtps( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_rsqrtss( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void sse_shufps( struct x86_function *p, struct x86_reg dest, struct x86_reg arg0,
|
||||
unsigned char shuf );
|
||||
void sse_pmovmskb( struct x86_function *p, struct x86_reg dest, struct x86_reg src );
|
||||
|
||||
void x86_add( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_and( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_cmp( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_dec( struct x86_function *p, struct x86_reg reg );
|
||||
void x86_inc( struct x86_function *p, struct x86_reg reg );
|
||||
void x86_lea( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_mov( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_mul( struct x86_function *p, struct x86_reg src );
|
||||
void x86_or( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_pop( struct x86_function *p, struct x86_reg reg );
|
||||
void x86_push( struct x86_function *p, struct x86_reg reg );
|
||||
void x86_ret( struct x86_function *p );
|
||||
void x86_sub( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_test( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_xor( struct x86_function *p, struct x86_reg dst, struct x86_reg src );
|
||||
void x86_sahf( struct x86_function *p );
|
||||
|
||||
void x87_f2xm1( struct x86_function *p );
|
||||
void x87_fabs( struct x86_function *p );
|
||||
void x87_fadd( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
|
||||
void x87_faddp( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fchs( struct x86_function *p );
|
||||
void x87_fclex( struct x86_function *p );
|
||||
void x87_fcom( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fcomp( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fcos( struct x86_function *p );
|
||||
void x87_fdiv( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
|
||||
void x87_fdivp( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fdivr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
|
||||
void x87_fdivrp( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fild( struct x86_function *p, struct x86_reg arg );
|
||||
void x87_fist( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fistp( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fld( struct x86_function *p, struct x86_reg arg );
|
||||
void x87_fld1( struct x86_function *p );
|
||||
void x87_fldcw( struct x86_function *p, struct x86_reg arg );
|
||||
void x87_fldl2e( struct x86_function *p );
|
||||
void x87_fldln2( struct x86_function *p );
|
||||
void x87_fldz( struct x86_function *p );
|
||||
void x87_fmul( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
|
||||
void x87_fmulp( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fnclex( struct x86_function *p );
|
||||
void x87_fprndint( struct x86_function *p );
|
||||
void x87_fscale( struct x86_function *p );
|
||||
void x87_fsin( struct x86_function *p );
|
||||
void x87_fsincos( struct x86_function *p );
|
||||
void x87_fsqrt( struct x86_function *p );
|
||||
void x87_fst( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fstp( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fsub( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
|
||||
void x87_fsubp( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fsubr( struct x86_function *p, struct x86_reg dst, struct x86_reg arg );
|
||||
void x87_fsubrp( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fxch( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fxtract( struct x86_function *p );
|
||||
void x87_fyl2x( struct x86_function *p );
|
||||
void x87_fyl2xp1( struct x86_function *p );
|
||||
void x87_fwait( struct x86_function *p );
|
||||
void x87_fnstsw( struct x86_function *p, struct x86_reg dst );
|
||||
void x87_fucompp( struct x86_function *p );
|
||||
void x87_fucomp( struct x86_function *p, struct x86_reg arg );
|
||||
void x87_fucom( struct x86_function *p, struct x86_reg arg );
|
||||
|
||||
|
||||
|
||||
/* Retreive a reference to one of the function arguments, taking into
|
||||
* account any push/pop activity. Note - doesn't track explict
|
||||
* manipulation of ESP by other instructions.
|
||||
*/
|
||||
struct x86_reg x86_fn_arg( struct x86_function *p, unsigned arg );
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -1,3 +1,18 @@
|
|||
default:
|
||||
cd ../.. ; make
|
||||
TOP = ../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
LIBNAME = tgsi
|
||||
|
||||
C_SOURCES = \
|
||||
exec/tgsi_exec.c \
|
||||
exec/tgsi_sse2.c \
|
||||
util/tgsi_build.c \
|
||||
util/tgsi_dump.c \
|
||||
util/tgsi_parse.c \
|
||||
util/tgsi_transform.c \
|
||||
util/tgsi_util.c
|
||||
|
||||
include ../../Makefile.template
|
||||
|
||||
symlinks:
|
||||
|
||||
|
|
|
|||
14
src/gallium/auxiliary/tgsi/SConscript
Normal file
14
src/gallium/auxiliary/tgsi/SConscript
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
Import('*')
|
||||
|
||||
tgsi = env.ConvenienceLibrary(
|
||||
target = 'tgsi',
|
||||
source = [
|
||||
'exec/tgsi_exec.c',
|
||||
'exec/tgsi_sse2.c',
|
||||
'util/tgsi_build.c',
|
||||
'util/tgsi_dump.c',
|
||||
'util/tgsi_parse.c',
|
||||
'util/tgsi_util.c',
|
||||
])
|
||||
|
||||
auxiliaries.insert(0, tgsi)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
default:
|
||||
cd ../../.. ; make
|
||||
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
#include "tgsi_exec.h"
|
||||
#include "tgsi_sse2.h"
|
||||
|
||||
#include "x86/rtasm/x86sse.h"
|
||||
#include "rtasm/rtasm_x86sse.h"
|
||||
|
||||
#if defined(__i386__) || defined(__386__)
|
||||
|
||||
|
|
@ -2356,11 +2356,17 @@ tgsi_emit_sse2_fs(
|
|||
ok = emit_instruction(
|
||||
func,
|
||||
&parse.FullToken.FullInstruction );
|
||||
|
||||
if (!ok) {
|
||||
debug_printf("failed to translate tgsi opcode %d\n",
|
||||
parse.FullToken.FullInstruction.Instruction.Opcode );
|
||||
}
|
||||
break;
|
||||
|
||||
case TGSI_TOKEN_TYPE_IMMEDIATE:
|
||||
/* XXX implement this */
|
||||
ok = 0;
|
||||
debug_printf("failed to emit immediate value\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
15
src/gallium/auxiliary/util/Makefile
Normal file
15
src/gallium/auxiliary/util/Makefile
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
TOP = ../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
LIBNAME = util
|
||||
|
||||
C_SOURCES = \
|
||||
p_debug.c \
|
||||
p_tile.c \
|
||||
p_util.c \
|
||||
u_mm.c
|
||||
|
||||
include ../../Makefile.template
|
||||
|
||||
symlinks:
|
||||
|
||||
12
src/gallium/auxiliary/util/SConscript
Normal file
12
src/gallium/auxiliary/util/SConscript
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
Import('*')
|
||||
|
||||
util = env.ConvenienceLibrary(
|
||||
target = 'util',
|
||||
source = [
|
||||
'p_debug.c',
|
||||
'p_tile.c',
|
||||
'p_util.c',
|
||||
'u_mm.c',
|
||||
])
|
||||
|
||||
auxiliaries.insert(0, util)
|
||||
|
|
@ -34,8 +34,8 @@
|
|||
* be protected using an external mutex.
|
||||
*/
|
||||
|
||||
#ifndef LINKED_LIST_H_
|
||||
#define LINKED_LIST_H_
|
||||
#ifndef _U_DOUBLE_LIST_H_
|
||||
#define _U_DOUBLE_LIST_H_
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
|
|
@ -88,4 +88,4 @@ struct list_head
|
|||
((__type *)(((char *)(__item)) - offsetof(__type, __field)))
|
||||
|
||||
|
||||
#endif /*LINKED_LIST_H_*/
|
||||
#endif /*_U_DOUBLE_LIST_H_*/
|
||||
283
src/gallium/auxiliary/util/u_mm.c
Normal file
283
src/gallium/auxiliary/util/u_mm.c
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999 Wittawat Yamwong
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_util.h"
|
||||
#include "pipe/p_debug.h"
|
||||
|
||||
#include "util/u_mm.h"
|
||||
|
||||
|
||||
void
|
||||
mmDumpMemInfo(const struct mem_block *heap)
|
||||
{
|
||||
debug_printf("Memory heap %p:\n", (void *)heap);
|
||||
if (heap == 0) {
|
||||
debug_printf(" heap == 0\n");
|
||||
} else {
|
||||
const struct mem_block *p;
|
||||
|
||||
for(p = heap->next; p != heap; p = p->next) {
|
||||
debug_printf(" Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
|
||||
p->free ? 'F':'.',
|
||||
p->reserved ? 'R':'.');
|
||||
}
|
||||
|
||||
debug_printf("\nFree list:\n");
|
||||
|
||||
for(p = heap->next_free; p != heap; p = p->next_free) {
|
||||
debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size,
|
||||
p->free ? 'F':'.',
|
||||
p->reserved ? 'R':'.');
|
||||
}
|
||||
|
||||
}
|
||||
debug_printf("End of memory blocks\n");
|
||||
}
|
||||
|
||||
struct mem_block *
|
||||
mmInit(int ofs, int size)
|
||||
{
|
||||
struct mem_block *heap, *block;
|
||||
|
||||
if (size <= 0)
|
||||
return NULL;
|
||||
|
||||
heap = CALLOC_STRUCT(mem_block);
|
||||
if (!heap)
|
||||
return NULL;
|
||||
|
||||
block = CALLOC_STRUCT(mem_block);
|
||||
if (!block) {
|
||||
FREE(heap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
heap->next = block;
|
||||
heap->prev = block;
|
||||
heap->next_free = block;
|
||||
heap->prev_free = block;
|
||||
|
||||
block->heap = heap;
|
||||
block->next = heap;
|
||||
block->prev = heap;
|
||||
block->next_free = heap;
|
||||
block->prev_free = heap;
|
||||
|
||||
block->ofs = ofs;
|
||||
block->size = size;
|
||||
block->free = 1;
|
||||
|
||||
return heap;
|
||||
}
|
||||
|
||||
|
||||
static struct mem_block *
|
||||
SliceBlock(struct mem_block *p,
|
||||
int startofs, int size,
|
||||
int reserved, int alignment)
|
||||
{
|
||||
struct mem_block *newblock;
|
||||
|
||||
/* break left [p, newblock, p->next], then p = newblock */
|
||||
if (startofs > p->ofs) {
|
||||
newblock = CALLOC_STRUCT(mem_block);
|
||||
if (!newblock)
|
||||
return NULL;
|
||||
newblock->ofs = startofs;
|
||||
newblock->size = p->size - (startofs - p->ofs);
|
||||
newblock->free = 1;
|
||||
newblock->heap = p->heap;
|
||||
|
||||
newblock->next = p->next;
|
||||
newblock->prev = p;
|
||||
p->next->prev = newblock;
|
||||
p->next = newblock;
|
||||
|
||||
newblock->next_free = p->next_free;
|
||||
newblock->prev_free = p;
|
||||
p->next_free->prev_free = newblock;
|
||||
p->next_free = newblock;
|
||||
|
||||
p->size -= newblock->size;
|
||||
p = newblock;
|
||||
}
|
||||
|
||||
/* break right, also [p, newblock, p->next] */
|
||||
if (size < p->size) {
|
||||
newblock = CALLOC_STRUCT(mem_block);
|
||||
if (!newblock)
|
||||
return NULL;
|
||||
newblock->ofs = startofs + size;
|
||||
newblock->size = p->size - size;
|
||||
newblock->free = 1;
|
||||
newblock->heap = p->heap;
|
||||
|
||||
newblock->next = p->next;
|
||||
newblock->prev = p;
|
||||
p->next->prev = newblock;
|
||||
p->next = newblock;
|
||||
|
||||
newblock->next_free = p->next_free;
|
||||
newblock->prev_free = p;
|
||||
p->next_free->prev_free = newblock;
|
||||
p->next_free = newblock;
|
||||
|
||||
p->size = size;
|
||||
}
|
||||
|
||||
/* p = middle block */
|
||||
p->free = 0;
|
||||
|
||||
/* Remove p from the free list:
|
||||
*/
|
||||
p->next_free->prev_free = p->prev_free;
|
||||
p->prev_free->next_free = p->next_free;
|
||||
|
||||
p->next_free = 0;
|
||||
p->prev_free = 0;
|
||||
|
||||
p->reserved = reserved;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
struct mem_block *
|
||||
mmAllocMem(struct mem_block *heap, int size, int align2, int startSearch)
|
||||
{
|
||||
struct mem_block *p;
|
||||
const int mask = (1 << align2)-1;
|
||||
int startofs = 0;
|
||||
int endofs;
|
||||
|
||||
if (!heap || align2 < 0 || size <= 0)
|
||||
return NULL;
|
||||
|
||||
for (p = heap->next_free; p != heap; p = p->next_free) {
|
||||
assert(p->free);
|
||||
|
||||
startofs = (p->ofs + mask) & ~mask;
|
||||
if ( startofs < startSearch ) {
|
||||
startofs = startSearch;
|
||||
}
|
||||
endofs = startofs+size;
|
||||
if (endofs <= (p->ofs+p->size))
|
||||
break;
|
||||
}
|
||||
|
||||
if (p == heap)
|
||||
return NULL;
|
||||
|
||||
assert(p->free);
|
||||
p = SliceBlock(p,startofs,size,0,mask+1);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
struct mem_block *
|
||||
mmFindBlock(struct mem_block *heap, int start)
|
||||
{
|
||||
struct mem_block *p;
|
||||
|
||||
for (p = heap->next; p != heap; p = p->next) {
|
||||
if (p->ofs == start)
|
||||
return p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static INLINE int
|
||||
Join2Blocks(struct mem_block *p)
|
||||
{
|
||||
/* XXX there should be some assertions here */
|
||||
|
||||
/* NOTE: heap->free == 0 */
|
||||
|
||||
if (p->free && p->next->free) {
|
||||
struct mem_block *q = p->next;
|
||||
|
||||
assert(p->ofs + p->size == q->ofs);
|
||||
p->size += q->size;
|
||||
|
||||
p->next = q->next;
|
||||
q->next->prev = p;
|
||||
|
||||
q->next_free->prev_free = q->prev_free;
|
||||
q->prev_free->next_free = q->next_free;
|
||||
|
||||
FREE(q);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mmFreeMem(struct mem_block *b)
|
||||
{
|
||||
if (!b)
|
||||
return 0;
|
||||
|
||||
if (b->free) {
|
||||
debug_printf("block already free\n");
|
||||
return -1;
|
||||
}
|
||||
if (b->reserved) {
|
||||
debug_printf("block is reserved\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
b->free = 1;
|
||||
b->next_free = b->heap->next_free;
|
||||
b->prev_free = b->heap;
|
||||
b->next_free->prev_free = b;
|
||||
b->prev_free->next_free = b;
|
||||
|
||||
Join2Blocks(b);
|
||||
if (b->prev != b->heap)
|
||||
Join2Blocks(b->prev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mmDestroy(struct mem_block *heap)
|
||||
{
|
||||
struct mem_block *p;
|
||||
|
||||
if (!heap)
|
||||
return;
|
||||
|
||||
for (p = heap->next; p != heap; ) {
|
||||
struct mem_block *next = p->next;
|
||||
FREE(p);
|
||||
p = next;
|
||||
}
|
||||
|
||||
FREE(heap);
|
||||
}
|
||||
91
src/gallium/auxiliary/util/u_mm.h
Normal file
91
src/gallium/auxiliary/util/u_mm.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999 Wittawat Yamwong
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Memory manager code. Primarily used by device drivers to manage texture
|
||||
* heaps, etc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _U_MM_H_
|
||||
#define _U_MM_H_
|
||||
|
||||
|
||||
struct mem_block {
|
||||
struct mem_block *next, *prev;
|
||||
struct mem_block *next_free, *prev_free;
|
||||
struct mem_block *heap;
|
||||
int ofs,size;
|
||||
unsigned int free:1;
|
||||
unsigned int reserved:1;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* input: total size in bytes
|
||||
* return: a heap pointer if OK, NULL if error
|
||||
*/
|
||||
extern struct mem_block *mmInit(int ofs, int size);
|
||||
|
||||
/**
|
||||
* Allocate 'size' bytes with 2^align2 bytes alignment,
|
||||
* restrict the search to free memory after 'startSearch'
|
||||
* depth and back buffers should be in different 4mb banks
|
||||
* to get better page hits if possible
|
||||
* input: size = size of block
|
||||
* align2 = 2^align2 bytes alignment
|
||||
* startSearch = linear offset from start of heap to begin search
|
||||
* return: pointer to the allocated block, 0 if error
|
||||
*/
|
||||
extern struct mem_block *mmAllocMem(struct mem_block *heap, int size, int align2,
|
||||
int startSearch);
|
||||
|
||||
/**
|
||||
* Free block starts at offset
|
||||
* input: pointer to a block
|
||||
* return: 0 if OK, -1 if error
|
||||
*/
|
||||
extern int mmFreeMem(struct mem_block *b);
|
||||
|
||||
/**
|
||||
* Free block starts at offset
|
||||
* input: pointer to a heap, start offset
|
||||
* return: pointer to a block
|
||||
*/
|
||||
extern struct mem_block *mmFindBlock(struct mem_block *heap, int start);
|
||||
|
||||
/**
|
||||
* destroy MM
|
||||
*/
|
||||
extern void mmDestroy(struct mem_block *mmInit);
|
||||
|
||||
/**
|
||||
* For debuging purpose.
|
||||
*/
|
||||
extern void mmDumpMemInfo(const struct mem_block *mmInit);
|
||||
|
||||
#endif
|
||||
197
src/gallium/auxiliary/util/u_simple_list.h
Normal file
197
src/gallium/auxiliary/util/u_simple_list.h
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/**
|
||||
* \file simple_list.h
|
||||
* Simple macros for type-safe, intrusive lists.
|
||||
*
|
||||
* Intended to work with a list sentinal which is created as an empty
|
||||
* list. Insert & delete are O(1).
|
||||
*
|
||||
* \author
|
||||
* (C) 1997, Keith Whitwell
|
||||
*/
|
||||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 3.5
|
||||
*
|
||||
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION 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 _U_SIMPLE_LIST_H_
|
||||
#define _U_SIMPLE_LIST_H_
|
||||
|
||||
/**
|
||||
* Remove an element from list.
|
||||
*
|
||||
* \param elem element to remove.
|
||||
*/
|
||||
#define remove_from_list(elem) \
|
||||
do { \
|
||||
(elem)->next->prev = (elem)->prev; \
|
||||
(elem)->prev->next = (elem)->next; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Insert an element to the list head.
|
||||
*
|
||||
* \param list list.
|
||||
* \param elem element to insert.
|
||||
*/
|
||||
#define insert_at_head(list, elem) \
|
||||
do { \
|
||||
(elem)->prev = list; \
|
||||
(elem)->next = (list)->next; \
|
||||
(list)->next->prev = elem; \
|
||||
(list)->next = elem; \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Insert an element to the list tail.
|
||||
*
|
||||
* \param list list.
|
||||
* \param elem element to insert.
|
||||
*/
|
||||
#define insert_at_tail(list, elem) \
|
||||
do { \
|
||||
(elem)->next = list; \
|
||||
(elem)->prev = (list)->prev; \
|
||||
(list)->prev->next = elem; \
|
||||
(list)->prev = elem; \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Move an element to the list head.
|
||||
*
|
||||
* \param list list.
|
||||
* \param elem element to move.
|
||||
*/
|
||||
#define move_to_head(list, elem) \
|
||||
do { \
|
||||
remove_from_list(elem); \
|
||||
insert_at_head(list, elem); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Move an element to the list tail.
|
||||
*
|
||||
* \param list list.
|
||||
* \param elem element to move.
|
||||
*/
|
||||
#define move_to_tail(list, elem) \
|
||||
do { \
|
||||
remove_from_list(elem); \
|
||||
insert_at_tail(list, elem); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Make a empty list empty.
|
||||
*
|
||||
* \param sentinal list (sentinal element).
|
||||
*/
|
||||
#define make_empty_list(sentinal) \
|
||||
do { \
|
||||
(sentinal)->next = sentinal; \
|
||||
(sentinal)->prev = sentinal; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Get list first element.
|
||||
*
|
||||
* \param list list.
|
||||
*
|
||||
* \return pointer to first element.
|
||||
*/
|
||||
#define first_elem(list) ((list)->next)
|
||||
|
||||
/**
|
||||
* Get list last element.
|
||||
*
|
||||
* \param list list.
|
||||
*
|
||||
* \return pointer to last element.
|
||||
*/
|
||||
#define last_elem(list) ((list)->prev)
|
||||
|
||||
/**
|
||||
* Get next element.
|
||||
*
|
||||
* \param elem element.
|
||||
*
|
||||
* \return pointer to next element.
|
||||
*/
|
||||
#define next_elem(elem) ((elem)->next)
|
||||
|
||||
/**
|
||||
* Get previous element.
|
||||
*
|
||||
* \param elem element.
|
||||
*
|
||||
* \return pointer to previous element.
|
||||
*/
|
||||
#define prev_elem(elem) ((elem)->prev)
|
||||
|
||||
/**
|
||||
* Test whether element is at end of the list.
|
||||
*
|
||||
* \param list list.
|
||||
* \param elem element.
|
||||
*
|
||||
* \return non-zero if element is at end of list, or zero otherwise.
|
||||
*/
|
||||
#define at_end(list, elem) ((elem) == (list))
|
||||
|
||||
/**
|
||||
* Test if a list is empty.
|
||||
*
|
||||
* \param list list.
|
||||
*
|
||||
* \return non-zero if list empty, or zero otherwise.
|
||||
*/
|
||||
#define is_empty_list(list) ((list)->next == (list))
|
||||
|
||||
/**
|
||||
* Walk through the elements of a list.
|
||||
*
|
||||
* \param ptr pointer to the current element.
|
||||
* \param list list.
|
||||
*
|
||||
* \note It should be followed by a { } block or a single statement, as in a \c
|
||||
* for loop.
|
||||
*/
|
||||
#define foreach(ptr, list) \
|
||||
for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next )
|
||||
|
||||
/**
|
||||
* Walk through the elements of a list.
|
||||
*
|
||||
* Same as #foreach but lets you unlink the current value during a list
|
||||
* traversal. Useful for freeing a list, element by element.
|
||||
*
|
||||
* \param ptr pointer to the current element.
|
||||
* \param t temporary pointer.
|
||||
* \param list list.
|
||||
*
|
||||
* \note It should be followed by a { } block or a single statement, as in a \c
|
||||
* for loop.
|
||||
*/
|
||||
#define foreach_s(ptr, t, list) \
|
||||
for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next)
|
||||
|
||||
#endif /* _U_SIMPLE_LIST_H_ */
|
||||
|
|
@ -2,12 +2,7 @@ TOP = ../../..
|
|||
include $(TOP)/configs/current
|
||||
|
||||
|
||||
ifeq ($(CONFIG_NAME), linux-cell)
|
||||
CELL_DIR = cell
|
||||
endif
|
||||
|
||||
SUBDIRS = softpipe i915simple i965simple nv30 nv40 nv50 \
|
||||
failover pipebuffer $(CELL_DIR)
|
||||
SUBDIRS = $(GALLIUM_DRIVER_DIRS)
|
||||
|
||||
|
||||
default: subdirs
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue