Merge commit 'origin/gallium-0.1' into gallium-0.2

Conflicts:

	Makefile
	progs/demos/Makefile
	progs/glsl/Makefile
	progs/redbook/Makefile
	progs/samples/Makefile
	progs/tests/Makefile
	progs/trivial/Makefile
	progs/xdemos/Makefile
	src/gallium/Makefile
	src/mesa/main/attrib.c
	src/mesa/main/bufferobj.c
	src/mesa/vbo/vbo_exec_draw.c
This commit is contained in:
Keith Whitwell 2008-09-11 18:32:05 +01:00
commit cc7dd4fc1b
184 changed files with 6124 additions and 2879 deletions

View File

@ -109,6 +109,7 @@ linux \
linux-alpha \
linux-alpha-static \
linux-cell \
linux-cell-debug \
linux-debug \
linux-directfb \
linux-dri \

View File

@ -50,6 +50,8 @@ opts.Add(ListOption('drivers', 'pipe drivers to build', default_drivers,
opts.Add(ListOption('winsys', 'winsys drivers to build', default_winsys,
['xlib', 'intel', 'gdi']))
opts.Add(EnumOption('MSVS_VERSION', 'MS Visual C++ version', None, allowed_values=('7.1', '8.0', '9.0')))
env = Environment(
options = opts,
tools = ['gallium'],

View File

@ -25,6 +25,10 @@ CXXFLAGS = -O
LDFLAGS =
GLU_CFLAGS =
# Compiler for building demos/tests/etc
APP_CC = $(CC)
APP_CXX = $(CXX)
# Misc tools and flags
SHELL = /bin/sh
MKLIB = $(SHELL) $(TOP)/bin/mklib

View File

@ -1,4 +1,4 @@
# linux-cell
# linux-cell (non-debug build)
include $(TOP)/configs/default
@ -12,11 +12,16 @@ GALLIUM_DRIVER_DIRS += cell
CC = ppu32-gcc
CXX = ppu32-g++
HOST_CC = gcc
APP_CC = gcc
APP_CXX = g++
OPT_FLAGS = -g
OPT_FLAGS = -O3
# Cell SDK location
SDK = /opt/ibm/cell-sdk/prototype/sysroot/usr
## For SDK 2.1: (plus, remove -DSPU_MAIN_PARAM_LONG_LONG below)
#SDK = /opt/ibm/cell-sdk/prototype/sysroot/usr
## For SDK 3.0:
SDK = /opt/cell/sdk/usr
CFLAGS = $(OPT_FLAGS) -Wall -Winline -fPIC -m32 -mabi=altivec -maltivec \
@ -36,6 +41,8 @@ GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread \
-L$(SDK)/lib -m32 -Wl,-m,elf32ppc -R$(SDK)/lib -lspe2
CELL_SPU_LIB = $(TOP)/src/gallium/drivers/cell/spu/g3d_spu.a
### SPU stuff
@ -43,6 +50,7 @@ SPU_CC = spu-gcc
SPU_CFLAGS = $(OPT_FLAGS) -W -Wall -Winline -Wmissing-prototypes -Wno-main \
-I. -I$(SDK)/spu/include -I$(TOP)/src/mesa/ $(INCLUDE_DIRS) \
-DSPU_MAIN_PARAM_LONG_LONG \
-include spu_intrinsics.h
SPU_LFLAGS = -L$(SDK)/spu/lib -Wl,-N -lmisc

10
configs/linux-cell-debug Normal file
View File

@ -0,0 +1,10 @@
# linux-cell-debug
include $(TOP)/configs/linux-cell
# just override name and OPT_FLAGS here:
CONFIG_NAME = linux-cell-debug
OPT_FLAGS = -g -DDEBUG

View File

@ -1,7 +1,6 @@
#ifndef __gl_h_
#define __gl_h_
/* $Id: gl.h 4533 2007-11-26 11:19:35Z markc $ */
#include <GLES/glplatform.h>

View File

@ -1,7 +1,6 @@
#ifndef __glext_h_
#define __glext_h_
/* $Id: glext.h 5687 2008-05-13 21:31:32Z oddhack $ */
#ifdef __cplusplus
extern "C" {

View File

@ -1,7 +1,6 @@
#ifndef __glplatform_h_
#define __glplatform_h_
/* $Id: glplatform.h 4585 2007-11-30 09:49:39Z markc $ */
#ifdef __cplusplus
extern "C" {

View File

@ -1,7 +1,6 @@
#ifndef __gl2_h_
#define __gl2_h_
/* $Id: gl2.h 5418 2008-03-26 19:57:12Z oddhack $ */
#include <GLES2/gl2platform.h>

View File

@ -1,7 +1,6 @@
#ifndef __gl2ext_h_
#define __gl2ext_h_
/* $Id: gl2ext.h 5767 2008-06-02 17:44:20Z benj $ */
#ifdef __cplusplus
extern "C" {

View File

@ -1,7 +1,6 @@
#ifndef __gl2platform_h_
#define __gl2platform_h_
/* $Id: gl2platform.h 4532 2007-11-26 11:12:44Z markc $ */
#ifdef __cplusplus
extern "C" {

View File

@ -81,7 +81,7 @@ PROGS = \
# make executable from .c file:
.c: $(LIB_DEP) readtex.o
$(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) $< readtex.o $(LIBS) -o $@
$(APP_CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) $< readtex.o $(APP_LIB_DEPS) -o $@
##### TARGETS #####
@ -97,7 +97,7 @@ readtex.h: $(TOP)/progs/util/readtex.h
cp $< .
readtex.o: readtex.c readtex.h
$(CC) -c -I$(INCDIR) $(CFLAGS) readtex.c
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) readtex.c
showbuffer.c: $(TOP)/progs/util/showbuffer.c
@ -107,7 +107,7 @@ showbuffer.h: $(TOP)/progs/util/showbuffer.h
cp $< .
showbuffer.o: showbuffer.c showbuffer.h
$(CC) -c -I$(INCDIR) $(CFLAGS) showbuffer.c
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) showbuffer.c
trackball.c: $(TOP)/progs/util/trackball.c
@ -117,7 +117,7 @@ trackball.h: $(TOP)/progs/util/trackball.h
cp $< .
trackball.o: trackball.c trackball.h
$(CC) -c -I$(INCDIR) $(CFLAGS) trackball.c
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) trackball.c
extfuncs.h: $(TOP)/progs/util/extfuncs.h
@ -125,38 +125,38 @@ extfuncs.h: $(TOP)/progs/util/extfuncs.h
reflect: reflect.o showbuffer.o readtex.o
$(CC) $(CFLAGS) $(LDFLAGS) reflect.o showbuffer.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) reflect.o showbuffer.o readtex.o $(LIBS) -o $@
reflect.o: reflect.c showbuffer.h
$(CC) -c -I$(INCDIR) $(CFLAGS) reflect.c
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) reflect.c
shadowtex: shadowtex.o showbuffer.o
$(CC) $(CFLAGS) $(LDFLAGS) shadowtex.o showbuffer.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) shadowtex.o showbuffer.o $(LIBS) -o $@
shadowtex.o: shadowtex.c showbuffer.h
$(CC) -c -I$(INCDIR) $(CFLAGS) shadowtex.c
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) shadowtex.c
gloss: gloss.o trackball.o readtex.o
$(CC) $(CFLAGS) $(LDFLAGS) gloss.o trackball.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) gloss.o trackball.o readtex.o $(LIBS) -o $@
gloss.o: gloss.c trackball.h
$(CC) -c -I$(INCDIR) $(CFLAGS) gloss.c
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) gloss.c
engine: engine.o trackball.o readtex.o
$(CC) $(CFLAGS) $(LDFLAGS) engine.o trackball.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) engine.o trackball.o readtex.o $(LIBS) -o $@
engine.o: engine.c trackball.h
$(CC) -c -I$(INCDIR) $(CFLAGS) engine.c
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) engine.c
fslight: fslight.o
$(CC) $(CFLAGS) $(LDFLAGS) fslight.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) fslight.o $(LIBS) -o $@
fslight.o: fslight.c extfuncs.h
$(CC) -c -I$(INCDIR) $(CFLAGS) fslight.c
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) fslight.c
rain: particles.o rain.o readtex.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ $(LIBS) -o $@

View File

@ -36,7 +36,7 @@ PROGS = \
# make executable from .c file:
.c: $(LIB_DEP)
$(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
$(APP_CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
##### TARGETS #####
@ -58,7 +58,7 @@ readtex.h: $(TOP)/progs/util/readtex.h
cp $< .
readtex.o: readtex.c readtex.h
$(CC) -c -I$(INCDIR) $(CFLAGS) readtex.c
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) readtex.c
shaderutil.c: $(TOP)/progs/util/shaderutil.c
@ -113,7 +113,6 @@ mandelbrot.o: mandelbrot.c extfuncs.h shaderutil.h
mandelbrot: mandelbrot.o shaderutil.o
$(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) mandelbrot.o shaderutil.o $(LIBS) -o $@
multitex.o: multitex.c extfuncs.h readtex.h shaderutil.h
$(CC) -c -I$(INCDIR) $(CFLAGS) multitex.c
@ -171,10 +170,10 @@ trirast: trirast.o shaderutil.o
convolutions: convolutions.o readtex.o
$(CC) -I$(INCDIR) $(CFLAGS) convolutions.o readtex.o $(APP_LIB_DEPS) -o $@
$(APP_CC) -I$(INCDIR) $(CFLAGS) convolutions.o readtex.o $(APP_LIB_DEPS) -o $@
convolutions.o: convolutions.c readtex.h
$(CC) -c -I$(INCDIR) $(CFLAGS) convolutions.c
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) convolutions.c
clean:

View File

@ -26,7 +26,7 @@ PROGS = aaindex aapoly aargb accanti accpersp alpha alpha3D anti \
.SUFFIXES: .c
.c: $(LIB_DEP)
$(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
$(APP_CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@

View File

@ -20,7 +20,7 @@ PROGS = accum bitmap1 bitmap2 blendeq blendxor copy cursor depth eval fog \
.SUFFIXES: .c
.c: $(LIB_DEP)
$(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
$(APP_CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
##### TARGETS #####
@ -29,10 +29,10 @@ default: $(PROGS)
sphere: sphere.o readtex.o
$(CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) sphere.o readtex.o $(LIBS) -o $@
$(APP_CC) -I$(INCDIR) $(CFLAGS) $(LDFLAGS) sphere.o readtex.o $(LIBS) -o $@
sphere.o: sphere.c readtex.h
$(CC) -c -I$(INCDIR) $(CFLAGS) sphere.c
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) sphere.c
readtex.c: $(TOP)/progs/util/readtex.c
cp $< .
@ -41,7 +41,7 @@ readtex.h: $(TOP)/progs/util/readtex.h
cp $< .
readtex.o: readtex.c readtex.h
$(CC) -c -I$(INCDIR) $(CFLAGS) $< -o $@
$(APP_CC) -c -I$(INCDIR) $(CFLAGS) $< -o $@
clean:

View File

@ -62,6 +62,7 @@ SOURCES = \
pbo.c \
prog_parameter.c \
projtex.c \
quads.c \
random.c \
readrate.c \
seccolor.c \
@ -116,13 +117,13 @@ clean:
.SUFFIXES: .c
.c:
$(CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
$(APP_CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
.S.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
# auto code generation
getprocaddress: getprocaddress.c getproclist.h
@ -131,58 +132,58 @@ getproclist.h: $(TOP)/src/mesa/glapi/gl_API.xml getprocaddress.c getprocaddress.
python getprocaddress.py > getproclist.h
arraytexture: arraytexture.o readtex.o
$(CC) $(CFLAGS) arraytexture.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) arraytexture.o readtex.o $(LIBS) -o $@
arraytexture.o: arraytexture.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) arraytexture.c -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) arraytexture.c -o $@
afsmultiarb: afsmultiarb.o readtex.o
$(CC) $(CFLAGS) $(LDFLAGS) afsmultiarb.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) afsmultiarb.o readtex.o $(LIBS) -o $@
afsmultiarb.o: afsmultiarb.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) afsmultiarb.c -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) afsmultiarb.c -o $@
drawbuffers: drawbuffers.o
$(CC) $(CFLAGS) $(LDFLAGS) drawbuffers.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) drawbuffers.o $(LIBS) -o $@
drawbuffers.o: drawbuffers.c extfuncs.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) drawbuffers.c -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) drawbuffers.c -o $@
texrect: texrect.o readtex.o
$(CC) $(CFLAGS) $(LDFLAGS) texrect.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) texrect.o readtex.o $(LIBS) -o $@
texrect.o: texrect.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) texrect.c -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) texrect.c -o $@
bug_3195: bug_3195.o readtex.o
$(CC) $(CFLAGS) $(LDFLAGS) bug_3195.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) bug_3195.o readtex.o $(LIBS) -o $@
bug_3195.o: bug_3195.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) bug_3195.c -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) bug_3195.c -o $@
invert: invert.o readtex.o
$(CC) $(CFLAGS) $(LDFLAGS) invert.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) invert.o readtex.o $(LIBS) -o $@
invert.o: invert.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) invert.c -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) invert.c -o $@
mipmap_view: mipmap_view.o readtex.o
$(CC) $(CFLAGS) mipmap_view.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) mipmap_view.o readtex.o $(LIBS) -o $@
mipmap_view.o: mipmap_view.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
fillrate: fillrate.o readtex.o
$(CC) $(CFLAGS) fillrate.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) fillrate.o readtex.o $(LIBS) -o $@
fillrate.o: fillrate.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
readtex.o: readtex.c
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) readtex.c -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) readtex.c -o $@
readtex.h: $(TOP)/progs/util/readtex.h

258
progs/tests/quads.c Normal file
View File

@ -0,0 +1,258 @@
/**
* Draw colored quads.
*/
#define GL_GLEXT_PROTOTYPES
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#define NUM_QUADS 20
static int Win;
static GLfloat Xrot = 40, Yrot = 0, Zrot = 0;
static GLboolean Anim = GL_TRUE;
static GLuint Vbuffer = 0;
static GLfloat buf[NUM_QUADS * 6 * 4];
static GLboolean SwapBuffers = GL_TRUE;
static GLint Frames = 0, T0 = 0;
static void
Idle(void)
{
Xrot += 3.0;
Yrot += 4.0;
Zrot += 2.0;
glutPostRedisplay();
}
static void
Draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(Xrot, 1, 0, 0);
glRotatef(Yrot, 0, 1, 0);
glRotatef(Zrot, 0, 0, 1);
glDrawArrays(GL_QUADS, 0, NUM_QUADS*4);
glPopMatrix();
if (SwapBuffers)
glutSwapBuffers();
/*
else
glFinish();
*/
{
GLint t = glutGet(GLUT_ELAPSED_TIME);
Frames++;
if (t - T0 >= 5000) {
GLfloat seconds = (t - T0) / 1000.0;
GLfloat fps = Frames / seconds;
printf("%d frames in %6.3f seconds = %6.3f FPS\n",
Frames, seconds, fps);
T0 = t;
Frames = 0;
}
}
}
static void
Reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -8.0);
}
static void
Key(unsigned char key, int x, int y)
{
const GLfloat step = 3.0;
(void) x;
(void) y;
switch (key) {
case 's':
SwapBuffers = !SwapBuffers;
break;
case 'a':
Anim = !Anim;
if (Anim)
glutIdleFunc(Idle);
else
glutIdleFunc(NULL);
break;
case 'z':
Zrot -= step;
break;
case 'Z':
Zrot += step;
break;
case 27:
glutDestroyWindow(Win);
exit(0);
break;
}
glutPostRedisplay();
}
static void
SpecialKey(int key, int x, int y)
{
const GLfloat step = 3.0;
(void) x;
(void) y;
switch (key) {
case GLUT_KEY_UP:
Xrot -= step;
break;
case GLUT_KEY_DOWN:
Xrot += step;
break;
case GLUT_KEY_LEFT:
Yrot -= step;
break;
case GLUT_KEY_RIGHT:
Yrot += step;
break;
}
glutPostRedisplay();
}
static void
quad(float x, float y, float z, float *v)
{
int k = 0;
/* color */
v[k++] = x * 0.5 + 0.5;
v[k++] = y * 0.5 + 0.5;
v[k++] = z * 0.5 + 0.5;
/* vert */
v[k++] = x;
v[k++] = y;
v[k++] = z;
/* color */
v[k++] = -x * 0.5 + 0.5;
v[k++] = -y * 0.5 + 0.5;
v[k++] = z * 0.5 + 0.5;
/* vert */
v[k++] = -x;
v[k++] = -y;
v[k++] = z;
/* color */
v[k++] = -x * 0.5 + 0.5;
v[k++] = -y * 0.5 + 0.5;
v[k++] = -z * 0.5 + 0.5;
/* vert */
v[k++] = -x;
v[k++] = -y;
v[k++] = -z;
/* color */
v[k++] = x * 0.5 + 0.5;
v[k++] = y * 0.5 + 0.5;
v[k++] = -z * 0.5 + 0.5;
/* vert */
v[k++] = x;
v[k++] = y;
v[k++] = -z;
}
static void
gen_quads(GLfloat *buf)
{
float *v = buf;
float r = 1.0;
int i;
for (i = 0; i < NUM_QUADS; i++) {
float angle = i / (float) NUM_QUADS * M_PI;
float x = r * cos(angle);
float y = r * sin(angle);
float z = 1.10;
quad(x, y, z, v);
v += 24;
}
if (0) {
float *p = buf;
for (i = 0; i < NUM_QUADS * 4 * 2; i++) {
printf("%d: %f %f %f\n", i, p[0], p[1], p[2]);
p += 3;
}
}
}
static void
Init(void)
{
int bytes = NUM_QUADS * 4 * 2 * 3 * sizeof(float);
GLfloat *f;
#if 1
glGenBuffers(1, &Vbuffer);
glBindBuffer(GL_ARRAY_BUFFER, Vbuffer);
glBufferData(GL_ARRAY_BUFFER_ARB, bytes, NULL, GL_STATIC_DRAW_ARB);
f = (float *) glMapBuffer(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
gen_quads(f);
glUnmapBuffer(GL_ARRAY_BUFFER_ARB);
glColorPointer(3, GL_FLOAT, 6*sizeof(float), (void *) 0);
glVertexPointer(3, GL_FLOAT, 6*sizeof(float), (void *) 12);
#else
f = buf;
gen_quads(f);
glColorPointer(3, GL_FLOAT, 6*sizeof(float), buf);
glVertexPointer(3, GL_FLOAT, 6*sizeof(float), buf + 3);
#endif
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_DEPTH_TEST);
glClearColor(0.5, 0.5, 0.5, 0.0);
}
int
main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowPosition(0, 0);
glutInitWindowSize(600, 600);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
Win = glutCreateWindow(argv[0]);
glutReshapeFunc(Reshape);
glutKeyboardFunc(Key);
glutSpecialFunc(SpecialKey);
glutDisplayFunc(Draw);
if (Anim)
glutIdleFunc(Idle);
Init();
glutMainLoop();
return 0;
}

View File

@ -41,6 +41,7 @@ SOURCES = \
linestrip-stipple-wide.c \
linestrip-stipple.c \
linestrip.c \
long-fixed-func.c \
pgon-mode.c \
point-clip.c \
point-param.c \
@ -138,13 +139,13 @@ UTIL_FILES = readtex.h readtex.c
.SUFFIXES: .c
.c:
$(CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
$(APP_CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
.S.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
##### TARGETS #####
@ -165,19 +166,19 @@ getproclist.h: $(TOP)/src/mesa/glapi/gl_API.xml getprocaddress.c getprocaddress.
texrect: texrect.o readtex.o
$(CC) $(CFLAGS) $(LDFLAGS) texrect.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) texrect.o readtex.o $(LIBS) -o $@
texrect.o: texrect.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
invert: invert.o readtex.o
$(CC) $(CFLAGS) $(LDFLAGS) invert.o readtex.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) invert.o readtex.o $(LIBS) -o $@
invert.o: invert.c readtex.h
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
readtex.o: readtex.c
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
$(APP_CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
readtex.h: $(TOP)/progs/util/readtex.h

View File

@ -0,0 +1,151 @@
/**
* Enable as much fixed-function vertex processing state as possible
* to test fixed-function -> program code generation.
*/
#define GL_GLEXT_PROTOTYPES
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <GL/glut.h>
static void
Reshape(int width, int height)
{
glViewport(0, 0, (GLint)width, (GLint)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
glMatrixMode(GL_MODELVIEW);
}
static void
Draw(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(.8,0,0);
glVertex3f(-0.9, -0.9, -30.0);
glColor3f(0,.9,0);
glVertex3f( 0.9, -0.9, -30.0);
glColor3f(0,0,.7);
glVertex3f( 0.0, 0.9, -30.0);
glEnd();
glFlush();
glutSwapBuffers();
}
static void
Init(void)
{
GLubyte tex[16][16][4];
GLfloat pos[4] = {5, 10, 3, 1.0};
int i, j;
fprintf(stderr, "GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
fprintf(stderr, "GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
fprintf(stderr, "GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
glClearColor(0.3, 0.1, 0.3, 0.0);
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++) {
if ((i+j) & 1) {
tex[i][j][0] = 100;
tex[i][j][1] = 100;
tex[i][j][2] = 100;
tex[i][j][3] = 255;
}
else {
tex[i][j][0] = 200;
tex[i][j][1] = 200;
tex[i][j][2] = 200;
tex[i][j][3] = 255;
}
}
}
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
glFogi(GL_FOG_MODE, GL_LINEAR);
glEnable(GL_FOG);
glPointParameterfv(GL_DISTANCE_ATTENUATION_EXT, pos);
for (i = 0; i < 8; i++) {
GLuint texObj;
glEnable(GL_LIGHT0 + i);
glLightf(GL_LIGHT0 + i, GL_SPOT_EXPONENT, 3.5);
glLightf(GL_LIGHT0 + i, GL_SPOT_CUTOFF, 30.);
glLightf(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, 3.);
glLightf(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, 3.);
glLightf(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, 3.);
glLightfv(GL_LIGHT0 + i, GL_POSITION, pos);
glActiveTexture(GL_TEXTURE0 + i);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_TEXTURE);
glScalef(2.0, 1.0, 3.0);
glGenTextures(1, &texObj);
glBindTexture(GL_TEXTURE_2D, texObj);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
GL_RGBA, GL_UNSIGNED_BYTE, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
glEnable(GL_LIGHTING);
glActiveTexture(GL_TEXTURE0);
glMatrixMode(GL_MODELVIEW);
}
static void
Key(unsigned char key, int x, int y)
{
if (key == 27) {
exit(0);
}
glutPostRedisplay();
}
int
main(int argc, char **argv)
{
GLenum type = GLUT_RGB | GLUT_DOUBLE;
glutInit(&argc, argv);
glutInitWindowPosition(0, 0);
glutInitWindowSize( 250, 250);
glutInitDisplayMode(type);
if (glutCreateWindow("tri-long-fixedfunc") == GL_FALSE) {
exit(1);
}
glutReshapeFunc(Reshape);
glutKeyboardFunc(Key);
glutDisplayFunc(Draw);
Init();
glutMainLoop();
return 0;
}

View File

@ -37,9 +37,36 @@
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
static int leftFirst = GL_TRUE;
static struct { GLenum func; const char *str; } funcs[] =
{
{ GL_LESS, "GL_LESS" },
{ GL_LEQUAL, "GL_LEQUAL" },
{ GL_GREATER, "GL_GREATER" },
{ GL_GEQUAL, "GL_GEQUAL" },
{ GL_EQUAL, "GL_EQUAL" },
{ GL_NOTEQUAL, "GL_NOTEQUAL" },
{ GL_ALWAYS, "GL_ALWAYS" },
{ GL_NEVER, "GL_NEVER" },
};
#define NUM_FUNCS (sizeof(funcs) / sizeof(funcs[0]))
static int curFunc = 0;
static double clearVal = 1.0;
static void usage(void)
{
printf("t - toggle rendering order of triangles\n");
printf("c - toggle Z clear value between 0, 1\n");
printf("f - cycle through depth test functions\n");
}
static void init(void)
{
glEnable(GL_DEPTH_TEST);
@ -70,6 +97,11 @@ static void drawRightTriangle(void)
void display(void)
{
printf("GL_CLEAR_DEPTH = %f GL_DEPTH_FUNC = %s\n",
clearVal, funcs[curFunc].str);
glClearDepth(clearVal);
glDepthFunc(funcs[curFunc].func);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (leftFirst) {
@ -99,6 +131,16 @@ void reshape(int w, int h)
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 'c':
case 'C':
clearVal = 1.0 - clearVal;
glutPostRedisplay();
break;
case 'f':
case 'F':
curFunc = (curFunc + 1) % NUM_FUNCS;
glutPostRedisplay();
break;
case 't':
case 'T':
leftFirst = !leftFirst;
@ -122,10 +164,11 @@ int main(int argc, char** argv)
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (200, 200);
glutCreateWindow (argv[0]);
init();
glutReshapeFunc (reshape);
glutKeyboardFunc (keyboard);
glutDisplayFunc (display);
init();
usage();
glutMainLoop();
return 0;
}

View File

@ -49,7 +49,7 @@ EXTRA_PROGS = \
.SUFFIXES: .c
.c: $(LIB_DEP)
$(CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
$(APP_CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@
##### TARGETS #####
@ -67,44 +67,44 @@ clean:
# special cases
pbinfo: pbinfo.o pbutil.o
$(CC) $(CFLAGS) $(LDFLAGS) pbinfo.o pbutil.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) pbinfo.o pbutil.o $(LIBS) -o $@
pbdemo: pbdemo.o pbutil.o
$(CC) $(CFLAGS) $(LDFLAGS) pbdemo.o pbutil.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) pbdemo.o pbutil.o $(LIBS) -o $@
pbinfo.o: pbinfo.c pbutil.h
$(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbinfo.c
$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbinfo.c
pbdemo.o: pbdemo.c pbutil.h
$(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbdemo.c
$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbdemo.c
pbutil.o: pbutil.c pbutil.h
$(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbutil.c
$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) pbutil.c
glxgears_fbconfig: glxgears_fbconfig.o pbutil.o
$(CC) $(CFLAGS) $(LDFLAGS) glxgears_fbconfig.o pbutil.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) glxgears_fbconfig.o pbutil.o $(LIBS) -o $@
glxgears_fbconfig.o: glxgears_fbconfig.c pbutil.h
$(CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) -c -I. $(CFLAGS) glxgears_fbconfig.c
$(APP_CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) -c -I. $(CFLAGS) glxgears_fbconfig.c
xrotfontdemo: xrotfontdemo.o xuserotfont.o
$(CC) $(CFLAGS) $(LDFLAGS) xrotfontdemo.o xuserotfont.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) $(LDFLAGS) xrotfontdemo.o xuserotfont.o $(LIBS) -o $@
xuserotfont.o: xuserotfont.c xuserotfont.h
$(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) xuserotfont.c
$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) xuserotfont.c
xrotfontdemo.o: xrotfontdemo.c xuserotfont.h
$(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) xrotfontdemo.c
$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) xrotfontdemo.c
corender: corender.o ipc.o
$(CC) $(CFLAGS) corender.o ipc.o $(LIBS) -o $@
$(APP_CC) $(CFLAGS) corender.o ipc.o $(LIBS) -o $@
corender.o: corender.c ipc.h
$(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) corender.c
$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) corender.c
ipc.o: ipc.c ipc.h
$(CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) ipc.c
$(APP_CC) -c -I. -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) ipc.c
yuvrect_client: yuvrect_client.c
$(CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $< $(LDFLAGS) $(LIBS) -l$(GLU_LIB) -o $@
$(APP_CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $< $(LDFLAGS) $(LIBS) -l$(GLU_LIB) -o $@

View File

@ -140,6 +140,29 @@ def createCodeGenerateMethod(env):
env.AddMethod(code_generate, 'CodeGenerate')
def symlink(target, source, env):
target = str(target[0])
source = str(source[0])
if os.path.islink(target) or os.path.exists(target):
os.remove(target)
os.symlink(os.path.basename(source), target)
def install_shared_library(env, source, version = ()):
source = str(source[0])
version = tuple(map(str, version))
target_dir = os.path.join(env.Dir('#.').srcnode().abspath, env['build'], 'lib')
target_name = '.'.join((str(source),) + version)
last = env.InstallAs(os.path.join(target_dir, target_name), source)
while len(version):
version = version[:-1]
target_name = '.'.join((str(source),) + version)
action = SCons.Action.Action(symlink, "$TARGET -> $SOURCE")
last = env.Command(os.path.join(target_dir, target_name), last, action)
def createInstallMethods(env):
env.AddMethod(install_shared_library, 'InstallSharedLibrary')
def generate(env):
"""Common environment generation code"""
@ -290,7 +313,7 @@ def generate(env):
]
if msvc:
# See also:
# - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
# - http://msdn.microsoft.com/en-us/library/19z1t1wy.aspx
# - cl /?
if debug:
cflags += [
@ -302,7 +325,8 @@ def generate(env):
cflags += [
'/Ox', # maximum optimizations
'/Oi', # enable intrinsic functions
'/Os', # favor code space
'/Ot', # favor code speed
#'/fp:fast', # fast floating point
]
if env['profile']:
cflags += [
@ -313,6 +337,11 @@ def generate(env):
'/W3', # warning level
#'/Wp64', # enable 64 bit porting warnings
]
if env['machine'] == 'x86':
cflags += [
#'/QIfist', # Suppress _ftol
#'/arch:SSE2', # use the SSE2 instructions
]
if platform == 'windows':
cflags += [
# TODO
@ -420,6 +449,7 @@ def generate(env):
# Custom builders and methods
createConvenienceLibBuilder(env)
createCodeGenerateMethod(env)
createInstallMethods(env)
# for debugging
#print env.Dump()

View File

@ -64,6 +64,12 @@
#include "egllog.h"
#include "eglsurface.h"
#include <GL/gl.h>
typedef void (*glGetIntegerv_t)(GLenum, GLint *);
typedef void (*glBindTexture_t)(GLenum, GLuint);
typedef void (*glCopyTexImage2D_t)(GLenum, GLint, GLenum, GLint, GLint,
GLint, GLint, GLint);
#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
@ -99,6 +105,8 @@ struct xdri_egl_context
_EGLContext Base; /**< base class */
__DRIcontext driContext;
GLint bound_tex_object;
};
@ -147,6 +155,11 @@ lookup_context(EGLContext c)
return (struct xdri_egl_context *) context;
}
static struct xdri_egl_context *
current_context(void)
{
return (struct xdri_egl_context *) _eglGetCurrentContext();
}
/** Map EGLConfig handle to xdri_egl_config object */
static struct xdri_egl_config *
@ -210,7 +223,8 @@ create_configs(_EGLDisplay *disp, __GLXdisplayPrivate *glx_priv)
SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
/* XXX only window rendering allowed ATM */
SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE,
(EGL_WINDOW_BIT | EGL_PBUFFER_BIT));
/* XXX possibly other things to init... */
@ -651,6 +665,35 @@ xdri_eglInitialize(_EGLDriver *drv, EGLDisplay dpy,
}
/*
* Do some clean-up that normally occurs in XCloseDisplay().
* We do this here because we're about to unload a dynamic library
* that has added some per-display extension data and callbacks.
* If we don't do this here we'll crash in XCloseDisplay() because it'll
* try to call functions that went away when the driver library was unloaded.
*/
static void
FreeDisplayExt(Display *dpy)
{
_XExtension *ext, *next;
for (ext = dpy->ext_procs; ext; ext = next) {
next = ext->next;
if (ext->close_display) {
ext->close_display(dpy, &ext->codes);
ext->close_display = NULL;
}
if (ext->name)
Xfree(ext->name);
Xfree(ext);
}
dpy->ext_procs = NULL;
_XFreeExtData (dpy->ext_data);
dpy->ext_data = NULL;
}
/**
* Called via eglTerminate(), drv->API.Terminate().
*/
@ -658,11 +701,16 @@ static EGLBoolean
xdri_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
{
struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
_EGLDisplay *disp = _eglLookupDisplay(dpy);
_eglLog(_EGL_DEBUG, "XDRI: eglTerminate");
_eglLog(_EGL_DEBUG, "XDRI: Closing %s", xdri_drv->dri_driver_name);
FreeDisplayExt(disp->Xdpy);
#if 0
/* this causes a segfault for some reason */
dlclose(xdri_drv->dri_driver_handle);
#endif
xdri_drv->dri_driver_handle = NULL;
@ -820,6 +868,86 @@ xdri_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
}
/**
* Called via eglCreatePbufferSurface(), drv->API.CreatePbufferSurface().
*/
static EGLSurface
xdri_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
const EGLint *attrib_list)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
struct xdri_egl_surface *xdri_surf;
struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config);
int scrn = DefaultScreen(disp->Xdpy);
Window window;
xdri_surf = CALLOC_STRUCT(xdri_egl_surface);
if (!xdri_surf)
return EGL_NO_SURFACE;
if (!_eglInitSurface(drv, dpy, &xdri_surf->Base, EGL_PBUFFER_BIT,
config, attrib_list)) {
free(xdri_surf);
return EGL_FALSE;
}
/* Create a dummy X window */
{
Window root = RootWindow(disp->Xdpy, scrn);
XSetWindowAttributes attr;
XVisualInfo *visInfo, visTemplate;
unsigned mask;
int nvis;
visTemplate.visualid = xdri_config->mode->visualID;
visInfo = XGetVisualInfo(disp->Xdpy, VisualIDMask, &visTemplate, &nvis);
if (!visInfo) {
return EGL_NO_SURFACE;
}
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap(disp->Xdpy, root,
visInfo->visual, AllocNone);
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
window = XCreateWindow(disp->Xdpy, root, 0, 0,
xdri_surf->Base.Width, xdri_surf->Base.Height,
0, visInfo->depth, InputOutput,
visInfo->visual, mask, &attr);
/*XMapWindow(disp->Xdpy, window);*/
XFree(visInfo);
/* set hints and properties */
/*
sizehints.width = xdri_surf->Base.Width;
sizehints.height = xdri_surf->Base.Height;
sizehints.flags = USPosition;
XSetNormalHints(disp->Xdpy, window, &sizehints);
*/
}
if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) {
free(xdri_surf);
return EGL_FALSE;
}
xdri_surf->driDrawable = window;
_eglSaveSurface(&xdri_surf->Base);
_eglLog(_EGL_DEBUG,
"XDRI: CreatePbufferSurface handle %d hDrawable %d",
_eglGetSurfaceHandle(&xdri_surf->Base),
(int) xdri_surf->hDrawable);
return _eglGetSurfaceHandle(&xdri_surf->Base);
}
static EGLBoolean
xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
{
@ -844,6 +972,137 @@ xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
}
static EGLBoolean
xdri_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
EGLint buffer)
{
typedef int (*bind_teximage)(__DRInativeDisplay *dpy,
__DRIid surface, __DRIscreen *psc,
int buffer, int target, int format,
int level, int mipmap);
bind_teximage egl_dri_bind_teximage;
_EGLDisplay *disp = _eglLookupDisplay(dpy);
struct xdri_egl_context *xdri_ctx = current_context();
struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
__DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0;
__GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
__DRIscreen *psc = &scrnConf->driScreen;
/* this call just does error checking */
if (!_eglBindTexImage(drv, dpy, surface, buffer)) {
return EGL_FALSE;
}
egl_dri_bind_teximage =
(bind_teximage) dlsym(NULL, "egl_dri_bind_teximage");
if (egl_dri_bind_teximage) {
return egl_dri_bind_teximage(disp->Xdpy, dri_surf, psc,
buffer,
xdri_surf->Base.TextureTarget,
xdri_surf->Base.TextureFormat,
xdri_surf->Base.MipmapLevel,
xdri_surf->Base.MipmapTexture);
}
else {
/* fallback path based on glCopyTexImage() */
/* Get/save currently bound 2D texobj name */
glGetIntegerv_t glGetIntegerv_func =
(glGetIntegerv_t) dlsym(NULL, "glGetIntegerv");
GLint curTexObj = 0;
if (glGetIntegerv_func) {
(*glGetIntegerv_func)(GL_TEXTURE_BINDING_2D, &curTexObj);
}
xdri_ctx->bound_tex_object = curTexObj;
}
return EGL_FALSE;
}
static EGLBoolean
xdri_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
EGLint buffer)
{
typedef int (*release_teximage)(__DRInativeDisplay *dpy,
__DRIid surface, __DRIscreen *psc,
int buffer, int target, int format,
int level, int mipmap);
release_teximage egl_dri_release_teximage;
_EGLDisplay *disp = _eglLookupDisplay(dpy);
struct xdri_egl_context *xdri_ctx = current_context();
struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
__DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0;
__GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
__DRIscreen *psc = &scrnConf->driScreen;
/* this call just does error checking */
if (!_eglReleaseTexImage(drv, dpy, surface, buffer)) {
return EGL_FALSE;
}
egl_dri_release_teximage =
(release_teximage) dlsym(NULL, "egl_dri_release_teximage");
if (egl_dri_release_teximage) {
return egl_dri_release_teximage(disp->Xdpy, dri_surf, psc,
buffer,
xdri_surf->Base.TextureTarget,
xdri_surf->Base.TextureFormat,
xdri_surf->Base.MipmapLevel,
xdri_surf->Base.MipmapTexture);
}
else {
/* fallback path based on glCopyTexImage() */
glGetIntegerv_t glGetIntegerv_func =
(glGetIntegerv_t) dlsym(NULL, "glGetIntegerv");
glBindTexture_t glBindTexture_func =
(glBindTexture_t) dlsym(NULL, "glBindTexture");
glCopyTexImage2D_t glCopyTexImage2D_func =
(glCopyTexImage2D_t) dlsym(NULL, "glCopyTexImage2D");
GLint curTexObj;
GLenum intFormat;
GLint level, width, height;
if (xdri_surf->Base.TextureFormat == EGL_TEXTURE_RGBA)
intFormat = GL_RGBA;
else
intFormat = GL_RGB;
level = xdri_surf->Base.MipmapLevel;
width = xdri_surf->Base.Width >> level;
height = xdri_surf->Base.Height >> level;
if (width > 0 && height > 0 &&
glGetIntegerv_func && glBindTexture_func && glCopyTexImage2D_func) {
glGetIntegerv_func(GL_TEXTURE_BINDING_2D, &curTexObj);
/* restore texobj from time of eglBindTexImage() call */
if (curTexObj != xdri_ctx->bound_tex_object)
glBindTexture_func(GL_TEXTURE_2D, xdri_ctx->bound_tex_object);
/* copy pbuffer image to texture */
glCopyTexImage2D_func(GL_TEXTURE_2D,
level,
intFormat,
0, 0, width, height, 0);
/* restore current texture */
if (curTexObj != xdri_ctx->bound_tex_object)
glBindTexture_func(GL_TEXTURE_2D, curTexObj);
}
xdri_ctx->bound_tex_object = -1;
}
return EGL_FALSE;
}
static EGLBoolean
xdri_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
{
@ -897,7 +1156,10 @@ _eglMain(_EGLDisplay *disp, const char *args)
xdri_drv->Base.API.CreateContext = xdri_eglCreateContext;
xdri_drv->Base.API.MakeCurrent = xdri_eglMakeCurrent;
xdri_drv->Base.API.CreateWindowSurface = xdri_eglCreateWindowSurface;
xdri_drv->Base.API.CreatePbufferSurface = xdri_eglCreatePbufferSurface;
xdri_drv->Base.API.DestroySurface = xdri_eglDestroySurface;
xdri_drv->Base.API.BindTexImage = xdri_eglBindTexImage;
xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage;
xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers;
xdri_drv->Base.ClientAPIsMask = (EGL_OPENGL_BIT |

View File

@ -61,6 +61,12 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
return EGL_FALSE;
}
if ((GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) & type) == 0) {
/* The config can't be used to create a surface of this type */
_eglError(EGL_BAD_CONFIG, func);
return EGL_FALSE;
}
/*
* Parse attribute list. Different kinds of surfaces support different
* attributes.
@ -277,12 +283,7 @@ _eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
/* Basically just do error checking here. Drivers have to do the
* actual buffer swap.
*/
_EGLContext *context = _eglGetCurrentContext();
_EGLSurface *surface = _eglLookupSurface(draw);
if (context && context->DrawSurface != surface) {
_eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
return EGL_FALSE;
}
if (surface == NULL) {
_eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
return EGL_FALSE;
@ -484,7 +485,8 @@ _eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
* Default fallback routine - drivers might override this.
*/
EGLBoolean
_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attribute, EGLint value)
_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
EGLint attribute, EGLint value)
{
_EGLSurface *surface = _eglLookupSurface(surf);
@ -506,18 +508,67 @@ _eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attri
EGLBoolean
_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer)
_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
EGLint buffer)
{
/* XXX unfinished */
return EGL_FALSE;
/* Just do basic error checking and return success/fail.
* Drivers must implement the real stuff.
*/
_EGLSurface *surface = _eglLookupSurface(surf);
if (!surface || surface->Type != EGL_PBUFFER_BIT) {
_eglError(EGL_BAD_SURFACE, "eglBindTexImage");
return EGL_FALSE;
}
if (surface->TextureFormat == EGL_NO_TEXTURE) {
_eglError(EGL_BAD_MATCH, "eglBindTexImage");
return EGL_FALSE;
}
if (buffer != EGL_BACK_BUFFER) {
_eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
return EGL_FALSE;
}
surface->BoundToTexture = EGL_TRUE;
return EGL_TRUE;
}
EGLBoolean
_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer)
_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
EGLint buffer)
{
/* XXX unfinished */
return EGL_FALSE;
/* Just do basic error checking and return success/fail.
* Drivers must implement the real stuff.
*/
_EGLSurface *surface = _eglLookupSurface(surf);
if (!surface || surface->Type != EGL_PBUFFER_BIT) {
_eglError(EGL_BAD_SURFACE, "eglBindTexImage");
return EGL_FALSE;
}
if (surface->TextureFormat == EGL_NO_TEXTURE) {
_eglError(EGL_BAD_MATCH, "eglBindTexImage");
return EGL_FALSE;
}
if (buffer != EGL_BACK_BUFFER) {
_eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
return EGL_FALSE;
}
if (!surface->BoundToTexture) {
_eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
return EGL_FALSE;
}
surface->BoundToTexture = EGL_FALSE;
return EGL_TRUE;
}

View File

@ -16,6 +16,7 @@ struct _egl_surface
/* May need reference counting here */
EGLBoolean IsBound;
EGLBoolean DeletePending;
EGLBoolean BoundToTexture;
EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */
EGLint Width, Height;

View File

@ -63,7 +63,8 @@ struct vcache_frontend {
unsigned opt;
};
static void vcache_flush( struct vcache_frontend *vcache )
static INLINE void
vcache_flush( struct vcache_frontend *vcache )
{
if (vcache->middle_prim != vcache->output_prim) {
vcache->middle_prim = vcache->output_prim;
@ -86,7 +87,8 @@ static void vcache_flush( struct vcache_frontend *vcache )
vcache->draw_count = 0;
}
static void vcache_check_flush( struct vcache_frontend *vcache )
static INLINE void
vcache_check_flush( struct vcache_frontend *vcache )
{
if ( vcache->draw_count + 6 >= DRAW_MAX ||
vcache->fetch_count + 4 >= FETCH_MAX )
@ -96,9 +98,10 @@ static void vcache_check_flush( struct vcache_frontend *vcache )
}
static INLINE void vcache_elt( struct vcache_frontend *vcache,
unsigned felt,
ushort flags )
static INLINE void
vcache_elt( struct vcache_frontend *vcache,
unsigned felt,
ushort flags )
{
unsigned idx = felt % CACHE_MAX;
@ -115,10 +118,11 @@ static INLINE void vcache_elt( struct vcache_frontend *vcache,
static void vcache_triangle( struct vcache_frontend *vcache,
unsigned i0,
unsigned i1,
unsigned i2 )
static INLINE void
vcache_triangle( struct vcache_frontend *vcache,
unsigned i0,
unsigned i1,
unsigned i2 )
{
vcache_elt(vcache, i0, 0);
vcache_elt(vcache, i1, 0);
@ -127,11 +131,12 @@ static void vcache_triangle( struct vcache_frontend *vcache,
}
static void vcache_triangle_flags( struct vcache_frontend *vcache,
ushort flags,
unsigned i0,
unsigned i1,
unsigned i2 )
static INLINE void
vcache_triangle_flags( struct vcache_frontend *vcache,
ushort flags,
unsigned i0,
unsigned i1,
unsigned i2 )
{
vcache_elt(vcache, i0, flags);
vcache_elt(vcache, i1, 0);
@ -139,9 +144,10 @@ static void vcache_triangle_flags( struct vcache_frontend *vcache,
vcache_check_flush(vcache);
}
static void vcache_line( struct vcache_frontend *vcache,
unsigned i0,
unsigned i1 )
static INLINE void
vcache_line( struct vcache_frontend *vcache,
unsigned i0,
unsigned i1 )
{
vcache_elt(vcache, i0, 0);
vcache_elt(vcache, i1, 0);
@ -149,10 +155,11 @@ static void vcache_line( struct vcache_frontend *vcache,
}
static void vcache_line_flags( struct vcache_frontend *vcache,
ushort flags,
unsigned i0,
unsigned i1 )
static INLINE void
vcache_line_flags( struct vcache_frontend *vcache,
ushort flags,
unsigned i0,
unsigned i1 )
{
vcache_elt(vcache, i0, flags);
vcache_elt(vcache, i1, 0);
@ -160,28 +167,31 @@ static void vcache_line_flags( struct vcache_frontend *vcache,
}
static void vcache_point( struct vcache_frontend *vcache,
unsigned i0 )
static INLINE void
vcache_point( struct vcache_frontend *vcache,
unsigned i0 )
{
vcache_elt(vcache, i0, 0);
vcache_check_flush(vcache);
}
static void vcache_quad( struct vcache_frontend *vcache,
unsigned i0,
unsigned i1,
unsigned i2,
unsigned i3 )
static INLINE void
vcache_quad( struct vcache_frontend *vcache,
unsigned i0,
unsigned i1,
unsigned i2,
unsigned i3 )
{
vcache_triangle( vcache, i0, i1, i3 );
vcache_triangle( vcache, i1, i2, i3 );
}
static void vcache_ef_quad( struct vcache_frontend *vcache,
unsigned i0,
unsigned i1,
unsigned i2,
unsigned i3 )
static INLINE void
vcache_ef_quad( struct vcache_frontend *vcache,
unsigned i0,
unsigned i1,
unsigned i2,
unsigned i3 )
{
vcache_triangle_flags( vcache,
( DRAW_PIPE_RESET_STIPPLE |
@ -213,10 +223,11 @@ static void vcache_ef_quad( struct vcache_frontend *vcache,
#define FUNC vcache_run
#include "draw_pt_vcache_tmp.h"
static void rebase_uint_elts( const unsigned *src,
unsigned count,
int delta,
ushort *dest )
static INLINE void
rebase_uint_elts( const unsigned *src,
unsigned count,
int delta,
ushort *dest )
{
unsigned i;
@ -224,9 +235,10 @@ static void rebase_uint_elts( const unsigned *src,
dest[i] = (ushort)(src[i] + delta);
}
static void rebase_ushort_elts( const ushort *src,
unsigned count,
int delta,
static INLINE void
rebase_ushort_elts( const ushort *src,
unsigned count,
int delta,
ushort *dest )
{
unsigned i;
@ -235,10 +247,11 @@ static void rebase_ushort_elts( const ushort *src,
dest[i] = (ushort)(src[i] + delta);
}
static void rebase_ubyte_elts( const ubyte *src,
unsigned count,
int delta,
ushort *dest )
static INLINE void
rebase_ubyte_elts( const ubyte *src,
unsigned count,
int delta,
ushort *dest )
{
unsigned i;
@ -248,9 +261,10 @@ static void rebase_ubyte_elts( const ubyte *src,
static void translate_uint_elts( const unsigned *src,
unsigned count,
ushort *dest )
static INLINE void
translate_uint_elts( const unsigned *src,
unsigned count,
ushort *dest )
{
unsigned i;
@ -258,9 +272,10 @@ static void translate_uint_elts( const unsigned *src,
dest[i] = (ushort)(src[i]);
}
static void translate_ushort_elts( const ushort *src,
unsigned count,
ushort *dest )
static INLINE void
translate_ushort_elts( const ushort *src,
unsigned count,
ushort *dest )
{
unsigned i;
@ -268,9 +283,10 @@ static void translate_ushort_elts( const ushort *src,
dest[i] = (ushort)(src[i]);
}
static void translate_ubyte_elts( const ubyte *src,
unsigned count,
ushort *dest )
static INLINE void
translate_ubyte_elts( const ubyte *src,
unsigned count,
ushort *dest )
{
unsigned i;
@ -282,7 +298,8 @@ static void translate_ubyte_elts( const ubyte *src,
#if 0
static enum pipe_format format_from_get_elt( pt_elt_func get_elt )
static INLINE enum pipe_format
format_from_get_elt( pt_elt_func get_elt )
{
switch (draw->pt.user.eltSize) {
case 1: return PIPE_FORMAT_R8_UNORM;
@ -293,10 +310,11 @@ static enum pipe_format format_from_get_elt( pt_elt_func get_elt )
}
#endif
static void vcache_check_run( struct draw_pt_front_end *frontend,
pt_elt_func get_elt,
const void *elts,
unsigned draw_count )
static INLINE void
vcache_check_run( struct draw_pt_front_end *frontend,
pt_elt_func get_elt,
const void *elts,
unsigned draw_count )
{
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
struct draw_context *draw = vcache->draw;
@ -416,10 +434,11 @@ static void vcache_check_run( struct draw_pt_front_end *frontend,
static void vcache_prepare( struct draw_pt_front_end *frontend,
unsigned prim,
struct draw_pt_middle_end *middle,
unsigned opt )
static void
vcache_prepare( struct draw_pt_front_end *frontend,
unsigned prim,
struct draw_pt_middle_end *middle,
unsigned opt )
{
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
@ -448,14 +467,16 @@ static void vcache_prepare( struct draw_pt_front_end *frontend,
static void vcache_finish( struct draw_pt_front_end *frontend )
static void
vcache_finish( struct draw_pt_front_end *frontend )
{
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
vcache->middle->finish( vcache->middle );
vcache->middle = NULL;
}
static void vcache_destroy( struct draw_pt_front_end *frontend )
static void
vcache_destroy( struct draw_pt_front_end *frontend )
{
FREE(frontend);
}

View File

@ -32,6 +32,7 @@
#include "util/u_memory.h"
#include "util/u_math.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_debug.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_util.h"
#include "tgsi/tgsi_exec.h"
@ -119,21 +120,26 @@ static struct x86_reg get_reg_ptr(struct aos_compilation *cp,
switch (file) {
case TGSI_FILE_INPUT:
assert(idx < MAX_INPUTS);
return x86_make_disp(ptr, Offset(struct aos_machine, input[idx]));
case TGSI_FILE_OUTPUT:
return x86_make_disp(ptr, Offset(struct aos_machine, output[idx]));
case TGSI_FILE_TEMPORARY:
assert(idx < MAX_TEMPS);
return x86_make_disp(ptr, Offset(struct aos_machine, temp[idx]));
case AOS_FILE_INTERNAL:
assert(idx < MAX_INTERNALS);
return x86_make_disp(ptr, Offset(struct aos_machine, internal[idx]));
case TGSI_FILE_IMMEDIATE:
assert(idx < MAX_IMMEDIATES); /* just a sanity check */
return x86_make_disp(aos_get_x86(cp, 0, X86_IMMEDIATES), idx * 4 * sizeof(float));
case TGSI_FILE_CONSTANT:
assert(idx < MAX_CONSTANTS); /* just a sanity check */
return x86_make_disp(aos_get_x86(cp, 1, X86_CONSTANTS), idx * 4 * sizeof(float));
default:
@ -2108,6 +2114,11 @@ static void PIPE_CDECL vaos_run_linear( struct draw_vs_varient *varient,
start,
count,
output_buffer );
/* Sanity spot checks to make sure we didn't trash our constants */
assert(machine->internal[IMM_ONES][0] == 1.0f);
assert(machine->internal[IMM_IDENTITY][0] == 0.0f);
assert(machine->internal[IMM_NEGS][0] == -1.0f);
}

View File

@ -51,11 +51,11 @@ struct x86_function;
#define W 3
#define MAX_INPUTS PIPE_MAX_ATTRIBS
#define MAX_OUTPUTS PIPE_MAX_ATTRIBS
#define MAX_TEMPS PIPE_MAX_ATTRIBS /* say */
#define MAX_CONSTANTS PIPE_MAX_ATTRIBS /* say */
#define MAX_IMMEDIATES PIPE_MAX_ATTRIBS /* say */
#define MAX_INTERNALS 8
#define MAX_OUTPUTS PIPE_MAX_SHADER_OUTPUTS
#define MAX_TEMPS TGSI_EXEC_NUM_TEMPS
#define MAX_CONSTANTS 1024 /** only used for sanity checking */
#define MAX_IMMEDIATES 1024 /** only used for sanity checking */
#define MAX_INTERNALS 8 /** see IMM_x values below */
#define AOS_FILE_INTERNAL TGSI_FILE_COUNT

View File

@ -55,9 +55,13 @@ static void emit_load_R32G32B32( struct aos_compilation *cp,
struct x86_reg src_ptr )
{
sse_movss(cp->func, data, x86_make_disp(src_ptr, 8));
/* data = z ? ? ? */
sse_shufps(cp->func, data, aos_get_internal_xmm( cp, IMM_IDENTITY ), SHUF(X,Y,Z,W) );
/* data = z ? 0 1 */
sse_shufps(cp->func, data, data, SHUF(Y,Z,X,W) );
/* data = ? 0 z 1 */
sse_movlps(cp->func, data, src_ptr);
/* data = x y z 1 */
}
static void emit_load_R32G32( struct aos_compilation *cp,

View File

@ -69,7 +69,7 @@
struct fenced_buffer_list
{
_glthread_Mutex mutex;
pipe_mutex mutex;
struct pipe_winsys *winsys;
@ -240,7 +240,7 @@ fenced_buffer_destroy(struct pb_buffer *buf)
struct fenced_buffer *fenced_buf = fenced_buffer(buf);
struct fenced_buffer_list *fenced_list = fenced_buf->list;
_glthread_LOCK_MUTEX(fenced_list->mutex);
pipe_mutex_lock(fenced_list->mutex);
assert(fenced_buf->base.base.refcount == 0);
if (fenced_buf->fence) {
struct pipe_winsys *winsys = fenced_list->winsys;
@ -263,7 +263,7 @@ fenced_buffer_destroy(struct pb_buffer *buf)
else {
_fenced_buffer_destroy(fenced_buf);
}
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
pipe_mutex_unlock(fenced_list->mutex);
}
@ -396,7 +396,7 @@ buffer_fence(struct pb_buffer *buf,
return;
}
_glthread_LOCK_MUTEX(fenced_list->mutex);
pipe_mutex_lock(fenced_list->mutex);
if (fenced_buf->fence)
_fenced_buffer_remove(fenced_list, fenced_buf);
if (fence) {
@ -404,7 +404,7 @@ buffer_fence(struct pb_buffer *buf,
fenced_buf->flags |= flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE;
_fenced_buffer_add(fenced_buf);
}
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
pipe_mutex_unlock(fenced_list->mutex);
}
@ -423,7 +423,7 @@ fenced_buffer_list_create(struct pipe_winsys *winsys)
fenced_list->numDelayed = 0;
_glthread_INIT_MUTEX(fenced_list->mutex);
pipe_mutex_init(fenced_list->mutex);
return fenced_list;
}
@ -433,28 +433,28 @@ void
fenced_buffer_list_check_free(struct fenced_buffer_list *fenced_list,
int wait)
{
_glthread_LOCK_MUTEX(fenced_list->mutex);
pipe_mutex_lock(fenced_list->mutex);
_fenced_buffer_list_check_free(fenced_list, wait);
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
pipe_mutex_unlock(fenced_list->mutex);
}
void
fenced_buffer_list_destroy(struct fenced_buffer_list *fenced_list)
{
_glthread_LOCK_MUTEX(fenced_list->mutex);
pipe_mutex_lock(fenced_list->mutex);
/* Wait on outstanding fences */
while (fenced_list->numDelayed) {
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
pipe_mutex_unlock(fenced_list->mutex);
#if defined(PIPE_OS_LINUX)
sched_yield();
#endif
_fenced_buffer_list_check_free(fenced_list, 1);
_glthread_LOCK_MUTEX(fenced_list->mutex);
pipe_mutex_lock(fenced_list->mutex);
}
_glthread_UNLOCK_MUTEX(fenced_list->mutex);
pipe_mutex_unlock(fenced_list->mutex);
FREE(fenced_list);
}

View File

@ -79,7 +79,7 @@ struct pb_cache_manager
struct pb_manager *provider;
unsigned usecs;
_glthread_Mutex mutex;
pipe_mutex mutex;
struct list_head delayed;
size_t numDelayed;
@ -153,7 +153,7 @@ pb_cache_buffer_destroy(struct pb_buffer *_buf)
struct pb_cache_buffer *buf = pb_cache_buffer(_buf);
struct pb_cache_manager *mgr = buf->mgr;
_glthread_LOCK_MUTEX(mgr->mutex);
pipe_mutex_lock(mgr->mutex);
assert(buf->base.base.refcount == 0);
_pb_cache_buffer_list_check_free(mgr);
@ -162,7 +162,7 @@ pb_cache_buffer_destroy(struct pb_buffer *_buf)
util_time_add(&buf->start, mgr->usecs, &buf->end);
LIST_ADDTAIL(&buf->head, &mgr->delayed);
++mgr->numDelayed;
_glthread_UNLOCK_MUTEX(mgr->mutex);
pipe_mutex_unlock(mgr->mutex);
}
@ -235,7 +235,7 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr,
struct list_head *curr, *next;
struct util_time now;
_glthread_LOCK_MUTEX(mgr->mutex);
pipe_mutex_lock(mgr->mutex);
buf = NULL;
curr = mgr->delayed.next;
@ -249,27 +249,35 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr,
buf = curr_buf;
else if(util_time_timeout(&curr_buf->start, &curr_buf->end, &now))
_pb_cache_buffer_destroy(curr_buf);
else
/* This buffer (and all hereafter) are still hot in cache */
break;
curr = next;
next = curr->next;
}
/* keep searching in the hot buffers */
while(!buf && curr != &mgr->delayed) {
curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
if(pb_cache_is_buffer_compat(curr_buf, size, desc))
buf = curr_buf;
curr = next;
next = curr->next;
if(!buf) {
while(curr != &mgr->delayed) {
curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
if(pb_cache_is_buffer_compat(curr_buf, size, desc)) {
buf = curr_buf;
break;
}
/* no need to check the timeout here */
curr = next;
next = curr->next;
}
}
if(buf) {
LIST_DEL(&buf->head);
_glthread_UNLOCK_MUTEX(mgr->mutex);
pipe_mutex_unlock(mgr->mutex);
++buf->base.base.refcount;
return &buf->base;
}
_glthread_UNLOCK_MUTEX(mgr->mutex);
pipe_mutex_unlock(mgr->mutex);
buf = CALLOC_STRUCT(pb_cache_buffer);
if(!buf)
@ -305,7 +313,7 @@ pb_cache_flush(struct pb_manager *_mgr)
struct list_head *curr, *next;
struct pb_cache_buffer *buf;
_glthread_LOCK_MUTEX(mgr->mutex);
pipe_mutex_lock(mgr->mutex);
curr = mgr->delayed.next;
next = curr->next;
while(curr != &mgr->delayed) {
@ -314,7 +322,7 @@ pb_cache_flush(struct pb_manager *_mgr)
curr = next;
next = curr->next;
}
_glthread_UNLOCK_MUTEX(mgr->mutex);
pipe_mutex_unlock(mgr->mutex);
}
@ -345,7 +353,7 @@ pb_cache_manager_create(struct pb_manager *provider,
mgr->usecs = usecs;
LIST_INITHEAD(&mgr->delayed);
mgr->numDelayed = 0;
_glthread_INIT_MUTEX(mgr->mutex);
pipe_mutex_init(mgr->mutex);
return &mgr->base;
}

View File

@ -129,7 +129,7 @@ check_random_pattern(const uint8_t *dst, size_t size,
for(i = 0; i < size; ++i) {
if(*dst++ != random_pattern[i % sizeof(random_pattern)]) {
*min_ofs = MIN2(*min_ofs, i);
*max_ofs = MIN2(*max_ofs, i);
*max_ofs = MAX2(*max_ofs, i);
result = FALSE;
}
}
@ -138,12 +138,30 @@ check_random_pattern(const uint8_t *dst, size_t size,
static void
pb_debug_buffer_destroy(struct pb_buffer *_buf)
pb_debug_buffer_fill(struct pb_debug_buffer *buf)
{
struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
uint8_t *map;
assert(!buf->base.base.refcount);
map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
assert(map);
if(map) {
fill_random_pattern(map, buf->underflow_size);
fill_random_pattern(map + buf->underflow_size + buf->base.base.size,
buf->overflow_size);
pb_unmap(buf->buffer);
}
}
/**
* Check for under/over flows.
*
* Should be called with the buffer unmaped.
*/
static void
pb_debug_buffer_check(struct pb_debug_buffer *buf)
{
uint8_t *map;
map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_READ);
assert(map);
@ -154,24 +172,45 @@ pb_debug_buffer_destroy(struct pb_buffer *_buf)
underflow = !check_random_pattern(map, buf->underflow_size,
&min_ofs, &max_ofs);
if(underflow) {
debug_printf("buffer underflow (%u of %u bytes) detected\n",
buf->underflow_size - min_ofs,
buf->underflow_size);
debug_printf("buffer underflow (offset -%u%s to -%u bytes) detected\n",
buf->underflow_size - min_ofs,
min_ofs == 0 ? "+" : "",
buf->underflow_size - max_ofs);
}
overflow = !check_random_pattern(map + buf->underflow_size + buf->base.base.size,
buf->overflow_size,
&min_ofs, &max_ofs);
if(overflow) {
debug_printf("buffer overflow (%u of %u bytes) detected\n",
debug_printf("buffer overflow (size %u plus offset %u to %u%s bytes) detected\n",
buf->base.base.size,
min_ofs,
max_ofs,
buf->overflow_size);
max_ofs == buf->overflow_size - 1 ? "+" : "");
}
debug_assert(!underflow && !overflow);
/* re-fill if not aborted */
if(underflow)
fill_random_pattern(map, buf->underflow_size);
if(overflow)
fill_random_pattern(map + buf->underflow_size + buf->base.base.size,
buf->overflow_size);
pb_unmap(buf->buffer);
}
}
static void
pb_debug_buffer_destroy(struct pb_buffer *_buf)
{
struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
assert(!buf->base.base.refcount);
pb_debug_buffer_check(buf);
pb_reference(&buf->buffer, NULL);
FREE(buf);
@ -183,9 +222,14 @@ pb_debug_buffer_map(struct pb_buffer *_buf,
unsigned flags)
{
struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
void *map = pb_map(buf->buffer, flags);
void *map;
pb_debug_buffer_check(buf);
map = pb_map(buf->buffer, flags);
if(!map)
return NULL;
return (uint8_t *)map + buf->underflow_size;
}
@ -195,6 +239,8 @@ pb_debug_buffer_unmap(struct pb_buffer *_buf)
{
struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
pb_unmap(buf->buffer);
pb_debug_buffer_check(buf);
}
@ -227,7 +273,6 @@ pb_debug_manager_create_buffer(struct pb_manager *_mgr,
struct pb_debug_buffer *buf;
struct pb_desc real_desc;
size_t real_size;
uint8_t *map;
buf = CALLOC_STRUCT(pb_debug_buffer);
if(!buf)
@ -262,13 +307,7 @@ pb_debug_manager_create_buffer(struct pb_manager *_mgr,
buf->underflow_size = mgr->band_size;
buf->overflow_size = buf->buffer->base.size - buf->underflow_size - size;
map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
assert(map);
if(map) {
fill_random_pattern(map, buf->underflow_size);
fill_random_pattern(map + buf->underflow_size + size, buf->overflow_size);
pb_unmap(buf->buffer);
}
pb_debug_buffer_fill(buf);
return &buf->base;
}

View File

@ -53,7 +53,7 @@ struct mm_pb_manager
{
struct pb_manager base;
_glthread_Mutex mutex;
pipe_mutex mutex;
size_t size;
struct mem_block *heap;
@ -99,10 +99,10 @@ mm_buffer_destroy(struct pb_buffer *buf)
assert(buf->base.refcount == 0);
_glthread_LOCK_MUTEX(mm->mutex);
pipe_mutex_lock(mm->mutex);
mmFreeMem(mm_buf->block);
FREE(buf);
_glthread_UNLOCK_MUTEX(mm->mutex);
pipe_mutex_unlock(mm->mutex);
}
@ -158,11 +158,11 @@ mm_bufmgr_create_buffer(struct pb_manager *mgr,
if(desc->alignment % (1 << mm->align2))
return NULL;
_glthread_LOCK_MUTEX(mm->mutex);
pipe_mutex_lock(mm->mutex);
mm_buf = CALLOC_STRUCT(mm_buffer);
if (!mm_buf) {
_glthread_UNLOCK_MUTEX(mm->mutex);
pipe_mutex_unlock(mm->mutex);
return NULL;
}
@ -185,7 +185,7 @@ mm_bufmgr_create_buffer(struct pb_manager *mgr,
mm_buf->block = mmAllocMem(mm->heap, size, mm->align2, 0);
if(!mm_buf->block) {
FREE(mm_buf);
_glthread_UNLOCK_MUTEX(mm->mutex);
pipe_mutex_unlock(mm->mutex);
return NULL;
}
}
@ -194,7 +194,7 @@ mm_bufmgr_create_buffer(struct pb_manager *mgr,
assert(0 <= (unsigned)mm_buf->block->ofs && (unsigned)mm_buf->block->ofs < mm->size);
assert(size <= (unsigned)mm_buf->block->size && (unsigned)mm_buf->block->ofs + (unsigned)mm_buf->block->size <= mm->size);
_glthread_UNLOCK_MUTEX(mm->mutex);
pipe_mutex_unlock(mm->mutex);
return SUPER(mm_buf);
}
@ -204,14 +204,14 @@ mm_bufmgr_destroy(struct pb_manager *mgr)
{
struct mm_pb_manager *mm = mm_pb_manager(mgr);
_glthread_LOCK_MUTEX(mm->mutex);
pipe_mutex_lock(mm->mutex);
mmDestroy(mm->heap);
pb_unmap(mm->buffer);
pb_reference(&mm->buffer, NULL);
_glthread_UNLOCK_MUTEX(mm->mutex);
pipe_mutex_unlock(mm->mutex);
FREE(mgr);
}
@ -236,7 +236,7 @@ mm_bufmgr_create_from_buffer(struct pb_buffer *buffer,
mm->size = size;
mm->align2 = align2; /* 64-byte alignment */
_glthread_INIT_MUTEX(mm->mutex);
pipe_mutex_init(mm->mutex);
mm->buffer = buffer;

View File

@ -56,7 +56,7 @@ struct pool_pb_manager
{
struct pb_manager base;
_glthread_Mutex mutex;
pipe_mutex mutex;
size_t bufSize;
size_t bufAlign;
@ -110,10 +110,10 @@ pool_buffer_destroy(struct pb_buffer *buf)
assert(pool_buf->base.base.refcount == 0);
_glthread_LOCK_MUTEX(pool->mutex);
pipe_mutex_lock(pool->mutex);
LIST_ADD(&pool_buf->head, &pool->free);
pool->numFree++;
_glthread_UNLOCK_MUTEX(pool->mutex);
pipe_mutex_unlock(pool->mutex);
}
@ -124,9 +124,9 @@ pool_buffer_map(struct pb_buffer *buf, unsigned flags)
struct pool_pb_manager *pool = pool_buf->mgr;
void *map;
_glthread_LOCK_MUTEX(pool->mutex);
pipe_mutex_lock(pool->mutex);
map = (unsigned char *) pool->map + pool_buf->start;
_glthread_UNLOCK_MUTEX(pool->mutex);
pipe_mutex_unlock(pool->mutex);
return map;
}
@ -171,10 +171,10 @@ pool_bufmgr_create_buffer(struct pb_manager *mgr,
assert(size == pool->bufSize);
assert(pool->bufAlign % desc->alignment == 0);
_glthread_LOCK_MUTEX(pool->mutex);
pipe_mutex_lock(pool->mutex);
if (pool->numFree == 0) {
_glthread_UNLOCK_MUTEX(pool->mutex);
pipe_mutex_unlock(pool->mutex);
debug_printf("warning: out of fixed size buffer objects\n");
return NULL;
}
@ -182,7 +182,7 @@ pool_bufmgr_create_buffer(struct pb_manager *mgr,
item = pool->free.next;
if (item == &pool->free) {
_glthread_UNLOCK_MUTEX(pool->mutex);
pipe_mutex_unlock(pool->mutex);
debug_printf("error: fixed size buffer pool corruption\n");
return NULL;
}
@ -190,7 +190,7 @@ pool_bufmgr_create_buffer(struct pb_manager *mgr,
LIST_DEL(item);
--pool->numFree;
_glthread_UNLOCK_MUTEX(pool->mutex);
pipe_mutex_unlock(pool->mutex);
pool_buf = LIST_ENTRY(struct pool_buffer, item, head);
assert(pool_buf->base.base.refcount == 0);
@ -206,14 +206,14 @@ static void
pool_bufmgr_destroy(struct pb_manager *mgr)
{
struct pool_pb_manager *pool = pool_pb_manager(mgr);
_glthread_LOCK_MUTEX(pool->mutex);
pipe_mutex_lock(pool->mutex);
FREE(pool->bufs);
pb_unmap(pool->buffer);
pb_reference(&pool->buffer, NULL);
_glthread_UNLOCK_MUTEX(pool->mutex);
pipe_mutex_unlock(pool->mutex);
FREE(mgr);
}
@ -246,7 +246,7 @@ pool_bufmgr_create(struct pb_manager *provider,
pool->bufSize = bufSize;
pool->bufAlign = desc->alignment;
_glthread_INIT_MUTEX(pool->mutex);
pipe_mutex_init(pool->mutex);
pool->buffer = provider->create_buffer(provider, numBufs*bufSize, desc);
if (!pool->buffer)

View File

@ -30,6 +30,8 @@
* @file
* S-lab pool implementation.
*
* @sa http://en.wikipedia.org/wiki/Slab_allocation
*
* @author Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
* @author Jose Fonseca <jrfonseca@tungstengraphics.com>
*/
@ -49,46 +51,96 @@
struct pb_slab;
/**
* Buffer in a slab.
*
* Sub-allocation of a contiguous buffer.
*/
struct pb_slab_buffer
{
struct pb_buffer base;
struct pb_slab *slab;
struct list_head head;
unsigned mapCount;
/** Offset relative to the start of the slab buffer. */
size_t start;
_glthread_Cond event;
/** Use when validating, to signal that all mappings are finished */
/* TODO: Actually validation does not reach this stage yet */
pipe_condvar event;
};
/**
* Slab -- a contiguous piece of memory.
*/
struct pb_slab
{
struct list_head head;
struct list_head freeBuffers;
size_t numBuffers;
size_t numFree;
struct pb_slab_buffer *buffers;
struct pb_slab_manager *mgr;
/** Buffer from the provider */
struct pb_buffer *bo;
void *virtual;
};
/**
* It adds/removes slabs as needed in order to meet the allocation/destruction
* of individual buffers.
*/
struct pb_slab_manager
{
struct pb_manager base;
/** From where we get our buffers */
struct pb_manager *provider;
/** Size of the buffers we hand on downstream */
size_t bufSize;
/** Size of the buffers we request upstream */
size_t slabSize;
/**
* Alignment, usage to be used to allocate the slab buffers.
*
* We can only provide buffers which are consistent (in alignment, usage)
* with this description.
*/
struct pb_desc desc;
/**
* Partial slabs
*
* Full slabs are not stored in any list. Empty slabs are destroyed
* immediatly.
*/
struct list_head slabs;
struct list_head freeSlabs;
_glthread_Mutex mutex;
pipe_mutex mutex;
};
/**
* Wrapper around several slabs, therefore capable of handling buffers of
* multiple sizes.
*
* This buffer manager just dispatches buffer allocations to the appropriate slab
* manager, according to the requested buffer size, or by passes the slab
* managers altogether for even greater sizes.
*
* The data of this structure remains constant after
* initialization and thus needs no mutex protection.
*/
@ -97,12 +149,17 @@ struct pb_slab_range_manager
struct pb_manager base;
struct pb_manager *provider;
size_t minBufSize;
size_t maxBufSize;
/** @sa pb_slab_manager::desc */
struct pb_desc desc;
unsigned numBuckets;
size_t *bucketSizes;
/** Array of pb_slab_manager, one for each bucket size */
struct pb_manager **buckets;
};
@ -143,7 +200,7 @@ pb_slab_buffer_destroy(struct pb_buffer *_buf)
struct pb_slab_manager *mgr = slab->mgr;
struct list_head *list = &buf->head;
_glthread_LOCK_MUTEX(mgr->mutex);
pipe_mutex_lock(mgr->mutex);
assert(buf->base.base.refcount == 0);
@ -156,30 +213,16 @@ pb_slab_buffer_destroy(struct pb_buffer *_buf)
if (slab->head.next == &slab->head)
LIST_ADDTAIL(&slab->head, &mgr->slabs);
/* If the slab becomes totally empty, free it */
if (slab->numFree == slab->numBuffers) {
list = &slab->head;
LIST_DEL(list);
LIST_ADDTAIL(list, &mgr->freeSlabs);
LIST_DELINIT(list);
pb_reference(&slab->bo, NULL);
FREE(slab->buffers);
FREE(slab);
}
if (mgr->slabs.next == &mgr->slabs || slab->numFree
!= slab->numBuffers) {
struct list_head *next;
for (list = mgr->freeSlabs.next, next = list->next; list
!= &mgr->freeSlabs; list = next, next = list->next) {
slab = LIST_ENTRY(struct pb_slab, list, head);
LIST_DELINIT(list);
pb_reference(&slab->bo, NULL);
FREE(slab->buffers);
FREE(slab);
}
}
_glthread_UNLOCK_MUTEX(mgr->mutex);
pipe_mutex_unlock(mgr->mutex);
}
@ -201,7 +244,7 @@ pb_slab_buffer_unmap(struct pb_buffer *_buf)
--buf->mapCount;
if (buf->mapCount == 0)
_glthread_COND_BROADCAST(buf->event);
pipe_condvar_broadcast(buf->event);
}
@ -225,6 +268,11 @@ pb_slab_buffer_vtbl = {
};
/**
* Create a new slab.
*
* Called when we ran out of free slabs.
*/
static enum pipe_error
pb_slab_create(struct pb_slab_manager *mgr)
{
@ -238,17 +286,14 @@ pb_slab_create(struct pb_slab_manager *mgr)
if (!slab)
return PIPE_ERROR_OUT_OF_MEMORY;
/*
* FIXME: We should perhaps allow some variation in slabsize in order
* to efficiently reuse slabs.
*/
slab->bo = mgr->provider->create_buffer(mgr->provider, mgr->slabSize, &mgr->desc);
if(!slab->bo) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto out_err0;
}
/* Note down the slab virtual address. All mappings are accessed directly
* through this address so it is required that the buffer is pinned. */
slab->virtual = pb_map(slab->bo,
PIPE_BUFFER_USAGE_CPU_READ |
PIPE_BUFFER_USAGE_CPU_WRITE);
@ -256,7 +301,6 @@ pb_slab_create(struct pb_slab_manager *mgr)
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto out_err1;
}
pb_unmap(slab->bo);
numBuffers = slab->bo->base.size / mgr->bufSize;
@ -283,12 +327,13 @@ pb_slab_create(struct pb_slab_manager *mgr)
buf->slab = slab;
buf->start = i* mgr->bufSize;
buf->mapCount = 0;
_glthread_INIT_COND(buf->event);
pipe_condvar_init(buf->event);
LIST_ADDTAIL(&buf->head, &slab->freeBuffers);
slab->numFree++;
buf++;
}
/* Add this slab to the list of partial slabs */
LIST_ADDTAIL(&slab->head, &mgr->slabs);
return PIPE_OK;
@ -328,23 +373,29 @@ pb_slab_manager_create_buffer(struct pb_manager *_mgr,
if(!pb_check_usage(desc->usage, mgr->desc.usage))
return NULL;
_glthread_LOCK_MUTEX(mgr->mutex);
pipe_mutex_lock(mgr->mutex);
/* Create a new slab, if we run out of partial slabs */
if (mgr->slabs.next == &mgr->slabs) {
(void) pb_slab_create(mgr);
if (mgr->slabs.next == &mgr->slabs) {
_glthread_UNLOCK_MUTEX(mgr->mutex);
pipe_mutex_unlock(mgr->mutex);
return NULL;
}
}
/* Allocate the buffer from a partial (or just created) slab */
list = mgr->slabs.next;
slab = LIST_ENTRY(struct pb_slab, list, head);
/* If totally full remove from the partial slab list */
if (--slab->numFree == 0)
LIST_DELINIT(list);
list = slab->freeBuffers.next;
LIST_DELINIT(list);
_glthread_UNLOCK_MUTEX(mgr->mutex);
pipe_mutex_unlock(mgr->mutex);
buf = LIST_ENTRY(struct pb_slab_buffer, list, head);
++buf->base.base.refcount;
@ -386,9 +437,8 @@ pb_slab_manager_create(struct pb_manager *provider,
mgr->desc = *desc;
LIST_INITHEAD(&mgr->slabs);
LIST_INITHEAD(&mgr->freeSlabs);
_glthread_INIT_MUTEX(mgr->mutex);
pipe_mutex_init(mgr->mutex);
return &mgr->base;
}

View File

@ -47,11 +47,12 @@
#include <unistd.h>
#include <sys/mman.h>
#include "pipe/p_thread.h"
#include "util/u_mm.h"
#define EXEC_HEAP_SIZE (10*1024*1024)
_glthread_DECLARE_STATIC_MUTEX(exec_mutex);
pipe_static_mutex(exec_mutex);
static struct mem_block *exec_heap = NULL;
static unsigned char *exec_mem = NULL;
@ -76,7 +77,7 @@ rtasm_exec_malloc(size_t size)
struct mem_block *block = NULL;
void *addr = NULL;
_glthread_LOCK_MUTEX(exec_mutex);
pipe_mutex_lock(exec_mutex);
init_heap();
@ -90,7 +91,7 @@ rtasm_exec_malloc(size_t size)
else
debug_printf("rtasm_exec_malloc failed\n");
_glthread_UNLOCK_MUTEX(exec_mutex);
pipe_mutex_unlock(exec_mutex);
return addr;
}
@ -99,7 +100,7 @@ rtasm_exec_malloc(size_t size)
void
rtasm_exec_free(void *addr)
{
_glthread_LOCK_MUTEX(exec_mutex);
pipe_mutex_lock(exec_mutex);
if (exec_heap) {
struct mem_block *block = mmFindBlock(exec_heap, (unsigned char *)addr - exec_mem);
@ -108,7 +109,7 @@ rtasm_exec_free(void *addr)
mmFreeMem(block);
}
_glthread_UNLOCK_MUTEX(exec_mutex);
pipe_mutex_unlock(exec_mutex);
}

View File

@ -151,8 +151,8 @@ static void emit_RR(struct spe_function *p, unsigned op, unsigned rT,
inst.inst.rB = rB;
inst.inst.rA = rA;
inst.inst.rT = rT;
*p->csr = inst.bits;
p->csr++;
p->store[p->num_inst++] = inst.bits;
assert(p->num_inst <= p->max_inst);
}
@ -165,8 +165,8 @@ static void emit_RRR(struct spe_function *p, unsigned op, unsigned rT,
inst.inst.rB = rB;
inst.inst.rA = rA;
inst.inst.rC = rC;
*p->csr = inst.bits;
p->csr++;
p->store[p->num_inst++] = inst.bits;
assert(p->num_inst <= p->max_inst);
}
@ -178,8 +178,8 @@ static void emit_RI7(struct spe_function *p, unsigned op, unsigned rT,
inst.inst.i7 = imm;
inst.inst.rA = rA;
inst.inst.rT = rT;
*p->csr = inst.bits;
p->csr++;
p->store[p->num_inst++] = inst.bits;
assert(p->num_inst <= p->max_inst);
}
@ -192,8 +192,8 @@ static void emit_RI8(struct spe_function *p, unsigned op, unsigned rT,
inst.inst.i8 = imm;
inst.inst.rA = rA;
inst.inst.rT = rT;
*p->csr = inst.bits;
p->csr++;
p->store[p->num_inst++] = inst.bits;
assert(p->num_inst <= p->max_inst);
}
@ -206,8 +206,8 @@ static void emit_RI10(struct spe_function *p, unsigned op, unsigned rT,
inst.inst.i10 = imm;
inst.inst.rA = rA;
inst.inst.rT = rT;
*p->csr = inst.bits;
p->csr++;
p->store[p->num_inst++] = inst.bits;
assert(p->num_inst <= p->max_inst);
}
@ -218,8 +218,8 @@ static void emit_RI16(struct spe_function *p, unsigned op, unsigned rT,
inst.inst.op = op;
inst.inst.i16 = imm;
inst.inst.rT = rT;
*p->csr = inst.bits;
p->csr++;
p->store[p->num_inst++] = inst.bits;
assert(p->num_inst <= p->max_inst);
}
@ -230,8 +230,8 @@ static void emit_RI18(struct spe_function *p, unsigned op, unsigned rT,
inst.inst.op = op;
inst.inst.i18 = imm;
inst.inst.rT = rT;
*p->csr = inst.bits;
p->csr++;
p->store[p->num_inst++] = inst.bits;
assert(p->num_inst <= p->max_inst);
}
@ -300,13 +300,16 @@ void _name (struct spe_function *p, int imm) \
#include "rtasm_ppc_spe.h"
/*
/**
* Initialize an spe_function.
* \param code_size size of instruction buffer to allocate, in bytes.
*/
void spe_init_func(struct spe_function *p, unsigned code_size)
{
p->store = align_malloc(code_size, 16);
p->csr = p->store;
p->num_inst = 0;
p->max_inst = code_size / SPE_INST_SIZE;
/* Conservatively treat R0 - R2 and R80 - R127 as non-volatile.
*/
p->regs[0] = ~7;
@ -316,21 +319,26 @@ void spe_init_func(struct spe_function *p, unsigned code_size)
void spe_release_func(struct spe_function *p)
{
assert(p->num_inst <= p->max_inst);
if (p->store != NULL) {
align_free(p->store);
}
p->store = NULL;
p->csr = NULL;
}
/**
* Alloate a SPE register.
* \return register index or -1 if none left.
*/
int spe_allocate_available_register(struct spe_function *p)
{
unsigned i;
for (i = 0; i < 128; i++) {
for (i = 0; i < SPE_NUM_REGS; i++) {
const uint64_t mask = (1ULL << (i % 64));
const unsigned idx = i / 64;
assert(idx < 2);
if ((p->regs[idx] & mask) != 0) {
p->regs[idx] &= ~mask;
return i;
@ -341,11 +349,15 @@ int spe_allocate_available_register(struct spe_function *p)
}
/**
* Mark the given SPE register as "allocated".
*/
int spe_allocate_register(struct spe_function *p, int reg)
{
const unsigned idx = reg / 64;
const unsigned bit = reg % 64;
assert(reg < SPE_NUM_REGS);
assert((p->regs[idx] & (1ULL << bit)) != 0);
p->regs[idx] &= ~(1ULL << bit);
@ -353,57 +365,75 @@ int spe_allocate_register(struct spe_function *p, int reg)
}
/**
* Mark the given SPE register as "unallocated".
*/
void spe_release_register(struct spe_function *p, int reg)
{
const unsigned idx = reg / 64;
const unsigned bit = reg % 64;
assert(idx < 2);
assert(reg < SPE_NUM_REGS);
assert((p->regs[idx] & (1ULL << bit)) == 0);
p->regs[idx] |= (1ULL << bit);
}
/**
* For branch instructions:
* \param d if 1, disable interupts if branch is taken
* \param e if 1, enable interupts if branch is taken
* If d and e are both zero, don't change interupt status (right?)
*/
/** Branch Indirect to address in rA */
void spe_bi(struct spe_function *p, unsigned rA, int d, int e)
{
emit_RI7(p, 0x1a8, 0, rA, (d << 5) | (e << 4));
}
/** Interupt Return */
void spe_iret(struct spe_function *p, unsigned rA, int d, int e)
{
emit_RI7(p, 0x1aa, 0, rA, (d << 5) | (e << 4));
}
/** Branch indirect and set link on external data */
void spe_bisled(struct spe_function *p, unsigned rT, unsigned rA, int d,
int e)
{
emit_RI7(p, 0x1ab, rT, rA, (d << 5) | (e << 4));
}
/** Branch indirect and set link. Save PC in rT, jump to rA. */
void spe_bisl(struct spe_function *p, unsigned rT, unsigned rA, int d,
int e)
{
emit_RI7(p, 0x1a9, rT, rA, (d << 5) | (e << 4));
}
void spe_biz(struct spe_function *p, unsigned rT, unsigned rA, int d,
int e)
/** Branch indirect if zero word. If rT.word[0]==0, jump to rA. */
void spe_biz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e)
{
emit_RI7(p, 0x128, rT, rA, (d << 5) | (e << 4));
}
/** Branch indirect if non-zero word. If rT.word[0]!=0, jump to rA. */
void spe_binz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e)
{
emit_RI7(p, 0x129, rT, rA, (d << 5) | (e << 4));
}
/** Branch indirect if zero halfword. If rT.halfword[1]==0, jump to rA. */
void spe_bihz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e)
{
emit_RI7(p, 0x12a, rT, rA, (d << 5) | (e << 4));
}
/** Branch indirect if non-zero halfword. If rT.halfword[1]!=0, jump to rA. */
void spe_bihnz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e)
{
emit_RI7(p, 0x12b, rT, rA, (d << 5) | (e << 4));
@ -432,4 +462,54 @@ EMIT_R (spe_mfspr, 0x00c);
EMIT_R (spe_mtspr, 0x10c);
#endif
/**
** Helper / "macro" instructions.
** Use somewhat verbose names as a reminder that these aren't native
** SPE instructions.
**/
void
spe_load_float(struct spe_function *p, unsigned rT, float x)
{
union {
float f;
unsigned u;
} bits;
bits.f = x;
spe_ilhu(p, rT, bits.u >> 16);
spe_iohl(p, rT, bits.u & 0xffff);
}
void
spe_load_int(struct spe_function *p, unsigned rT, int i)
{
spe_ilhu(p, rT, i >> 16);
spe_iohl(p, rT, i & 0xffff);
}
void
spe_complement(struct spe_function *p, unsigned rT)
{
spe_nor(p, rT, rT, rT);
}
void
spe_move(struct spe_function *p, unsigned rT, unsigned rA)
{
spe_ori(p, rT, rA, 0);
}
void
spe_zero(struct spe_function *p, unsigned rT)
{
spe_xor(p, rT, rT, rT);
}
#endif /* GALLIUM_CELL */

View File

@ -25,6 +25,7 @@
/**
* \file
* Real-time assembly generation interface for Cell B.E. SPEs.
* For details, see /opt/cell/sdk/docs/arch/SPU_ISA_v1.2_27Jan2007_pub.pdf
*
* \author Ian Romanick <idr@us.ibm.com>
*/
@ -32,13 +33,24 @@
#ifndef RTASM_PPC_SPE_H
#define RTASM_PPC_SPE_H
struct spe_function {
/**
*
*/
uint32_t *store;
uint32_t *csr;
const char *fn;
/** 4 bytes per instruction */
#define SPE_INST_SIZE 4
/** number of general-purpose SIMD registers */
#define SPE_NUM_REGS 128
/** Return Address register */
#define SPE_REG_RA 0
/** Stack Pointer register */
#define SPE_REG_SP 1
struct spe_function
{
uint32_t *store; /**< instruction buffer */
uint num_inst;
uint max_inst;
/**
* Mask of used / unused registers
@ -50,7 +62,7 @@ struct spe_function {
* spe_allocate_register, spe_allocate_available_register,
* spe_release_register
*/
uint64_t regs[2];
uint64_t regs[SPE_NUM_REGS / 64];
};
extern void spe_init_func(struct spe_function *p, unsigned code_size);
@ -119,7 +131,8 @@ EMIT_RI16(spe_ilhu, 0x082);
EMIT_RI16(spe_il, 0x081);
EMIT_RI18(spe_ila, 0x021);
EMIT_RI16(spe_iohl, 0x0c1);
EMIT_RI16(spe_fsmbi, 0x0c5);
EMIT_RI16(spe_fsmbi, 0x065);
/* Integer and logical instructions
@ -271,6 +284,27 @@ extern void spe_bihnz(struct spe_function *p, unsigned rT, unsigned rA,
int d, int e);
/** Load/splat immediate float into rT. */
extern void
spe_load_float(struct spe_function *p, unsigned rT, float x);
/** Load/splat immediate int into rT. */
extern void
spe_load_int(struct spe_function *p, unsigned rT, int i);
/** Complement/invert all bits in rT. */
extern void
spe_complement(struct spe_function *p, unsigned rT);
/** rT = rA. */
extern void
spe_move(struct spe_function *p, unsigned rT, unsigned rA);
/** rT = {0,0,0,0}. */
extern void
spe_zero(struct spe_function *p, unsigned rT);
/* Floating-point instructions
*/
EMIT_RR (spe_fa, 0x2c4);

View File

@ -27,7 +27,7 @@
#include "pipe/p_compiler.h"
#include "pipe/p_debug.h"
#include "pipe/p_pointer.h"
#include "util/u_pointer.h"
#include "rtasm_execmem.h"
#include "rtasm_x86sse.h"

View File

@ -37,30 +37,40 @@ struct dump_ctx
uint instno;
struct util_strbuf *sbuf;
void (*printf)(struct dump_ctx *ctx, const char *format, ...);
};
static void
dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
{
va_list ap;
(void)ctx;
va_start(ap, format);
debug_vprintf(format, ap);
va_end(ap);
}
static void
dump_enum(
struct util_strbuf *sbuf,
struct dump_ctx *ctx,
uint e,
const char **enums,
uint enum_count )
{
if (e >= enum_count)
util_strbuf_printf( sbuf, "%u", e );
ctx->printf( ctx, "%u", e );
else
util_strbuf_printf( sbuf, "%s", enums[e] );
ctx->printf( ctx, "%s", enums[e] );
}
#define EOL() util_strbuf_printf( sbuf, "\n" )
#define TXT(S) util_strbuf_printf( sbuf, "%s", S )
#define CHR(C) util_strbuf_printf( sbuf, "%c", C )
#define UIX(I) util_strbuf_printf( sbuf, "0x%x", I )
#define UID(I) util_strbuf_printf( sbuf, "%u", I )
#define SID(I) util_strbuf_printf( sbuf, "%d", I )
#define FLT(F) util_strbuf_printf( sbuf, "%10.4f", F )
#define ENM(E,ENUMS) dump_enum( sbuf, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
#define EOL() ctx->printf( ctx, "\n" )
#define TXT(S) ctx->printf( ctx, "%s", S )
#define CHR(C) ctx->printf( ctx, "%c", C )
#define UIX(I) ctx->printf( ctx, "0x%x", I )
#define UID(I) ctx->printf( ctx, "%u", I )
#define SID(I) ctx->printf( ctx, "%d", I )
#define FLT(F) ctx->printf( ctx, "%10.4f", F )
#define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
static const char *processor_type_names[] =
{
@ -148,7 +158,7 @@ static const char *modulate_names[TGSI_MODULATE_COUNT] =
static void
_dump_register(
struct util_strbuf *sbuf,
struct dump_ctx *ctx,
uint file,
int first,
int last )
@ -165,7 +175,7 @@ _dump_register(
static void
_dump_register_ind(
struct util_strbuf *sbuf,
struct dump_ctx *ctx,
uint file,
int index,
uint ind_file,
@ -187,7 +197,7 @@ _dump_register_ind(
static void
_dump_writemask(
struct util_strbuf *sbuf,
struct dump_ctx *ctx,
uint writemask )
{
if (writemask != TGSI_WRITEMASK_XYZW) {
@ -208,18 +218,17 @@ iter_declaration(
struct tgsi_iterate_context *iter,
struct tgsi_full_declaration *decl )
{
struct dump_ctx *ctx = (struct dump_ctx *) iter;
struct util_strbuf *sbuf = ctx->sbuf;
struct dump_ctx *ctx = (struct dump_ctx *)iter;
TXT( "DCL " );
_dump_register(
sbuf,
ctx,
decl->Declaration.File,
decl->DeclarationRange.First,
decl->DeclarationRange.Last );
_dump_writemask(
sbuf,
ctx,
decl->Declaration.UsageMask );
if (decl->Declaration.Semantic) {
@ -245,17 +254,11 @@ void
tgsi_dump_declaration(
const struct tgsi_full_declaration *decl )
{
static char str[1024];
struct util_strbuf sbuf;
struct dump_ctx ctx;
util_strbuf_init(&sbuf, str, sizeof(str));
ctx.sbuf = &sbuf;
ctx.printf = dump_ctx_printf;
iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
debug_printf("%s", str);
}
static boolean
@ -264,7 +267,6 @@ iter_immediate(
struct tgsi_full_immediate *imm )
{
struct dump_ctx *ctx = (struct dump_ctx *) iter;
struct util_strbuf *sbuf = ctx->sbuf;
uint i;
@ -295,17 +297,11 @@ void
tgsi_dump_immediate(
const struct tgsi_full_immediate *imm )
{
static char str[1024];
struct util_strbuf sbuf;
struct dump_ctx ctx;
util_strbuf_init(&sbuf, str, sizeof(str));
ctx.sbuf = &sbuf;
ctx.printf = dump_ctx_printf;
iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
debug_printf("%s", str);
}
static boolean
@ -314,7 +310,6 @@ iter_instruction(
struct tgsi_full_instruction *inst )
{
struct dump_ctx *ctx = (struct dump_ctx *) iter;
struct util_strbuf *sbuf = ctx->sbuf;
uint instno = ctx->instno++;
uint i;
@ -345,12 +340,12 @@ iter_instruction(
CHR( ' ' );
_dump_register(
sbuf,
ctx,
dst->DstRegister.File,
dst->DstRegister.Index,
dst->DstRegister.Index );
ENM( dst->DstRegisterExtModulate.Modulate, modulate_names );
_dump_writemask( sbuf, dst->DstRegister.WriteMask );
_dump_writemask( ctx, dst->DstRegister.WriteMask );
first_reg = FALSE;
}
@ -377,7 +372,7 @@ iter_instruction(
if (src->SrcRegister.Indirect) {
_dump_register_ind(
sbuf,
ctx,
src->SrcRegister.File,
src->SrcRegister.Index,
src->SrcRegisterInd.File,
@ -385,7 +380,7 @@ iter_instruction(
}
else {
_dump_register(
sbuf,
ctx,
src->SrcRegister.File,
src->SrcRegister.Index,
src->SrcRegister.Index );
@ -460,18 +455,12 @@ tgsi_dump_instruction(
const struct tgsi_full_instruction *inst,
uint instno )
{
static char str[1024];
struct util_strbuf sbuf;
struct dump_ctx ctx;
util_strbuf_init(&sbuf, str, sizeof(str));
ctx.instno = instno;
ctx.sbuf = &sbuf;
ctx.printf = dump_ctx_printf;
iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
debug_printf("%s", str);
}
static boolean
@ -479,7 +468,6 @@ prolog(
struct tgsi_iterate_context *iter )
{
struct dump_ctx *ctx = (struct dump_ctx *) iter;
struct util_strbuf *sbuf = ctx->sbuf;
ENM( iter->processor.Processor, processor_type_names );
UID( iter->version.MajorVersion );
CHR( '.' );
@ -489,17 +477,12 @@ prolog(
}
void
tgsi_dump_str(
tgsi_dump(
const struct tgsi_token *tokens,
uint flags,
char *str,
size_t size)
uint flags )
{
struct util_strbuf sbuf;
struct dump_ctx ctx;
util_strbuf_init(&sbuf, str, size);
ctx.iter.prolog = prolog;
ctx.iter.iterate_instruction = iter_instruction;
ctx.iter.iterate_declaration = iter_declaration;
@ -507,34 +490,57 @@ tgsi_dump_str(
ctx.iter.epilog = NULL;
ctx.instno = 0;
ctx.sbuf = &sbuf;
ctx.printf = dump_ctx_printf;
tgsi_iterate_shader( tokens, &ctx.iter );
}
void
tgsi_dump(
const struct tgsi_token *tokens,
uint flags )
struct str_dump_ctx
{
static char str[4096];
uint len;
char *p = str;
struct dump_ctx base;
char *str;
char *ptr;
size_t left;
};
tgsi_dump_str(tokens, flags, str, sizeof(str));
/* Workaround output buffer size limitations.
*/
len = strlen( str );
while (len > 256) {
char piggy_bank;
piggy_bank = p[256];
p[256] = '\0';
debug_printf( "%s", p );
p[256] = piggy_bank;
p += 256;
len -= 256;
static void
str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
{
struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
if(sctx->left > 1) {
size_t written;
va_list ap;
va_start(ap, format);
written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
va_end(ap);
sctx->ptr += written;
sctx->left -= written;
}
debug_printf( "%s", p );
}
void
tgsi_dump_str(
const struct tgsi_token *tokens,
uint flags,
char *str,
size_t size)
{
struct str_dump_ctx ctx;
ctx.base.iter.prolog = prolog;
ctx.base.iter.iterate_instruction = iter_instruction;
ctx.base.iter.iterate_declaration = iter_declaration;
ctx.base.iter.iterate_immediate = iter_immediate;
ctx.base.iter.epilog = NULL;
ctx.base.instno = 0;
ctx.base.printf = &str_dump_ctx_printf;
ctx.str = str;
ctx.str[0] = 0;
ctx.ptr = str;
ctx.left = size;
tgsi_iterate_shader( tokens, &ctx.base.iter );
}

View File

@ -957,6 +957,7 @@ fetch_src_file_channel(
case TGSI_EXTSWIZZLE_W:
switch( file ) {
case TGSI_FILE_CONSTANT:
assert(mach->Consts);
chan->f[0] = mach->Consts[index->i[0]][swizzle];
chan->f[1] = mach->Consts[index->i[1]][swizzle];
chan->f[2] = mach->Consts[index->i[2]][swizzle];

View File

@ -322,7 +322,7 @@ epilog(
/* Print totals, if any.
*/
if (ctx->errors || ctx->warnings)
debug_printf( "\n%u errors, %u warnings", ctx->errors, ctx->warnings );
debug_printf( "%u errors, %u warnings\n", ctx->errors, ctx->warnings );
return TRUE;
}

View File

@ -601,12 +601,10 @@ static void PIPE_CDECL
cos4f(
float *store )
{
const unsigned X = 0;
store[X + 0] = cosf( store[X + 0] );
store[X + 1] = cosf( store[X + 1] );
store[X + 2] = cosf( store[X + 2] );
store[X + 3] = cosf( store[X + 3] );
store[0] = cosf( store[0] );
store[1] = cosf( store[1] );
store[2] = cosf( store[2] );
store[3] = cosf( store[3] );
}
static void
@ -624,18 +622,16 @@ static void PIPE_CDECL
ex24f(
float *store )
{
const unsigned X = 0;
#if FAST_MATH
store[X + 0] = util_fast_exp2( store[X + 0] );
store[X + 1] = util_fast_exp2( store[X + 1] );
store[X + 2] = util_fast_exp2( store[X + 2] );
store[X + 3] = util_fast_exp2( store[X + 3] );
store[0] = util_fast_exp2( store[0] );
store[1] = util_fast_exp2( store[1] );
store[2] = util_fast_exp2( store[2] );
store[3] = util_fast_exp2( store[3] );
#else
store[X + 0] = powf( 2.0f, store[X + 0] );
store[X + 1] = powf( 2.0f, store[X + 1] );
store[X + 2] = powf( 2.0f, store[X + 2] );
store[X + 3] = powf( 2.0f, store[X + 3] );
store[0] = powf( 2.0f, store[0] );
store[1] = powf( 2.0f, store[1] );
store[2] = powf( 2.0f, store[2] );
store[3] = powf( 2.0f, store[3] );
#endif
}
@ -665,12 +661,10 @@ static void PIPE_CDECL
flr4f(
float *store )
{
const unsigned X = 0;
store[X + 0] = floorf( store[X + 0] );
store[X + 1] = floorf( store[X + 1] );
store[X + 2] = floorf( store[X + 2] );
store[X + 3] = floorf( store[X + 3] );
store[0] = floorf( store[0] );
store[1] = floorf( store[1] );
store[2] = floorf( store[2] );
store[3] = floorf( store[3] );
}
static void
@ -688,12 +682,10 @@ static void PIPE_CDECL
frc4f(
float *store )
{
const unsigned X = 0;
store[X + 0] -= floorf( store[X + 0] );
store[X + 1] -= floorf( store[X + 1] );
store[X + 2] -= floorf( store[X + 2] );
store[X + 3] -= floorf( store[X + 3] );
store[0] -= floorf( store[0] );
store[1] -= floorf( store[1] );
store[2] -= floorf( store[2] );
store[3] -= floorf( store[3] );
}
static void
@ -711,12 +703,10 @@ static void PIPE_CDECL
lg24f(
float *store )
{
const unsigned X = 0;
store[X + 0] = util_fast_log2( store[X + 0] );
store[X + 1] = util_fast_log2( store[X + 1] );
store[X + 2] = util_fast_log2( store[X + 2] );
store[X + 3] = util_fast_log2( store[X + 3] );
store[0] = util_fast_log2( store[0] );
store[1] = util_fast_log2( store[1] );
store[2] = util_fast_log2( store[2] );
store[3] = util_fast_log2( store[3] );
}
static void
@ -770,18 +760,16 @@ static void PIPE_CDECL
pow4f(
float *store )
{
const unsigned X = 0;
#if FAST_MATH
store[X + 0] = util_fast_pow( store[X + 0], store[X + 4] );
store[X + 1] = util_fast_pow( store[X + 1], store[X + 5] );
store[X + 2] = util_fast_pow( store[X + 2], store[X + 6] );
store[X + 3] = util_fast_pow( store[X + 3], store[X + 7] );
store[0] = util_fast_pow( store[0], store[4] );
store[1] = util_fast_pow( store[1], store[5] );
store[2] = util_fast_pow( store[2], store[6] );
store[3] = util_fast_pow( store[3], store[7] );
#else
store[X + 0] = powf( store[X + 0], store[X + 4] );
store[X + 1] = powf( store[X + 1], store[X + 5] );
store[X + 2] = powf( store[X + 2], store[X + 6] );
store[X + 3] = powf( store[X + 3], store[X + 7] );
store[0] = powf( store[0], store[4] );
store[1] = powf( store[1], store[5] );
store[2] = powf( store[2], store[6] );
store[3] = powf( store[3], store[7] );
#endif
}
@ -877,12 +865,10 @@ static void PIPE_CDECL
sin4f(
float *store )
{
const unsigned X = 0;
store[X + 0] = sinf( store[X + 0] );
store[X + 1] = sinf( store[X + 1] );
store[X + 2] = sinf( store[X + 2] );
store[X + 3] = sinf( store[X + 3] );
store[0] = sinf( store[0] );
store[1] = sinf( store[1] );
store[2] = sinf( store[2] );
store[3] = sinf( store[3] );
}
static void
@ -2416,3 +2402,4 @@ tgsi_emit_sse2(
}
#endif /* PIPE_ARCH_X86 */

View File

@ -415,6 +415,12 @@ static fetch_func get_fetch_func( enum pipe_format format )
static emit_func get_emit_func( enum pipe_format format )
{
/* silence warnings */
(void) emit_R32G32B32A32_FIXED;
(void) emit_R32G32B32_FIXED;
(void) emit_R32G32_FIXED;
(void) emit_R32_FIXED;
switch (format) {
case PIPE_FORMAT_R64_FLOAT:
return &emit_R64_FLOAT;

View File

@ -15,8 +15,11 @@ C_SOURCES = \
u_rect.c \
u_simple_shaders.c \
u_snprintf.c \
u_stream_stdc.c \
u_stream_wd.c \
u_tile.c \
u_time.c
u_time.c \
u_timed_winsys.c
include ../../Makefile.template

View File

@ -16,6 +16,8 @@ util = env.ConvenienceLibrary(
'u_rect.c',
'u_simple_shaders.c',
'u_snprintf.c',
'u_stream_stdc.c',
'u_stream_wd.c',
'u_tile.c',
'u_time.c',
])

View File

@ -55,7 +55,11 @@
#include "pipe/p_format.h"
#include "pipe/p_state.h"
#include "pipe/p_inlines.h"
#include "util/u_memory.h"
#include "util/u_string.h"
#include "util/u_stream.h"
#include "util/u_math.h"
#include "util/u_tile.h"
#ifdef PIPE_SUBSYSTEM_WINDOWS_DISPLAY
@ -76,7 +80,7 @@ void _debug_vprintf(const char *format, va_list ap)
/* EngDebugPrint does not handle float point arguments, so we need to use
* our own vsnprintf implementation. It is also very slow, so buffer until
* we find a newline. */
static char buf[512 + 1] = {'\0'};
static char buf[512] = {'\0'};
size_t len = strlen(buf);
int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
@ -584,4 +588,109 @@ error2:
error1:
;
}
#pragma pack(push,2)
struct bmp_file_header {
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
};
#pragma pack(pop)
struct bmp_info_header {
uint32_t biSize;
int32_t biWidth;
int32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
};
struct bmp_rgb_quad {
uint8_t rgbBlue;
uint8_t rgbGreen;
uint8_t rgbRed;
uint8_t rgbAlpha;
};
void
debug_dump_surface_bmp(const char *filename,
struct pipe_surface *surface)
{
struct util_stream *stream;
unsigned surface_usage;
struct bmp_file_header bmfh;
struct bmp_info_header bmih;
float *rgba;
unsigned x, y;
if (!surface)
goto error1;
rgba = MALLOC(surface->width*4*sizeof(float));
if(!rgba)
goto error1;
bmfh.bfType = 0x4d42;
bmfh.bfSize = 14 + 40 + surface->height*surface->width*4;
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
bmfh.bfOffBits = 14 + 40;
bmih.biSize = 40;
bmih.biWidth = surface->width;
bmih.biHeight = surface->height;
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = 0;
bmih.biSizeImage = surface->height*surface->width*4;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
stream = util_stream_create(filename, bmfh.bfSize);
if(!stream)
goto error2;
util_stream_write(stream, &bmfh, 14);
util_stream_write(stream, &bmih, 40);
/* XXX: force mappable surface */
surface_usage = surface->usage;
surface->usage |= PIPE_BUFFER_USAGE_CPU_READ;
y = surface->height;
while(y--) {
pipe_get_tile_rgba(surface,
0, y, surface->width, 1,
rgba);
for(x = 0; x < surface->width; ++x)
{
struct bmp_rgb_quad pixel;
pixel.rgbRed = float_to_ubyte(rgba[x*4 + 0]);
pixel.rgbGreen = float_to_ubyte(rgba[x*4 + 1]);
pixel.rgbBlue = float_to_ubyte(rgba[x*4 + 2]);
pixel.rgbAlpha = float_to_ubyte(rgba[x*4 + 3]);
util_stream_write(stream, &pixel, 4);
}
}
surface->usage = surface_usage;
util_stream_close(stream);
error2:
FREE(rgba);
error1:
;
}
#endif

View File

@ -138,10 +138,10 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
/* fragment shader */
ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader);
ctx->vbuf = pipe->winsys->buffer_create(pipe->winsys,
32,
PIPE_BUFFER_USAGE_VERTEX,
sizeof(ctx->vertices));
ctx->vbuf = pipe_buffer_create(pipe->screen,
32,
PIPE_BUFFER_USAGE_VERTEX,
sizeof(ctx->vertices));
if (!ctx->vbuf) {
FREE(ctx);
ctx->pipe->delete_fs_state(ctx->pipe, ctx->fs);
@ -174,7 +174,7 @@ util_destroy_blit(struct blit_state *ctx)
FREE((void*) ctx->vert_shader.tokens);
FREE((void*) ctx->frag_shader.tokens);
pipe->winsys->buffer_destroy(pipe->winsys, ctx->vbuf);
pipe_buffer_reference(pipe->screen, &ctx->vbuf, NULL);
FREE(ctx);
}
@ -214,12 +214,12 @@ setup_vertex_data(struct blit_state *ctx,
ctx->vertices[3][1][0] = 0.0f;
ctx->vertices[3][1][1] = 1.0f;
buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf);
pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
}
@ -259,12 +259,12 @@ setup_vertex_data_tex(struct blit_state *ctx,
ctx->vertices[3][1][0] = s0;
ctx->vertices[3][1][1] = t1;
buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf);
pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
}
/**
* Copy pixel block from src surface to dst surface.

View File

@ -86,11 +86,11 @@ util_draw_texquad(struct pipe_context *pipe,
vertexBytes = 4 * (4 * numAttribs * sizeof(float));
/* XXX create one-time */
vbuf = pipe->winsys->buffer_create(pipe->winsys, 32,
PIPE_BUFFER_USAGE_VERTEX, vertexBytes);
vbuf = pipe_buffer_create(pipe->screen, 32,
PIPE_BUFFER_USAGE_VERTEX, vertexBytes);
if (vbuf) {
float *v = (float *) pipe->winsys->buffer_map(pipe->winsys, vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
float *v = (float *) pipe_buffer_map(pipe->screen, vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
if (v) {
/*
* Load vertex buffer
@ -123,10 +123,10 @@ util_draw_texquad(struct pipe_context *pipe,
v[28] = 0.0;
v[29] = 1.0;
pipe->winsys->buffer_unmap(pipe->winsys, vbuf);
pipe_buffer_unmap(pipe->screen, vbuf);
util_draw_vertex_buffer(pipe, vbuf, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
}
pipe_buffer_reference(pipe->winsys, &vbuf, NULL);
pipe_buffer_reference(pipe->screen, &vbuf, NULL);
}
}

View File

@ -580,7 +580,6 @@ make_1d_mipmap(struct gen_mipmap_state *ctx,
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_winsys *winsys = pipe->winsys;
const uint zslice = 0;
uint dstLevel;
@ -595,19 +594,19 @@ make_1d_mipmap(struct gen_mipmap_state *ctx,
dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
PIPE_BUFFER_USAGE_CPU_WRITE);
srcMap = ((ubyte *) winsys->buffer_map(winsys, srcSurf->buffer,
PIPE_BUFFER_USAGE_CPU_READ)
srcMap = ((ubyte *) pipe_buffer_map(screen, srcSurf->buffer,
PIPE_BUFFER_USAGE_CPU_READ)
+ srcSurf->offset);
dstMap = ((ubyte *) winsys->buffer_map(winsys, dstSurf->buffer,
PIPE_BUFFER_USAGE_CPU_WRITE)
dstMap = ((ubyte *) pipe_buffer_map(screen, dstSurf->buffer,
PIPE_BUFFER_USAGE_CPU_WRITE)
+ dstSurf->offset);
reduce_1d(pt->format,
srcSurf->width, srcMap,
dstSurf->width, dstMap);
winsys->buffer_unmap(winsys, srcSurf->buffer);
winsys->buffer_unmap(winsys, dstSurf->buffer);
pipe_buffer_unmap(screen, srcSurf->buffer);
pipe_buffer_unmap(screen, dstSurf->buffer);
pipe_surface_reference(&srcSurf, NULL);
pipe_surface_reference(&dstSurf, NULL);
@ -622,7 +621,6 @@ make_2d_mipmap(struct gen_mipmap_state *ctx,
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_winsys *winsys = pipe->winsys;
const uint zslice = 0;
uint dstLevel;
@ -639,11 +637,11 @@ make_2d_mipmap(struct gen_mipmap_state *ctx,
dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
PIPE_BUFFER_USAGE_CPU_WRITE);
srcMap = ((ubyte *) winsys->buffer_map(winsys, srcSurf->buffer,
PIPE_BUFFER_USAGE_CPU_READ)
srcMap = ((ubyte *) pipe_buffer_map(screen, srcSurf->buffer,
PIPE_BUFFER_USAGE_CPU_READ)
+ srcSurf->offset);
dstMap = ((ubyte *) winsys->buffer_map(winsys, dstSurf->buffer,
PIPE_BUFFER_USAGE_CPU_WRITE)
dstMap = ((ubyte *) pipe_buffer_map(screen, dstSurf->buffer,
PIPE_BUFFER_USAGE_CPU_WRITE)
+ dstSurf->offset);
reduce_2d(pt->format,
@ -652,8 +650,8 @@ make_2d_mipmap(struct gen_mipmap_state *ctx,
dstSurf->width, dstSurf->height,
dstSurf->stride, dstMap);
winsys->buffer_unmap(winsys, srcSurf->buffer);
winsys->buffer_unmap(winsys, dstSurf->buffer);
pipe_buffer_unmap(screen, srcSurf->buffer);
pipe_buffer_unmap(screen, dstSurf->buffer);
pipe_surface_reference(&srcSurf, NULL);
pipe_surface_reference(&dstSurf, NULL);
@ -759,10 +757,10 @@ util_create_gen_mipmap(struct pipe_context *pipe,
/* fragment shader */
ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader);
ctx->vbuf = pipe->winsys->buffer_create(pipe->winsys,
32,
PIPE_BUFFER_USAGE_VERTEX,
sizeof(ctx->vertices));
ctx->vbuf = pipe_buffer_create(pipe->screen,
32,
PIPE_BUFFER_USAGE_VERTEX,
sizeof(ctx->vertices));
if (!ctx->vbuf) {
FREE(ctx);
return NULL;
@ -805,12 +803,12 @@ set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
ctx->vertices[3][1][0] = 0.0f;
ctx->vertices[3][1][1] = 1.0f;
buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf);
pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
}
@ -829,7 +827,7 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
FREE((void*) ctx->vert_shader.tokens);
FREE((void*) ctx->frag_shader.tokens);
pipe->winsys->buffer_destroy(pipe->winsys, ctx->vbuf);
pipe_buffer_reference(pipe->screen, &ctx->vbuf, NULL);
FREE(ctx);
}

View File

@ -39,7 +39,12 @@
#include "pipe/p_debug.h"
/* Define ENOMEM for WINCE */
#ifdef __cplusplus
extern "C" {
#endif
/* Define ENOMEM for WINCE */
#if (_WIN32_WCE < 600)
#ifndef ENOMEM
#define ENOMEM 12
@ -47,7 +52,6 @@
#endif
#if defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) && defined(DEBUG)
/* memory debugging */
@ -220,4 +224,9 @@ mem_dup(const void *src, uint size)
#ifdef __cplusplus
}
#endif
#endif /* U_MEMORY_H */

View File

@ -141,6 +141,161 @@ util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a,
}
/**
* Unpack RGBA from a packed pixel, returning values as ubytes in [0,255].
*/
static INLINE void
util_unpack_color_ub(enum pipe_format format, const void *src,
ubyte *r, ubyte *g, ubyte *b, ubyte *a)
{
switch (format) {
case PIPE_FORMAT_R8G8B8A8_UNORM:
{
uint p = ((const uint *) src)[0];
*r = (ubyte) ((p >> 24) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 8) & 0xff);
*a = (ubyte) ((p >> 0) & 0xff);
}
return;
case PIPE_FORMAT_R8G8B8X8_UNORM:
{
uint p = ((const uint *) src)[0];
*r = (ubyte) ((p >> 24) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 8) & 0xff);
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_A8R8G8B8_UNORM:
{
uint p = ((const uint *) src)[0];
*r = (ubyte) ((p >> 16) & 0xff);
*g = (ubyte) ((p >> 8) & 0xff);
*b = (ubyte) ((p >> 0) & 0xff);
*a = (ubyte) ((p >> 24) & 0xff);
}
return;
case PIPE_FORMAT_X8R8G8B8_UNORM:
{
uint p = ((const uint *) src)[0];
*r = (ubyte) ((p >> 16) & 0xff);
*g = (ubyte) ((p >> 8) & 0xff);
*b = (ubyte) ((p >> 0) & 0xff);
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_B8G8R8A8_UNORM:
{
uint p = ((const uint *) src)[0];
*r = (ubyte) ((p >> 8) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 24) & 0xff);
*a = (ubyte) ((p >> 0) & 0xff);
}
return;
case PIPE_FORMAT_B8G8R8X8_UNORM:
{
uint p = ((const uint *) src)[0];
*r = (ubyte) ((p >> 8) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 24) & 0xff);
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_R5G6B5_UNORM:
{
ushort p = ((const ushort *) src)[0];
*r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7));
*g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3));
*b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_A1R5G5B5_UNORM:
{
ushort p = ((const ushort *) src)[0];
*r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
*g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
*b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
*a = (ubyte) (0xff * (p >> 15));
}
return;
case PIPE_FORMAT_A4R4G4B4_UNORM:
{
ushort p = ((const ushort *) src)[0];
*r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf));
*g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf));
*b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf));
*a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf));
}
return;
case PIPE_FORMAT_A8_UNORM:
{
ubyte p = ((const ubyte *) src)[0];
*r = *g = *b = (ubyte) 0xff;
*a = p;
}
return;
case PIPE_FORMAT_L8_UNORM:
{
ubyte p = ((const ubyte *) src)[0];
*r = *g = *b = p;
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_I8_UNORM:
{
ubyte p = ((const ubyte *) src)[0];
*r = *g = *b = *a = p;
}
return;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
{
const float *p = (const float *) src;
*r = float_to_ubyte(p[0]);
*g = float_to_ubyte(p[1]);
*b = float_to_ubyte(p[2]);
*a = float_to_ubyte(p[3]);
}
return;
case PIPE_FORMAT_R32G32B32_FLOAT:
{
const float *p = (const float *) src;
*r = float_to_ubyte(p[0]);
*g = float_to_ubyte(p[1]);
*b = float_to_ubyte(p[2]);
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_R32G32_FLOAT:
{
const float *p = (const float *) src;
*r = float_to_ubyte(p[0]);
*g = float_to_ubyte(p[1]);
*b = *a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_R32_FLOAT:
{
const float *p = (const float *) src;
*r = float_to_ubyte(p[0]);
*g = *b = *a = (ubyte) 0xff;
}
return;
/* XXX lots more cases to add */
default:
debug_print_format("gallium: unhandled format in util_unpack_color_ub()",
format);
assert(0);
}
}
/**
* Note rgba outside [0,1] will be clamped for int pixel formats.
*/

View File

@ -32,6 +32,8 @@
#include "pipe/p_defines.h"
#include "pipe/p_format.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "util/u_rect.h"
@ -148,3 +150,179 @@ pipe_fill_rect(ubyte * dst,
break;
}
}
/**
* Fallback function for pipe->surface_copy().
* Note: (X,Y)=(0,0) is always the upper-left corner.
* if do_flip, flip the image vertically on its way from src rect to dst rect.
* XXX should probably put this in new u_surface.c file...
*/
void
util_surface_copy(struct pipe_context *pipe,
boolean do_flip,
struct pipe_surface *dst,
unsigned dst_x, unsigned dst_y,
struct pipe_surface *src,
unsigned src_x, unsigned src_y,
unsigned w, unsigned h)
{
struct pipe_screen *screen = pipe->screen;
struct pipe_surface *new_src = NULL, *new_dst = NULL;
void *dst_map;
const void *src_map;
assert(dst->block.size == src->block.size);
assert(dst->block.width == src->block.width);
assert(dst->block.height == src->block.height);
if ((src->usage & PIPE_BUFFER_USAGE_CPU_READ) == 0) {
/* Need to create new src surface which is CPU readable */
assert(src->texture);
if (!src->texture)
return;
new_src = screen->get_tex_surface(screen,
src->texture,
src->face,
src->level,
src->zslice,
PIPE_BUFFER_USAGE_CPU_READ);
src = new_src;
}
if ((dst->usage & PIPE_BUFFER_USAGE_CPU_WRITE) == 0) {
/* Need to create new dst surface which is CPU writable */
assert(dst->texture);
if (!dst->texture)
return;
new_dst = screen->get_tex_surface(screen,
dst->texture,
dst->face,
dst->level,
dst->zslice,
PIPE_BUFFER_USAGE_CPU_WRITE);
dst = new_dst;
}
src_map = pipe->screen->surface_map(screen,
src, PIPE_BUFFER_USAGE_CPU_READ);
dst_map = pipe->screen->surface_map(screen,
dst, PIPE_BUFFER_USAGE_CPU_WRITE);
assert(src_map);
assert(dst_map);
if (src_map && dst_map) {
/* If do_flip, invert src_y position and pass negative src stride */
pipe_copy_rect(dst_map,
&dst->block,
dst->stride,
dst_x, dst_y,
w, h,
src_map,
do_flip ? -(int) src->stride : src->stride,
src_x, src_y);
}
pipe->screen->surface_unmap(pipe->screen, src);
pipe->screen->surface_unmap(pipe->screen, dst);
if (new_src)
screen->tex_surface_release(screen, &new_src);
if (new_dst)
screen->tex_surface_release(screen, &new_dst);
}
static void *
get_pointer(struct pipe_surface *dst, void *dst_map, unsigned x, unsigned y)
{
return (char *)dst_map
+ y / dst->block.height * dst->stride
+ x / dst->block.width * dst->block.size;
}
#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
/**
* Fallback for pipe->surface_fill() function.
* XXX should probably put this in new u_surface.c file...
*/
void
util_surface_fill(struct pipe_context *pipe,
struct pipe_surface *dst,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height, unsigned value)
{
struct pipe_screen *screen = pipe->screen;
struct pipe_surface *new_dst = NULL;
void *dst_map;
if ((dst->usage & PIPE_BUFFER_USAGE_CPU_WRITE) == 0) {
/* Need to create new dst surface which is CPU writable */
assert(dst->texture);
if (!dst->texture)
return;
new_dst = screen->get_tex_surface(screen,
dst->texture,
dst->face,
dst->level,
dst->zslice,
PIPE_BUFFER_USAGE_CPU_WRITE);
dst = new_dst;
}
dst_map = pipe->screen->surface_map(screen,
dst, PIPE_BUFFER_USAGE_CPU_WRITE);
assert(dst_map);
if (dst_map) {
assert(dst->stride > 0);
switch (dst->block.size) {
case 1:
case 2:
case 4:
pipe_fill_rect(dst_map, &dst->block, dst->stride,
dstx, dsty, width, height, value);
break;
case 8:
{
/* expand the 4-byte clear value to an 8-byte value */
ushort *row = (ushort *) get_pointer(dst, dst_map, dstx, dsty);
ushort val0 = UBYTE_TO_USHORT((value >> 0) & 0xff);
ushort val1 = UBYTE_TO_USHORT((value >> 8) & 0xff);
ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff);
ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff);
unsigned i, j;
val0 = (val0 << 8) | val0;
val1 = (val1 << 8) | val1;
val2 = (val2 << 8) | val2;
val3 = (val3 << 8) | val3;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
row[j*4+0] = val0;
row[j*4+1] = val1;
row[j*4+2] = val2;
row[j*4+3] = val3;
}
row += dst->stride/2;
}
}
break;
default:
assert(0);
break;
}
}
pipe->screen->surface_unmap(pipe->screen, dst);
if (new_dst)
screen->tex_surface_release(screen, &new_dst);
}

View File

@ -37,6 +37,9 @@
#include "pipe/p_format.h"
struct pipe_context;
struct pipe_surface;
extern void
pipe_copy_rect(ubyte * dst, const struct pipe_format_block *block,
@ -50,5 +53,20 @@ pipe_fill_rect(ubyte * dst, const struct pipe_format_block *block,
unsigned width, unsigned height, uint32_t value);
extern void
util_surface_copy(struct pipe_context *pipe,
boolean do_flip,
struct pipe_surface *dst,
unsigned dst_x, unsigned dst_y,
struct pipe_surface *src,
unsigned src_x, unsigned src_y,
unsigned w, unsigned h);
extern void
util_surface_fill(struct pipe_context *pipe,
struct pipe_surface *dst,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height, unsigned value);
#endif /* U_RECT_H */

View File

@ -28,32 +28,34 @@
/**
* @file
* Cross-platform sequential access stream abstraction.
*
* These are really general purpose file access functions, and might one day
* be moved into the util module.
*/
#ifndef TR_STREAM_H
#define TR_STREAM_H
#ifndef U_STREAM_H
#define U_STREAM_H
#include "pipe/p_compiler.h"
struct trace_stream;
struct util_stream;
struct trace_stream *
trace_stream_create(const char *filename);
/**
* Create a stream
* @param filename relative or absolute path (necessary for windows)
* @param optional maximum file size (0 for a growable size).
*/
struct util_stream *
util_stream_create(const char *filename, size_t max_size);
boolean
trace_stream_write(struct trace_stream *stream, const void *data, size_t size);
util_stream_write(struct util_stream *stream, const void *data, size_t size);
void
trace_stream_flush(struct trace_stream *stream);
util_stream_flush(struct util_stream *stream);
void
trace_stream_close(struct trace_stream *stream);
util_stream_close(struct util_stream *stream);
#endif /* TR_STREAM_H */
#endif /* U_STREAM_H */

View File

@ -32,27 +32,29 @@
#include "pipe/p_config.h"
#if defined(PIPE_OS_LINUX)
#if defined(PIPE_OS_LINUX) || defined(PIPE_SUBSYSTEM_WINDOWS_USER)
#include <stdio.h>
#include "util/u_memory.h"
#include "tr_stream.h"
#include "u_stream.h"
struct trace_stream
struct util_stream
{
FILE *file;
};
struct trace_stream *
trace_stream_create(const char *filename)
struct util_stream *
util_stream_create(const char *filename, size_t max_size)
{
struct trace_stream *stream;
struct util_stream *stream;
stream = CALLOC_STRUCT(trace_stream);
(void)max_size;
stream = CALLOC_STRUCT(util_stream);
if(!stream)
goto error1;
@ -70,7 +72,7 @@ error1:
boolean
trace_stream_write(struct trace_stream *stream, const void *data, size_t size)
util_stream_write(struct util_stream *stream, const void *data, size_t size)
{
if(!stream)
return FALSE;
@ -80,7 +82,7 @@ trace_stream_write(struct trace_stream *stream, const void *data, size_t size)
void
trace_stream_flush(struct trace_stream *stream)
util_stream_flush(struct util_stream *stream)
{
if(!stream)
return;
@ -90,7 +92,7 @@ trace_stream_flush(struct trace_stream *stream)
void
trace_stream_close(struct trace_stream *stream)
util_stream_close(struct util_stream *stream)
{
if(!stream)
return;

View File

@ -40,16 +40,18 @@
#include "util/u_memory.h"
#include "util/u_string.h"
#include "tr_stream.h"
#include "u_stream.h"
#define MAP_FILE_SIZE (4*1024*1024)
struct trace_stream
struct util_stream
{
char filename[MAX_PATH + 1];
WCHAR wFileName[MAX_PATH + 1];
boolean growable;
size_t map_size;
ULONG_PTR iFile;
char *pMap;
size_t written;
@ -58,17 +60,23 @@ struct trace_stream
static INLINE boolean
trace_stream_map(struct trace_stream *stream)
util_stream_map(struct util_stream *stream)
{
ULONG BytesInUnicodeString;
static char filename[MAX_PATH + 1];
unsigned filename_len;
filename_len = util_snprintf(filename,
sizeof(filename),
"\\??\\%s.%04x",
stream->filename,
stream->suffix++);
if(stream->growable)
filename_len = util_snprintf(filename,
sizeof(filename),
"%s.%04x",
stream->filename,
stream->suffix++);
else
filename_len = util_snprintf(filename,
sizeof(filename),
"%s",
stream->filename);
EngMultiByteToUnicodeN(
stream->wFileName,
@ -77,11 +85,11 @@ trace_stream_map(struct trace_stream *stream)
filename,
filename_len);
stream->pMap = EngMapFile(stream->wFileName, MAP_FILE_SIZE, &stream->iFile);
stream->pMap = EngMapFile(stream->wFileName, stream->map_size, &stream->iFile);
if(!stream->pMap)
return FALSE;
memset(stream->pMap, 0, MAP_FILE_SIZE);
memset(stream->pMap, 0, stream->map_size);
stream->written = 0;
return TRUE;
@ -89,10 +97,10 @@ trace_stream_map(struct trace_stream *stream)
static INLINE void
trace_stream_unmap(struct trace_stream *stream)
util_stream_unmap(struct util_stream *stream)
{
EngUnmapFile(stream->iFile);
if(stream->written < MAP_FILE_SIZE) {
if(stream->written < stream->map_size) {
/* Truncate file size */
stream->pMap = EngMapFile(stream->wFileName, stream->written, &stream->iFile);
if(stream->pMap)
@ -103,18 +111,51 @@ trace_stream_unmap(struct trace_stream *stream)
}
struct trace_stream *
trace_stream_create(const char *filename)
static INLINE void
util_stream_full_qualified_filename(char *dst, size_t size, const char *src)
{
struct trace_stream *stream;
boolean need_drive, need_root;
stream = CALLOC_STRUCT(trace_stream);
if((('A' <= src[0] && src[0] <= 'Z') || ('a' <= src[0] && src[0] <= 'z')) && src[1] == ':') {
need_drive = FALSE;
need_root = src[2] == '\\' ? FALSE : TRUE;
}
else {
need_drive = TRUE;
need_root = src[0] == '\\' ? FALSE : TRUE;
}
util_snprintf(dst, size,
"\\??\\%s%s%s",
need_drive ? "C:" : "",
need_root ? "\\" : "",
src);
}
struct util_stream *
util_stream_create(const char *filename, size_t max_size)
{
struct util_stream *stream;
stream = CALLOC_STRUCT(util_stream);
if(!stream)
goto error1;
strncpy(stream->filename, filename, sizeof(stream->filename));
util_stream_full_qualified_filename(stream->filename,
sizeof(stream->filename),
filename);
if(!trace_stream_map(stream))
if(max_size) {
stream->growable = FALSE;
stream->map_size = max_size;
}
else {
stream->growable = TRUE;
stream->map_size = MAP_FILE_SIZE;
}
if(!util_stream_map(stream))
goto error2;
return stream;
@ -127,16 +168,16 @@ error1:
static INLINE void
trace_stream_copy(struct trace_stream *stream, const char *data, size_t size)
util_stream_copy(struct util_stream *stream, const char *data, size_t size)
{
assert(stream->written + size <= MAP_FILE_SIZE);
assert(stream->written + size <= stream->map_size);
memcpy(stream->pMap + stream->written, data, size);
stream->written += size;
}
boolean
trace_stream_write(struct trace_stream *stream, const void *data, size_t size)
util_stream_write(struct util_stream *stream, const void *data, size_t size)
{
if(!stream)
return FALSE;
@ -144,37 +185,37 @@ trace_stream_write(struct trace_stream *stream, const void *data, size_t size)
if(!stream->pMap)
return FALSE;
while(stream->written + size > MAP_FILE_SIZE) {
size_t step = MAP_FILE_SIZE - stream->written;
trace_stream_copy(stream, data, step);
while(stream->written + size > stream->map_size) {
size_t step = stream->map_size - stream->written;
util_stream_copy(stream, data, step);
data = (const char *)data + step;
size -= step;
trace_stream_unmap(stream);
if(!trace_stream_map(stream))
util_stream_unmap(stream);
if(!stream->growable || !util_stream_map(stream))
return FALSE;
}
trace_stream_copy(stream, data, size);
util_stream_copy(stream, data, size);
return TRUE;
}
void
trace_stream_flush(struct trace_stream *stream)
util_stream_flush(struct util_stream *stream)
{
(void)stream;
}
void
trace_stream_close(struct trace_stream *stream)
util_stream_close(struct util_stream *stream)
{
if(!stream)
return;
trace_stream_unmap(stream);
util_stream_unmap(stream);
FREE(stream);
}

View File

@ -136,6 +136,26 @@ util_time_diff(const struct util_time *t1,
}
uint64_t
util_time_micros( void )
{
struct util_time t1;
util_time_get(&t1);
#if defined(PIPE_OS_LINUX)
return t1.tv.tv_usec + t1.tv.tv_sec*1000000LL;
#elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE)
util_time_get_frequency();
return t1.counter*INT64_C(1000000)/frequency;
#elif defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)
return t1.counter/10;
#endif
}
/**
* Compare two time values.
*

View File

@ -74,6 +74,9 @@ util_time_add(const struct util_time *t1,
int64_t usecs,
struct util_time *t2);
uint64_t
util_time_micros( void );
int64_t
util_time_diff(const struct util_time *t1,
const struct util_time *t2);

View File

@ -0,0 +1,346 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
**************************************************************************/
/*
* Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com>
*/
#include "pipe/p_winsys.h"
#include "u_timed_winsys.h"
#include "util/u_memory.h"
#include "util/u_time.h"
struct timed_winsys {
struct pipe_winsys base;
struct pipe_winsys *backend;
uint64_t last_dump;
struct {
const char *name_key;
double total;
unsigned calls;
} funcs[13];
};
static struct timed_winsys *timed_winsys( struct pipe_winsys *winsys )
{
return (struct timed_winsys *)winsys;
}
static uint64_t time_start( void )
{
return util_time_micros();
}
static void time_display( struct pipe_winsys *winsys )
{
struct timed_winsys *tws = timed_winsys(winsys);
unsigned i;
double overall = 0;
for (i = 0; i < Elements(tws->funcs); i++) {
if (tws->funcs[i].name_key) {
debug_printf("*** %-25s %5.3fms (%d calls, avg %.3fms)\n",
tws->funcs[i].name_key,
tws->funcs[i].total,
tws->funcs[i].calls,
tws->funcs[i].total / tws->funcs[i].calls);
overall += tws->funcs[i].total;
tws->funcs[i].calls = 0;
tws->funcs[i].total = 0;
}
}
debug_printf("*** %-25s %5.3fms\n",
"OVERALL WINSYS",
overall);
}
static void time_finish( struct pipe_winsys *winsys,
long long startval,
unsigned idx,
const char *name )
{
struct timed_winsys *tws = timed_winsys(winsys);
uint64_t endval = util_time_micros();
double elapsed = (endval - startval)/1000.0;
if (endval - startval > 1000LL)
debug_printf("*** %s %.3f\n", name, elapsed );
assert( tws->funcs[idx].name_key == name ||
tws->funcs[idx].name_key == NULL);
tws->funcs[idx].name_key = name;
tws->funcs[idx].total += elapsed;
tws->funcs[idx].calls++;
if (endval - tws->last_dump > 10LL * 1000LL * 1000LL) {
time_display( winsys );
tws->last_dump = endval;
}
}
/* Pipe has no concept of pools, but the psb driver passes a flag that
* can be mapped onto pools in the backend.
*/
static struct pipe_buffer *
timed_buffer_create(struct pipe_winsys *winsys,
unsigned alignment,
unsigned usage,
unsigned size )
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
struct pipe_buffer *buf = backend->buffer_create( backend, alignment, usage, size );
time_finish(winsys, start, 0, __FUNCTION__);
return buf;
}
static struct pipe_buffer *
timed_user_buffer_create(struct pipe_winsys *winsys,
void *data,
unsigned bytes)
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
struct pipe_buffer *buf = backend->user_buffer_create( backend, data, bytes );
time_finish(winsys, start, 1, __FUNCTION__);
return buf;
}
static void *
timed_buffer_map(struct pipe_winsys *winsys,
struct pipe_buffer *buf,
unsigned flags)
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
void *map = backend->buffer_map( backend, buf, flags );
time_finish(winsys, start, 2, __FUNCTION__);
return map;
}
static void
timed_buffer_unmap(struct pipe_winsys *winsys,
struct pipe_buffer *buf)
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
backend->buffer_unmap( backend, buf );
time_finish(winsys, start, 3, __FUNCTION__);
}
static void
timed_buffer_destroy(struct pipe_winsys *winsys,
struct pipe_buffer *buf)
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
backend->buffer_destroy( backend, buf );
time_finish(winsys, start, 4, __FUNCTION__);
}
static void
timed_flush_frontbuffer( struct pipe_winsys *winsys,
struct pipe_surface *surf,
void *context_private)
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
backend->flush_frontbuffer( backend, surf, context_private );
time_finish(winsys, start, 5, __FUNCTION__);
}
static struct pipe_surface *
timed_surface_alloc(struct pipe_winsys *winsys)
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
struct pipe_surface *surf = backend->surface_alloc( backend );
time_finish(winsys, start, 6, __FUNCTION__);
return surf;
}
static int
timed_surface_alloc_storage(struct pipe_winsys *winsys,
struct pipe_surface *surf,
unsigned width, unsigned height,
enum pipe_format format,
unsigned flags,
unsigned tex_usage)
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
int ret = backend->surface_alloc_storage( backend, surf, width, height,
format, flags, tex_usage );
time_finish(winsys, start, 7, __FUNCTION__);
return ret;
}
static void
timed_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
backend->surface_release( backend, s );
time_finish(winsys, start, 8, __FUNCTION__);
}
static const char *
timed_get_name( struct pipe_winsys *winsys )
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
const char *ret = backend->get_name( backend );
time_finish(winsys, start, 9, __FUNCTION__);
return ret;
}
static void
timed_fence_reference(struct pipe_winsys *winsys,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *fence)
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
backend->fence_reference( backend, ptr, fence );
time_finish(winsys, start, 10, __FUNCTION__);
}
static int
timed_fence_signalled( struct pipe_winsys *winsys,
struct pipe_fence_handle *fence,
unsigned flag )
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
int ret = backend->fence_signalled( backend, fence, flag );
time_finish(winsys, start, 11, __FUNCTION__);
return ret;
}
static int
timed_fence_finish( struct pipe_winsys *winsys,
struct pipe_fence_handle *fence,
unsigned flag )
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
uint64_t start = time_start();
int ret = backend->fence_finish( backend, fence, flag );
time_finish(winsys, start, 12, __FUNCTION__);
return ret;
}
static void
timed_winsys_destroy( struct pipe_winsys *winsys )
{
struct pipe_winsys *backend = timed_winsys(winsys)->backend;
backend->destroy( backend );
FREE(winsys);
}
struct pipe_winsys *u_timed_winsys_create( struct pipe_winsys *backend )
{
struct timed_winsys *ws = CALLOC_STRUCT(timed_winsys);
ws->base.user_buffer_create = timed_user_buffer_create;
ws->base.buffer_map = timed_buffer_map;
ws->base.buffer_unmap = timed_buffer_unmap;
ws->base.buffer_destroy = timed_buffer_destroy;
ws->base.buffer_create = timed_buffer_create;
ws->base.flush_frontbuffer = timed_flush_frontbuffer;
ws->base.get_name = timed_get_name;
ws->base.surface_alloc = timed_surface_alloc;
ws->base.surface_alloc_storage = timed_surface_alloc_storage;
ws->base.surface_release = timed_surface_release;
ws->base.fence_reference = timed_fence_reference;
ws->base.fence_signalled = timed_fence_signalled;
ws->base.fence_finish = timed_fence_finish;
ws->base.destroy = timed_winsys_destroy;
ws->backend = backend;
return &ws->base;
}

View File

@ -0,0 +1,41 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
**************************************************************************/
/*
* Authors: Keith Whitwell <keithw-at-tungstengraphics-dot-com>
*/
#ifndef U_TIMED_WINSYS_H
#define U_TIMED_WINSYS_H
struct pipe_winsys;
struct pipe_winsys *u_timed_winsys_create( struct pipe_winsys *backend );
#endif

View File

@ -84,7 +84,7 @@
#define CELL_CMD_BATCH 5
#define CELL_CMD_RELEASE_VERTS 6
#define CELL_CMD_STATE_FRAMEBUFFER 10
#define CELL_CMD_STATE_DEPTH_STENCIL 11
#define CELL_CMD_STATE_FRAGMENT_OPS 11
#define CELL_CMD_STATE_SAMPLER 12
#define CELL_CMD_STATE_TEXTURE 13
#define CELL_CMD_STATE_VERTEX_INFO 14
@ -92,9 +92,7 @@
#define CELL_CMD_STATE_UNIFORMS 16
#define CELL_CMD_STATE_VS_ARRAY_INFO 17
#define CELL_CMD_STATE_BIND_VS 18
#define CELL_CMD_STATE_BLEND 19
#define CELL_CMD_STATE_ATTRIB_FETCH 20
#define CELL_CMD_STATE_LOGICOP 21
#define CELL_CMD_VS_EXECUTE 22
#define CELL_CMD_FLUSH_BUFFER_RANGE 23
@ -106,30 +104,24 @@
#define CELL_BUFFER_STATUS_USED 20
#define CELL_DEBUG_CHECKER (1 << 0)
#define CELL_DEBUG_SYNC (1 << 1)
/**
*/
struct cell_command_depth_stencil_alpha_test {
uint64_t base; /**< Effective address of code start. */
unsigned size; /**< Size in bytes of SPE code. */
unsigned read_depth; /**< Flag: should depth be read? */
unsigned read_stencil; /**< Flag: should stencil be read? */
};
/** Max instructions for doing per-fragment operations */
#define SPU_MAX_FRAGMENT_OPS_INSTS 64
/**
* Upload code to perform framebuffer blend operation
* Command to specify per-fragment operations state and generated code.
*/
struct cell_command_blend {
uint64_t base; /**< Effective address of code start. */
unsigned size; /**< Size in bytes of SPE code. */
unsigned read_fb; /**< Flag: should framebuffer be read? */
};
struct cell_command_logicop {
uint64_t base; /**< Effective address of code start. */
unsigned size; /**< Size in bytes of SPE code. */
struct cell_command_fragment_ops
{
uint64_t opcode; /**< CELL_CMD_STATE_FRAGMENT_OPS */
struct pipe_depth_stencil_alpha_state dsa;
struct pipe_blend_state blend;
unsigned code[SPU_MAX_FRAGMENT_OPS_INSTS];
};
@ -169,13 +161,15 @@ struct cell_array_info
};
struct cell_attribute_fetch_code {
struct cell_attribute_fetch_code
{
uint64_t base;
uint size;
};
struct cell_buffer_range {
struct cell_buffer_range
{
uint64_t base;
unsigned size;
};
@ -263,6 +257,7 @@ struct cell_init_info
{
unsigned id;
unsigned num_spus;
unsigned debug_flags; /**< mask of CELL_DEBUG_x flags */
struct cell_command *cmd;
/** Buffers for command batches, vertex/index data */

View File

@ -5,7 +5,7 @@
TOP = ../../../../..
include $(TOP)/configs/linux-cell
include $(TOP)/configs/current
# This is the "top-level" cell PPU driver code, will get pulled into libGL.so
@ -25,9 +25,9 @@ SOURCES = \
cell_context.c \
cell_draw_arrays.c \
cell_flush.c \
cell_gen_fragment.c \
cell_state_derived.c \
cell_state_emit.c \
cell_state_per_fragment.c \
cell_state_shader.c \
cell_pipe_state.c \
cell_screen.c \

View File

@ -32,6 +32,13 @@
/**
* Search the buffer pool for an empty/free buffer and return its index.
* Buffers are used for storing vertex data, state and commands which
* will be sent to the SPUs.
* If no empty buffers are available, wait for one.
* \return buffer index in [0, CELL_NUM_BUFFERS-1]
*/
uint
cell_get_empty_buffer(struct cell_context *cell)
{
@ -74,6 +81,11 @@ cell_get_empty_buffer(struct cell_context *cell)
}
/**
* Flush the current batch buffer to the SPUs.
* An empty buffer will be found and set as the new current batch buffer
* for subsequent commands/data.
*/
void
cell_batch_flush(struct cell_context *cell)
{
@ -93,11 +105,11 @@ cell_batch_flush(struct cell_context *cell)
/*
printf("cell_batch_dispatch: buf %u at %p, size %u\n",
batch, &cell->batch_buffer[batch][0], size);
batch, &cell->buffer[batch][0], size);
*/
/*
* Build "BATCH" command and sent to all SPUs.
* Build "BATCH" command and send to all SPUs.
*/
cmd_word = CELL_CMD_BATCH | (batch << 8) | (size << 16);
@ -120,6 +132,9 @@ cell_batch_flush(struct cell_context *cell)
}
/**
* Return the number of bytes free in the current batch buffer.
*/
uint
cell_batch_free_space(const struct cell_context *cell)
{
@ -129,7 +144,9 @@ cell_batch_free_space(const struct cell_context *cell)
/**
* Append data to current batch.
* Append data to the current batch buffer.
* \param data address of block of bytes to append
* \param bytes size of block of bytes
*/
void
cell_batch_append(struct cell_context *cell, const void *data, uint bytes)
@ -165,6 +182,10 @@ cell_batch_append(struct cell_context *cell, const void *data, uint bytes)
}
/**
* Allocate space in the current batch buffer for 'bytes' space.
* \return address in batch buffer to put data
*/
void *
cell_batch_alloc(struct cell_context *cell, uint bytes)
{
@ -172,6 +193,10 @@ cell_batch_alloc(struct cell_context *cell, uint bytes)
}
/**
* Same as \sa cell_batch_alloc, but return an address at a particular
* alignment.
*/
void *
cell_batch_alloc_aligned(struct cell_context *cell, uint bytes,
uint alignment)
@ -215,3 +240,28 @@ cell_batch_alloc_aligned(struct cell_context *cell, uint bytes,
return pos;
}
/**
* One-time init of batch buffers.
*/
void
cell_init_batch_buffers(struct cell_context *cell)
{
uint spu, buf;
/* init command, vertex/index buffer info */
for (buf = 0; buf < CELL_NUM_BUFFERS; buf++) {
cell->buffer_size[buf] = 0;
/* init batch buffer status values,
* mark 0th buffer as used, rest as free.
*/
for (spu = 0; spu < cell->num_spus; spu++) {
if (buf == 0)
cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED;
else
cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_FREE;
}
}
}

View File

@ -54,5 +54,8 @@ extern void *
cell_batch_alloc_aligned(struct cell_context *cell, uint bytes,
uint alignment);
extern void
cell_init_batch_buffers(struct cell_context *cell);
#endif /* CELL_BATCH_H */

View File

@ -35,6 +35,7 @@
#include <stdint.h>
#include "pipe/p_inlines.h"
#include "util/u_memory.h"
#include "util/u_pack_color.h"
#include "cell/common.h"
#include "cell_clear.h"
#include "cell_context.h"
@ -44,6 +45,27 @@
#include "cell_state.h"
/**
* Convert packed pixel from one format to another.
*/
static unsigned
convert_color(enum pipe_format srcFormat, unsigned srcColor,
enum pipe_format dstFormat)
{
ubyte r, g, b, a;
unsigned dstColor;
util_unpack_color_ub(srcFormat, &srcColor, &r, &g, &b, &a);
util_pack_color_ub(r, g, b, a, dstFormat, &dstColor);
return dstColor;
}
/**
* Called via pipe->clear()
*/
void
cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps,
unsigned clearValue)
@ -61,13 +83,21 @@ cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps,
PIPE_BUFFER_USAGE_GPU_WRITE);
if (ps == cell->framebuffer.zsbuf) {
/* clear z/stencil buffer */
surfIndex = 1;
}
else {
/* clear color buffer */
surfIndex = 0;
if (ps->format != PIPE_FORMAT_A8R8G8B8_UNORM) {
clearValue = convert_color(PIPE_FORMAT_A8R8G8B8_UNORM, clearValue,
ps->format);
}
}
/* Build a CLEAR command and place it in the current batch buffer */
{
struct cell_command_clear_surface *clr
= (struct cell_command_clear_surface *)

View File

@ -43,11 +43,11 @@
#include "draw/draw_private.h"
#include "cell/common.h"
#include "cell_batch.h"
#include "cell_clear.h"
#include "cell_context.h"
#include "cell_draw_arrays.h"
#include "cell_flush.h"
#include "cell_render.h"
#include "cell_state.h"
#include "cell_surface.h"
#include "cell_spu.h"
@ -85,12 +85,20 @@ cell_draw_create(struct cell_context *cell)
}
#ifdef DEBUG
static const struct debug_named_value cell_debug_flags[] = {
{"checker", CELL_DEBUG_CHECKER},/**< modulate tile clear color by SPU ID */
{"sync", CELL_DEBUG_SYNC}, /**< SPUs do synchronous DMA */
{NULL, 0}
};
#endif
struct pipe_context *
cell_create_context(struct pipe_screen *screen,
struct cell_winsys *cws)
{
struct cell_context *cell;
uint spu, buf;
/* some fields need to be 16-byte aligned, so align the whole object */
cell = (struct cell_context*) align_malloc(sizeof(struct cell_context), 16);
@ -104,15 +112,6 @@ cell_create_context(struct pipe_screen *screen,
cell->pipe.screen = screen;
cell->pipe.destroy = cell_destroy_context;
/* state setters */
cell->pipe.set_vertex_buffers = cell_set_vertex_buffers;
cell->pipe.set_vertex_elements = cell_set_vertex_elements;
cell->pipe.draw_arrays = cell_draw_arrays;
cell->pipe.draw_elements = cell_draw_elements;
cell->pipe.draw_range_elements = cell_draw_range_elements;
cell->pipe.set_edgeflags = cell_set_edgeflags;
cell->pipe.clear = cell_clear_surface;
cell->pipe.flush = cell_flush;
@ -122,20 +121,28 @@ cell_create_context(struct pipe_screen *screen,
cell->pipe.wait_query = cell_wait_query;
#endif
cell_init_draw_functions(cell);
cell_init_state_functions(cell);
cell_init_shader_functions(cell);
cell_init_surface_functions(cell);
cell_init_texture_functions(cell);
cell_init_vertex_functions(cell);
cell->draw = cell_draw_create(cell);
cell_init_vbuf(cell);
draw_set_rasterize_stage(cell->draw, cell->vbuf);
/* convert all points/lines to tris for the time being */
draw_wide_point_threshold(cell->draw, 0.0);
draw_wide_line_threshold(cell->draw, 0.0);
/* get env vars or read config file to get debug flags */
cell->debug_flags = debug_get_flags_option("CELL_DEBUG",
cell_debug_flags,
0 );
/*
* SPU stuff
*/
@ -146,20 +153,7 @@ cell_create_context(struct pipe_screen *screen,
cell_start_spus(cell);
/* init command, vertex/index buffer info */
for (buf = 0; buf < CELL_NUM_BUFFERS; buf++) {
cell->buffer_size[buf] = 0;
/* init batch buffer status values,
* mark 0th buffer as used, rest as free.
*/
for (spu = 0; spu < cell->num_spus; spu++) {
if (buf == 0)
cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_USED;
else
cell->buffer_status[spu][buf][0] = CELL_BUFFER_STATUS_FREE;
}
}
cell_init_batch_buffers(cell);
return &cell->pipe;
}

View File

@ -39,8 +39,13 @@
#include "rtasm/rtasm_ppc_spe.h"
#include "tgsi/tgsi_scan.h"
struct cell_vbuf_render;
/**
* Cell vertex shader state, subclass of pipe_shader_state.
*/
struct cell_vertex_shader_state
{
struct pipe_shader_state shader;
@ -49,6 +54,9 @@ struct cell_vertex_shader_state
};
/**
* Cell fragment shader state, subclass of pipe_shader_state.
*/
struct cell_fragment_shader_state
{
struct pipe_shader_state shader;
@ -57,7 +65,11 @@ struct cell_fragment_shader_state
};
struct cell_blend_state {
/**
* Cell blend state atom, subclass of pipe_blend_state.
*/
struct cell_blend_state
{
struct pipe_blend_state base;
/**
@ -67,17 +79,24 @@ struct cell_blend_state {
};
struct cell_depth_stencil_alpha_state {
struct pipe_depth_stencil_alpha_state base;
/**
* Cell depth/stencil/alpha state atom, subclass of
* pipe_depth_stencil_alpha_state.
*/
struct cell_depth_stencil_alpha_state
{
struct pipe_depth_stencil_alpha_state base;
/**
* Generated code to perform alpha, stencil, and depth testing on the SPE
*/
struct spe_function code;
};
/**
* Per-context state, subclass of pipe_context.
*/
struct cell_context
{
struct pipe_context pipe;
@ -144,6 +163,8 @@ struct cell_context
struct spe_function attrib_fetch;
unsigned attrib_fetch_offsets[PIPE_MAX_ATTRIBS];
unsigned debug_flags;
};

View File

@ -34,6 +34,7 @@
#include "pipe/p_defines.h"
#include "pipe/p_context.h"
#include "pipe/p_winsys.h"
#include "pipe/p_inlines.h"
#include "cell_context.h"
#include "cell_draw_arrays.h"
@ -76,14 +77,6 @@ cell_unmap_constant_buffers(struct cell_context *sp)
}
boolean
cell_draw_arrays(struct pipe_context *pipe, unsigned mode,
unsigned start, unsigned count)
{
return cell_draw_elements(pipe, NULL, 0, mode, start, count);
}
/**
* Draw vertex arrays, with optional indexing.
@ -92,7 +85,7 @@ cell_draw_arrays(struct pipe_context *pipe, unsigned mode,
*
* XXX should the element buffer be specified/bound with a separate function?
*/
boolean
static boolean
cell_draw_range_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer,
unsigned indexSize,
@ -116,7 +109,7 @@ cell_draw_range_elements(struct pipe_context *pipe,
* Map vertex buffers
*/
for (i = 0; i < sp->num_vertex_buffers; i++) {
void *buf = pipe->winsys->buffer_map(pipe->winsys,
void *buf = pipe_buffer_map(pipe->screen,
sp->vertex_buffer[i].buffer,
PIPE_BUFFER_USAGE_CPU_READ);
cell_flush_buffer_range(sp, buf, sp->vertex_buffer[i].buffer->size);
@ -124,7 +117,7 @@ cell_draw_range_elements(struct pipe_context *pipe,
}
/* Map index buffer, if present */
if (indexBuffer) {
void *mapped_indexes = pipe->winsys->buffer_map(pipe->winsys,
void *mapped_indexes = pipe_buffer_map(pipe->screen,
indexBuffer,
PIPE_BUFFER_USAGE_CPU_READ);
draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes);
@ -143,11 +136,11 @@ cell_draw_range_elements(struct pipe_context *pipe,
*/
for (i = 0; i < sp->num_vertex_buffers; i++) {
draw_set_mapped_vertex_buffer(draw, i, NULL);
pipe->winsys->buffer_unmap(pipe->winsys, sp->vertex_buffer[i].buffer);
pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer);
}
if (indexBuffer) {
draw_set_mapped_element_buffer(draw, 0, NULL);
pipe->winsys->buffer_unmap(pipe->winsys, indexBuffer);
pipe_buffer_unmap(pipe->screen, indexBuffer);
}
/* Note: leave drawing surfaces mapped */
@ -157,7 +150,7 @@ cell_draw_range_elements(struct pipe_context *pipe,
}
boolean
static boolean
cell_draw_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer,
unsigned indexSize,
@ -170,10 +163,29 @@ cell_draw_elements(struct pipe_context *pipe,
}
static boolean
cell_draw_arrays(struct pipe_context *pipe, unsigned mode,
unsigned start, unsigned count)
{
return cell_draw_elements(pipe, NULL, 0, mode, start, count);
}
void
static void
cell_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags)
{
struct cell_context *cell = cell_context(pipe);
draw_set_edgeflags(cell->draw, edgeflags);
}
void
cell_init_draw_functions(struct cell_context *cell)
{
cell->pipe.draw_arrays = cell_draw_arrays;
cell->pipe.draw_elements = cell_draw_elements;
cell->pipe.draw_range_elements = cell_draw_range_elements;
cell->pipe.set_edgeflags = cell_set_edgeflags;
}

View File

@ -29,26 +29,8 @@
#define CELL_DRAW_ARRAYS_H
extern boolean
cell_draw_arrays(struct pipe_context *pipe, unsigned mode,
unsigned start, unsigned count);
extern boolean
cell_draw_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer,
unsigned indexSize,
unsigned mode, unsigned start, unsigned count);
extern boolean
cell_draw_range_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer,
unsigned indexSize,
unsigned min_index,
unsigned max_index,
unsigned mode, unsigned start, unsigned count);
extern void
cell_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags);
cell_init_draw_functions(struct cell_context *cell);
#endif /* CELL_DRAW_ARRAYS_H */

View File

@ -34,6 +34,9 @@
#include "draw/draw_context.h"
/**
* Called via pipe->flush()
*/
void
cell_flush(struct pipe_context *pipe, unsigned flags,
struct pipe_fence_handle **fence)
@ -50,16 +53,19 @@ cell_flush(struct pipe_context *pipe, unsigned flags,
flags |= CELL_FLUSH_WAIT;
draw_flush( cell->draw );
cell_flush_int(pipe, flags);
cell_flush_int(cell, flags);
}
/** internal flush */
/**
* Cell internal flush function. Send the current batch buffer to all SPUs.
* If flags & CELL_FLUSH_WAIT, do not return until the SPUs are idle.
* \param flags bitmask of flags CELL_FLUSH_WAIT, or zero
*/
void
cell_flush_int(struct pipe_context *pipe, unsigned flags)
cell_flush_int(struct cell_context *cell, unsigned flags)
{
static boolean flushing = FALSE; /* recursion catcher */
struct cell_context *cell = cell_context(pipe);
uint i;
ASSERT(!flushing);

View File

@ -36,7 +36,7 @@ cell_flush(struct pipe_context *pipe, unsigned flags,
struct pipe_fence_handle **fence);
extern void
cell_flush_int(struct pipe_context *pipe, unsigned flags);
cell_flush_int(struct cell_context *cell, unsigned flags);
extern void
cell_flush_buffer_range(struct cell_context *cell, void *ptr,

View File

@ -0,0 +1,862 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* Generate SPU per-fragment code (actually per-quad code).
* \author Brian Paul
*/
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
#include "rtasm/rtasm_ppc_spe.h"
#include "cell_context.h"
#include "cell_gen_fragment.h"
/** Do extra optimizations? */
#define OPTIMIZATIONS 1
/**
* Generate SPE code to perform Z/depth testing.
*
* \param dsa Gallium depth/stencil/alpha state to gen code for
* \param f SPE function to append instruction onto.
* \param mask_reg register containing quad/pixel "alive" mask (in/out)
* \param ifragZ_reg register containing integer fragment Z values (in)
* \param ifbZ_reg register containing integer frame buffer Z values (in/out)
* \param zmask_reg register containing result of Z test/comparison (out)
*/
static void
gen_depth_test(const struct pipe_depth_stencil_alpha_state *dsa,
struct spe_function *f,
int mask_reg, int ifragZ_reg, int ifbZ_reg, int zmask_reg)
{
ASSERT(dsa->depth.enabled);
switch (dsa->depth.func) {
case PIPE_FUNC_EQUAL:
/* zmask = (ifragZ == ref) */
spe_ceq(f, zmask_reg, ifragZ_reg, ifbZ_reg);
/* mask = (mask & zmask) */
spe_and(f, mask_reg, mask_reg, zmask_reg);
break;
case PIPE_FUNC_NOTEQUAL:
/* zmask = (ifragZ == ref) */
spe_ceq(f, zmask_reg, ifragZ_reg, ifbZ_reg);
/* mask = (mask & ~zmask) */
spe_andc(f, mask_reg, mask_reg, zmask_reg);
break;
case PIPE_FUNC_GREATER:
/* zmask = (ifragZ > ref) */
spe_cgt(f, zmask_reg, ifragZ_reg, ifbZ_reg);
/* mask = (mask & zmask) */
spe_and(f, mask_reg, mask_reg, zmask_reg);
break;
case PIPE_FUNC_LESS:
/* zmask = (ref > ifragZ) */
spe_cgt(f, zmask_reg, ifbZ_reg, ifragZ_reg);
/* mask = (mask & zmask) */
spe_and(f, mask_reg, mask_reg, zmask_reg);
break;
case PIPE_FUNC_LEQUAL:
/* zmask = (ifragZ > ref) */
spe_cgt(f, zmask_reg, ifragZ_reg, ifbZ_reg);
/* mask = (mask & ~zmask) */
spe_andc(f, mask_reg, mask_reg, zmask_reg);
break;
case PIPE_FUNC_GEQUAL:
/* zmask = (ref > ifragZ) */
spe_cgt(f, zmask_reg, ifbZ_reg, ifragZ_reg);
/* mask = (mask & ~zmask) */
spe_andc(f, mask_reg, mask_reg, zmask_reg);
break;
case PIPE_FUNC_NEVER:
spe_il(f, mask_reg, 0); /* mask = {0,0,0,0} */
spe_move(f, zmask_reg, mask_reg); /* zmask = mask */
break;
case PIPE_FUNC_ALWAYS:
/* mask unchanged */
spe_il(f, zmask_reg, ~0); /* zmask = {~0,~0,~0,~0} */
break;
default:
ASSERT(0);
break;
}
if (dsa->depth.writemask) {
/*
* If (ztest passed) {
* framebufferZ = fragmentZ;
* }
* OR,
* framebufferZ = (ztest_passed ? fragmentZ : framebufferZ;
*/
spe_selb(f, ifbZ_reg, ifbZ_reg, ifragZ_reg, mask_reg);
}
}
/**
* Generate SPE code to perform alpha testing.
*
* \param dsa Gallium depth/stencil/alpha state to gen code for
* \param f SPE function to append instruction onto.
* \param mask_reg register containing quad/pixel "alive" mask (in/out)
* \param fragA_reg register containing four fragment alpha values (in)
*/
static void
gen_alpha_test(const struct pipe_depth_stencil_alpha_state *dsa,
struct spe_function *f, int mask_reg, int fragA_reg)
{
int ref_reg = spe_allocate_available_register(f);
int amask_reg = spe_allocate_available_register(f);
ASSERT(dsa->alpha.enabled);
if ((dsa->alpha.func != PIPE_FUNC_NEVER) &&
(dsa->alpha.func != PIPE_FUNC_ALWAYS)) {
/* load/splat the alpha reference float value */
spe_load_float(f, ref_reg, dsa->alpha.ref);
}
/* emit code to do the alpha comparison, updating 'mask' */
switch (dsa->alpha.func) {
case PIPE_FUNC_EQUAL:
/* amask = (fragA == ref) */
spe_fceq(f, amask_reg, fragA_reg, ref_reg);
/* mask = (mask & amask) */
spe_and(f, mask_reg, mask_reg, amask_reg);
break;
case PIPE_FUNC_NOTEQUAL:
/* amask = (fragA == ref) */
spe_fceq(f, amask_reg, fragA_reg, ref_reg);
/* mask = (mask & ~amask) */
spe_andc(f, mask_reg, mask_reg, amask_reg);
break;
case PIPE_FUNC_GREATER:
/* amask = (fragA > ref) */
spe_fcgt(f, amask_reg, fragA_reg, ref_reg);
/* mask = (mask & amask) */
spe_and(f, mask_reg, mask_reg, amask_reg);
break;
case PIPE_FUNC_LESS:
/* amask = (ref > fragA) */
spe_fcgt(f, amask_reg, ref_reg, fragA_reg);
/* mask = (mask & amask) */
spe_and(f, mask_reg, mask_reg, amask_reg);
break;
case PIPE_FUNC_LEQUAL:
/* amask = (fragA > ref) */
spe_fcgt(f, amask_reg, fragA_reg, ref_reg);
/* mask = (mask & ~amask) */
spe_andc(f, mask_reg, mask_reg, amask_reg);
break;
case PIPE_FUNC_GEQUAL:
/* amask = (ref > fragA) */
spe_fcgt(f, amask_reg, ref_reg, fragA_reg);
/* mask = (mask & ~amask) */
spe_andc(f, mask_reg, mask_reg, amask_reg);
break;
case PIPE_FUNC_NEVER:
spe_il(f, mask_reg, 0); /* mask = [0,0,0,0] */
break;
case PIPE_FUNC_ALWAYS:
/* no-op, mask unchanged */
break;
default:
ASSERT(0);
break;
}
#if OPTIMIZATIONS
/* if mask == {0,0,0,0} we're all done, return */
{
/* re-use amask reg here */
int tmp_reg = amask_reg;
/* tmp[0] = (mask[0] | mask[1] | mask[2] | mask[3]) */
spe_orx(f, tmp_reg, mask_reg);
/* if tmp[0] == 0 then return from function call */
spe_biz(f, tmp_reg, SPE_REG_RA, 0, 0);
}
#endif
spe_release_register(f, ref_reg);
spe_release_register(f, amask_reg);
}
/**
* Generate SPE code to implement the given blend mode for a quad of pixels.
* \param f SPE function to append instruction onto.
* \param fragR_reg register with fragment red values (float) (in/out)
* \param fragG_reg register with fragment green values (float) (in/out)
* \param fragB_reg register with fragment blue values (float) (in/out)
* \param fragA_reg register with fragment alpha values (float) (in/out)
* \param fbRGBA_reg register with packed framebuffer colors (integer) (in)
*/
static void
gen_blend(const struct pipe_blend_state *blend,
struct spe_function *f,
enum pipe_format color_format,
int fragR_reg, int fragG_reg, int fragB_reg, int fragA_reg,
int fbRGBA_reg)
{
int term1R_reg = spe_allocate_available_register(f);
int term1G_reg = spe_allocate_available_register(f);
int term1B_reg = spe_allocate_available_register(f);
int term1A_reg = spe_allocate_available_register(f);
int term2R_reg = spe_allocate_available_register(f);
int term2G_reg = spe_allocate_available_register(f);
int term2B_reg = spe_allocate_available_register(f);
int term2A_reg = spe_allocate_available_register(f);
int fbR_reg = spe_allocate_available_register(f);
int fbG_reg = spe_allocate_available_register(f);
int fbB_reg = spe_allocate_available_register(f);
int fbA_reg = spe_allocate_available_register(f);
int one_reg = spe_allocate_available_register(f);
int tmp_reg = spe_allocate_available_register(f);
ASSERT(blend->blend_enable);
/* Unpack/convert framebuffer colors from four 32-bit packed colors
* (fbRGBA) to four float RGBA vectors (fbR, fbG, fbB, fbA).
* Each 8-bit color component is expanded into a float in [0.0, 1.0].
*/
{
int mask_reg = spe_allocate_available_register(f);
/* mask = {0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff} */
spe_fsmbi(f, mask_reg, 0x1111);
/* XXX there may be more clever ways to implement the following code */
switch (color_format) {
case PIPE_FORMAT_A8R8G8B8_UNORM:
/* fbB = fbB & mask */
spe_and(f, fbB_reg, fbRGBA_reg, mask_reg);
/* mask = mask << 8 */
spe_roti(f, mask_reg, mask_reg, 8);
/* fbG = fbRGBA & mask */
spe_and(f, fbG_reg, fbRGBA_reg, mask_reg);
/* fbG = fbG >> 8 */
spe_roti(f, fbG_reg, fbG_reg, -8);
/* mask = mask << 8 */
spe_roti(f, mask_reg, mask_reg, 8);
/* fbR = fbRGBA & mask */
spe_and(f, fbR_reg, fbRGBA_reg, mask_reg);
/* fbR = fbR >> 16 */
spe_roti(f, fbR_reg, fbR_reg, -16);
/* mask = mask << 8 */
spe_roti(f, mask_reg, mask_reg, 8);
/* fbA = fbRGBA & mask */
spe_and(f, fbA_reg, fbRGBA_reg, mask_reg);
/* fbA = fbA >> 24 */
spe_roti(f, fbA_reg, fbA_reg, -24);
break;
case PIPE_FORMAT_B8G8R8A8_UNORM:
/* fbA = fbA & mask */
spe_and(f, fbA_reg, fbRGBA_reg, mask_reg);
/* mask = mask << 8 */
spe_roti(f, mask_reg, mask_reg, 8);
/* fbR = fbRGBA & mask */
spe_and(f, fbR_reg, fbRGBA_reg, mask_reg);
/* fbR = fbR >> 8 */
spe_roti(f, fbR_reg, fbR_reg, -8);
/* mask = mask << 8 */
spe_roti(f, mask_reg, mask_reg, 8);
/* fbG = fbRGBA & mask */
spe_and(f, fbG_reg, fbRGBA_reg, mask_reg);
/* fbG = fbG >> 16 */
spe_roti(f, fbG_reg, fbG_reg, -16);
/* mask = mask << 8 */
spe_roti(f, mask_reg, mask_reg, 8);
/* fbB = fbRGBA & mask */
spe_and(f, fbB_reg, fbRGBA_reg, mask_reg);
/* fbB = fbB >> 24 */
spe_roti(f, fbB_reg, fbB_reg, -24);
break;
default:
ASSERT(0);
}
/* convert int[4] in [0,255] to float[4] in [0.0, 1.0] */
spe_cuflt(f, fbR_reg, fbR_reg, 8);
spe_cuflt(f, fbG_reg, fbG_reg, 8);
spe_cuflt(f, fbB_reg, fbB_reg, 8);
spe_cuflt(f, fbA_reg, fbA_reg, 8);
spe_release_register(f, mask_reg);
}
/*
* Compute Src RGB terms
*/
switch (blend->rgb_src_factor) {
case PIPE_BLENDFACTOR_ONE:
spe_move(f, term1R_reg, fragR_reg);
spe_move(f, term1G_reg, fragG_reg);
spe_move(f, term1B_reg, fragB_reg);
break;
case PIPE_BLENDFACTOR_ZERO:
spe_zero(f, term1R_reg);
spe_zero(f, term1G_reg);
spe_zero(f, term1B_reg);
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
spe_fm(f, term1R_reg, fragR_reg, fragR_reg);
spe_fm(f, term1G_reg, fragG_reg, fragG_reg);
spe_fm(f, term1B_reg, fragB_reg, fragB_reg);
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
spe_fm(f, term1R_reg, fragR_reg, fragA_reg);
spe_fm(f, term1G_reg, fragG_reg, fragA_reg);
spe_fm(f, term1B_reg, fragB_reg, fragA_reg);
break;
/* XXX more cases */
default:
ASSERT(0);
}
/*
* Compute Src Alpha term
*/
switch (blend->alpha_src_factor) {
case PIPE_BLENDFACTOR_ONE:
spe_move(f, term1A_reg, fragA_reg);
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
spe_fm(f, term1A_reg, fragA_reg, fragA_reg);
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
spe_fm(f, term1A_reg, fragA_reg, fragA_reg);
break;
/* XXX more cases */
default:
ASSERT(0);
}
/*
* Compute Dest RGB terms
*/
switch (blend->rgb_dst_factor) {
case PIPE_BLENDFACTOR_ONE:
spe_move(f, term2R_reg, fbR_reg);
spe_move(f, term2G_reg, fbG_reg);
spe_move(f, term2B_reg, fbB_reg);
break;
case PIPE_BLENDFACTOR_ZERO:
spe_zero(f, term2R_reg);
spe_zero(f, term2G_reg);
spe_zero(f, term2B_reg);
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
spe_fm(f, term2R_reg, fbR_reg, fragR_reg);
spe_fm(f, term2G_reg, fbG_reg, fragG_reg);
spe_fm(f, term2B_reg, fbB_reg, fragB_reg);
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
spe_fm(f, term2R_reg, fbR_reg, fragA_reg);
spe_fm(f, term2G_reg, fbG_reg, fragA_reg);
spe_fm(f, term2B_reg, fbB_reg, fragA_reg);
break;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
/* one = {1.0, 1.0, 1.0, 1.0} */
spe_load_float(f, one_reg, 1.0f);
/* tmp = one - fragA */
spe_fs(f, tmp_reg, one_reg, fragA_reg);
/* term = fb * tmp */
spe_fm(f, term2R_reg, fbR_reg, tmp_reg);
spe_fm(f, term2G_reg, fbG_reg, tmp_reg);
spe_fm(f, term2B_reg, fbB_reg, tmp_reg);
break;
/* XXX more cases */
default:
ASSERT(0);
}
/*
* Compute Dest Alpha term
*/
switch (blend->alpha_dst_factor) {
case PIPE_BLENDFACTOR_ONE:
spe_move(f, term2A_reg, fbA_reg);
break;
case PIPE_BLENDFACTOR_ZERO:
spe_zero(f, term2A_reg);
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
spe_fm(f, term2A_reg, fbA_reg, fragA_reg);
break;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
/* one = {1.0, 1.0, 1.0, 1.0} */
spe_load_float(f, one_reg, 1.0f);
/* tmp = one - fragA */
spe_fs(f, tmp_reg, one_reg, fragA_reg);
/* termA = fbA * tmp */
spe_fm(f, term2A_reg, fbA_reg, tmp_reg);
break;
/* XXX more cases */
default:
ASSERT(0);
}
/*
* Combine Src/Dest RGB terms
*/
switch (blend->rgb_func) {
case PIPE_BLEND_ADD:
spe_fa(f, fragR_reg, term1R_reg, term2R_reg);
spe_fa(f, fragG_reg, term1G_reg, term2G_reg);
spe_fa(f, fragB_reg, term1B_reg, term2B_reg);
break;
case PIPE_BLEND_SUBTRACT:
spe_fs(f, fragR_reg, term1R_reg, term2R_reg);
spe_fs(f, fragG_reg, term1G_reg, term2G_reg);
spe_fs(f, fragB_reg, term1B_reg, term2B_reg);
break;
/* XXX more cases */
default:
ASSERT(0);
}
/*
* Combine Src/Dest A term
*/
switch (blend->alpha_func) {
case PIPE_BLEND_ADD:
spe_fa(f, fragA_reg, term1A_reg, term2A_reg);
break;
case PIPE_BLEND_SUBTRACT:
spe_fs(f, fragA_reg, term1A_reg, term2A_reg);
break;
/* XXX more cases */
default:
ASSERT(0);
}
spe_release_register(f, term1R_reg);
spe_release_register(f, term1G_reg);
spe_release_register(f, term1B_reg);
spe_release_register(f, term1A_reg);
spe_release_register(f, term2R_reg);
spe_release_register(f, term2G_reg);
spe_release_register(f, term2B_reg);
spe_release_register(f, term2A_reg);
spe_release_register(f, fbR_reg);
spe_release_register(f, fbG_reg);
spe_release_register(f, fbB_reg);
spe_release_register(f, fbA_reg);
spe_release_register(f, one_reg);
spe_release_register(f, tmp_reg);
}
static void
gen_logicop(const struct pipe_blend_state *blend,
struct spe_function *f,
int fragRGBA_reg, int fbRGBA_reg)
{
/* XXX to-do */
/* operate on 32-bit packed pixels, not float colors */
}
static void
gen_colormask(uint colormask,
struct spe_function *f,
int fragRGBA_reg, int fbRGBA_reg)
{
/* XXX to-do */
/* operate on 32-bit packed pixels, not float colors */
}
/**
* Generate code to pack a quad of float colors into a four 32-bit integers.
*
* \param f SPE function to append instruction onto.
* \param color_format the dest color packing format
* \param r_reg register containing four red values (in/clobbered)
* \param g_reg register containing four green values (in/clobbered)
* \param b_reg register containing four blue values (in/clobbered)
* \param a_reg register containing four alpha values (in/clobbered)
* \param rgba_reg register to store the packed RGBA colors (out)
*/
static void
gen_pack_colors(struct spe_function *f,
enum pipe_format color_format,
int r_reg, int g_reg, int b_reg, int a_reg,
int rgba_reg)
{
/* Convert float[4] in [0.0,1.0] to int[4] in [0,~0], with clamping */
spe_cfltu(f, r_reg, r_reg, 32);
spe_cfltu(f, g_reg, g_reg, 32);
spe_cfltu(f, b_reg, b_reg, 32);
spe_cfltu(f, a_reg, a_reg, 32);
/* Shift the most significant bytes to least the significant positions.
* I.e.: reg = reg >> 24
*/
spe_rotmi(f, r_reg, r_reg, -24);
spe_rotmi(f, g_reg, g_reg, -24);
spe_rotmi(f, b_reg, b_reg, -24);
spe_rotmi(f, a_reg, a_reg, -24);
/* Shift the color bytes according to the surface format */
if (color_format == PIPE_FORMAT_A8R8G8B8_UNORM) {
spe_roti(f, g_reg, g_reg, 8); /* green <<= 8 */
spe_roti(f, r_reg, r_reg, 16); /* red <<= 16 */
spe_roti(f, a_reg, a_reg, 24); /* alpha <<= 24 */
}
else if (color_format == PIPE_FORMAT_B8G8R8A8_UNORM) {
spe_roti(f, r_reg, r_reg, 8); /* red <<= 8 */
spe_roti(f, g_reg, g_reg, 16); /* green <<= 16 */
spe_roti(f, b_reg, b_reg, 24); /* blue <<= 24 */
}
else {
ASSERT(0);
}
/* Merge red, green, blue, alpha registers to make packed RGBA colors.
* Eg: after shifting according to color_format we might have:
* R = {0x00ff0000, 0x00110000, 0x00220000, 0x00330000}
* G = {0x0000ff00, 0x00004400, 0x00005500, 0x00006600}
* B = {0x000000ff, 0x00000077, 0x00000088, 0x00000099}
* A = {0xff000000, 0xaa000000, 0xbb000000, 0xcc000000}
* OR-ing all those together gives us four packed colors:
* RGBA = {0xffffffff, 0xaa114477, 0xbb225588, 0xcc336699}
*/
spe_or(f, rgba_reg, r_reg, g_reg);
spe_or(f, rgba_reg, rgba_reg, b_reg);
spe_or(f, rgba_reg, rgba_reg, a_reg);
}
/**
* Generate SPE code to implement the fragment operations (alpha test,
* depth test, stencil test, blending, colormask, and final
* framebuffer write) as specified by the current context state.
*
* Logically, this code will be called after running the fragment
* shader. But under some circumstances we could run some of this
* code before the fragment shader to cull fragments/quads that are
* totally occluded/discarded.
*
* XXX we only support PIPE_FORMAT_Z24S8_UNORM z/stencil buffer right now.
*
* See the spu_default_fragment_ops() function to see how the per-fragment
* operations would be done with ordinary C code.
* The code we generate here though has no branches, is SIMD, etc and
* should be much faster.
*
* \param cell the rendering context (in)
* \param f the generated function (out)
*/
void
gen_fragment_function(struct cell_context *cell, struct spe_function *f)
{
const struct pipe_depth_stencil_alpha_state *dsa =
&cell->depth_stencil->base;
const struct pipe_blend_state *blend = &cell->blend->base;
const enum pipe_format color_format = cell->framebuffer.cbufs[0]->format;
/* For SPE function calls: reg $3 = first param, $4 = second param, etc. */
const int x_reg = 3; /* uint */
const int y_reg = 4; /* uint */
const int color_tile_reg = 5; /* tile_t * */
const int depth_tile_reg = 6; /* tile_t * */
const int fragZ_reg = 7; /* vector float */
const int fragR_reg = 8; /* vector float */
const int fragG_reg = 9; /* vector float */
const int fragB_reg = 10; /* vector float */
const int fragA_reg = 11; /* vector float */
const int mask_reg = 12; /* vector uint */
/* offset of quad from start of tile
* XXX assuming 4-byte pixels for color AND Z/stencil!!!!
*/
int quad_offset_reg;
int fbRGBA_reg; /**< framebuffer's RGBA colors for quad */
int fbZS_reg; /**< framebuffer's combined z/stencil values for quad */
spe_init_func(f, SPU_MAX_FRAGMENT_OPS_INSTS * SPE_INST_SIZE);
spe_allocate_register(f, x_reg);
spe_allocate_register(f, y_reg);
spe_allocate_register(f, color_tile_reg);
spe_allocate_register(f, depth_tile_reg);
spe_allocate_register(f, fragZ_reg);
spe_allocate_register(f, fragR_reg);
spe_allocate_register(f, fragG_reg);
spe_allocate_register(f, fragB_reg);
spe_allocate_register(f, fragA_reg);
spe_allocate_register(f, mask_reg);
quad_offset_reg = spe_allocate_available_register(f);
fbRGBA_reg = spe_allocate_available_register(f);
fbZS_reg = spe_allocate_available_register(f);
/* compute offset of quad from start of tile, in bytes */
{
int x2_reg = spe_allocate_available_register(f);
int y2_reg = spe_allocate_available_register(f);
ASSERT(TILE_SIZE == 32);
spe_rotmi(f, x2_reg, x_reg, -1); /* x2 = x / 2 */
spe_rotmi(f, y2_reg, y_reg, -1); /* y2 = y / 2 */
spe_shli(f, y2_reg, y2_reg, 4); /* y2 *= 16 */
spe_a(f, quad_offset_reg, y2_reg, x2_reg); /* offset = y2 + x2 */
spe_shli(f, quad_offset_reg, quad_offset_reg, 4); /* offset *= 16 */
spe_release_register(f, x2_reg);
spe_release_register(f, y2_reg);
}
if (dsa->alpha.enabled) {
gen_alpha_test(dsa, f, mask_reg, fragA_reg);
}
if (dsa->depth.enabled || dsa->stencil[0].enabled) {
const enum pipe_format zs_format = cell->framebuffer.zsbuf->format;
boolean write_depth_stencil;
int fbZ_reg = spe_allocate_available_register(f); /* Z values */
int fbS_reg = spe_allocate_available_register(f); /* Stencil values */
/* fetch quad of depth/stencil values from tile at (x,y) */
/* Load: fbZS_reg = memory[depth_tile_reg + offset_reg] */
spe_lqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg);
if (dsa->depth.enabled) {
/* Extract Z bits from fbZS_reg into fbZ_reg */
if (zs_format == PIPE_FORMAT_S8Z24_UNORM ||
zs_format == PIPE_FORMAT_X8Z24_UNORM) {
int mask_reg = spe_allocate_available_register(f);
spe_fsmbi(f, mask_reg, 0x7777); /* mask[0,1,2,3] = 0x00ffffff */
spe_and(f, fbZ_reg, fbZS_reg, mask_reg); /* fbZ = fbZS & mask */
spe_release_register(f, mask_reg);
/* OK, fbZ_reg has four 24-bit Z values now */
}
else {
/* XXX handle other z/stencil formats */
ASSERT(0);
}
/* Convert fragZ values from float[4] to uint[4] */
if (zs_format == PIPE_FORMAT_S8Z24_UNORM ||
zs_format == PIPE_FORMAT_X8Z24_UNORM ||
zs_format == PIPE_FORMAT_Z24S8_UNORM ||
zs_format == PIPE_FORMAT_Z24X8_UNORM) {
/* 24-bit Z values */
int scale_reg = spe_allocate_available_register(f);
/* scale_reg[0,1,2,3] = float(2^24-1) */
spe_load_float(f, scale_reg, (float) 0xffffff);
/* XXX these two instructions might be combined */
spe_fm(f, fragZ_reg, fragZ_reg, scale_reg); /* fragZ *= scale */
spe_cfltu(f, fragZ_reg, fragZ_reg, 0); /* fragZ = (int) fragZ */
spe_release_register(f, scale_reg);
}
else {
/* XXX handle 16-bit Z format */
ASSERT(0);
}
}
if (dsa->stencil[0].enabled) {
/* Extract Stencil bit sfrom fbZS_reg into fbS_reg */
if (zs_format == PIPE_FORMAT_S8Z24_UNORM ||
zs_format == PIPE_FORMAT_X8Z24_UNORM) {
/* XXX extract with a shift */
ASSERT(0);
}
else if (zs_format == PIPE_FORMAT_Z24S8_UNORM ||
zs_format == PIPE_FORMAT_Z24X8_UNORM) {
/* XXX extract with a mask */
ASSERT(0);
}
}
if (dsa->stencil[0].enabled) {
/* XXX this may involve depth testing too */
// gen_stencil_test(dsa, f, ... );
ASSERT(0);
}
else if (dsa->depth.enabled) {
int zmask_reg = spe_allocate_available_register(f);
gen_depth_test(dsa, f, mask_reg, fragZ_reg, fbZ_reg, zmask_reg);
spe_release_register(f, zmask_reg);
}
/* do we need to write Z and/or Stencil back into framebuffer? */
write_depth_stencil = (dsa->depth.writemask |
dsa->stencil[0].write_mask |
dsa->stencil[1].write_mask);
if (write_depth_stencil) {
/* Merge latest Z and Stencil values into fbZS_reg.
* fbZ_reg has four Z vals in bits [23..0] or bits [15..0].
* fbS_reg has four 8-bit Z values in bits [7..0].
*/
if (zs_format == PIPE_FORMAT_S8Z24_UNORM ||
zs_format == PIPE_FORMAT_X8Z24_UNORM) {
spe_shli(f, fbS_reg, fbS_reg, 24); /* fbS = fbS << 24 */
spe_or(f, fbZS_reg, fbS_reg, fbZ_reg); /* fbZS = fbS | fbZ */
}
else if (zs_format == PIPE_FORMAT_S8Z24_UNORM ||
zs_format == PIPE_FORMAT_X8Z24_UNORM) {
/* XXX to do */
ASSERT(0);
}
else if (zs_format == PIPE_FORMAT_Z16_UNORM) {
/* XXX to do */
ASSERT(0);
}
else if (zs_format == PIPE_FORMAT_S8_UNORM) {
/* XXX to do */
ASSERT(0);
}
else {
/* bad zs_format */
ASSERT(0);
}
/* Store: memory[depth_tile_reg + quad_offset_reg] = fbZS */
spe_stqx(f, fbZS_reg, depth_tile_reg, quad_offset_reg);
}
spe_release_register(f, fbZ_reg);
spe_release_register(f, fbS_reg);
}
/* Get framebuffer quad/colors. We'll need these for blending,
* color masking, and to obey the quad/pixel mask.
* Load: fbRGBA_reg = memory[color_tile + quad_offset]
* Note: if mask={~0,~0,~0,~0} and we're not blending or colormasking
* we could skip this load.
*/
spe_lqx(f, fbRGBA_reg, color_tile_reg, quad_offset_reg);
if (blend->blend_enable) {
gen_blend(blend, f, color_format,
fragR_reg, fragG_reg, fragB_reg, fragA_reg, fbRGBA_reg);
}
/*
* Write fragment colors to framebuffer/tile.
* This involves converting the fragment colors from float[4] to the
* tile's specific format and obeying the quad/pixel mask.
*/
{
int rgba_reg = spe_allocate_available_register(f);
/* Pack four float colors as four 32-bit int colors */
gen_pack_colors(f, color_format,
fragR_reg, fragG_reg, fragB_reg, fragA_reg,
rgba_reg);
if (blend->logicop_enable) {
gen_logicop(blend, f, rgba_reg, fbRGBA_reg);
}
if (blend->colormask != 0xf) {
gen_colormask(blend->colormask, f, rgba_reg, fbRGBA_reg);
}
/* Mix fragment colors with framebuffer colors using the quad/pixel mask:
* if (mask[i])
* rgba[i] = rgba[i];
* else
* rgba[i] = framebuffer[i];
*/
spe_selb(f, rgba_reg, fbRGBA_reg, rgba_reg, mask_reg);
/* Store updated quad in tile:
* memory[color_tile + quad_offset] = rgba_reg;
*/
spe_stqx(f, rgba_reg, color_tile_reg, quad_offset_reg);
spe_release_register(f, rgba_reg);
}
printf("gen_fragment_ops nr instructions: %u\n", f->num_inst);
spe_bi(f, SPE_REG_RA, 0, 0); /* return from function call */
spe_release_register(f, fbRGBA_reg);
spe_release_register(f, fbZS_reg);
spe_release_register(f, quad_offset_reg);
}

View File

@ -1,6 +1,6 @@
/**************************************************************************
*
* Copyright 2007-2008 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
@ -25,71 +25,14 @@
*
**************************************************************************/
#ifndef P_POINTER_H
#define P_POINTER_H
#include "p_compiler.h"
#ifndef CELL_GEN_FRAGMENT_H
#define CELL_GEN_FRAGMENT_H
#ifdef __cplusplus
extern "C" {
#endif
static INLINE intptr_t
pointer_to_intptr( const void *p )
{
union {
const void *p;
intptr_t i;
} pi;
pi.p = p;
return pi.i;
}
extern void
gen_fragment_function(struct cell_context *cell, struct spe_function *f);
static INLINE void *
intptr_to_pointer( intptr_t i )
{
union {
void *p;
intptr_t i;
} pi;
pi.i = i;
return pi.p;
}
static INLINE uintptr_t
pointer_to_uintptr( const void *ptr )
{
union {
const void *p;
uintptr_t u;
} pu;
pu.p = ptr;
return pu.u;
}
#endif /* CELL_GEN_FRAGMENT_H */
static INLINE void *
uintptr_to_pointer( uintptr_t u )
{
union {
void *p;
uintptr_t u;
} pu;
pu.u = u;
return pu.p;
}
/**
* Return a pointer aligned to next multiple of N bytes.
*/
static INLINE void *
align_pointer( const void *unaligned, uintptr_t alignment )
{
uintptr_t aligned = (pointer_to_uintptr( unaligned ) + alignment - 1) & ~(alignment - 1);
return uintptr_to_pointer( aligned );
}
#ifdef __cplusplus
}
#endif
#endif /* P_POINTER_H */

View File

@ -34,6 +34,7 @@
#include "pipe/p_inlines.h"
#include "draw/draw_context.h"
#include "cell_context.h"
#include "cell_flush.h"
#include "cell_state.h"
#include "cell_texture.h"
#include "cell_state_per_fragment.h"
@ -130,8 +131,9 @@ cell_delete_depth_stencil_alpha_state(struct pipe_context *pipe, void *depth)
}
static void cell_set_clip_state( struct pipe_context *pipe,
const struct pipe_clip_state *clip )
static void
cell_set_clip_state(struct pipe_context *pipe,
const struct pipe_clip_state *clip)
{
struct cell_context *cell = cell_context(pipe);
@ -310,8 +312,21 @@ cell_set_framebuffer_state(struct pipe_context *pipe,
cell->zsbuf_map = NULL;
}
/* update my state */
cell->framebuffer = *fb;
/* Finish any pending rendering to the current surface before
* installing a new surface!
*/
cell_flush_int(cell, CELL_FLUSH_WAIT);
/* update my state
* (this is also where old surfaces will finally get freed)
*/
cell->framebuffer.width = fb->width;
cell->framebuffer.height = fb->height;
cell->framebuffer.num_cbufs = fb->num_cbufs;
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
pipe_surface_reference(&cell->framebuffer.cbufs[i], fb->cbufs[i]);
}
pipe_surface_reference(&cell->framebuffer.zsbuf, fb->zsbuf);
/* map new surfaces */
if (csurf)

View File

@ -26,6 +26,11 @@
**************************************************************************/
/**
* Utility/wrappers for communicating with the SPUs.
*/
#include <pthread.h>
#include "cell_spu.h"
@ -40,6 +45,9 @@ helpful headers:
*/
/**
* Cell/SPU info that's not per-context.
*/
struct cell_global_info cell_global;
@ -74,7 +82,11 @@ wait_mbox_message(spe_context_ptr_t ctx)
}
static void *cell_thread_function(void *arg)
/**
* Called by pthread_create() to spawn an SPU thread.
*/
static void *
cell_thread_function(void *arg)
{
struct cell_init_info *init = (struct cell_init_info *) arg;
unsigned entry = SPE_DEFAULT_ENTRY;
@ -92,7 +104,10 @@ static void *cell_thread_function(void *arg)
/**
* Create the SPU threads
* Create the SPU threads. This is done once during driver initialization.
* This involves setting the the "init" message which is sent to each SPU.
* The init message specifies an SPU id, total number of SPUs, location
* and number of batch buffers, etc.
*/
void
cell_start_spus(struct cell_context *cell)
@ -100,7 +115,6 @@ cell_start_spus(struct cell_context *cell)
static boolean one_time_init = FALSE;
uint i, j;
if (one_time_init) {
fprintf(stderr, "PPU: Multiple rendering contexts not yet supported "
"on Cell.\n");
@ -120,6 +134,7 @@ cell_start_spus(struct cell_context *cell)
for (i = 0; i < cell->num_spus; i++) {
cell_global.inits[i].id = i;
cell_global.inits[i].num_spus = cell->num_spus;
cell_global.inits[i].debug_flags = cell->debug_flags;
cell_global.inits[i].cmd = &cell_global.command[i];
for (j = 0; j < CELL_NUM_BUFFERS; j++) {
cell_global.inits[i].buffers[j] = cell->buffer[j];
@ -137,14 +152,17 @@ cell_start_spus(struct cell_context *cell)
exit(1);
}
pthread_create(&cell_global.spe_threads[i], NULL, &cell_thread_function,
&cell_global.inits[i]);
pthread_create(&cell_global.spe_threads[i], /* returned thread handle */
NULL, /* pthread attribs */
&cell_thread_function, /* start routine */
&cell_global.inits[i]); /* thread argument */
}
}
/**
* Tell all the SPUs to stop/exit.
* This is done when the driver's exiting / cleaning up.
*/
void
cell_spu_exit(struct cell_context *cell)

View File

@ -48,19 +48,17 @@
#define CELL_NEW_VERTEX_INFO 0x8000
void cell_set_vertex_elements(struct pipe_context *,
unsigned count,
const struct pipe_vertex_element *);
void cell_set_vertex_buffers(struct pipe_context *,
unsigned count,
const struct pipe_vertex_buffer *);
void cell_update_derived( struct cell_context *softpipe );
extern void
cell_update_derived( struct cell_context *softpipe );
void
extern void
cell_init_shader_functions(struct cell_context *cell);
extern void
cell_init_vertex_functions(struct cell_context *cell);
#endif /* CELL_STATE_H */

View File

@ -35,21 +35,6 @@
#include "cell_state_emit.h"
static int
find_vs_output(const struct cell_vertex_shader_state *vs,
uint semantic_name,
uint semantic_index)
{
uint i;
for (i = 0; i < vs->info.num_outputs; i++) {
if (vs->info.output_semantic_name[i] == semantic_name &&
vs->info.output_semantic_index[i] == semantic_index)
return i;
}
return -1;
}
/**
* Determine how to map vertex program outputs to fragment program inputs.
* Basically, this will be used when computing the triangle interpolation
@ -58,7 +43,6 @@ find_vs_output(const struct cell_vertex_shader_state *vs,
static void
calculate_vertex_layout( struct cell_context *cell )
{
const struct cell_vertex_shader_state *vs = cell->vs;
const struct cell_fragment_shader_state *fs = cell->fs;
const enum interp_mode colorInterp
= cell->rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
@ -82,7 +66,7 @@ calculate_vertex_layout( struct cell_context *cell )
vinfo->num_attribs = 0;
/* we always want to emit vertex pos */
src = find_vs_output(vs, TGSI_SEMANTIC_POSITION, 0);
src = draw_find_vs_output(cell->draw, TGSI_SEMANTIC_POSITION, 0);
assert(src >= 0);
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_POS, src);
@ -98,14 +82,14 @@ calculate_vertex_layout( struct cell_context *cell )
break;
case TGSI_SEMANTIC_COLOR:
src = find_vs_output(vs, TGSI_SEMANTIC_COLOR,
fs->info.input_semantic_index[i]);
src = draw_find_vs_output(cell->draw, TGSI_SEMANTIC_COLOR,
fs->info.input_semantic_index[i]);
assert(src >= 0);
draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
break;
case TGSI_SEMANTIC_FOG:
src = find_vs_output(vs, TGSI_SEMANTIC_FOG, 0);
src = draw_find_vs_output(cell->draw, TGSI_SEMANTIC_FOG, 0);
#if 1
if (src < 0) /* XXX temp hack, try demos/fogcoord.c with this */
src = 0;
@ -116,7 +100,7 @@ calculate_vertex_layout( struct cell_context *cell )
case TGSI_SEMANTIC_GENERIC:
/* this includes texcoords and varying vars */
src = find_vs_output(vs, TGSI_SEMANTIC_GENERIC,
src = draw_find_vs_output(cell->draw, TGSI_SEMANTIC_GENERIC,
fs->info.input_semantic_index[i]);
assert(src >= 0);
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
@ -163,6 +147,9 @@ compute_cliprect(struct cell_context *sp)
/**
* Update derived state, send current state to SPUs prior to rendering.
*/
void cell_update_derived( struct cell_context *cell )
{
if (cell->dirty & (CELL_NEW_RASTERIZER |

View File

@ -27,6 +27,7 @@
#include "util/u_memory.h"
#include "cell_context.h"
#include "cell_gen_fragment.h"
#include "cell_state.h"
#include "cell_state_emit.h"
#include "cell_state_per_fragment.h"
@ -47,27 +48,13 @@ emit_state_cmd(struct cell_context *cell, uint cmd,
}
/**
* For state marked as 'dirty', construct a state-update command block
* and insert it into the current batch buffer.
*/
void
cell_emit_state(struct cell_context *cell)
{
if (cell->dirty & (CELL_NEW_FRAMEBUFFER | CELL_NEW_BLEND)) {
struct cell_command_logicop logicop;
if (cell->logic_op.store != NULL) {
spe_release_func(& cell->logic_op);
}
cell_generate_logic_op(& cell->logic_op,
& cell->blend->base,
cell->framebuffer.cbufs[0]);
logicop.base = (intptr_t) cell->logic_op.store;
logicop.size = 64 * 4;
emit_state_cmd(cell, CELL_CMD_STATE_LOGICOP, &logicop,
sizeof(logicop));
}
if (cell->dirty & CELL_NEW_FRAMEBUFFER) {
struct pipe_surface *cbuf = cell->framebuffer.cbufs[0];
struct pipe_surface *zbuf = cell->framebuffer.zsbuf;
@ -80,44 +67,33 @@ cell_emit_state(struct cell_context *cell)
fb->depth_format = zbuf ? zbuf->format : PIPE_FORMAT_NONE;
fb->width = cell->framebuffer.width;
fb->height = cell->framebuffer.height;
#if 0
printf("EMIT color format %s\n", pf_name(fb->color_format));
printf("EMIT depth format %s\n", pf_name(fb->depth_format));
#endif
}
if (cell->dirty & CELL_NEW_BLEND) {
struct cell_command_blend blend;
if (cell->blend != NULL) {
blend.base = (intptr_t) cell->blend->code.store;
blend.size = (char *) cell->blend->code.csr
- (char *) cell->blend->code.store;
blend.read_fb = TRUE;
} else {
blend.base = 0;
blend.size = 0;
blend.read_fb = FALSE;
}
if (cell->dirty & (CELL_NEW_FRAMEBUFFER |
CELL_NEW_DEPTH_STENCIL |
CELL_NEW_BLEND)) {
/* XXX we don't want to always do codegen here. We should have
* a hash/lookup table to cache previous results...
*/
struct cell_command_fragment_ops *fops
= cell_batch_alloc(cell, sizeof(*fops));
struct spe_function spe_code;
emit_state_cmd(cell, CELL_CMD_STATE_BLEND, &blend, sizeof(blend));
}
if (cell->dirty & CELL_NEW_DEPTH_STENCIL) {
struct cell_command_depth_stencil_alpha_test dsat;
if (cell->depth_stencil != NULL) {
dsat.base = (intptr_t) cell->depth_stencil->code.store;
dsat.size = (char *) cell->depth_stencil->code.csr
- (char *) cell->depth_stencil->code.store;
dsat.read_depth = TRUE;
dsat.read_stencil = FALSE;
} else {
dsat.base = 0;
dsat.size = 0;
dsat.read_depth = FALSE;
dsat.read_stencil = FALSE;
}
emit_state_cmd(cell, CELL_CMD_STATE_DEPTH_STENCIL, &dsat,
sizeof(dsat));
/* generate new code */
gen_fragment_function(cell, &spe_code);
/* put the new code into the batch buffer */
fops->opcode = CELL_CMD_STATE_FRAGMENT_OPS;
memcpy(&fops->code, spe_code.store,
SPU_MAX_FRAGMENT_OPS_INSTS * SPE_INST_SIZE);
fops->dsa = cell->depth_stencil->base;
fops->blend = cell->blend->base;
/* free codegen buffer */
spe_release_func(&spe_code);
}
if (cell->dirty & CELL_NEW_SAMPLER) {
@ -157,7 +133,8 @@ cell_emit_state(struct cell_context *cell)
emit_state_cmd(cell, CELL_CMD_STATE_VERTEX_INFO,
&cell->vertex_info, sizeof(struct vertex_info));
}
#if 0
if (cell->dirty & CELL_NEW_VS) {
const struct draw_context *const draw = cell->draw;
struct cell_shader_info info;
@ -170,7 +147,7 @@ cell_emit_state(struct cell_context *cell)
info.immediates = (uintptr_t) draw->vs.machine.Imms;
info.num_immediates = draw->vs.machine.ImmLimit / 4;
emit_state_cmd(cell, CELL_CMD_STATE_BIND_VS,
& info, sizeof(info));
emit_state_cmd(cell, CELL_CMD_STATE_BIND_VS, &info, sizeof(info));
}
#endif
}

View File

@ -132,9 +132,9 @@ emit_alpha_test(struct pipe_depth_stencil_alpha_state *dsa,
/**
* Generate code to perform Z testing. Four Z values are tested at once.
* \param dsa Current depth-test state
* \param f Function to which code should be appended
* \param m Mask of allocated / free SPE registers
* \param mask Index of register to contain depth-pass mask
* \param stored Index of register containing values from depth buffer
* \param calculated Index of register containing per-fragment depth values
@ -198,6 +198,7 @@ emit_depth_test(struct pipe_depth_stencil_alpha_state *dsa,
/**
* Generate code to apply the stencil operation (after testing).
* \note Emits a maximum of 5 instructions.
*
* \warning
@ -222,9 +223,13 @@ emit_stencil_op(struct spe_function *f,
spe_il(f, result, ref);
break;
case PIPE_STENCIL_OP_INCR:
/* clamp = [0xff, 0xff, 0xff, 0xff] */
spe_il(f, clamp, 0x0ff);
/* result[i] = in[i] + 1 */
spe_ai(f, result, in, 1);
/* clamp_mask[i] = (result[i] > 0xff) */
spe_clgti(f, clamp_mask, result, 0x0ff);
/* result[i] = clamp_mask[i] ? clamp[i] : result[i] */
spe_selb(f, result, result, clamp, clamp_mask);
break;
case PIPE_STENCIL_OP_DECR:
@ -259,10 +264,10 @@ emit_stencil_op(struct spe_function *f,
/**
* Generate code to do stencil test. Four pixels are tested at once.
* \param dsa Depth / stencil test state
* \param face 0 for front face, 1 for back face
* \param f Function to append instructions to
* \param reg_mask Mask of allocated registers
* \param mask Register containing mask of fragments passing the
* alpha test
* \param depth_mask Register containing mask of fragments passing the
@ -310,13 +315,14 @@ emit_stencil_test(struct pipe_depth_stencil_alpha_state *dsa,
switch (dsa->stencil[face].func) {
case PIPE_FUNC_NEVER:
spe_il(f, stencil_mask, 0);
spe_il(f, stencil_mask, 0); /* stencil_mask[0..3] = [0,0,0,0] */
break;
case PIPE_FUNC_NOTEQUAL:
complement = TRUE;
/* FALLTHROUGH */
case PIPE_FUNC_EQUAL:
/* stencil_mask[i] = (stored[i] == ref) */
spe_ceqi(f, stencil_mask, stored, ref);
break;
@ -324,6 +330,8 @@ emit_stencil_test(struct pipe_depth_stencil_alpha_state *dsa,
complement = TRUE;
/* FALLTHROUGH */
case PIPE_FUNC_GREATER:
complement = TRUE;
/* stencil_mask[i] = (stored[i] > ref) */
spe_clgti(f, stencil_mask, stored, ref);
break;
@ -331,8 +339,11 @@ emit_stencil_test(struct pipe_depth_stencil_alpha_state *dsa,
complement = TRUE;
/* FALLTHROUGH */
case PIPE_FUNC_GEQUAL:
/* stencil_mask[i] = (stored[i] > ref) */
spe_clgti(f, stencil_mask, stored, ref);
/* tmp[i] = (stored[i] == ref) */
spe_ceqi(f, tmp, stored, ref);
/* stencil_mask[i] = stencil_mask[i] | tmp[i] */
spe_or(f, stencil_mask, stencil_mask, tmp);
break;
@ -461,7 +472,7 @@ cell_generate_depth_stencil_test(struct cell_depth_stencil_alpha_state *cdsa)
* + 25 (front stencil) + 25 (back stencil) + 4 = 63 instructions. Round
* up to 64 to make it a happy power-of-two.
*/
spe_init_func(f, 4 * 64);
spe_init_func(f, SPE_INST_SIZE * 64);
/* Allocate registers for the function's input parameters. Cleverly (and
@ -540,7 +551,7 @@ cell_generate_depth_stencil_test(struct cell_depth_stencil_alpha_state *cdsa)
spe_selb(f, depth, depth, zvals, mask);
}
spe_bi(f, 0, 0, 0);
spe_bi(f, 0, 0, 0); /* return from function call */
#if 0
@ -956,7 +967,7 @@ cell_generate_alpha_blend(struct cell_blend_state *cb)
* + 4 (fragment mask) + 1 (return) = 55 instlructions. Round up to 64 to
* make it a happy power-of-two.
*/
spe_init_func(f, 4 * 64);
spe_init_func(f, SPE_INST_SIZE * 64);
const int frag[4] = {
@ -1144,9 +1155,10 @@ cell_generate_alpha_blend(struct cell_blend_state *cb)
}
int PC_OFFSET(const struct spe_function *f, const void *d)
static int
PC_OFFSET(const struct spe_function *f, const void *d)
{
const intptr_t pc = (intptr_t) f->csr;
const intptr_t pc = (intptr_t) &f->store[f->num_inst];
const intptr_t ea = ~0x0f & (intptr_t) d;
return (ea - pc) >> 2;
@ -1178,7 +1190,7 @@ cell_generate_logic_op(struct spe_function *f,
* bytes (equiv. to 8 instructions) are needed for data storage. Round up
* to 64 to make it a happy power-of-two.
*/
spe_init_func(f, 4 * 64);
spe_init_func(f, SPE_INST_SIZE * 64);
/* Pixel colors in framebuffer format in AoS layout.

View File

@ -53,7 +53,10 @@ cell_vertex_shader_state(void *shader)
}
/**
* Create fragment shader state.
* Called via pipe->create_fs_state()
*/
static void *
cell_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
@ -77,6 +80,9 @@ cell_create_fs_state(struct pipe_context *pipe,
}
/**
* Called via pipe->bind_fs_state()
*/
static void
cell_bind_fs_state(struct pipe_context *pipe, void *fs)
{
@ -88,6 +94,9 @@ cell_bind_fs_state(struct pipe_context *pipe, void *fs)
}
/**
* Called via pipe->delete_fs_state()
*/
static void
cell_delete_fs_state(struct pipe_context *pipe, void *fs)
{
@ -98,6 +107,10 @@ cell_delete_fs_state(struct pipe_context *pipe, void *fs)
}
/**
* Create vertex shader state.
* Called via pipe->create_vs_state()
*/
static void *
cell_create_vs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
@ -128,6 +141,9 @@ cell_create_vs_state(struct pipe_context *pipe,
}
/**
* Called via pipe->bind_vs_state()
*/
static void
cell_bind_vs_state(struct pipe_context *pipe, void *vs)
{
@ -142,6 +158,9 @@ cell_bind_vs_state(struct pipe_context *pipe, void *vs)
}
/**
* Called via pipe->delete_vs_state()
*/
static void
cell_delete_vs_state(struct pipe_context *pipe, void *vs)
{
@ -154,6 +173,9 @@ cell_delete_vs_state(struct pipe_context *pipe, void *vs)
}
/**
* Called via pipe->set_constant_buffer()
*/
static void
cell_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
@ -166,7 +188,7 @@ cell_set_constant_buffer(struct pipe_context *pipe,
assert(index == 0);
/* note: reference counting */
pipe_buffer_reference(ws,
winsys_buffer_reference(ws,
&cell->constants[shader].buffer,
buf->buffer);
cell->constants[shader].size = buf->size;

View File

@ -35,7 +35,7 @@
#include "draw/draw_context.h"
void
static void
cell_set_vertex_elements(struct pipe_context *pipe,
unsigned count,
const struct pipe_vertex_element *elements)
@ -53,7 +53,7 @@ cell_set_vertex_elements(struct pipe_context *pipe,
}
void
static void
cell_set_vertex_buffers(struct pipe_context *pipe,
unsigned count,
const struct pipe_vertex_buffer *buffers)
@ -69,3 +69,11 @@ cell_set_vertex_buffers(struct pipe_context *pipe,
draw_set_vertex_buffers(cell->draw, count, buffers);
}
void
cell_init_vertex_functions(struct cell_context *cell)
{
cell->pipe.set_vertex_buffers = cell_set_vertex_buffers;
cell->pipe.set_vertex_elements = cell_set_vertex_elements;
}

View File

@ -25,108 +25,13 @@
*
**************************************************************************/
#include "pipe/p_defines.h"
#include "pipe/p_inlines.h"
#include "pipe/p_winsys.h"
#include "util/u_memory.h"
#include "util/u_rect.h"
#include "util/u_tile.h"
#include "cell_context.h"
#include "cell_surface.h"
static void
cell_surface_copy(struct pipe_context *pipe,
boolean do_flip,
struct pipe_surface *dst,
unsigned dstx, unsigned dsty,
struct pipe_surface *src,
unsigned srcx, unsigned srcy,
unsigned width, unsigned height)
{
assert( dst->cpp == src->cpp );
pipe_copy_rect(pipe_surface_map(dst, PIPE_BUFFER_USAGE_CPU_WRITE),
&dst->block,
dst->stride,
dstx, dsty,
width, height,
pipe_surface_map(src, PIPE_BUFFER_USAGE_CPU_READ),
do_flip ? -src->stride : src->stride,
srcx, do_flip ? height - 1 - srcy : srcy);
pipe_surface_unmap(src);
pipe_surface_unmap(dst);
}
static void *
get_pointer(struct pipe_surface *dst, void *dst_map, unsigned x, unsigned y)
{
return (char *)dst_map + y / dst->block.height * dst->stride + x / dst->block.width * dst->block.size;
}
#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
/**
* Fill a rectangular sub-region. Need better logic about when to
* push buffers into AGP - will currently do so whenever possible.
*/
static void
cell_surface_fill(struct pipe_context *pipe,
struct pipe_surface *dst,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height, unsigned value)
{
unsigned i, j;
void *dst_map = pipe_surface_map(dst, PIPE_BUFFER_USAGE_CPU_WRITE);
assert(dst->stride > 0);
switch (dst->block.size) {
case 1:
case 2:
case 4:
pipe_fill_rect(dst_map, &dst->block, dst->stride, dstx, dsty, width, height, value);
break;
case 8:
{
/* expand the 4-byte clear value to an 8-byte value */
ushort *row = (ushort *) get_pointer(dst, dst_map, dstx, dsty);
ushort val0 = UBYTE_TO_USHORT((value >> 0) & 0xff);
ushort val1 = UBYTE_TO_USHORT((value >> 8) & 0xff);
ushort val2 = UBYTE_TO_USHORT((value >> 16) & 0xff);
ushort val3 = UBYTE_TO_USHORT((value >> 24) & 0xff);
val0 = (val0 << 8) | val0;
val1 = (val1 << 8) | val1;
val2 = (val2 << 8) | val2;
val3 = (val3 << 8) | val3;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
row[j*4+0] = val0;
row[j*4+1] = val1;
row[j*4+2] = val2;
row[j*4+3] = val3;
}
row += dst->stride/2;
}
}
break;
default:
assert(0);
break;
}
pipe_surface_unmap( dst );
}
void
cell_init_surface_functions(struct cell_context *cell)
{
cell->pipe.surface_copy = cell_surface_copy;
cell->pipe.surface_fill = cell_surface_fill;
cell->pipe.surface_copy = util_surface_copy;
cell->pipe.surface_fill = util_surface_fill;
}

View File

@ -63,19 +63,30 @@ cell_texture_layout(struct cell_texture * spt)
spt->buffer_size = 0;
for ( level = 0 ; level <= pt->last_level ; level++ ) {
unsigned size;
unsigned w_tile, h_tile;
/* width, height, rounded up to tile size */
w_tile = align(width, TILE_SIZE);
h_tile = align(height, TILE_SIZE);
pt->width[level] = width;
pt->height[level] = height;
pt->depth[level] = depth;
pt->nblocksx[level] = pf_get_nblocksx(&pt->block, width);
pt->nblocksy[level] = pf_get_nblocksy(&pt->block, height);
pt->nblocksx[level] = pf_get_nblocksx(&pt->block, w_tile);
pt->nblocksy[level] = pf_get_nblocksy(&pt->block, h_tile);
spt->stride[level] = pt->nblocksx[level] * pt->block.size;
spt->level_offset[level] = spt->buffer_size;
spt->buffer_size += (pt->nblocksy[level] *
((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
pt->nblocksx[level] * pt->block.size);
size = pt->nblocksx[level] * pt->nblocksy[level] * pt->block.size;
if (pt->target == PIPE_TEXTURE_CUBE)
size *= 6;
else
size *= depth;
spt->buffer_size += size;
width = minify(width);
height = minify(height);
@ -85,8 +96,8 @@ cell_texture_layout(struct cell_texture * spt)
static struct pipe_texture *
cell_texture_create_screen(struct pipe_screen *screen,
const struct pipe_texture *templat)
cell_texture_create(struct pipe_screen *screen,
const struct pipe_texture *templat)
{
struct pipe_winsys *ws = screen->winsys;
struct cell_texture *spt = CALLOC_STRUCT(cell_texture);
@ -113,8 +124,8 @@ cell_texture_create_screen(struct pipe_screen *screen,
static void
cell_texture_release_screen(struct pipe_screen *screen,
struct pipe_texture **pt)
cell_texture_release(struct pipe_screen *screen,
struct pipe_texture **pt)
{
if (!*pt)
return;
@ -130,7 +141,7 @@ cell_texture_release_screen(struct pipe_screen *screen,
DBG("%s deleting %p\n", __FUNCTION__, (void *) spt);
*/
pipe_buffer_reference(screen->winsys, &spt->buffer, NULL);
pipe_buffer_reference(screen, &spt->buffer, NULL);
FREE(spt);
}
@ -138,6 +149,7 @@ cell_texture_release_screen(struct pipe_screen *screen,
}
#if 0
static void
cell_texture_update(struct pipe_context *pipe, struct pipe_texture *texture,
uint face, uint levelsMask)
@ -145,13 +157,14 @@ cell_texture_update(struct pipe_context *pipe, struct pipe_texture *texture,
/* XXX TO DO: re-tile the texture data ... */
}
#endif
static struct pipe_surface *
cell_get_tex_surface_screen(struct pipe_screen *screen,
struct pipe_texture *pt,
unsigned face, unsigned level, unsigned zslice,
unsigned usage)
cell_get_tex_surface(struct pipe_screen *screen,
struct pipe_texture *pt,
unsigned face, unsigned level, unsigned zslice,
unsigned usage)
{
struct pipe_winsys *ws = screen->winsys;
struct cell_texture *spt = cell_texture(pt);
@ -161,7 +174,7 @@ cell_get_tex_surface_screen(struct pipe_screen *screen,
if (ps) {
assert(ps->refcount);
assert(ps->winsys);
pipe_buffer_reference(ws, &ps->buffer, spt->buffer);
winsys_buffer_reference(ws, &ps->buffer, spt->buffer);
ps->format = pt->format;
ps->block = pt->block;
ps->width = pt->width[level];
@ -174,12 +187,17 @@ cell_get_tex_surface_screen(struct pipe_screen *screen,
/* XXX may need to override usage flags (see sp_texture.c) */
pipe_texture_reference(&ps->texture, pt);
ps->face = face;
ps->level = level;
ps->zslice = zslice;
if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) {
ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) *
ps->nblocksy *
ps->stride;
} else {
}
else {
assert(face == 0);
assert(zslice == 0);
}
@ -189,6 +207,11 @@ cell_get_tex_surface_screen(struct pipe_screen *screen,
/**
* Copy tile data from linear layout to tiled layout.
* XXX this should be rolled into the future surface-creation code.
* XXX also need "untile" code...
*/
static void
tile_copy_data(uint w, uint h, uint tile_size, uint *dst, const uint *src)
{
@ -219,6 +242,7 @@ tile_copy_data(uint w, uint h, uint tile_size, uint *dst, const uint *src)
/**
* Convert linear texture image data to tiled format for SPU usage.
* XXX recast this in terms of pipe_surfaces (aka texture views).
*/
static void
cell_tile_texture(struct cell_context *cell,
@ -285,6 +309,21 @@ cell_update_texture_mapping(struct cell_context *cell)
}
static void
cell_tex_surface_release(struct pipe_screen *screen,
struct pipe_surface **s)
{
/* Effectively do the texture_update work here - if texture images
* needed post-processing to put them into hardware layout, this is
* where it would happen. For softpipe, nothing to do.
*/
assert ((*s)->texture);
pipe_texture_reference(&(*s)->texture, NULL);
screen->winsys->surface_release(screen->winsys, s);
}
static void *
cell_surface_map( struct pipe_screen *screen,
struct pipe_surface *surface,
@ -297,7 +336,7 @@ cell_surface_map( struct pipe_screen *screen,
return NULL;
}
map = screen->winsys->buffer_map( screen->winsys, surface->buffer, flags );
map = pipe_buffer_map( screen, surface->buffer, flags );
if (map == NULL)
return NULL;
@ -323,7 +362,7 @@ static void
cell_surface_unmap(struct pipe_screen *screen,
struct pipe_surface *surface)
{
screen->winsys->buffer_unmap( screen->winsys, surface->buffer );
pipe_buffer_unmap( screen, surface->buffer );
}
@ -333,12 +372,15 @@ cell_init_texture_functions(struct cell_context *cell)
/*cell->pipe.texture_update = cell_texture_update;*/
}
void
cell_init_screen_texture_funcs(struct pipe_screen *screen)
{
screen->texture_create = cell_texture_create_screen;
screen->texture_release = cell_texture_release_screen;
screen->get_tex_surface = cell_get_tex_surface_screen;
screen->texture_create = cell_texture_create;
screen->texture_release = cell_texture_release;
screen->get_tex_surface = cell_get_tex_surface;
screen->tex_surface_release = cell_tex_surface_release;
screen->surface_map = cell_surface_map;
screen->surface_unmap = cell_surface_unmap;

View File

@ -26,6 +26,11 @@
**************************************************************************/
/**
* Vertex buffer code. The draw module transforms vertices to window
* coords, etc. and emits the vertices into buffer supplied by this module.
* When a vertex buffer is full, or we flush, we'll send the vertex data
* to the SPUs.
*
* Authors
* Brian Paul
*/
@ -113,7 +118,7 @@ cell_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices,
}
cvbr->vertex_buf = ~0;
cell_flush_int(&cell->pipe, 0x0);
cell_flush_int(cell, 0x0);
assert(vertices == cvbr->vertex_buffer);
cvbr->vertex_buffer = NULL;
@ -121,12 +126,13 @@ cell_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices,
static void
static boolean
cell_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
{
struct cell_vbuf_render *cvbr = cell_vbuf_render(vbr);
cvbr->prim = prim;
/*printf("cell_set_prim %u\n", prim);*/
return TRUE;
}
@ -244,7 +250,7 @@ cell_vbuf_draw(struct vbuf_render *vbr,
#if 0
/* helpful for debug */
cell_flush_int(&cell->pipe, CELL_FLUSH_WAIT);
cell_flush_int(cell, CELL_FLUSH_WAIT);
#endif
}

View File

@ -297,10 +297,9 @@ void cell_update_vertex_fetch(struct draw_context *draw)
/* Each fetch function can be a maximum of 34 instructions (note: this is
* actually a slight over-estimate). That means (34 * 4) = 136 bytes
* each maximum.
* actually a slight over-estimate).
*/
spe_init_func(p, 136 * unique_attr_formats);
spe_init_func(p, 34 * SPE_INST_SIZE * unique_attr_formats);
/* Allocate registers for the function's input parameters.

View File

@ -135,7 +135,7 @@ cell_vertex_shader_queue_flush(struct draw_context *draw)
vs->num_elts = n;
send_mbox_message(cell_global.spe_contexts[0], CELL_CMD_VS_EXECUTE);
cell_flush_int(& cell->pipe, CELL_FLUSH_WAIT);
cell_flush_int(cell, CELL_FLUSH_WAIT);
}
draw->vs.post_nr = draw->vs.queue_nr;

View File

@ -5,7 +5,7 @@
TOP = ../../../../..
include $(TOP)/configs/linux-cell
include $(TOP)/configs/current
PROG = g3d
@ -22,12 +22,15 @@ SOURCES = \
spu_render.c \
spu_texture.c \
spu_tile.c \
spu_tri.c \
spu_tri.c
OLD_SOURCES = \
spu_exec.c \
spu_util.c \
spu_vertex_fetch.c \
spu_vertex_shader.c
SPU_OBJECTS = $(SOURCES:.c=.o) \
SPU_ASM_OUT = $(SOURCES:.c=.s) \
@ -43,7 +46,7 @@ INCLUDE_DIRS = \
$(SPU_CC) $(SPU_CFLAGS) -c $<
.c.s:
$(SPU_CC) $(SPU_CFLAGS) -S $<
$(SPU_CC) $(SPU_CFLAGS) -O3 -S $<
# The .a file will be linked into the main/PPU executable

View File

@ -79,14 +79,14 @@ spu_pack_color_shuffle(vector float rgba, vector unsigned char shuffle)
static INLINE vector float
spu_unpack_color(uint color)
spu_unpack_B8G8R8A8(uint color)
{
vector unsigned int color_u4 = spu_splats(color);
color_u4 = spu_shuffle(color_u4, color_u4,
((vector unsigned char) {
0, 0, 0, 0,
5, 5, 5, 5,
10, 10, 10, 10,
5, 5, 5, 5,
0, 0, 0, 0,
15, 15, 15, 15}) );
return spu_convtf(color_u4, 32);
}

View File

@ -382,10 +382,10 @@ fetch_src_file_channel(
break;
case TGSI_FILE_IMMEDIATE:
assert( index->i[0] < (int) mach->ImmLimit );
assert( index->i[1] < (int) mach->ImmLimit );
assert( index->i[2] < (int) mach->ImmLimit );
assert( index->i[3] < (int) mach->ImmLimit );
ASSERT( index->i[0] < (int) mach->ImmLimit );
ASSERT( index->i[1] < (int) mach->ImmLimit );
ASSERT( index->i[2] < (int) mach->ImmLimit );
ASSERT( index->i[3] < (int) mach->ImmLimit );
chan->f[0] = mach->Imms[index->i[0]][swizzle];
chan->f[1] = mach->Imms[index->i[1]][swizzle];
@ -409,7 +409,7 @@ fetch_src_file_channel(
break;
default:
assert( 0 );
ASSERT( 0 );
}
break;
@ -422,7 +422,7 @@ fetch_src_file_channel(
break;
default:
assert( 0 );
ASSERT( 0 );
}
}
@ -471,7 +471,7 @@ fetch_source(
index.q = si_shli(index.q, 12);
break;
default:
assert( 0 );
ASSERT( 0 );
}
index.i[0] += reg->SrcRegisterDim.Index;
@ -558,7 +558,7 @@ store_dest(
break;
default:
assert( 0 );
ASSERT( 0 );
return;
}
@ -582,11 +582,11 @@ store_dest(
break;
case TGSI_SAT_MINUS_PLUS_ONE:
assert( 0 );
ASSERT( 0 );
break;
default:
assert( 0 );
ASSERT( 0 );
}
}
@ -769,7 +769,7 @@ exec_tex(struct spu_exec_machine *mach,
break;
default:
assert (0);
ASSERT (0);
}
FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
@ -861,7 +861,7 @@ exec_declaration(struct spu_exec_machine *mach,
break;
default:
assert( 0 );
ASSERT( 0 );
}
if( mask == TGSI_WRITEMASK_XYZW ) {
@ -971,11 +971,11 @@ exec_instruction(
break;
case TGSI_OPCODE_EXP:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_LOG:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_MUL:
@ -1151,24 +1151,24 @@ exec_instruction(
break;
case TGSI_OPCODE_CND:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_CND0:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_DOT2ADD:
/* TGSI_OPCODE_DP2A */
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_INDEX:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_NEGATE:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_FRAC:
@ -1181,7 +1181,7 @@ exec_instruction(
break;
case TGSI_OPCODE_CLAMP:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_FLOOR:
@ -1276,7 +1276,7 @@ exec_instruction(
break;
case TGSI_OPCODE_MULTIPLYMATRIX:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_ABS:
@ -1290,7 +1290,7 @@ exec_instruction(
break;
case TGSI_OPCODE_RCC:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_DPH:
@ -1353,23 +1353,23 @@ exec_instruction(
break;
case TGSI_OPCODE_PK2H:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_PK2US:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_PK4B:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_PK4UB:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_RFL:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_SEQ:
@ -1384,7 +1384,7 @@ exec_instruction(
break;
case TGSI_OPCODE_SFL:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_SGT:
@ -1429,7 +1429,7 @@ exec_instruction(
break;
case TGSI_OPCODE_STR:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_TEX:
@ -1452,7 +1452,7 @@ exec_instruction(
/* src[1] = d[strq]/dx */
/* src[2] = d[strq]/dy */
/* src[3] = sampler unit */
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_TXL:
@ -1470,35 +1470,35 @@ exec_instruction(
break;
case TGSI_OPCODE_UP2H:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_UP2US:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_UP4B:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_UP4UB:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_X2D:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_ARA:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_ARR:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_BRA:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_CAL:
@ -1507,14 +1507,14 @@ exec_instruction(
/* do the call */
/* push the Cond, Loop, Cont stacks */
assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
ASSERT(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
mach->CondStack[mach->CondStackTop++] = mach->CondMask;
assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
ASSERT(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
ASSERT(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
mach->ContStack[mach->ContStackTop++] = mach->ContMask;
assert(mach->FuncStackTop < TGSI_EXEC_MAX_CALL_NESTING);
ASSERT(mach->FuncStackTop < TGSI_EXEC_MAX_CALL_NESTING);
mach->FuncStack[mach->FuncStackTop++] = mach->FuncMask;
/* note that PC was already incremented above */
@ -1538,13 +1538,13 @@ exec_instruction(
*pc = mach->CallStack[--mach->CallStackTop];
/* pop the Cond, Loop, Cont stacks */
assert(mach->CondStackTop > 0);
ASSERT(mach->CondStackTop > 0);
mach->CondMask = mach->CondStack[--mach->CondStackTop];
assert(mach->LoopStackTop > 0);
ASSERT(mach->LoopStackTop > 0);
mach->LoopMask = mach->LoopStack[--mach->LoopStackTop];
assert(mach->ContStackTop > 0);
ASSERT(mach->ContStackTop > 0);
mach->ContMask = mach->ContStack[--mach->ContStackTop];
assert(mach->FuncStackTop > 0);
ASSERT(mach->FuncStackTop > 0);
mach->FuncMask = mach->FuncStack[--mach->FuncStackTop];
UPDATE_EXEC_MASK(mach);
@ -1552,7 +1552,7 @@ exec_instruction(
break;
case TGSI_OPCODE_SSG:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_CMP:
@ -1592,11 +1592,11 @@ exec_instruction(
break;
case TGSI_OPCODE_NRM:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_DIV:
assert( 0 );
ASSERT( 0 );
break;
case TGSI_OPCODE_DP2:
@ -1615,7 +1615,7 @@ exec_instruction(
case TGSI_OPCODE_IF:
/* push CondMask */
assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
ASSERT(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
mach->CondStack[mach->CondStackTop++] = mach->CondMask;
FETCH( &r[0], 0, CHAN_X );
/* update CondMask */
@ -1639,7 +1639,7 @@ exec_instruction(
/* invert CondMask wrt previous mask */
{
uint prevMask;
assert(mach->CondStackTop > 0);
ASSERT(mach->CondStackTop > 0);
prevMask = mach->CondStack[mach->CondStackTop - 1];
mach->CondMask = ~mach->CondMask & prevMask;
UPDATE_EXEC_MASK(mach);
@ -1649,7 +1649,7 @@ exec_instruction(
case TGSI_OPCODE_ENDIF:
/* pop CondMask */
assert(mach->CondStackTop > 0);
ASSERT(mach->CondStackTop > 0);
mach->CondMask = mach->CondStack[--mach->CondStackTop];
UPDATE_EXEC_MASK(mach);
break;
@ -1660,19 +1660,19 @@ exec_instruction(
break;
case TGSI_OPCODE_REP:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_ENDREP:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_PUSHA:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_POPA:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_CEIL:
@ -1746,7 +1746,7 @@ exec_instruction(
break;
case TGSI_OPCODE_MOD:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_XOR:
@ -1759,15 +1759,15 @@ exec_instruction(
break;
case TGSI_OPCODE_SAD:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_TXF:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_TXQ:
assert (0);
ASSERT (0);
break;
case TGSI_OPCODE_EMIT:
@ -1784,9 +1784,9 @@ exec_instruction(
/* fall-through (for now) */
case TGSI_OPCODE_BGNLOOP2:
/* push LoopMask and ContMasks */
assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
ASSERT(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
ASSERT(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
mach->ContStack[mach->ContStackTop++] = mach->ContMask;
break;
@ -1794,7 +1794,7 @@ exec_instruction(
/* fall-through (for now at least) */
case TGSI_OPCODE_ENDLOOP2:
/* Restore ContMask, but don't pop */
assert(mach->ContStackTop > 0);
ASSERT(mach->ContStackTop > 0);
mach->ContMask = mach->ContStack[mach->ContStackTop - 1];
if (mach->LoopMask) {
/* repeat loop: jump to instruction just past BGNLOOP */
@ -1802,10 +1802,10 @@ exec_instruction(
}
else {
/* exit loop: pop LoopMask */
assert(mach->LoopStackTop > 0);
ASSERT(mach->LoopStackTop > 0);
mach->LoopMask = mach->LoopStack[--mach->LoopStackTop];
/* pop ContMask */
assert(mach->ContStackTop > 0);
ASSERT(mach->ContStackTop > 0);
mach->ContMask = mach->ContStack[--mach->ContStackTop];
}
UPDATE_EXEC_MASK(mach);
@ -1834,26 +1834,26 @@ exec_instruction(
break;
case TGSI_OPCODE_NOISE1:
assert( 0 );
ASSERT( 0 );
break;
case TGSI_OPCODE_NOISE2:
assert( 0 );
ASSERT( 0 );
break;
case TGSI_OPCODE_NOISE3:
assert( 0 );
ASSERT( 0 );
break;
case TGSI_OPCODE_NOISE4:
assert( 0 );
ASSERT( 0 );
break;
case TGSI_OPCODE_NOP:
break;
default:
assert( 0 );
ASSERT( 0 );
}
}
@ -1874,11 +1874,11 @@ spu_exec_machine_run( struct spu_exec_machine *mach )
mach->FuncMask = 0xf;
mach->ExecMask = 0xf;
mach->CondStackTop = 0; /* temporarily subvert this assertion */
assert(mach->CondStackTop == 0);
assert(mach->LoopStackTop == 0);
assert(mach->ContStackTop == 0);
assert(mach->CallStackTop == 0);
mach->CondStackTop = 0; /* temporarily subvert this ASSERTion */
ASSERT(mach->CondStackTop == 0);
ASSERT(mach->LoopStackTop == 0);
ASSERT(mach->ContStackTop == 0);
ASSERT(mach->CallStackTop == 0);
mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] = 0;
mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] = 0;

View File

@ -34,6 +34,7 @@
#include "spu_main.h"
#include "spu_render.h"
#include "spu_per_fragment_op.h"
#include "spu_texture.h"
#include "spu_tile.h"
//#include "spu_test.h"
@ -46,7 +47,7 @@
/*
helpful headers:
/usr/lib/gcc/spu/4.1.1/include/spu_mfcio.h
/opt/ibm/cell-sdk/prototype/sysroot/usr/include/libmisc.h
/opt/cell/sdk/usr/include/libmisc.h
*/
boolean Debug = FALSE;
@ -55,17 +56,13 @@ struct spu_global spu;
struct spu_vs_context draw;
/**
* Buffers containing dynamically generated SPU code:
*/
static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS]
ALIGN16_ATTRIB;
static unsigned char depth_stencil_code_buffer[4 * 64]
ALIGN16_ATTRIB;
static unsigned char fb_blend_code_buffer[4 * 64]
ALIGN16_ATTRIB;
static unsigned char logicop_code_buffer[4 * 64]
ALIGN16_ATTRIB;
/**
@ -136,54 +133,75 @@ really_clear_tiles(uint surfaceIndex)
static void
cmd_clear_surface(const struct cell_command_clear_surface *clear)
{
const uint num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
uint i;
if (Debug)
printf("SPU %u: CLEAR SURF %u to 0x%08x\n", spu.init.id,
clear->surface, clear->value);
if (clear->surface == 0) {
spu.fb.color_clear_value = clear->value;
if (spu.init.debug_flags & CELL_DEBUG_CHECKER) {
uint x = (spu.init.id << 4) | (spu.init.id << 12) |
(spu.init.id << 20) | (spu.init.id << 28);
spu.fb.color_clear_value ^= x;
}
}
else {
spu.fb.depth_clear_value = clear->value;
}
#define CLEAR_OPT 1
#if CLEAR_OPT
/* set all tile's status to CLEAR */
/* Simply set all tiles' status to CLEAR.
* When we actually begin rendering into a tile, we'll initialize it to
* the clear value. If any tiles go untouched during the frame,
* really_clear_tiles() will set them to the clear value.
*/
if (clear->surface == 0) {
memset(spu.ctile_status, TILE_STATUS_CLEAR, sizeof(spu.ctile_status));
spu.fb.color_clear_value = clear->value;
}
else {
memset(spu.ztile_status, TILE_STATUS_CLEAR, sizeof(spu.ztile_status));
spu.fb.depth_clear_value = clear->value;
}
return;
#endif
if (clear->surface == 0) {
spu.fb.color_clear_value = clear->value;
clear_c_tile(&spu.ctile);
}
else {
spu.fb.depth_clear_value = clear->value;
clear_z_tile(&spu.ztile);
}
#else
/*
* This path clears the whole framebuffer to the clear color right now.
*/
/*
printf("SPU: %s num=%d w=%d h=%d\n",
__FUNCTION__, num_tiles, spu.fb.width_tiles, spu.fb.height_tiles);
*/
for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
uint tx = i % spu.fb.width_tiles;
uint ty = i / spu.fb.width_tiles;
if (clear->surface == 0)
put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 0);
else
put_tile(tx, ty, &spu.ztile, TAG_SURFACE_CLEAR, 1);
/* XXX we don't want this here, but it fixes bad tile results */
/* init a single tile to the clear value */
if (clear->surface == 0) {
clear_c_tile(&spu.ctile);
}
else {
clear_z_tile(&spu.ztile);
}
#if 0
wait_on_mask(1 << TAG_SURFACE_CLEAR);
#endif
/* walk over my tiles, writing the 'clear' tile's data */
{
const uint num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
uint i;
for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
uint tx = i % spu.fb.width_tiles;
uint ty = i / spu.fb.width_tiles;
if (clear->surface == 0)
put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 0);
else
put_tile(tx, ty, &spu.ztile, TAG_SURFACE_CLEAR, 1);
}
}
if (spu.init.debug_flags & CELL_DEBUG_SYNC) {
wait_on_mask(1 << TAG_SURFACE_CLEAR);
}
#endif /* CLEAR_OPT */
if (Debug)
printf("SPU %u: CLEAR SURF done\n", spu.init.id);
@ -201,6 +219,31 @@ cmd_release_verts(const struct cell_command_release_verts *release)
}
/**
* Process a CELL_CMD_STATE_FRAGMENT_OPS command.
* This involves installing new fragment ops SPU code.
* If this function is never called, we'll use a regular C fallback function
* for fragment processing.
*/
static void
cmd_state_fragment_ops(const struct cell_command_fragment_ops *fops)
{
if (Debug)
printf("SPU %u: CMD_STATE_FRAGMENT_OPS\n", spu.init.id);
/* Copy SPU code from batch buffer to spu buffer */
memcpy(spu.fragment_ops_code, fops->code, SPU_MAX_FRAGMENT_OPS_INSTS * 4);
/* Copy state info */
memcpy(&spu.depth_stencil_alpha, &fops->dsa, sizeof(fops->dsa));
memcpy(&spu.blend, &fops->blend, sizeof(fops->blend));
/* Point function pointer at new code */
spu.fragment_ops = (spu_fragment_ops_func) spu.fragment_ops_code;
spu.read_depth = spu.depth_stencil_alpha.depth.enabled;
spu.read_stencil = spu.depth_stencil_alpha.stencil[0].enabled;
}
static void
cmd_state_framebuffer(const struct cell_command_framebuffer *cmd)
{
@ -227,87 +270,24 @@ cmd_state_framebuffer(const struct cell_command_framebuffer *cmd)
switch (spu.fb.depth_format) {
case PIPE_FORMAT_Z32_UNORM:
spu.fb.zsize = 4;
spu.fb.zscale = (float) 0xffffffffu;
break;
case PIPE_FORMAT_Z24S8_UNORM:
case PIPE_FORMAT_S8Z24_UNORM:
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
spu.fb.zsize = 4;
spu.fb.zscale = (float) 0x00ffffffu;
break;
case PIPE_FORMAT_Z16_UNORM:
spu.fb.zsize = 2;
spu.fb.zscale = (float) 0xffffu;
break;
default:
spu.fb.zsize = 0;
break;
}
if (spu.fb.color_format == PIPE_FORMAT_A8R8G8B8_UNORM)
spu.color_shuffle = ((vector unsigned char) {
12, 0, 4, 8, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0});
else if (spu.fb.color_format == PIPE_FORMAT_B8G8R8A8_UNORM)
spu.color_shuffle = ((vector unsigned char) {
8, 4, 0, 12, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0});
else
ASSERT(0);
}
static void
cmd_state_blend(const struct cell_command_blend *state)
{
if (Debug)
printf("SPU %u: BLEND: enabled %d\n",
spu.init.id,
(state->size != 0));
ASSERT_ALIGN16(state->base);
if (state->size != 0) {
mfc_get(fb_blend_code_buffer,
(unsigned int) state->base, /* src */
ROUNDUP16(state->size),
TAG_BATCH_BUFFER,
0, /* tid */
0 /* rid */);
wait_on_mask(1 << TAG_BATCH_BUFFER);
spu.blend = (blend_func) fb_blend_code_buffer;
spu.read_fb = state->read_fb;
} else {
spu.read_fb = FALSE;
}
}
static void
cmd_state_depth_stencil(const struct cell_command_depth_stencil_alpha_test *state)
{
if (Debug)
printf("SPU %u: DEPTH_STENCIL: ztest %d\n",
spu.init.id,
state->read_depth);
ASSERT_ALIGN16(state->base);
if (state->size != 0) {
mfc_get(depth_stencil_code_buffer,
(unsigned int) state->base, /* src */
ROUNDUP16(state->size),
TAG_BATCH_BUFFER,
0, /* tid */
0 /* rid */);
wait_on_mask(1 << TAG_BATCH_BUFFER);
} else {
/* If there is no code, emit a return instruction.
*/
depth_stencil_code_buffer[0] = 0x35;
depth_stencil_code_buffer[1] = 0x00;
depth_stencil_code_buffer[2] = 0x00;
depth_stencil_code_buffer[3] = 0x00;
}
spu.frag_test = (frag_test_func) depth_stencil_code_buffer;
spu.read_depth = state->read_depth;
spu.read_stencil = state->read_stencil;
}
@ -380,6 +360,21 @@ cmd_state_vs_array_info(const struct cell_array_info *vs_info)
}
static void
cmd_state_attrib_fetch(const struct cell_attribute_fetch_code *code)
{
mfc_get(attribute_fetch_code_buffer,
(unsigned int) code->base, /* src */
code->size,
TAG_BATCH_BUFFER,
0, /* tid */
0 /* rid */);
wait_on_mask(1 << TAG_BATCH_BUFFER);
draw.vertex_fetch.code = attribute_fetch_code_buffer;
}
static void
cmd_finish(void)
{
@ -395,7 +390,9 @@ cmd_finish(void)
/**
* Execute a batch of commands
* Execute a batch of commands which was sent to us by the PPU.
* See the cell_emit_state.c code to see where the commands come from.
*
* The opcode param encodes the location of the buffer and its size.
*/
static void
@ -432,16 +429,14 @@ cmd_batch(uint opcode)
printf("SPU %u: release batch buf %u\n", spu.init.id, buf);
release_buffer(buf);
/*
* Loop over commands in the batch buffer
*/
for (pos = 0; pos < usize; /* no incr */) {
switch (buffer[pos]) {
case CELL_CMD_STATE_FRAMEBUFFER:
{
struct cell_command_framebuffer *fb
= (struct cell_command_framebuffer *) &buffer[pos];
cmd_state_framebuffer(fb);
pos += sizeof(*fb) / 8;
}
break;
/*
* rendering commands
*/
case CELL_CMD_CLEAR_SURFACE:
{
struct cell_command_clear_surface *clr
@ -459,26 +454,24 @@ cmd_batch(uint opcode)
pos += pos_incr;
}
break;
case CELL_CMD_RELEASE_VERTS:
/*
* state-update commands
*/
case CELL_CMD_STATE_FRAMEBUFFER:
{
struct cell_command_release_verts *release
= (struct cell_command_release_verts *) &buffer[pos];
cmd_release_verts(release);
pos += sizeof(*release) / 8;
struct cell_command_framebuffer *fb
= (struct cell_command_framebuffer *) &buffer[pos];
cmd_state_framebuffer(fb);
pos += sizeof(*fb) / 8;
}
break;
case CELL_CMD_FINISH:
cmd_finish();
pos += 1;
break;
case CELL_CMD_STATE_BLEND:
cmd_state_blend((struct cell_command_blend *) &buffer[pos+1]);
pos += (1 + ROUNDUP8(sizeof(struct cell_command_blend)) / 8);
break;
case CELL_CMD_STATE_DEPTH_STENCIL:
cmd_state_depth_stencil((struct cell_command_depth_stencil_alpha_test *)
&buffer[pos+1]);
pos += (1 + ROUNDUP8(sizeof(struct cell_command_depth_stencil_alpha_test)) / 8);
case CELL_CMD_STATE_FRAGMENT_OPS:
{
struct cell_command_fragment_ops *fops
= (struct cell_command_fragment_ops *) &buffer[pos];
cmd_state_fragment_ops(fops);
pos += sizeof(*fops) / 8;
}
break;
case CELL_CMD_STATE_SAMPLER:
{
@ -514,42 +507,32 @@ cmd_batch(uint opcode)
pos += (1 + ROUNDUP8(sizeof(struct cell_array_info)) / 8);
break;
case CELL_CMD_STATE_BIND_VS:
#if 0
spu_bind_vertex_shader(&draw,
(struct cell_shader_info *) &buffer[pos+1]);
#endif
pos += (1 + ROUNDUP8(sizeof(struct cell_shader_info)) / 8);
break;
case CELL_CMD_STATE_ATTRIB_FETCH: {
struct cell_attribute_fetch_code *code =
(struct cell_attribute_fetch_code *) &buffer[pos+1];
mfc_get(attribute_fetch_code_buffer,
(unsigned int) code->base, /* src */
code->size,
TAG_BATCH_BUFFER,
0, /* tid */
0 /* rid */);
wait_on_mask(1 << TAG_BATCH_BUFFER);
draw.vertex_fetch.code = attribute_fetch_code_buffer;
case CELL_CMD_STATE_ATTRIB_FETCH:
cmd_state_attrib_fetch((struct cell_attribute_fetch_code *)
&buffer[pos+1]);
pos += (1 + ROUNDUP8(sizeof(struct cell_attribute_fetch_code)) / 8);
break;
}
case CELL_CMD_STATE_LOGICOP: {
struct cell_command_logicop *code =
(struct cell_command_logicop *) &buffer[pos+1];
mfc_get(logicop_code_buffer,
(unsigned int) code->base, /* src */
code->size,
TAG_BATCH_BUFFER,
0, /* tid */
0 /* rid */);
wait_on_mask(1 << TAG_BATCH_BUFFER);
spu.logicop = (logicop_func) logicop_code_buffer;
pos += (1 + ROUNDUP8(sizeof(struct cell_command_logicop)) / 8);
/*
* misc commands
*/
case CELL_CMD_FINISH:
cmd_finish();
pos += 1;
break;
case CELL_CMD_RELEASE_VERTS:
{
struct cell_command_release_verts *release
= (struct cell_command_release_verts *) &buffer[pos];
cmd_release_verts(release);
pos += sizeof(*release) / 8;
}
break;
}
case CELL_CMD_FLUSH_BUFFER_RANGE: {
struct cell_buffer_range *br = (struct cell_buffer_range *)
&buffer[pos+1];
@ -618,7 +601,9 @@ main_loop(void)
exitFlag = 1;
break;
case CELL_CMD_VS_EXECUTE:
#if 0
spu_execute_vertex_shader(&draw, &cmd.vs);
#endif
break;
case CELL_CMD_BATCH:
cmd_batch(opcode);
@ -643,6 +628,11 @@ one_time_init(void)
memset(spu.ctile_status, TILE_STATUS_DEFINED, sizeof(spu.ctile_status));
memset(spu.ztile_status, TILE_STATUS_DEFINED, sizeof(spu.ztile_status));
invalidate_tex_cache();
/* Install default/fallback fragment processing function.
* This will normally be overriden by a code-gen'd function.
*/
spu.fragment_ops = spu_fallback_fragment_ops;
}

View File

@ -41,6 +41,10 @@
#define MAX_HEIGHT 1024
/**
* A tile is basically a TILE_SIZE x TILE_SIZE block of 4-byte pixels.
* The data may be addressed through several different types.
*/
typedef union {
ushort us[TILE_SIZE][TILE_SIZE];
uint ui[TILE_SIZE][TILE_SIZE];
@ -56,38 +60,23 @@ typedef union {
#define TILE_STATUS_GETTING 5 /**< mfc_get() called but not yet arrived */
struct spu_frag_test_results {
qword mask;
qword depth;
qword stencil;
};
/** Function for sampling textures */
typedef vector float (*spu_sample_texture_func)(uint unit,
vector float texcoord);
typedef struct spu_frag_test_results (*frag_test_func)(qword frag_mask,
qword pixel_depth, qword pixel_stencil, qword frag_depth,
qword frag_alpha, qword facing);
/** Function for performing per-fragment ops */
typedef void (*spu_fragment_ops_func)(uint x, uint y,
tile_t *colorTile,
tile_t *depthStencilTile,
vector float fragZ,
vector float fragRed,
vector float fragGreen,
vector float fragBlue,
vector float fragAlpha,
vector unsigned int mask);
struct spu_blend_results {
qword r;
qword g;
qword b;
qword a;
};
typedef struct spu_blend_results (*blend_func)(
qword frag_r, qword frag_g, qword frag_b, qword frag_a,
qword pixel_r, qword pixel_g, qword pixel_b, qword pixel_a,
qword const_r, qword const_g, qword const_b, qword const_a);
typedef struct spu_blend_results (*logicop_func)(
qword pixel_r, qword pixel_g, qword pixel_b, qword pixel_a,
qword frag_r, qword frag_g, qword frag_b, qword frag_a,
qword frag_mask);
typedef vector float (*sample_texture_func)(uint unit, vector float texcoord);
struct spu_framebuffer {
struct spu_framebuffer
{
void *color_start; /**< addr of color surface in main memory */
void *depth_start; /**< addr of depth surface in main memory */
enum pipe_format color_format;
@ -99,6 +88,7 @@ struct spu_framebuffer {
uint depth_clear_value;
uint zsize; /**< 0, 2 or 4 bytes per Z */
float zscale; /**< 65535.0, 2^24-1 or 2^32-1 */
} ALIGN16_ATTRIB;
@ -115,35 +105,31 @@ struct spu_texture
/**
* All SPU global/context state will be in singleton object of this type:
* All SPU global/context state will be in a singleton object of this type:
*/
struct spu_global
{
/** One-time init/constant info */
struct cell_init_info init;
/*
* Current state
*/
struct spu_framebuffer fb;
boolean read_depth;
boolean read_stencil;
frag_test_func frag_test;
boolean read_fb;
blend_func blend;
qword const_blend_color[4] ALIGN16_ATTRIB;
logicop_func logicop;
struct pipe_depth_stencil_alpha_state depth_stencil_alpha;
struct pipe_blend_state blend;
struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS];
struct spu_texture texture[PIPE_MAX_SAMPLERS];
struct vertex_info vertex_info;
/* XXX more state to come */
/** current color and Z tiles */
/** Current color and Z tiles */
tile_t ctile ALIGN16_ATTRIB;
tile_t ztile ALIGN16_ATTRIB;
/** Read depth/stencil tiles? */
boolean read_depth;
boolean read_stencil;
/** Current tiles' status */
ubyte cur_ctile_status, cur_ztile_status;
@ -151,11 +137,13 @@ struct spu_global
ubyte ctile_status[MAX_HEIGHT/TILE_SIZE][MAX_WIDTH/TILE_SIZE] ALIGN16_ATTRIB;
ubyte ztile_status[MAX_HEIGHT/TILE_SIZE][MAX_WIDTH/TILE_SIZE] ALIGN16_ATTRIB;
/** Current fragment ops machine code */
uint fragment_ops_code[SPU_MAX_FRAGMENT_OPS_INSTS];
/** Current fragment ops function */
spu_fragment_ops_func fragment_ops;
/** for converting RGBA to PIPE_FORMAT_x colors */
vector unsigned char color_shuffle;
sample_texture_func sample_texture[CELL_MAX_SAMPLERS];
/** Current texture sampler function */
spu_sample_texture_func sample_texture[CELL_MAX_SAMPLERS];
} ALIGN16_ATTRIB;

View File

@ -1,211 +1,475 @@
/*
* (C) Copyright IBM Corporation 2008
/**************************************************************************
*
* 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
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
* copy of this software and 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 spu_per_fragment_op.c
* SPU implementation various per-fragment operations.
*
* \author Ian Romanick <idr@us.ibm.com>
* \author Brian Paul
*/
#include <transpose_matrix4x4.h>
#include "pipe/p_format.h"
#include "spu_main.h"
#include "spu_colorpack.h"
#include "spu_per_fragment_op.h"
#define ZERO 0x80
static void
read_ds_quad(tile_t *buffer, unsigned x, unsigned y,
enum pipe_format depth_format, qword *depth,
qword *stencil)
#define LINEAR_QUAD_LAYOUT 1
/**
* Called by rasterizer for each quad after the shader has run. Do
* all the per-fragment operations including alpha test, z test,
* stencil test, blend, colormask and logicops. This is a
* fallback/debug function. In reality we'll use a generated function
* produced by the PPU. But this function is useful for
* debug/validation.
*/
void
spu_fallback_fragment_ops(uint x, uint y,
tile_t *colorTile,
tile_t *depthStencilTile,
vector float fragZ,
vector float fragR,
vector float fragG,
vector float fragB,
vector float fragA,
vector unsigned int mask)
{
const int ix = x / 2;
const int iy = y / 2;
vector float frag_aos[4];
unsigned int c0, c1, c2, c3;
switch (depth_format) {
case PIPE_FORMAT_Z16_UNORM: {
qword *ptr = (qword *) &buffer->us8[iy][ix / 2];
/* do alpha test */
if (spu.depth_stencil_alpha.alpha.enabled) {
vector float ref = spu_splats(spu.depth_stencil_alpha.alpha.ref);
vector unsigned int amask;
const qword shuf_vec = (qword) {
ZERO, ZERO, 0, 1, ZERO, ZERO, 2, 3,
ZERO, ZERO, 4, 5, ZERO, ZERO, 6, 7
};
switch (spu.depth_stencil_alpha.alpha.func) {
case PIPE_FUNC_LESS:
amask = spu_cmpgt(ref, fragA); /* mask = (fragA < ref) */
break;
case PIPE_FUNC_GREATER:
amask = spu_cmpgt(fragA, ref); /* mask = (fragA > ref) */
break;
case PIPE_FUNC_GEQUAL:
amask = spu_cmpgt(ref, fragA);
amask = spu_nor(amask, amask);
break;
case PIPE_FUNC_LEQUAL:
amask = spu_cmpgt(fragA, ref);
amask = spu_nor(amask, amask);
break;
case PIPE_FUNC_EQUAL:
amask = spu_cmpeq(ref, fragA);
break;
case PIPE_FUNC_NOTEQUAL:
amask = spu_cmpeq(ref, fragA);
amask = spu_nor(amask, amask);
break;
case PIPE_FUNC_ALWAYS:
amask = spu_splats(0xffffffffU);
break;
case PIPE_FUNC_NEVER:
amask = spu_splats( 0x0U);
break;
default:
;
}
mask = spu_and(mask, amask);
}
/* At even X values we want the first 4 shorts, and at odd X values we
* want the second 4 shorts.
/* Z and/or stencil testing... */
if (spu.depth_stencil_alpha.depth.enabled ||
spu.depth_stencil_alpha.stencil[0].enabled) {
/* get four Z/Stencil values from tile */
vector unsigned int mask24 = spu_splats((unsigned int)0x00ffffffU);
vector unsigned int ifbZS = depthStencilTile->ui4[y/2][x/2];
vector unsigned int ifbZ = spu_and(ifbZS, mask24);
vector unsigned int ifbS = spu_andc(ifbZS, mask24);
if (spu.depth_stencil_alpha.stencil[0].enabled) {
/* do stencil test */
ASSERT(spu.fb.depth_format == PIPE_FORMAT_S8Z24_UNORM);
}
else if (spu.depth_stencil_alpha.depth.enabled) {
/* do depth test */
ASSERT(spu.fb.depth_format == PIPE_FORMAT_S8Z24_UNORM ||
spu.fb.depth_format == PIPE_FORMAT_X8Z24_UNORM);
vector unsigned int ifragZ;
vector unsigned int zmask;
/* convert four fragZ from float to uint */
fragZ = spu_mul(fragZ, spu_splats((float) 0xffffff));
ifragZ = spu_convtu(fragZ, 0);
/* do depth comparison, setting zmask with results */
switch (spu.depth_stencil_alpha.depth.func) {
case PIPE_FUNC_LESS:
zmask = spu_cmpgt(ifbZ, ifragZ); /* mask = (ifragZ < ifbZ) */
break;
case PIPE_FUNC_GREATER:
zmask = spu_cmpgt(ifragZ, ifbZ); /* mask = (ifbZ > ifragZ) */
break;
case PIPE_FUNC_GEQUAL:
zmask = spu_cmpgt(ifbZ, ifragZ);
zmask = spu_nor(zmask, zmask);
break;
case PIPE_FUNC_LEQUAL:
zmask = spu_cmpgt(ifragZ, ifbZ);
zmask = spu_nor(zmask, zmask);
break;
case PIPE_FUNC_EQUAL:
zmask = spu_cmpeq(ifbZ, ifragZ);
break;
case PIPE_FUNC_NOTEQUAL:
zmask = spu_cmpeq(ifbZ, ifragZ);
zmask = spu_nor(zmask, zmask);
break;
case PIPE_FUNC_ALWAYS:
zmask = spu_splats(0xffffffffU);
break;
case PIPE_FUNC_NEVER:
zmask = spu_splats( 0x0U);
break;
default:
;
}
mask = spu_and(mask, zmask);
/* merge framebuffer Z and fragment Z according to the mask */
ifbZ = spu_or(spu_and(ifragZ, mask),
spu_andc(ifbZ, mask));
}
if (spu_extract(spu_orx(mask), 0)) {
/* put new fragment Z/Stencil values back into Z/Stencil tile */
depthStencilTile->ui4[y/2][x/2] = spu_or(ifbZ, ifbS);
spu.cur_ztile_status = TILE_STATUS_DIRTY;
}
}
if (spu.blend.blend_enable) {
/* blending terms, misc regs */
vector float term1r, term1g, term1b, term1a;
vector float term2r, term2g, term2b, term2a;
vector float one, tmp;
vector float fbRGBA[4]; /* current framebuffer colors */
/* get colors from framebuffer/tile */
{
vector float fc[4];
uint c0, c1, c2, c3;
#if LINEAR_QUAD_LAYOUT /* See comments/diagram below */
c0 = colorTile->ui[y][x*2+0];
c1 = colorTile->ui[y][x*2+1];
c2 = colorTile->ui[y][x*2+2];
c3 = colorTile->ui[y][x*2+3];
#else
c0 = colorTile->ui[y+0][x+0];
c1 = colorTile->ui[y+0][x+1];
c2 = colorTile->ui[y+1][x+0];
c3 = colorTile->ui[y+1][x+1];
#endif
switch (spu.fb.color_format) {
case PIPE_FORMAT_B8G8R8A8_UNORM:
fc[0] = spu_unpack_B8G8R8A8(c0);
fc[1] = spu_unpack_B8G8R8A8(c1);
fc[2] = spu_unpack_B8G8R8A8(c2);
fc[3] = spu_unpack_B8G8R8A8(c3);
break;
case PIPE_FORMAT_A8R8G8B8_UNORM:
fc[0] = spu_unpack_A8R8G8B8(c0);
fc[1] = spu_unpack_A8R8G8B8(c1);
fc[2] = spu_unpack_A8R8G8B8(c2);
fc[3] = spu_unpack_A8R8G8B8(c3);
break;
default:
ASSERT(0);
}
_transpose_matrix4x4(fbRGBA, fc);
}
/*
* Compute Src RGB terms
*/
qword bias = (qword) spu_splats((unsigned char) ((ix & 0x01) << 3));
qword bias_mask = si_fsmbi(0x3333);
qword sv = si_a(shuf_vec, si_and(bias_mask, bias));
switch (spu.blend.rgb_src_factor) {
case PIPE_BLENDFACTOR_ONE:
term1r = fragR;
term1g = fragG;
term1b = fragB;
break;
case PIPE_BLENDFACTOR_ZERO:
term1r =
term1g =
term1b = spu_splats(0.0f);
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
term1r = spu_mul(fragR, fragR);
term1g = spu_mul(fragG, fragG);
term1b = spu_mul(fragB, fragB);
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
term1r = spu_mul(fragR, fragA);
term1g = spu_mul(fragG, fragA);
term1b = spu_mul(fragB, fragA);
break;
/* XXX more cases */
default:
ASSERT(0);
}
*depth = si_shufb(*ptr, *ptr, sv);
*stencil = si_il(0);
break;
/*
* Compute Src Alpha term
*/
switch (spu.blend.alpha_src_factor) {
case PIPE_BLENDFACTOR_ONE:
term1a = fragA;
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
term1a = spu_splats(0.0f);
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
term1a = spu_mul(fragA, fragA);
break;
/* XXX more cases */
default:
ASSERT(0);
}
/*
* Compute Dest RGB terms
*/
switch (spu.blend.rgb_dst_factor) {
case PIPE_BLENDFACTOR_ONE:
term2r = fragR;
term2g = fragG;
term2b = fragB;
break;
case PIPE_BLENDFACTOR_ZERO:
term2r =
term2g =
term2b = spu_splats(0.0f);
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
term2r = spu_mul(fbRGBA[0], fragR);
term2g = spu_mul(fbRGBA[1], fragG);
term2b = spu_mul(fbRGBA[2], fragB);
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
term2r = spu_mul(fbRGBA[0], fragA);
term2g = spu_mul(fbRGBA[1], fragA);
term2b = spu_mul(fbRGBA[2], fragA);
break;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
one = spu_splats(1.0f);
tmp = spu_sub(one, fragA);
term2r = spu_mul(fbRGBA[0], tmp);
term2g = spu_mul(fbRGBA[1], tmp);
term2b = spu_mul(fbRGBA[2], tmp);
break;
/* XXX more cases */
default:
ASSERT(0);
}
/*
* Compute Dest Alpha term
*/
switch (spu.blend.alpha_dst_factor) {
case PIPE_BLENDFACTOR_ONE:
term2a = fragA;
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
term2a = spu_splats(0.0f);
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
term2a = spu_mul(fbRGBA[3], fragA);
break;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
one = spu_splats(1.0f);
tmp = spu_sub(one, fragA);
term2a = spu_mul(fbRGBA[3], tmp);
break;
/* XXX more cases */
default:
ASSERT(0);
}
/*
* Combine Src/Dest RGB terms
*/
switch (spu.blend.rgb_func) {
case PIPE_BLEND_ADD:
fragR = spu_add(term1r, term2r);
fragG = spu_add(term1g, term2g);
fragB = spu_add(term1b, term2b);
break;
case PIPE_BLEND_SUBTRACT:
fragR = spu_sub(term1r, term2r);
fragG = spu_sub(term1g, term2g);
fragB = spu_sub(term1b, term2b);
break;
/* XXX more cases */
default:
ASSERT(0);
}
/*
* Combine Src/Dest A term
*/
switch (spu.blend.alpha_func) {
case PIPE_BLEND_ADD:
fragA = spu_add(term1a, term2a);
break;
case PIPE_BLEND_SUBTRACT:
fragA = spu_sub(term1a, term2a);
break;
/* XXX more cases */
default:
ASSERT(0);
}
}
case PIPE_FORMAT_Z32_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
*depth = *ptr;
*stencil = si_il(0);
break;
}
case PIPE_FORMAT_Z24S8_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
qword mask = si_fsmbi(0xEEEE);
*depth = si_rotmai(si_and(*ptr, mask), -8);
*stencil = si_andc(*ptr, mask);
break;
}
case PIPE_FORMAT_S8Z24_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
*depth = si_and(*ptr, si_fsmbi(0x7777));
*stencil = si_andi(si_roti(*ptr, 8), 0x0ff);
break;
}
default:
assert(0);
break;
}
}
static void
write_ds_quad(tile_t *buffer, unsigned x, unsigned y,
enum pipe_format depth_format,
qword depth, qword stencil)
{
const int ix = x / 2;
const int iy = y / 2;
(void) stencil;
switch (depth_format) {
case PIPE_FORMAT_Z16_UNORM: {
qword *ptr = (qword *) &buffer->us8[iy][ix / 2];
qword sv = ((ix & 0x01) == 0)
? (qword) { 2, 3, 6, 7, 10, 11, 14, 15,
24, 25, 26, 27, 28, 29, 30, 31 }
: (qword) { 16, 17, 18, 19, 20 , 21, 22, 23,
2, 3, 6, 7, 10, 11, 14, 15 };
*ptr = si_shufb(depth, *ptr, sv);
break;
}
case PIPE_FORMAT_Z32_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
*ptr = depth;
break;
}
case PIPE_FORMAT_Z24S8_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
qword mask = si_fsmbi(0xEEEE);
depth = si_shli(depth, 8);
*ptr = si_selb(stencil, depth, mask);
break;
}
case PIPE_FORMAT_S8Z24_UNORM: {
qword *ptr = (qword *) &buffer->ui4[iy][ix];
qword mask = si_fsmbi(0x7777);
stencil = si_shli(stencil, 24);
*ptr = si_selb(stencil, depth, mask);
break;
}
default:
assert(0);
break;
}
}
qword
spu_do_depth_stencil(int x, int y,
qword frag_mask, qword frag_depth, qword frag_alpha,
qword facing)
{
struct spu_frag_test_results result;
qword pixel_depth;
qword pixel_stencil;
/* All of this preable code (everthing before the call to frag_test) should
* be generated on the PPU and upload to the SPU.
/*
* Convert RRRR,GGGG,BBBB,AAAA to RGBA,RGBA,RGBA,RGBA.
*/
if (spu.read_depth || spu.read_stencil) {
read_ds_quad(&spu.ztile, x, y, spu.fb.depth_format,
&pixel_depth, &pixel_stencil);
#if 0
/* original code */
{
vector float frag_soa[4];
frag_soa[0] = fragR;
frag_soa[1] = fragG;
frag_soa[2] = fragB;
frag_soa[3] = fragA;
_transpose_matrix4x4(frag_aos, frag_soa);
}
switch (spu.fb.depth_format) {
case PIPE_FORMAT_Z16_UNORM:
frag_depth = si_fm(frag_depth, (qword)spu_splats((float)(0x0000ffffu)));
frag_depth = si_cfltu(frag_depth, 0);
#else
/* short-cut relying on function parameter layout: */
_transpose_matrix4x4(frag_aos, &fragR);
(void) fragG;
(void) fragB;
#endif
/*
* Pack float colors into 32-bit RGBA words.
*/
switch (spu.fb.color_format) {
case PIPE_FORMAT_A8R8G8B8_UNORM:
c0 = spu_pack_A8R8G8B8(frag_aos[0]);
c1 = spu_pack_A8R8G8B8(frag_aos[1]);
c2 = spu_pack_A8R8G8B8(frag_aos[2]);
c3 = spu_pack_A8R8G8B8(frag_aos[3]);
break;
case PIPE_FORMAT_Z32_UNORM:
frag_depth = si_fm(frag_depth, (qword)spu_splats((float)(0xffffffffu)));
frag_depth = si_cfltu(frag_depth, 0);
break;
case PIPE_FORMAT_Z24S8_UNORM:
case PIPE_FORMAT_S8Z24_UNORM:
frag_depth = si_fm(frag_depth, (qword)spu_splats((float)(0x00ffffffu)));
frag_depth = si_cfltu(frag_depth, 0);
case PIPE_FORMAT_B8G8R8A8_UNORM:
c0 = spu_pack_B8G8R8A8(frag_aos[0]);
c1 = spu_pack_B8G8R8A8(frag_aos[1]);
c2 = spu_pack_B8G8R8A8(frag_aos[2]);
c3 = spu_pack_B8G8R8A8(frag_aos[3]);
break;
default:
fprintf(stderr, "SPU: Bad pixel format in spu_default_fragment_ops\n");
ASSERT(0);
break;
}
result = (*spu.frag_test)(frag_mask, pixel_depth, pixel_stencil,
frag_depth, frag_alpha, facing);
/* This code (everthing after the call to frag_test) should
* be generated on the PPU and upload to the SPU.
/*
* Color masking
*/
if (spu.read_depth || spu.read_stencil) {
write_ds_quad(&spu.ztile, x, y, spu.fb.depth_format,
result.depth, result.stencil);
if (spu.blend.colormask != 0xf) {
/* XXX to do */
/* apply color mask to 32-bit packed colors */
}
return result.mask;
/*
* Logic Ops
*/
if (spu.blend.logicop_enable) {
/* XXX to do */
/* apply logicop to 32-bit packed colors */
}
/*
* If mask is non-zero, mark tile as dirty.
*/
if (spu_extract(spu_orx(mask), 0)) {
spu.cur_ctile_status = TILE_STATUS_DIRTY;
}
else {
return;
}
/*
* Write new quad colors to the framebuffer/tile.
* Only write pixels where the corresponding mask word is set.
*/
#if LINEAR_QUAD_LAYOUT
/*
* Quad layout:
* +--+--+--+--+
* |p0|p1|p2|p3|
* +--+--+--+--+
*/
if (spu_extract(mask, 0))
colorTile->ui[y][x*2] = c0;
if (spu_extract(mask, 1))
colorTile->ui[y][x*2+1] = c1;
if (spu_extract(mask, 2))
colorTile->ui[y][x*2+2] = c2;
if (spu_extract(mask, 3))
colorTile->ui[y][x*2+3] = c3;
#else
/*
* Quad layout:
* +--+--+
* |p0|p1|
* +--+--+
* |p2|p3|
* +--+--+
*/
if (spu_extract(mask, 0))
colorTile->ui[y+0][x+0] = c0;
if (spu_extract(mask, 1))
colorTile->ui[y+0][x+1] = c1;
if (spu_extract(mask, 2))
colorTile->ui[y+1][x+0] = c2;
if (spu_extract(mask, 3))
colorTile->ui[y+1][x+1] = c3;
#endif
}

View File

@ -1,32 +1,44 @@
/*
* (C) Copyright IBM Corporation 2008
/**************************************************************************
*
* 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
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SPU_PER_FRAGMENT_OP
#define SPU_PER_FRAGMENT_OP
extern qword
spu_do_depth_stencil(int x, int y, qword frag_mask, qword frag_depth,
qword frag_alpha, qword facing);
extern void
spu_fallback_fragment_ops(uint x, uint y,
tile_t *colorTile,
tile_t *depthStencilTile,
vector float fragZ,
vector float fragRed,
vector float fragGreen,
vector float fragBlue,
vector float fragAlpha,
vector unsigned int mask);
#endif /* SPU_PER_FRAGMENT_OP */

View File

@ -97,7 +97,7 @@ get_four_texels(uint unit, vec_uint4 x, vec_uint4 y, vec_uint4 *texels)
const qword offset_y = si_andi((qword) y, 0x1f);
const qword tiles_per_row = (qword) spu_splats(spu.texture[unit].tiles_per_row);
const qword tile_size = (qword) spu_splats(sizeof(tile_t));
const qword tile_size = (qword) spu_splats((unsigned) sizeof(tile_t));
qword tile_offset = si_mpya((qword) tile_y, tiles_per_row, (qword) tile_x);
tile_offset = si_mpy((qword) tile_offset, tile_size);

View File

@ -31,6 +31,9 @@
#include "spu_main.h"
/**
* Get tile of color or Z values from main memory, put into SPU memory.
*/
void
get_tile(uint tx, uint ty, tile_t *tile, int tag, int zBuf)
{
@ -56,6 +59,9 @@ get_tile(uint tx, uint ty, tile_t *tile, int tag, int zBuf)
}
/**
* Move tile of color or Z values from SPU memory to main memory.
*/
void
put_tile(uint tx, uint ty, const tile_t *tile, int tag, int zBuf)
{

View File

@ -38,7 +38,6 @@
#include "spu_texture.h"
#include "spu_tile.h"
#include "spu_tri.h"
#include "spu_per_fragment_op.h"
/** Masks are uint[4] vectors with each element being 0 or 0xffffffff */
@ -209,7 +208,7 @@ clip_emit_quad(struct setup_stage *setup)
/**
* Evaluate attribute coefficients (plane equations) to compute
* attribute values for the four fragments in a quad.
* Eg: four colors will be compute.
* Eg: four colors will be computed (in AoS format).
*/
static INLINE void
eval_coeff(uint slot, float x, float y, vector float result[4])
@ -255,31 +254,6 @@ eval_z(float x, float y)
}
static INLINE mask_t
do_depth_test(int x, int y, mask_t quadmask)
{
float4 zvals;
mask_t mask;
if (spu.fb.depth_format == PIPE_FORMAT_NONE)
return quadmask;
zvals.v = eval_z((float) x, (float) y);
mask = (mask_t) spu_do_depth_stencil(x - setup.cliprect_minx,
y - setup.cliprect_miny,
(qword) quadmask,
(qword) zvals.v,
(qword) spu_splats((unsigned char) 0x0ffu),
(qword) spu_splats((unsigned int) 0x01u));
if (spu_extract(spu_orx(mask), 0))
spu.cur_ztile_status = TILE_STATUS_DIRTY;
return mask;
}
/**
* Emit a quad (pass to next stage). No clipping is done.
* Note: about 1/5 to 1/7 of the time, mask is zero and this function
@ -289,18 +263,6 @@ do_depth_test(int x, int y, mask_t quadmask)
static INLINE void
emit_quad( int x, int y, mask_t mask )
{
#if 0
struct softpipe_context *sp = setup.softpipe;
setup.quad.x0 = x;
setup.quad.y0 = y;
setup.quad.mask = mask;
sp->quad.first->run(sp->quad.first, &setup.quad);
#else
if (spu.read_depth) {
mask = do_depth_test(x, y, mask);
}
/* If any bits in mask are set... */
if (spu_extract(spu_orx(mask), 0)) {
const int ix = x - setup.cliprect_minx;
@ -308,6 +270,7 @@ emit_quad( int x, int y, mask_t mask )
vector float colors[4];
spu.cur_ctile_status = TILE_STATUS_DIRTY;
spu.cur_ztile_status = TILE_STATUS_DIRTY;
if (spu.texture[0].start) {
/* texture mapping */
@ -355,55 +318,29 @@ emit_quad( int x, int y, mask_t mask )
}
/* Convert fragment data from AoS to SoA format.
*/
qword soa_frag[4];
_transpose_matrix4x4((vec_float4 *) soa_frag, colors);
/* Read the current framebuffer values.
*/
const qword pix[4] = {
(qword) spu_splats(spu.ctile.ui[iy+0][ix+0]),
(qword) spu_splats(spu.ctile.ui[iy+0][ix+1]),
(qword) spu_splats(spu.ctile.ui[iy+1][ix+0]),
(qword) spu_splats(spu.ctile.ui[iy+1][ix+1]),
};
qword soa_pix[4];
if (spu.read_fb) {
/* Convert pixel data from AoS to SoA format.
{
/* Convert fragment data from AoS to SoA format.
* I.e. (RGBA,RGBA,RGBA,RGBA) -> (RRRR,GGGG,BBBB,AAAA)
* This is temporary!
*/
vec_float4 aos_pix[4] = {
spu_unpack_A8R8G8B8(spu.ctile.ui[iy+0][ix+0]),
spu_unpack_A8R8G8B8(spu.ctile.ui[iy+0][ix+1]),
spu_unpack_A8R8G8B8(spu.ctile.ui[iy+1][ix+0]),
spu_unpack_A8R8G8B8(spu.ctile.ui[iy+1][ix+1]),
};
vector float soa_frag[4];
_transpose_matrix4x4(soa_frag, colors);
_transpose_matrix4x4((vec_float4 *) soa_pix, aos_pix);
float4 fragZ;
fragZ.v = eval_z((float) x, (float) y);
/* Do all per-fragment/quad operations here, including:
* alpha test, z test, stencil test, blend and framebuffer writing.
*/
spu.fragment_ops(ix, iy, &spu.ctile, &spu.ztile,
fragZ.v,
soa_frag[0], soa_frag[1],
soa_frag[2], soa_frag[3],
mask);
}
struct spu_blend_results result =
(*spu.blend)(soa_frag[0], soa_frag[1], soa_frag[2], soa_frag[3],
soa_pix[0], soa_pix[1], soa_pix[2], soa_pix[3],
spu.const_blend_color[0], spu.const_blend_color[1],
spu.const_blend_color[2], spu.const_blend_color[3]);
/* Convert final pixel data from SoA to AoS format.
*/
result = (*spu.logicop)(pix[0], pix[1], pix[2], pix[3],
result.r, result.g, result.b, result.a,
(qword) mask);
spu.ctile.ui[iy+0][ix+0] = spu_extract((vec_uint4) result.r, 0);
spu.ctile.ui[iy+0][ix+1] = spu_extract((vec_uint4) result.g, 0);
spu.ctile.ui[iy+1][ix+0] = spu_extract((vec_uint4) result.b, 0);
spu.ctile.ui[iy+1][ix+1] = spu_extract((vec_uint4) result.a, 0);
}
#endif
}

View File

@ -1,4 +1,5 @@
#include "cell/common.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_debug.h"
#include "tgsi/tgsi_parse.h"
@ -20,7 +21,7 @@ tgsi_util_get_src_register_swizzle(
case 3:
return reg->SwizzleW;
default:
assert( 0 );
ASSERT( 0 );
}
return 0;
}
@ -40,7 +41,7 @@ tgsi_util_get_src_register_extswizzle(
case 3:
return reg->ExtSwizzleW;
default:
assert( 0 );
ASSERT( 0 );
}
return 0;
}
@ -60,12 +61,12 @@ tgsi_util_get_full_src_register_extswizzle(
&reg->SrcRegisterExtSwz,
component );
assert (TGSI_SWIZZLE_X == TGSI_EXTSWIZZLE_X);
assert (TGSI_SWIZZLE_Y == TGSI_EXTSWIZZLE_Y);
assert (TGSI_SWIZZLE_Z == TGSI_EXTSWIZZLE_Z);
assert (TGSI_SWIZZLE_W == TGSI_EXTSWIZZLE_W);
assert (TGSI_EXTSWIZZLE_ZERO > TGSI_SWIZZLE_W);
assert (TGSI_EXTSWIZZLE_ONE > TGSI_SWIZZLE_W);
ASSERT (TGSI_SWIZZLE_X == TGSI_EXTSWIZZLE_X);
ASSERT (TGSI_SWIZZLE_Y == TGSI_EXTSWIZZLE_Y);
ASSERT (TGSI_SWIZZLE_Z == TGSI_EXTSWIZZLE_Z);
ASSERT (TGSI_SWIZZLE_W == TGSI_EXTSWIZZLE_W);
ASSERT (TGSI_EXTSWIZZLE_ZERO > TGSI_SWIZZLE_W);
ASSERT (TGSI_EXTSWIZZLE_ONE > TGSI_SWIZZLE_W);
/*
* Second, calculate the simple swizzle for the unswizzled channel index.
@ -95,7 +96,7 @@ tgsi_util_get_src_register_extnegate(
case 3:
return reg->NegateW;
default:
assert( 0 );
ASSERT( 0 );
}
return 0;
}
@ -120,7 +121,7 @@ tgsi_util_set_src_register_extnegate(
reg->NegateW = negate;
break;
default:
assert( 0 );
ASSERT( 0 );
}
}

View File

@ -92,7 +92,7 @@ static void generic_vertex_fetch(struct spu_vs_context *draw,
unsigned nr_attrs = draw->vertex_fetch.nr_attrs;
unsigned attr;
assert(count <= 4);
ASSERT(count <= 4);
#if DRAW_DBG
printf("SPU: %s count = %u, nr_attrs = %u\n",

View File

@ -112,7 +112,7 @@ run_vertex_program(struct spu_vs_context *draw,
const float *scale = draw->viewport.scale;
const float *trans = draw->viewport.translate;
assert(count <= 4);
ASSERT(count <= 4);
machine->Processor = TGSI_PROCESSOR_VERTEX;

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